1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-22 05:59:10 +00:00

Compare commits

..

149 Commits

Author SHA1 Message Date
rubidium
9df8a3bd4c (svn r9978) -Release 0.5.2. 2007-05-29 18:13:06 +00:00
rubidium
4f757bb914 (svn r9977) [0.5] -Prepare 0.5 branch for release of 0.5.2. 2007-05-29 18:02:14 +00:00
rubidium
aafb49b3c4 (svn r9968) [0.5] -Backport from trunk (r9966):
- Fix: bridges and tunnels were not always removed on bankruptcy, thus leaving tunnels/bridges with an invalid owner that would crash the game when clicking with the query tool on them.
2007-05-28 22:11:42 +00:00
glx
4bbc264c72 (svn r9864) [0.5] -Codechange (win32): Remove references to MSLU and hide UNICODE notice for win9x users in installer 2007-05-17 19:47:04 +00:00
rubidium
f042798507 (svn r9863) [0.5] -Backport from trunk (r9759, r9861):
- Feature: Add threading support for MorphOS (r9759)
- Fix: Null pointer dereference under MorphOS and AmigaOS (r9861)
2007-05-17 15:04:28 +00:00
rubidium
909edb84af (svn r9859) [0.5] -Prepare 0.5 branch for release of 0.5.2-RC1. 2007-05-16 21:41:34 +00:00
rubidium
906a606418 (svn r9858) [0.5] -Backport from trunk (r9771, r9856):
- Feature: Add password protected status to 'players' (network server) console command (r9771)
- Fix: Loading some TTDP savegames caused an instant assertion on loading (r9857)
2007-05-16 21:33:07 +00:00
rubidium
2c6a0e46a9 (svn r9856) [0.5] -Backport from trunk (r9855):
- Fix: Do not perform any commands on MP_VOID tiles [FS#779] (r9855)
2007-05-16 08:21:16 +00:00
rubidium
236237740a (svn r9854) [0.5] -Backport from trunk (r9715, r9724, r9774, r9796, r9811, r9847): language updates. 2007-05-15 23:32:50 +00:00
rubidium
3a195edcad (svn r9853) [0.5] -Backport from trunk (r9837, r9827, r9785, r9775, r9758, r9716):
- Feature: Add server_lang in [network] section of openttd.cfg (r9716)
- Fix: [NewGRF] Catch occurance of division-by-zero in varaction handling (r9837)
- Fix: Only non dedicated servers cannot have 0 players [FS#765] (r9785)
- Fix: Remove arbitrary limit on length of NewGRF strings (r9775)
- Fix: [NewGRF] Ignore axis-bit of station tile layouts [FS#756] (r9758)
2007-05-15 22:02:32 +00:00
glx
c50cf74889 (svn r9852) [0.5] -Backport from trunk (r9728, r9834):
- Fix: [win32] Dead key and open/close console. (r9728)
- Add: win9x check in win32 builds
2007-05-15 22:00:41 +00:00
rubidium
4b6d1f9027 (svn r9851) [0.5] -Backport from trunk (r9731, r9741, r9743, r9753, r9757):
- Fix: when you have closed the "Load game"/"New game" windows which you started from the "start server" menu, you shouldn't start a server when starting a new game [SF#1244842] (r9757)
- Fix: Trains were lost after autorenewal/autoreplace [FS#732] (r9753)
- Fix: Stop flooded towns from building roads on water [FS#598] (r9743)
- Fix: Station signs were not resized when the language changed [FS#672] (r9741)
- Fix: In news history, newlines were not replaced with spaces [FS#677] (r9731)
2007-05-15 21:42:27 +00:00
rubidium
c9c087e858 (svn r9849) [0.5] -Backport from trunk (r9693, r9694, r9697, r9718, r9719, r9725 and 9726):
- Fix: Crash when destroying bridge with train partially on it [FS#738] (r9726)
- Fix: Planes made a 270 degree turn instead of a 90 degree turn on the southern runway of the intercontinental airport [FS#743] (r9725)
- Fix: In-game private messages did not work for clients with high ClientIDs (r9719)
- Fix: Do not allow building of rail vehicles whose railtype is not available (r9718)
- Fix: [YAPF] The guessed path was ignored for ships [FS#736] (r9694)
2007-05-15 21:24:18 +00:00
rubidium
ac66e29910 (svn r9698) [0.5] -Prepare 0.5 branch for release of 0.5.1. 2007-04-20 19:45:38 +00:00
rubidium
b7749bde91 (svn r9695) [0.5] -Backport from trunk (r9668, r9680, r9681, r9687): language updates. 2007-04-20 19:40:07 +00:00
rubidium
635eff5e51 (svn r9660) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC3. 2007-04-17 20:11:11 +00:00
truelight
4cd6870777 (svn r9659) [0.5] -Fix r9656: missed 2 hunks in last commit 2007-04-17 19:08:08 +00:00
truelight
54cfb12334 (svn r9657) [0.5] -Backport from trunk (r9585, r9613, r9615, r9633, r9640, r9649):
- Language updates (r9585, r9613, r9615, r9633, r9640, r9649)
2007-04-17 19:05:47 +00:00
rubidium
2d746c52c8 (svn r9656) [0.5] -Backport from trunk (r9602, r9641, r9647):
- Fix: Building rail on steep slopes ignored build_on_slopes patch setting (r9602)
- Fix: namegen.cpp was not UTF-8, which caused artefacts in Finnish town names (r9641)
- Fix: Select "Custom" in the difficulty settings gui when changing a setting [FS#733] (r9647)
2007-04-17 18:09:12 +00:00
truelight
cb001e017a (svn r9589) [0.5] -Fix (r9587, r9588): this time I really do hope turkish.txt went okay... 2007-04-10 13:12:15 +00:00
truelight
9bee2fc641 (svn r9588) [0.5] -Fix r9587: something went wrong in turkish.txt update 2007-04-10 13:04:44 +00:00
truelight
7399e107e1 (svn r9587) [0.5] -Backport from trunk (r9585):
- Language updates (r9585)
2007-04-10 13:02:01 +00:00
truelight
70db6b3f40 (svn r9586) [0.5] -Backport from trunk (r9525, r9527, r9547, r9548, r9570, r9571, r9572, r9576):
- Language updates (r9525, r9527, r9547, r9548, r9570, r9571, r9572, r9576)
2007-04-10 12:58:05 +00:00
truelight
ac6aefa07b (svn r9584) [0.5] -Backport frmo trunk (r9542, r9565, r9573):
- Fix: when checking for no vehicle on ground-tiles, don't take into account vehicles that are in the air (r9542)
- Feature: add list_patches to console commands; shows all patches and values (r9565)
- Fix: enclose settings names containing spaces with quotes (r9573)
2007-04-10 09:57:35 +00:00
truelight
c04f0af19b (svn r9583) [0.5] -Backport from trunk (r9529, r9533, r9540, r9541):
- Fix: when 2 clients joined together, the second asserted on the NewCompany command of the first (r9529)
- Fix: when company is removed, sell all shares he has first, then sell all shares other people might have in this company (r9533)
- Fix: bankrupt AIs no longer buy over themselves (also added safeguards to prevent in future) (r9540 / r9541)
2007-04-10 09:49:41 +00:00
truelight
c8c8667dc8 (svn r9582) [0.5] -Backport from trunk (r9425, r9437, r9455, r9519):
- Fix: housekeeping in convert rail functions (r9425)
- Fix: dedicated server crashed when the y part of the resolution was less than 10 (r9437)
- Fix: values of diff_custom and snow_line in .cfg weren't checked properly (r9455)
- Fix: free the malloc'd variable, not the pointer to that variable (r9519)
2007-04-10 09:40:36 +00:00
belugas
a0688e8d85 (svn r9471) [0.5] -Backport from trunk (r9467 & r9469):
Reset the whole currency array while preserving custom one.  Also, max data of to_euro is now 300, not 1000, disabling any proper loading of the patch setting
2007-03-26 00:20:22 +00:00
truelight
c85022e3db (svn r9430) [0.5] -Backport r9429: when deleting a vehicle which has shared orders with one more vehicle and no orders, segfaulted 2007-03-24 15:16:41 +00:00
rubidium
be39b87154 (svn r9422) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC2. 2007-03-23 22:54:19 +00:00
rubidium
71aa3a4de2 (svn r9421) [0.5] -Backport from trunk (r9392, r9415, r9420, custom):
- Fix: crashes when the chatbox would be drawn outside of the main window [FS#701] (r9420)
- Language updates (r9392, r9414, custom Simplified Chinese)
2007-03-23 22:44:03 +00:00
rubidium
f7fd8eca21 (svn r9394) [0.5] -Fix (r9343): reading out of an array caused a segmentation fault. 2007-03-21 23:06:01 +00:00
bjarni
ab77a35093 (svn r9384) [0.5] -Fix: [MorphOS] updated make release to avoid the need to specify RELEASE when building 2007-03-21 00:00:08 +00:00
rubidium
a808b77b2b (svn r9382) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC1. 2007-03-20 21:12:18 +00:00
rubidium
52a0d04473 (svn r9380) [0.5] -Backport from trunk (r9378):
- Fix: cancel in password queries reduces amount of players in the network game when they haven't joined the game yet (r9378)
2007-03-20 20:36:45 +00:00
glx
64f7b3a059 (svn r9358) [0.5] -Backport from trunk (r9055, r9082, r9083, r9084, r9085, r9086):
- Codechange: Change windows unicode handling and allow a pure non-unicode build to function. (r9055)
- Codechange: [win32] Update VS2003 and VS2005 project files to build in UNICODE mode. When making a release it is probably better to make two binaries, one without UNICODE, the other with, guaranteeing full Win9x compatibility (UNICODE with MSLU also works, without it's even better). (r9082)
- Codechange: Be more lenient when trimming UTF-8 strings and don't terminate the string when an invalid encoding is encountered, but only focus on maximum length. (r9083)
- Fix: [win9x] Clipboard paste for Windows95 (doesn't have CF_UNICODETEXT) correctly converts the input to the current locale. (r9084)
- Fix: [win32] Move the initialisation of _codepage (non-UNICODE) to winMain as a dedicated server, or different video driver will not have a win32 messageloop. (r9085)
- Fix: [win32] Rewrite keyboard input and handle all keypresses in a WM_CHAR event. This saves us from doing translation (ToUnicode[Ex], ToAscii[Ex]), and we get free IME-input support as a plus. (r9086)
2007-03-20 00:02:18 +00:00
rubidium
b70c3613fa (svn r9355) [0.5] -Backport from trunk (r8906):
- Feature: translation dependant formatting of dates (r8906)
2007-03-19 22:08:18 +00:00
glx
3158cdaa7a (svn r9354) [0.5] -Backport from trunk (r8975, r9003, r9011, r9012):
-Regression: [win32] Possible buffer overflow if unicode text is pasted into an input box and needs trimming. (r8975)
-Codechange: Introduce a function Utf8PrevCharLen that finds the starting character of an UTF-8 sequence from a given position and returns the length to the first UTF-8 encoding byte of that sequence. (r9003)
-Codechange: Rework Utf8PrevChar so that it returns a pointer to the previous UTF8 character's first byte instead of a byte-length offset (r9011)
-Fix: When cutting strings into multiple lines also take into consideration whitespace characters of more than 1 byte length (eg IDEOGRAPHIC SPACE, IsWhitespace() function). When trimming such strings, account for multiple-byte long sequences so use *Utf8PrevChar(v) = '\0'. (r9012)
-Codechange: Add a function Utf8TrimString() that properly trims a string to an UTF8 encoding seperation instead of somewhere in the wild (and use it in the chat area) (r9012)
2007-03-19 21:42:05 +00:00
rubidium
140abde4ef (svn r9353) [0.5] -Backport language updates from trunk (r8957, r9002, r9005, r9013, r9014, r9020, r9021, r9054, r9116, r9118, r9132, r9286, r9292) 2007-03-19 21:04:06 +00:00
rubidium
850f73719f (svn r9351) [0.5] -Backport from trunk (r9147, r9205, r9251, r9298):
- Fix: when loadin games, enroute_from was updated in the wrong place, causing issues with TTD savegames/scenarios (r9147)
- Fix: when you started openttd with '-g' you got the same map every run (r9205)
- Fix: use a less CPU-intensive algorithm to find a random industry for the AI to prevent it slowing down the game (r9251)
- Fix: A34-1000, Z-Shuttle, and Kelling K1 are now listed as small aircraft (r9298)
2007-03-19 20:38:26 +00:00
rubidium
d2ce2009b5 (svn r9350) [0.5] -Backport from trunk (r9105, r9115, r9117, r9146):
- Fix: disable the ability to make flooding water with the canal build tool. In the scenario editor you can still make both canals and flooding water at height level 0 (r9105)
- Fix: make clear in the tooltips when the canal build tool (in the scenario editor) makes flooding water (r9115)
- Fix: difficulty level button was not selected when opening the difficulty window (r9117)
- Fix: "Train is lost" message is generated incorrectly (r9146)
2007-03-19 20:23:27 +00:00
rubidium
6ad4716dc1 (svn r9349) [0.5] -Backport from trunk (r9043, r9062, r9064, r9070):
- Fix: the personal (.openttd) directories were hidden in the load/save directory listings (r9043)
- Fix: the station list, sorted by cargo rating, now takes stations into account that have no cargo waiting (r9062)
- Fix: don't keep on scrolling for non-numeric values in settings, but require reclick (r9064)
- Fix: when a bribe failed and you haven't picked up cargo yet, you would never be able to do so for a given station (r9070)
2007-03-19 20:17:24 +00:00
rubidium
0ec558f99f (svn r9348) [0.5] -Backport from trunk (r8974, r8994, r9074):
- Fix: support compilation with the Vista Platform SDK (r8974)
- Fix: resolution doubled in cfg file when fullscreen mode used (r8994)
- Fix: win32 dedicated console now doesn't need an extra 'enter' to fully quit (r9074)
2007-03-19 20:05:49 +00:00
rubidium
41727b6e23 (svn r9347) [0.5] -Backport from trunk (r9019, r9076, r9077):
- Fix: use <> for system-headers (r9019)
- Fix: the intercontinental airport used 'T-junction' runway sprites when there is no exit in the middle of the runway as in the city airport (r9076)
- Fix: the wrong catenary wires were drawn for tunnel entrances (r9077)
2007-03-19 19:56:16 +00:00
rubidium
c559703312 (svn r9345) [0.5] -Backport from trunk (r9277, r9337, r9338):
- Fix: shared orders got messed up when the 'first' trains got removed in the depot (r9277)
- Fix: assert() when you removed the orders of a shared list while having the shared order vehicle list open (r9337)
- Fix: close the Shared Order Vehicle List if you remove the shared link with only 2 vehicles (r9338)
2007-03-19 19:42:40 +00:00
rubidium
1e7cca8f8b (svn r9344) [0.5] -Backport from trunk (r9027, r9038, r9061, r9071):
- Fix: desync caused by buffer overflow (r9027)
- Feature: kick inactive initial network connections after some time (r9038, r9061)
- Fix: take over companies properly in multiplayer games (r9071)
2007-03-19 19:34:44 +00:00
rubidium
759d155b08 (svn r9343) [0.5] -Backport from trunk (r9000, r9001, r9097, r9137):
- Fix: new locomotive names were not announced in the news, it said "new railway locomotive available - railway locomotive" (r9000, r9001)
- Feature: add an extra news group for opening and closing of industries (r9097)
- Fix: when all news-setting buttons are 'full', make the for-all button show 'full' too (r9137)
2007-03-19 19:22:26 +00:00
rubidium
11b1c6f2ee (svn r9342) [0.5] -Backport from trunk (r8980, r9065, r9339):
- Fix: the industry list should also be (re)set when the number of industries is 0 (r8980)
- Fix: possible dereference of NULL pointer (r9065)
- Codechange: disable shares by default and increase the default maximum distance from edge for oil refineries (r9339)
2007-03-19 18:54:48 +00:00
rubidium
98f77876e6 (svn r9341) [0.5] -Backport from trunk (r8943, r8955, r8976, r8999, r9009):
- Fix: NewGRF support for vehicle variable 48 (r8943)
- Fix: crash on loading savegames with GRFs that do not have their GRF info/name set (r8955)
- Fix: reinitialize all engines after grf files have been reloaded/changed (r8976)
- Fix: do not select a disabled platform length/number of track count when going out of drag-drop mode (r8999)
- Fix: play the correct engine sound based on the engine type instead of the sprite (r9009)
2007-03-19 18:47:10 +00:00
rubidium
5a703390ec (svn r9128) [0.5] -Fix: trains slow down under bridges when they were going down on the tile before the bridge tile. 2007-03-11 23:03:14 +00:00
Darkvater
e925f8b2c3 (svn r8930) [0.5] -Backport from trunk (r8929):
- [win32] Installer update (r8929)
2007-02-27 22:13:15 +00:00
Darkvater
01e3d92118 (svn r8923) [0.5] -Prepare (again) 0.5 branch for release, update a few dates and changelog 2007-02-27 16:29:22 +00:00
Darkvater
9321458918 (svn r8922) [0.5] -Backport from trunk (r8907, r8919, r8920, r8921):
- [OSX] Reading from an unitialized variable (r8907)
 - [Win9x] FindFile with C:\\* doesn't work, don't append a slash doubly (r8919)
 - Do not require to press 'Apply changes' in the newgrf GUI if the changes in there are not activated (this happens in the title screen) (r8920)
 - Possible crashes, problems with aircraft and airport removal (r8921)
2007-02-27 16:23:02 +00:00
Darkvater
cd6d6d32d3 (svn r8917) [0.5] -Codechange (win32): Do not empty the data-path for the installer if you press the 'Back' button. 2007-02-27 15:51:52 +00:00
Darkvater
5bfdc6e75a (svn r8916) [0.5] -Codechange (win32): Update the installer, add proper indentation, use MUI throughout and add a custom page about UNICODE and MSLU (remove some obsolete files) 2007-02-27 15:29:11 +00:00
Darkvater
274f841c61 (svn r8915) [0.5] -Codechange: Renamed remotely 2007-02-27 15:19:36 +00:00
matthijs
2b8a0dfacb (svn r8910) [Debian] -Fix: Remove old reference to rc4. 2007-02-26 21:37:14 +00:00
matthijs
4ba3761ab1 (svn r8909) [Debian] -Change: Update debian packaging files to those used for releases.
- Compile with freetype / fontconfig support.
	- Make menu files translatable.
	- Other packaging cleanups.
	- Bump version number to 0.5.0-1.
2007-02-26 21:18:57 +00:00
Darkvater
93586cb6b6 (svn r8905) [0.5] -Update readme's, bugs, installers, changelogs etc. to prepare for 0.5.0.
[0.5] -Remove the limitation that games are refused to be loaded if no newgrf is present (was already like this in trunk/).
2007-02-26 00:19:31 +00:00
Darkvater
c4768438b7 (svn r8895) [0.5] -Backport from trunk (r8645, r8671, r8686, r8690, r8719, r8728, r8729,
r8736, r8742, r8751, r8764, r8788, r8829, r8848, custom):
 - Language file updates.
 - Ukrainian(2), Lithuanian(15), Galician(151)
2007-02-25 10:05:33 +00:00
Darkvater
b3b28dced2 (svn r8883) [0.5] -Backport from trunk (r8740, r8793, r8865, r8878):
- GCC warnings for r8738 (r8740)
 - Correct spelling of real french townnames and 'remove' a duplicate (r8793)
 - (NewGRF) Ignore 1 byte action 0s during safety check (r8865)
 - Stricter checks for CmdMoveRailVehicle() parameters (r8878)
2007-02-24 16:46:36 +00:00
Darkvater
3b2bcbf0f0 (svn r8874) [0.5] -Backport from trunk (r8744, r8685):
- Call GetFirstVehicleInChain only for trains thus increasing performance in large games (r8744)
 - (Feature) Selecting "end of orders" and deleting will delete all the vehicle's orders (in unshared mode, shared is unchanged) (r8685)
2007-02-24 01:47:26 +00:00
Darkvater
1cdfa87b21 (svn r8873) [0.5] -Backport from trunk (r8766, r8836, r8869):
- Rail station platform penalty not calculated properly (r8766)
 - Don't tell destination was found if it was only guessed (r8836)
 - Large Train Stations/Trains causes assert due to wrong cost calculation (r8869)
2007-02-24 01:39:59 +00:00
Darkvater
9e3f020ae8 (svn r8872) [0.5] -Backport from trunk (r8784, r8821, r8823, r8824):
- Unable to load TTDP (on *NIX) games (r8784)
 - Unable to browse directories on *nix if the filesystem is not in UTF-8 charset and special characters are used (r8821, r8823, r8824)
2007-02-24 01:21:31 +00:00
Darkvater
36134a7285 (svn r8871) [0.5] -Backport from trunk (r8689, r8794, r8802, r8808):
- Crash when an old savegame had buoys on the northern edge of the map (r8689)
 - It was possible to take over buoys by building a station next to them (r8794)
 - Adhere order types for ship order insertion to determine destination type (r8802)
 - Do not show the 'edit sign' window for spectators (r8808)
2007-02-24 01:14:54 +00:00
Darkvater
edc2ac8bbf (svn r8870) [0.5] -Backport from trunk (r8684, r8709, r8738, r8777, r8828):
- Bool (uint32 in PPC) was written to as a uint8 (r8684)
 - Fix a problem where loading times for overhanging trains are miscomputed (r8709)
 - Load newer TTDP games (update coastal tiles) (r8738)
 - Cloning unaware of articulated locomotives that could refit without refitting the front unit (r8777)
 - Load station rectangle for all savegames, not only after version 27 (r8828)
2007-02-24 01:02:15 +00:00
Darkvater
c92b6e1e8b (svn r8861) [0.5] -Backport from trunk (r8526, r8792, r8825, r8843):
- Add stubs for unsupported newgrf station properties (r8526)
 - Be more strict about grf-string input (r8792, r8825)
 - Fix an off-by-one error in GRFComment (r8843)
2007-02-23 18:25:11 +00:00
rubidium
524919326b (svn r8761) [0.5] -Update: add some missing strings that are in 0.5, but not in trunk. 2007-02-16 18:36:36 +00:00
rubidium
2d3a64ffcc (svn r8687) [0.5] -Fix [FS#617]: assertion when getting the height of a bridge from the ramp tile. 2007-02-12 10:03:42 +00:00
rubidium
9aa9579283 (svn r8650) [0.5] -Fix: 'Searching Server' is not worthy of debug level 0, as this opens an extra window on MorphOS for no reason. 2007-02-09 11:13:03 +00:00
rubidium
3f987f460d (svn r8649) [0.5] -Fix (8630): accidentally removed strings that were still in use for by 0.5 and forgot to add new languages to langs*.vcproj. 2007-02-09 10:52:21 +00:00
bjarni
23e62bfb15 (svn r8643) [0.5] -Fix: [OSX] link statically to freetype when STATIC is set 2007-02-08 19:24:36 +00:00
rubidium
bbbe65e1e5 (svn r8639) [0.5] -Update readme's, bugs, installers, changelogs etc. to prepare for 0.5.0-RC5. 2007-02-08 16:18:11 +00:00
rubidium
e3c71534e1 (svn r8638) [0.5] -Backport from trunk (8637):
-Fix: CTRL-clicking on a hangar in the order list segfaulted as hangars are part of a station instead of real depots
2007-02-08 16:17:15 +00:00
rubidium
f8b2fb4484 (svn r8636) [0.5] -Backport from trunk (8634, 8635):
-Fix: draw canal edges under buoys that are in a canal
-Codechange: replace missing sprites with a red question mark
2007-02-08 14:10:14 +00:00
rubidium
87bbb7a413 (svn r8630) [0.5] -Backport lots of language updates from trunk 2007-02-08 11:26:09 +00:00
rubidium
61b95ff1fc (svn r8627) [0.5] -Backport from trunk (8409, 8420 + 8421, 8533, 8612):
-Regression: When the latest news was deleted, the news queue wrapped back to the oldest item, showing all news again.
-Regression [FS#573]: ShowLastNewsMessage could show an out-of-bounds news item because it did not checked if a previous item actually existed the first time it is called (forced news is INVALID_NEWS).
-Codechange: Rename the 'New <vehtype>' button of the global vehicle lists to 'Available <vehtype>' as it is a view-only list, not one from which you can purchase (rolling) stock.
-Fix: segmentation fault when the toolbar gets removed and you have selected one of the items in a submenu of the toolbar. 
-Fix [FS#582]: When the currently selected player in the performance details window is no longer active, choose the first active player instead of the first player as that may also be inactive.
2007-02-08 11:03:00 +00:00
rubidium
0543461f5e (svn r8626) [0.5] -Backport from trunk (8294, 8296, 8536, 8540, 8609):
-Fix: deleting a vehicle with shared orders, but no orders would fail to reset prev_shared and next_shared
-Fix: GenerateVehicleSortList()/CmdMassStartStopVehicle() tried to put a TileIndex into an uint16
-Fix (FS#577): Road Vehicles now can obtain a slot even if the station is very spread out 
-Fix[YAPF]: Assert when buoy is placed on NE or NW map edge (Dan)
-Fix: a road vehicle that is very close after another (slower) road vehicle gets its speed reset to 0 when entering a tunnel, which causes a traffic jam outside of the tunnel.
2007-02-08 10:41:45 +00:00
rubidium
4e3652f337 (svn r8625) [0.5] -Backport from trunk (8253, 8273, 8497, 8520 + 8542):
-Codechange: Be more strict about language generation and fail any languages not having the mandatory ##name, ##ownname and ##isocode pragma's.
-Fix: return value from clamp was ignored 
-Codechange: Increase the size of the sound/video/music-drivers to 32 bytes (instead of 16) so their actual parameters can be passed. Sound has for example 'bufsize' and 'hz'.
-Fix/Feature: requery gameservers that did not respond to their first query.
2007-02-08 10:19:03 +00:00
rubidium
1584e061eb (svn r8624) [0.5] -Backport from trunk (8239, 8240, 8315):
-Regression (r7278): Help window was empty for UNICODE builds 
-Fix (r8013): Put the output of -h to stdout and not to stderr (through ShowInfo) 
-Fix: use ShowInfo over fprintf(stderr, as Windows doesn't always have a stderr visible/available
2007-02-08 10:04:57 +00:00
rubidium
03bfa6e525 (svn r8623) [0.5] -Backport from trunk (8593, 8608, 8619, 8620)
-Fix (FS#564): bridges do not get destroyed when the bridge head gets flooded and there is a vehicle on the bridge.
-Fix: you were unable to build roads in the scenario editor when there is no town 0, even though there are other towns. 
-Fix: store the ownership of a water tile in the buoy tile and set the ownership of the water tile when the buoy is removed. This solves the issue of removing ownership from canal tiles thus making is possible for other players to remove the canal tile.
-Fix: buoys on canal tiles do not flood anymore.
2007-02-08 10:00:22 +00:00
bjarni
5467635bf9 (svn r8500) [0.5] -Fix: [OSX] freetype failed to be detected (now it's always enabled because Xcode installs it)
-Fix: [OSX] fontconfig is disabled even if it's found because the default one in OSX is 2.1.0 and OpenTTD needs at least 2.3.0
      -Fix: FREETYPE_CONFIG is only set when it's undefined. This makes it possible to add it as argument to make
2007-01-31 22:08:23 +00:00
rubidium
47c158bbc5 (svn r8490) [0.5] -Add: logging of the IP address and port of invalid/illegal UDP packets. 2007-01-31 12:47:35 +00:00
rubidium
4e1c7b8197 (svn r8489) [0.5] -Backport from trunk (8459, 8461): check for NewGRF compatability before actually downloading the map from a game server when connecting from the command prompt and internal console. 2007-01-31 12:39:41 +00:00
Darkvater
1ec915e1c8 (svn r8228) [0.5] -Revert win32 changes 2007-01-18 00:52:33 +00:00
Darkvater
b30c56d15a (svn r8227) [0.5] -Fix:?
- Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC4
2007-01-18 00:50:56 +00:00
Darkvater
c3fcb2ef2a (svn r8222) [0.5] -Backport from trunk (lang, r8171, r8186, r8218):
- last missed chunk of danish language changes (lang)
 - (FS#556) return SL_ERROR when unthreaded saves failed (r8171)
 - (FS#557) apply railtype offset to station graphics if no custom station is in use (r8186)
 - Increase spritecache size to 2MB (r8218).
2007-01-17 23:39:13 +00:00
Darkvater
1a5957ef7f (svn r8217) [0.5] -Backport some mixed changes for WT2, remove wrong norwegian languages:
- Untranslated strings: Polish (4), Icelandic (221!), Galician (144)
2007-01-17 23:13:19 +00:00
Darkvater
0867ed49a3 (svn r8213) [0.5] -Backport from trunk (r7975, r7983, r7986, r7987, r8012, r8039, r8051,
r8053,  r8068, r8069, r8073, r8082, r8084, r8085, r8086, r8087, r8088, r8108,
 r8121, r8122, r8148, r8162, r8163, r8193, r8206):
 - Language file updates.
 - Untranslated strings: Polish (4), Icelandic (221!), Galician (144), Brazilian-Portugese (4).
 - Add Japanese, Norwegian bokmal/nynorsk, Slovenian as finished.
2007-01-17 22:37:14 +00:00
Darkvater
6c3b245d88 (svn r8182) -Backport from trunk (r8137, r8147, r8157):
- (FS#551) roadstop->num_vehicles was wrong for old savegames loaded for MP (r8137)
 - v->leave_depot_instantly was not always reset correctly (r8147)
 - moving cargo during auto replaces did not update the cached vehicle weight for trains properly (r8157)
 *NOTE* This fixes several desync issues. Big props to Rubidium for finding, debugging
 and fixing them!
2007-01-17 01:23:50 +00:00
Darkvater
a74b15af79 (svn r8181) -Backport from trunk (r8133):
- (FS#535) "out of sprite memory" warning messages (smatz)
2007-01-17 01:19:09 +00:00
Darkvater
ac3b1883ed (svn r8180) -Backport from trunk (r8093, r8094, r8105, r8106, (r8107), r8111, r8165):
- Show the activated status of the GRF after pressing apply in window (r8094)
 - Add the ability to load savegames without matching grf's.
   *NOTE*: currently this feature is different from trunk in behaviour as it does NOT
   allow you to load savegames with MISSING grfs only compatible (matching GRFID, non-
   matching MD5SUM).
2007-01-17 01:17:44 +00:00
Darkvater
40245ce496 (svn r8179) -Backport from trunk (r8065, r8101, r8119, r8123, r8140, r8150):
- The station list does now remember the sort settings (r8065)
 - Uninitializing windows calls WE_DESTROY to free dynamic memory used (r8101, r8119)
 - (FS#538) Findfirstbit returns first bit (bouys now numbered 1..9) (r8123)
 - FS#54) Combat helicopter shoots from right position, (r8140)
 - Submarine disaster did not move around (r8158)
2007-01-17 01:02:51 +00:00
Darkvater
c73bbe531e (svn r8178) -Backport from turnk (r8049, r8079, r8080, r8135):
- oe more news-window fix and fix up ShowLastNewsMessage (r8049)
 - float division by 0 in YAPF code on Win9x (r8079, r8080)
 - do not assert when removing duplicates would remove non-static grf (r8135)
2007-01-17 00:51:04 +00:00
matthijs
8576c2cc40 (svn r8177) - [Debian] Prepare debian packaging files for 0.5.0-rc4 2007-01-17 00:38:51 +00:00
Darkvater
1778566ab8 (svn r8176) -Backport from trunk (r8042, r8089, r8090, r8112):
- OS/2 compilation with GCC (thanks to Paul Smedley and TrueBrain for help) (r8042)
 - [win32] *nprintf functions are broken, 'len = count' wasn't handled (r8089, r8090)
 - MSVC solution files will make openttd THE startup project (r8112)
2007-01-17 00:38:27 +00:00
Darkvater
a4bab5f17f (svn r8175) -Backport from trunk (r8030, r8070, r8071, r8074):
- crash when removing a town in the scenario editor and the query tool is open for a town's tile (r8030)
 - (FS#537) heightmap crashes when rescaling, or using 24bpp bitmaps (r8070, r8074)
 - (FS#536) inauguration date of companies from TTDP games was wrong (r8071)
2007-01-17 00:29:16 +00:00
Darkvater
06367834c6 (svn r8174) -Backport from trunk (r8027, r8028, r8043, r8132):
- (FS#486) pause command issues with shift-pressed did not pause the game, interference with pause_on_join (r8027)
 - overflow of ticks was not handled properly, possibly resulting a non-reacting gameserver/gameclient (r8028, r8043)
 - The game could crash when the chat key (<ENTER>) is pressed too quickly during join (r8132)
2007-01-17 00:20:23 +00:00
Darkvater
f08141ae48 (svn r8173) -Backport from trunk (r8026):
- picking up transferring cargo, trains will now also have the virtual profit deducted
2007-01-17 00:08:49 +00:00
Darkvater
25059d28df (svn r8172) -Backport from trunk (r8013, r8134):
- Show error messages about our own data files as ShowInfo(F) and output console error to stderr and not stdout.
2007-01-17 00:05:51 +00:00
Darkvater
b57b2224e9 (svn r8170) -Backport from trunk (r7984, r8118, r8167, r8168):
- out-of-bounds read access on _clients array (Quark) (r7984)
 - change the ordering of the network list (r8118)
 - (FS#556): a network client crashes, due to a division by zero (r8167)
 - ParseConnectionstring didn't use the port parameter if a player was also specified (r8168)
2007-01-16 23:59:03 +00:00
celestar
70920944d8 (svn r7979) [0.5] - Fix: Segfault in the newgrf loading code (grfmsg => DEBUG). Do it in the right directory this time. Sorry for da mess :S 2007-01-08 14:01:05 +00:00
Darkvater
06b5d32983 (svn r7970) -Backport from trunk (r7968, r7969):
- Update year throughout the program to 2007
 - Minor update to changelog, known-bugs file (Bjarni)
2007-01-07 17:38:58 +00:00
Darkvater
34f8ab2f81 (svn r7967) - Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC3 2007-01-07 16:43:46 +00:00
Darkvater
315ec78344 (svn r7963) -Backport from trunk (r7716, r7717, r7718):
- Bad signal propagation through tunnel-ends, incompatible railtype signal propagation
 still possible (not fixed).
2007-01-07 14:10:56 +00:00
Darkvater
0bf1d6c49d (svn r7962) -Backport from trunk (r7689, r7696, r7699, r7701, r7704, r7706, r7707, r7713,
r7715, r7723, r7732, r7738, r7742, r7743, r7746, r7754, r7756, r7787, r7800,
 r7803, r7806, r7807, r7819, r7828, r7857, r7884, r7896, r7905):
 - Language file updates.
 - Untranslated strings: Icelandic (217!), Hungarian (2), Galician (140), Finnish (3),
   Brazilian-Portugese (3).
 - Moved Lithuanian from unfinished to finished.
2007-01-07 13:49:54 +00:00
matthijs
6f291a7e6d (svn r7958) - [Debian] Prepare debian packing files for 0.5.0-rc3 2007-01-07 12:44:45 +00:00
Darkvater
04d77258c5 (svn r7957) -Backport from trunk (r7936):
- Only update the signals and YAPF cache on a DC_EXEC action for bridge-building
2007-01-07 12:20:48 +00:00
Darkvater
fbfa0b8009 (svn r7956) -Backport from trunk (r7930):
- wrong TTDPatch GRF flag was set for gradual loading
2007-01-07 12:19:56 +00:00
Darkvater
8960b5740f (svn r7955) -Backport from trunk (r7886):
- [osx] control+enter no longer fullscreens, interfered with team-chat.
2007-01-07 12:19:08 +00:00
Darkvater
30fadfb54b (svn r7954) -Backport from trunk (r7864):
- offset engines/wagons by half width in details window; fixes overflowing for display
2007-01-07 12:18:05 +00:00
Darkvater
b342991853 (svn r7953) -Backport from trunk (r7840, r7843):
- [win32] Update crash window text (+crash.dmp -submit)
2007-01-07 12:16:53 +00:00
Darkvater
0a635c692e (svn r7952) -Backport from trunk (r7823, r7861):
- News windows could still crash due to moving news items around while a news window was still open.
2007-01-07 12:15:36 +00:00
Darkvater
0a211097ac (svn r7951) -Backport from trunk (r7810, r7812):
- Building airport whose size exceeds max station spread-out caused assert. (r7810)
 - rail station build window was not correctly updated after station_spread change (r7812)
2007-01-07 12:13:57 +00:00
Darkvater
1277599c30 (svn r7950) -Backport from trunk (r7760, r7766):
- Sprite usage debug message showed the starting sprite, not current sprite, and only do this during activation (r7760).
 - [OSX] Remove incorrect debug message about missing grf files.
2007-01-07 12:11:54 +00:00
Darkvater
bae0695ac9 (svn r7949) -Backport from trunk (r7733):
- do not use WP(w, querystr_d) and WP(w, def_d) for the same window
2007-01-07 12:07:07 +00:00
Darkvater
630f81c382 (svn r7948) -Backport from trunk (r7731):
- off-by-one error in the date to YMD calculation for first 4 years of a century that was not divisable by 400
2007-01-07 12:06:34 +00:00
Darkvater
2684cb2525 (svn r7947) -Backport from trunk (r7727):
- [sdl] sometimes ALT-TAB could trigger the fast forward
2007-01-07 12:05:47 +00:00
Darkvater
610b6e3953 (svn r7946) -Backport from trunk (r7711, r7795, r7831):
- NewGRF Action 7, GRF check condition 10 didn't ignore unknown GRF IDs (r7354)
 - NewGRF safety scan fixes action E (allow unifont.grf) and Action 0 prop D (bridge) (r7795, r7831)
2007-01-07 11:53:12 +00:00
Darkvater
563857d5bd (svn r7945) -Backport from trunk (r7700):
- Caret randomly jumping back&forth for new randomseed (r7182)
2007-01-07 11:37:23 +00:00
Darkvater
58d18a3ef3 (svn r7944) -Backport from trunk (r7692):
- -OpenTTD didn't compile without network enabled (newgrf sync code)
2007-01-07 11:34:20 +00:00
rubidium
0b7ab719f3 (svn r7893) [0.5] -Fix (FS#485): the configure script did not work work for dash, a sh compatible shell. 2007-01-05 23:43:20 +00:00
Darkvater
f5439821c1 (svn r7694) -Update known-bugs file. 2006-12-31 11:28:42 +00:00
Darkvater
d11a6a439a (svn r7685) - Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC2 2006-12-31 01:21:00 +00:00
Darkvater
99096b83bd (svn r7684) -Backport from trunk (r7620):
- Bad signal update through incompatible rail types, bridge.
2006-12-31 00:52:33 +00:00
Darkvater
75c538962d (svn r7683) -Backport from trunk (r7552, r7553, r7574, r7581, r7601, r7611, r7654, r7658):
- Language file updates.
 - Untranslated strings: Turkish (2), Swedish (1), Romanian (3), Norwegian (2),
   Icelandic (217!), Hungarian (2), German (1), Galician (173), Finnish (26),
   Danish (23), Czech (34), Bulgarian (39), Brazilian-Portugese (3)
2006-12-31 00:01:07 +00:00
Darkvater
51cd7bd43b (svn r7682) -Backport from trunk (r7539, r7541, r7603):
- Added esperanto language files to MS projects (r7539).
 - Polish townname generator uses proper UNICODE characters (r7603).
2006-12-30 23:38:41 +00:00
Darkvater
0b67caa8ad (svn r7681) -Backport from trunk (r7585, r7590, r7599):
- Drastically reduce CheckStationSpreadOut CPU usage which got called way too much by the AI.
2006-12-30 23:35:01 +00:00
Darkvater
4ec96ba2d0 (svn r7680) -Backport from trunk (r7586):
- Remove landscaping toolbar from road-toolbar in scenario editor
2006-12-30 23:32:22 +00:00
Darkvater
b93e8d6c71 (svn r7679) -Backport from trunk (r7628):
- [YAPF] suppress 'Train is lost' message if pathfinding ended on the first
   two-way red signal
2006-12-30 23:30:21 +00:00
Darkvater
ac945ced7e (svn r7678) -Fix (r7674): DEBUG macro has been changed 2006-12-30 23:29:33 +00:00
Darkvater
5c190a0c33 (svn r7677) -Backport from trunk (r7657):
- 'Goto Depot' did not work for helicopters going to an airport without depot
2006-12-30 23:26:47 +00:00
Darkvater
b5715acaf8 (svn r7676) -Backport from trunk (r7630, r7631):
- cur/old economy memmove magic (r7630).
 - wrong pointer arithmetic that totally corrupted animated_tiles table, desyncing
   between different endiannes-machines in multiplayer (r7631).
2006-12-30 23:25:57 +00:00
Darkvater
0e7701fbe6 (svn r7675) -Backport from trunk (r7606):
- [NewStations] Add support for variables 45 and 65.
2006-12-30 23:23:43 +00:00
Darkvater
59167f686e (svn r7674) -Backport from trunk (r7580):
- Wrong bounding boxes were computed for certain strings.
2006-12-30 23:22:55 +00:00
Darkvater
0adf61e7fa (svn r7673) -Backport from trunk (r7563):
- [FS#468] Removing towns in scenario editor didn't remove their subsidies.
2006-12-30 23:21:55 +00:00
Darkvater
6fa93f4a7a (svn r7672) -Backport from trunk (r7562):
- [win32] OpenTTD didn't always remember its maximized state on restart.
2006-12-30 23:21:02 +00:00
Darkvater
f3424f51bc (svn r7671) -Backport from trunk (r7560, r7561, r7566):
- No new company could join if 8 clients were connected in less than 8 companies (r7560).
 - [FS#431] internal and visible settings of autorenew could go out of sync (r8561).
 - Server told clients to start syncing from a bad position, causing asserts/crashes (r7566).
2006-12-30 23:20:00 +00:00
Darkvater
6c8f12de78 (svn r7670) -Backport from trunk (r7558, r7559):
- [FS#464] do not wait till a crashed vehicle is removed before starting to load
 other vehicles (r7558).
 - [FS#456] clicking 'full load' can change depot order under certain circumstances (r7559).
2006-12-30 23:14:39 +00:00
Darkvater
953fc9e196 (svn r7669) -Backport from trunk (r7556):
- screenshot no_con didn't remove console from screenshot.
2006-12-30 23:12:05 +00:00
Darkvater
737220f39c (svn r7668) -Backport from trunk (r7555):
- off-by-one error due do truncation on division by 2 in heightmap code.
2006-12-30 23:11:14 +00:00
Darkvater
e00a47d47d (svn r7667) -Backport from trunk (r7549, r7551, r7554, r7582, r7594):
- change size of newgrf GUI to same size as TTDP (no overflows) (r7549).
 - segmentation fault on showing NewGRF settings of a network game (r7551).
 - in Action 0xE, don't deactivate the current GRF (r7554).
 - appending static GRF's could cause duplicate GRF's in the list (r7582).
 - GRF config not cleared when no GRF's are used (r7594).
2006-12-30 23:09:27 +00:00
Darkvater
cf52f00f46 (svn r7666) -Backport from trunk (r7548):
- Some MorphOS changes to get OpenTTD compiled, packaged.
2006-12-30 23:04:14 +00:00
Darkvater
d4b335fffb (svn r7665) -Backport from trunk (r7547):
- When removing a rail station, the cost was added for the full rectangle not for
   only the removed tiles themselves.
2006-12-30 23:03:15 +00:00
Darkvater
652e834ee7 (svn r7664) -Backport from trunk (r7587, r7588, r7600, r7605, r7626, r7629):
- [OSX] universal binary docs, makefile (r7587, r7588, r7626).
 - General documentation update (r7600, r7605).
 - openttd -h showed outdated help for '-n' switch (r7629).
2006-12-30 23:00:52 +00:00
Darkvater
dfab8c779b (svn r7662) -Backport from trunk (r7557, r7624):
- [OSX] makefile fixes (static libfontconfig) (r7557).
 - [FS#470] Install openttd.32.bmp on install so that SDL window has icon (r76240.
2006-12-30 22:55:31 +00:00
Darkvater
bbdbdf3818 (svn r7661) -Backport from trunk (r7550):
- [win32] x64 compile fixed.
2006-12-30 22:53:05 +00:00
Darkvater
0264283116 (svn r7660) -Backport from trunk (r7537, r7539):
- Changelog updates
2006-12-30 22:50:49 +00:00
matthijs
6f97748c80 (svn r7659) - [Debian] Prepare debian packing files for 0.5.0-rc2 2006-12-30 22:36:22 +00:00
Darkvater
65d6403497 (svn r7536) -Branch: add 0.5 branch 2006-12-21 20:56:57 +00:00
1202 changed files with 174396 additions and 305532 deletions

12
.gitignore vendored
View File

@@ -1,12 +0,0 @@
Makefile*
bin/*
bundle/*
!bin/data/chars.grf
!bin/data/openttdd.grf
!bin/data/openttdw.grf
!bin/data/opntitle.grf
!bin/scenario/README
!bin/scripts*
config.*
objs/*
src/rev.cpp

View File

@@ -1,11 +0,0 @@
bin/lang/*
bin/opentd*
bundle/*
config.cache.*
config.log
config.pwd
Makefile
Makefile.am
media/openttd.desktop*
objs/*
src/rev.cpp

7
BUGS Normal file
View File

@@ -0,0 +1,7 @@
/* $Id$ */
KNOWN BUGS / PROBLEMS:
Normal and elrail depots look the same. Use 'X' (transparent buildings)
to distinguish between them
Missing curors / icons for construction (currently using the conventional ones)

View File

@@ -5,6 +5,7 @@ PROJECT_NAME = openttd
OUTPUT_DIRECTORY = docs/source/
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
@@ -76,14 +77,13 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ./src/
INPUT = ./
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.h \
*.hpp \
table/*.h
RECURSIVE = YES
EXCLUDE =
@@ -158,7 +158,7 @@ RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
@@ -185,13 +185,13 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED = DEF_COMMAND
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
@@ -220,6 +220,8 @@ DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO

1125
Makefile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,192 +0,0 @@
#
# Creation of bundles
#
# The revision is needed for the bundle name and creating an OSX application bundle.
ifdef REVISION
REV := $(REVISION)
else
# Detect the revision
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
endif
# Make sure we have something in REV
ifeq ($(REV),)
REV := norev000
endif
ifndef BUNDLE_NAME
BUNDLE_NAME = openttd-custom-$(REV)-$(OS)
endif
# An OSX application bundle needs the data files, lang files and openttd executable in a different location.
ifdef OSXAPP
DATA_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/data
LANG_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/lang
TTD_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/MacOS
else
DATA_DIR = $(BUNDLE_DIR)/data
LANG_DIR = $(BUNDLE_DIR)/lang
TTD_DIR = $(BUNDLE_DIR)
endif
bundle: all
@echo '[BUNDLE] Constructing bundle'
$(Q)rm -rf "$(BUNDLE_DIR)"
$(Q)mkdir -p "$(BUNDLE_DIR)"
$(Q)mkdir -p "$(BUNDLE_DIR)/docs"
$(Q)mkdir -p "$(BUNDLE_DIR)/scenario"
$(Q)mkdir -p "$(BUNDLE_DIR)/scenario/heightmap"
$(Q)mkdir -p "$(BUNDLE_DIR)/media"
$(Q)mkdir -p "$(BUNDLE_DIR)/scripts"
$(Q)mkdir -p "$(TTD_DIR)"
$(Q)mkdir -p "$(DATA_DIR)"
$(Q)mkdir -p "$(LANG_DIR)"
ifdef OSXAPP
$(Q)mkdir -p "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources"
$(Q)echo "APPL????" > "$(BUNDLE_DIR)/$(OSXAPP)/Contents/PkgInfo"
$(Q)cp "$(ROOT_DIR)/os/macosx/openttd.icns" "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/openttd.icns"
$(Q)$(ROOT_DIR)/os/macosx/plistgen.sh "$(BUNDLE_DIR)/$(OSXAPP)" "$(REV)"
$(Q)cp "$(ROOT_DIR)/docs/OSX_install_instructions.txt" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/os/macosx/splash.png" "$(DATA_DIR)"
endif
$(Q)cp "$(BIN_DIR)/$(TTD)" "$(TTD_DIR)/"
$(Q)cp "$(BIN_DIR)/data/"*.grf "$(DATA_DIR)/"
$(Q)cp "$(BIN_DIR)/data/"*.obg "$(DATA_DIR)/"
$(Q)cp "$(BIN_DIR)/data/opntitle.dat" "$(DATA_DIR)/"
$(Q)cp "$(BIN_DIR)/lang/"*.lng "$(LANG_DIR)/"
$(Q)cp "$(ROOT_DIR)/readme.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/COPYING" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/docs/obg_format.txt" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.txt" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/docs/32bpp.txt" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/changelog.txt" "$(BUNDLE_DIR)/"
ifdef MAN_DIR
$(Q)mkdir -p "$(BUNDLE_DIR)/man/"
$(Q)cp "$(ROOT_DIR)/docs/openttd.6" "$(BUNDLE_DIR)/man/"
$(Q)gzip -9 "$(BUNDLE_DIR)/man/openttd.6"
endif
$(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/"
$(Q)cp "$(ROOT_DIR)/media/openttd."*.png "$(BUNDLE_DIR)/media/"
$(Q)cp "$(BIN_DIR)/scripts/"* "$(BUNDLE_DIR)/scripts/"
ifdef MENU_DIR
$(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/"
$(Q)cat "$(ROOT_DIR)/media/openttd.desktop" | sed s/=openttd/=$(BINARY_NAME)/g > "$(ROOT_DIR)/media/openttd.desktop.install"
endif
ifeq ($(shell if test -n "`ls -l \"$(BIN_DIR)/scenario/\"*.scn 2> /dev/null`"; then echo 1; fi), 1)
$(Q)cp "$(BIN_DIR)/scenario/"*.scn "$(BUNDLE_DIR)/scenario/"
endif
ifeq ($(shell if test -n "`ls -l \"$(BIN_DIR)/scenario/heightmaps/\"* 2>/dev/null`"; then echo 1; fi), 1)
$(Q)cp "$(BIN_DIR)/scenario/heightmaps/"* "$(BUNDLE_DIR)/scenario/heightmap/"
endif
ifeq ($(TTD), openttd.exe)
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/readme.txt" "$(BUNDLE_DIR)/COPYING" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt"
ifeq ($(OS), DOS)
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.txt" "$(BUNDLE_DIR)/docs/"
ifndef STRIP
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.exe" "$(TTD_DIR)/"
endif
endif
endif
### Packing the current bundle into several compressed file formats ###
#
# Zips & dmgs do not contain a root folder, i.e. they have files in the root of the zip/dmg.
# gzip, bzip2 and lha archives have a root folder, with the same name as the bundle.
#
# One can supply a custom name by adding BUNDLE_NAME:=<name> to the make command.
#
bundle_zip: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).zip'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)cd "$(BUNDLE_DIR)" && zip -r $(shell if test -z "$(VERBOSE)"; then echo '-q'; fi) "$(BUNDLES_DIR)/$(BUNDLE_NAME).zip" .
bundle_gzip: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.gz'
$(Q)mkdir -p "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.gzip" && tar -zc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.gz" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.gzip"
bundle_bzip2: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.bz2'
$(Q)mkdir -p "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.bzip2" && tar -jc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.bz2" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.bzip2"
bundle_lha: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).lha'
$(Q)mkdir -p "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.lha" && lha ao6 "$(BUNDLES_DIR)/$(BUNDLE_NAME).lha" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.lha"
bundle_dmg: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).dmg'
$(Q)mkdir -p "$(BUNDLES_DIR)/OpenTTD $(REV)"
$(Q)cp -R "$(BUNDLE_DIR)/" "$(BUNDLES_DIR)/OpenTTD $(REV)"
$(Q)hdiutil create -ov -format UDZO -srcfolder "$(BUNDLES_DIR)/OpenTTD $(REV)" "$(BUNDLES_DIR)/$(BUNDLE_NAME).dmg"
$(Q)rm -fr "$(BUNDLES_DIR)/OpenTTD $(REV)"
bundle_exe: all
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)unix2dos "$(ROOT_DIR)/docs/"* "$(ROOT_DIR)/readme.txt" "$(ROOT_DIR)/COPYING" "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt"
$(Q)cd $(ROOT_DIR)/os/win32/installer && makensis.exe //DVERSION_INCLUDE=version_$(PLATFORM).txt install.nsi
$(Q)mv $(ROOT_DIR)/os/win32/installer/*$(PLATFORM).exe "$(BUNDLES_DIR)/$(BUNDLE_NAME).exe"
ifdef OSXAPP
install:
@echo '[INSTALL] Cannot install the OSX Application Bundle'
else
install: bundle
@echo '[INSTALL] Installing OpenTTD'
$(Q)install -d "$(INSTALL_BINARY_DIR)"
$(Q)install -d "$(INSTALL_ICON_DIR)"
$(Q)install -d "$(INSTALL_DATA_DIR)/gm"
$(Q)install -d "$(INSTALL_DATA_DIR)/data"
$(Q)install -d "$(INSTALL_DATA_DIR)/lang"
$(Q)install -d "$(INSTALL_DATA_DIR)/scripts"
$(Q)install -d "$(INSTALL_DOC_DIR)"
ifeq ($(TTD), openttd.exe)
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}.exe"
else
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}"
endif
$(Q)install -m 644 "$(BUNDLE_DIR)/lang/"* "$(INSTALL_DATA_DIR)/lang"
$(Q)install -m 644 "$(BUNDLE_DIR)/data/"* "$(INSTALL_DATA_DIR)/data"
$(Q)install -m 644 "$(BUNDLE_DIR)/scripts/"* "$(INSTALL_DATA_DIR)/scripts"
$(Q)install -m 644 "$(BUNDLE_DIR)/docs/"* "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/"*.txt "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING" "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)/${BINARY_NAME}.32.xpm"
ifdef ICON_THEME_DIR
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/16x16/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.16.png" "$(INSTALL_ICON_THEME_DIR)/16x16/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/32x32/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.png" "$(INSTALL_ICON_THEME_DIR)/32x32/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/48x48/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.48.png" "$(INSTALL_ICON_THEME_DIR)/48x48/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/64x64/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.64.png" "$(INSTALL_ICON_THEME_DIR)/64x64/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/128x128/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.128.png" "$(INSTALL_ICON_THEME_DIR)/128x128/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/256x256/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.256.png" "$(INSTALL_ICON_THEME_DIR)/256x256/apps/${BINARY_NAME}.png"
else
$(Q)install -m 644 "$(BUNDLE_DIR)/media/"*.png "$(INSTALL_ICON_DIR)"
endif
ifdef MAN_DIR
$(Q)install -d "$(INSTALL_MAN_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/man/openttd.6.gz" "$(INSTALL_MAN_DIR)/${BINARY_NAME}.6.gz"
endif
ifdef MENU_DIR
$(Q)install -d "$(INSTALL_MENU_DIR)"
$(Q)install -m 644 "$(ROOT_DIR)/media/openttd.desktop.install" "$(INSTALL_MENU_DIR)/${BINARY_NAME}.desktop"
endif
$(Q)cp -R "$(BUNDLE_DIR)/scenario" "$(INSTALL_DATA_DIR)"
endif # OSXAPP

View File

@@ -1,157 +0,0 @@
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
else
Q = @
endif
include Makefile.am
SOURCE_LIST = !!SOURCE_LIST!!
CONFIG_CACHE_SOURCE_LIST = !!CONFIG_CACHE_SOURCE_LIST!!
CONFIG_CACHE_PWD = !!CONFIG_CACHE_PWD!!
CONFIGURE_FILES = !!CONFIGURE_FILES!!
LIPO = !!LIPO!!
BIN_DIR = !!BIN_DIR!!
ICON_THEME_DIR = !!ICON_THEME_DIR!!
MAN_DIR = !!MAN_DIR!!
MENU_DIR = !!MENU_DIR!!
SRC_DIR = !!SRC_DIR!!
ROOT_DIR = !!ROOT_DIR!!
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
INSTALL_DIR = !!INSTALL_DIR!!
INSTALL_BINARY_DIR = "$(INSTALL_DIR)/"!!BINARY_DIR!!
INSTALL_MAN_DIR = "$(INSTALL_DIR)/$(MAN_DIR)"
INSTALL_MENU_DIR = "$(INSTALL_DIR)/$(MENU_DIR)"
INSTALL_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!!
INSTALL_ICON_THEME_DIR = "$(INSTALL_DIR)/$(ICON_THEME_DIR)"
INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!!
INSTALL_DOC_DIR = "$(INSTALL_DIR)/"!!DOC_DIR!!
BINARY_NAME = !!BINARY_NAME!!
STRIP = !!STRIP!!
TTD = !!TTD!!
TTDS = $(SRC_DIRS:%=%/$(TTD))
OS = !!OS!!
OSXAPP = !!OSXAPP!!
REVISION = !!REVISION!!
AWK = !!AWK!!
DISTCC = !!DISTCC!!
RES := $(shell if [ ! -f $(CONFIG_CACHE_PWD) ] || [ "`pwd`" != "`cat $(CONFIG_CACHE_PWD)`" ]; then echo "`pwd`" > $(CONFIG_CACHE_PWD); fi )
RES := $(shell if [ ! -f $(CONFIG_CACHE_SOURCE_LIST) ] || [ -n "`cmp $(CONFIG_CACHE_SOURCE_LIST) $(SOURCE_LIST) 2>/dev/null`" ]; then cp $(SOURCE_LIST) $(CONFIG_CACHE_SOURCE_LIST); fi )
all: config.pwd config.cache
ifdef DISTCC
@if [ -z "`echo '$(MFLAGS)' | grep '\-j'`" ]; then echo; echo "WARNING: you enabled distcc support, but you don't seem to be using the -jN paramter"; echo; fi
endif
@for dir in $(DIRS); do \
$(MAKE) -C $$dir all; \
done
ifdef LIPO
# Lipo is an OSX thing. If it is defined, it means we are building for universal,
# and so we have have to combine the binaries into one big binary
# Remove the last binary made by the last compiled target
$(Q)rm -f $(BIN_DIR)/$(TTD)
# Make all the binaries into one
$(Q)$(LIPO) -create -output $(BIN_DIR)/$(TTD) $(TTDS)
endif
help:
@echo "Available make commands:"
@echo ""
@echo "Compilation:"
@echo " all compile the executable and the lang files"
@echo " lang compile the lang files only"
@echo "Clean up:"
@echo " clean remove the files generated during compilation"
@echo " mrproper remove the files generated during configuration and compilation"
@echo "Run after compilation:"
@echo " run execute openttd after the compilation"
@echo " run-gdb execute openttd in debug mode after the compilation"
@echo " run-prof execute openttd in profiling mode after the compilation"
@echo "Installation:"
@echo " install install the compiled files and the data-files after the compilation"
@echo " bundle create the base for an installation bundle"
@echo " bundle_zip create the zip installation bundle"
@echo " bundle_gzip create the gzip installation bundle"
@echo " bundle_bzip2 create the bzip2 installation bundle"
@echo " bundle_lha create the lha installation bundle"
@echo " bundle_dmg create the dmg installation bundle"
config.pwd: $(CONFIG_CACHE_PWD)
$(MAKE) reconfigure
config.cache: $(CONFIG_CACHE_SOURCE_LIST) $(CONFIGURE_FILES)
$(MAKE) reconfigure
reconfigure:
ifeq ($(shell if test -f config.cache; then echo 1; fi), 1)
@echo "----------------"
@echo "The system detected that source.list or any configure file is altered."
@echo " Going to reconfigure with last known settings..."
@echo "----------------"
# Make sure we don't lock config.cache
@$(shell cat config.cache | sed 's~\\ ~\\\\ ~g') || exit 1
@echo "----------------"
@echo "Reconfig done. Please re-execute make."
@echo "----------------"
else
@echo "----------------"
@echo "Have not found a configuration, please run configure first."
@echo "----------------"
@exit 1
endif
clean:
@for dir in $(DIRS); do \
$(MAKE) -C $$dir clean; \
done
$(Q)rm -rf $(BUNDLE_TARGET)
lang:
@for dir in $(LANG_DIRS); do \
$(MAKE) -C $$dir all; \
done
mrproper:
@for dir in $(DIRS); do \
$(MAKE) -C $$dir mrproper; \
rm -f $$dir/Makefile; \
done
$(Q)rm -rf objs
$(Q)rm -f Makefile Makefile.am Makefile.bundle
$(Q)rm -f media/openttd.desktop
$(Q)rm -f $(CONFIG_CACHE_SOURCE_LIST) config.cache config.pwd config.log $(CONFIG_CACHE_PWD)
$(Q)rm -rf $(BUNDLE_DIR)
$(Q)rm -rf $(BUNDLES_DIR)
depend:
@for dir in $(SRC_DIRS); do \
$(MAKE) -C $$dir depend; \
done
run: all
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS)
run-gdb: all
$(Q)cd !!BIN_DIR!! && gdb --ex run --args ./!!TTD!! $(OPENTTD_ARGS)
run-prof: all
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS) && gprof !!TTD!! | less
regression: all
$(Q)cd !!BIN_DIR!! && sh ai/regression/run.sh
%.o:
@for dir in $(SRC_DIRS); do \
$(MAKE) -C $$dir $(@:src/%=%); \
done
%.lng:
@for dir in $(LANG_DIRS); do \
$(MAKE) -C $$dir $@; \
done
include Makefile.bundle

View File

@@ -1,87 +0,0 @@
STRGEN = !!STRGEN!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
SRC_DIR = !!SRC_DIR!!
LANG_DIR = !!LANG_DIR!!
BIN_DIR = !!BIN_DIR!!
LANGS_SRC = $(shell ls $(LANG_DIR)/*.txt)
LANGS = $(LANGS_SRC:$(LANG_DIR)/%.txt=%.lng)
CXX_BUILD = !!CXX_BUILD!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
STRGEN_FLAGS = !!STRGEN_FLAGS!!
STAGE = !!STAGE!!
LANG_SUPPRESS= !!LANG_SUPPRESS!!
LANG_OBJS_DIR= !!LANG_OBJS_DIR!!
ifeq ($(LANG_SUPPRESS), yes)
LANG_ERRORS = >/dev/null 2>&1
endif
# Make sure endian_host.h is reasable as if it was in the src/ dir
CFLAGS_BUILD += -I $(LANG_OBJS_DIR)
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
RES := $(shell mkdir -p $(BIN_DIR)/lang )
all: table/strings.h $(LANGS)
strgen.o: $(SRC_DIR)/strgen/strgen.cpp endian_host.h $(SRC_DIR)/table/control_codes.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
string.o: $(SRC_DIR)/string.cpp endian_host.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
lang/english.txt: $(LANG_DIR)/english.txt
$(Q)mkdir -p lang
$(Q)cp $(LANG_DIR)/english.txt lang/english.txt
$(STRGEN): alloc_func.o string.o strgen.o
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $^ -o $@
table/strings.h: lang/english.txt $(STRGEN)
$(E) '$(STAGE) Generating $@'
@mkdir -p table
$(Q)./$(STRGEN) -s $(LANG_DIR) -d table
$(LANGS): %.lng: $(LANG_DIR)/%.txt $(STRGEN) lang/english.txt
$(E) '$(STAGE) Compiling language $(*F)'
$(Q)./$(STRGEN) $(STRGEN_FLAGS) -s $(LANG_DIR) -d $(LANG_OBJS_DIR) $< $(LANG_ERRORS) && cp $@ $(BIN_DIR)/lang || true # Do not fail all languages when one fails
# The targets to compile the endian-code
endian_host.h: $(ENDIAN_CHECK)
$(E) '$(STAGE) Testing endianness for host'
$(Q)./$(ENDIAN_CHECK) > $@
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
depend:
clean:
$(E) '$(STAGE) Cleaning up language files'
$(Q)rm -f strgen.o string.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* $(ENDIAN_TARGETS)
mrproper: clean
%.lng:
@echo '$(STAGE) No such language: $(@:%.lng=%)'
.PHONY: all mrproper depend clean

View File

@@ -1,28 +0,0 @@
#
# Makefile for creating bundles of MSVC's binaries in the same way as we make
# the zip bundles for ALL other OSes.
#
# Usage: make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=openttd-<version>-win[32|64]
# or make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=OTTD-win[32|64]-nightly-<revision>
#
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
else
Q = @
endif
AWK = "awk"
ROOT_DIR := $(shell pwd)
BIN_DIR = "$(ROOT_DIR)/bin"
SRC_DIR = "$(ROOT_DIR)/src"
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
TTD = "openttd.exe"
TARGET := $(shell echo $(PLATFORM) | sed "s~win64~x64~;s~win32~Win32~")
all:
$(Q)cp objs/$(TARGET)/Release/$(TTD) $(BIN_DIR)/$(TTD)
include Makefile.bundle.in

View File

@@ -1,302 +0,0 @@
CC_HOST = !!CC_HOST!!
CXX_HOST = !!CXX_HOST!!
CC_BUILD = !!CC_BUILD!!
CXX_BUILD = !!CXX_BUILD!!
WINDRES = !!WINDRES!!
STRIP = !!STRIP!!
CC_CFLAGS = !!CC_CFLAGS!!
CFLAGS = !!CFLAGS!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
LIBS = !!LIBS!!
LDFLAGS = !!LDFLAGS!!
ROOT_DIR = !!ROOT_DIR!!
BIN_DIR = !!BIN_DIR!!
LANG_DIR = !!LANG_DIR!!
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
LANG_OBJS_DIR= !!LANG_OBJS_DIR!!
SRC_DIR = !!SRC_DIR!!
SCRIPT_SRC_DIR=!!SCRIPT_SRC_DIR!!
MEDIA_DIR = !!MEDIA_DIR!!
TTD = !!TTD!!
STRGEN = !!STRGEN!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
ENDIAN_FORCE = !!ENDIAN_FORCE!!
OS = !!OS!!
STAGE = !!STAGE!!
MAKEDEPEND = !!MAKEDEPEND!!
CFLAGS_MAKEDEP= !!CFLAGS_MAKEDEP!!
SORT = !!SORT!!
REVISION = !!REVISION!!
AWK = !!AWK!!
GCC295 = !!GCC295!!
CONFIG_CACHE_COMPILER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_COMPILER!!
CONFIG_CACHE_LINKER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_LINKER!!
CONFIG_CACHE_ENDIAN = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_ENDIAN!!
CONFIG_CACHE_SOURCE = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_SOURCE!!
CONFIG_CACHE_VERSION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_VERSION!!
OBJS_C := !!OBJS_C!!
OBJS_CPP := !!OBJS_CPP!!
OBJS_MM := !!OBJS_MM!!
OBJS_RC := !!OBJS_RC!!
OBJS := $(OBJS_C) $(OBJS_CPP) $(OBJS_MM) $(OBJS_RC)
SRCS := !!SRCS!!
# All C-files depend on those 3 files
FILE_DEP := $(CONFIG_CACHE_COMPILER) endian_target.h
# Create all dirs and subdirs
RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
# Make sure endian_target.h is reasable as if it was in the src/ dir
CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR)
CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SCRIPT_SRC_DIR)
ENDIAN_TARGETS := endian_target.h $(ENDIAN_CHECK)
# This 'sed' basicly just removes 'const' from the line if it is a 2+D array
# For more information, please check:
# http://maillist.openttd.org/pipermail/devs/2007-April/000284.html
# http://maillist.openttd.org/pipermail/devs/2007-February/000248.html
GCC295_FIX=sed -r 's~^(\t*)(.*)( const )([A-Za-z0-9_ ]+(\[.*\]){2,})(( = \{)|(;))(.*)$$~\1\2 \4\6\8\9~g'
# This 'sed' removes the 3rd '4' in the # lines of the -E output of
# gcc 2.95.3 and lower, as it should indicate that it is a C-linkage, but the
# compiler can't handle that information (just don't ask). So we remove it
# and then it compiles happily and without bitching :)
# Furthermore gcc 2.95 has some trouble with protected and private when
# accessing the protected/private stuff of the enclosing class (or the
# super class of the enclosing class).
GCC295_FIX_2=sed -e 's~\(^\# [0-9][0-9]* "[^"]*"[ 0-9]*\) 4$$~\1~g;s~private:~public:~g;s~protected:~public:~g'
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
# Our default target
all: $(BIN_DIR)/$(TTD)
# This are 2 rules that are pointing back to STRGEN stuff.
# There is not really a need to have them here, but in case
# some weirdo wants to run 'make' in the 'src' dir and expects
# the languages to be recompiled, this catches that case and
# takes care of it nicely.
$(LANG_OBJS_DIR)/$(STRGEN):
$(MAKE) -C $(LANG_OBJS_DIR) $(STRGEN)
$(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
# Always run version detection, so we always have an accurate modified
# flag
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
MODIFIED := $(shell echo "$(VERSIONS)" | cut -f 3 -d' ')
ifdef REVISION
# Use specified revision (which should be of the form "r000").
REV := $(REVISION)
REV_NR := $(shell echo $(REVISION) | sed "s~[^0-9]~~g")
else
# Use autodetected revisions
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
REV_NR := $(shell echo "$(VERSIONS)" | cut -f 2 -d' ')
endif
# Make sure we have something in REV and REV_NR
ifeq ($(REV),)
REV := norev000
endif
ifeq ($(REV_NR),)
REV_NR := 0
endif
# This helps to recompile if flags change
RES := $(shell if [ "`cat $(CONFIG_CACHE_COMPILER) 2>/dev/null`" != "$(CC_CFLAGS) $(CFLAGS)" ]; then echo "$(CC_CFLAGS) $(CFLAGS)" > $(CONFIG_CACHE_COMPILER); fi )
RES := $(shell if [ "`cat $(CONFIG_CACHE_LINKER) 2>/dev/null`" != "$(LDFLAGS) $(LIBS)" ]; then echo "$(LDFLAGS) $(LIBS)" > $(CONFIG_CACHE_LINKER); fi )
RES := $(shell if [ "`cat $(CONFIG_CACHE_ENDIAN) 2>/dev/null`" != "$(ENDIAN_FORCE)" ]; then echo "$(ENDIAN_FORCE)" > $(CONFIG_CACHE_ENDIAN); fi )
# If there is a change in the source-file-list, make sure we recheck the deps
RES := $(shell if [ "`cat $(CONFIG_CACHE_SOURCE) 2>/dev/null`" != "$(SRCS)" ]; then echo "$(SRCS)" > $(CONFIG_CACHE_SOURCE); fi )
# If there is a change in the revision, make sure we recompile rev.cpp
RES := $(shell if [ "`cat $(CONFIG_CACHE_VERSION) 2>/dev/null`" != "$(REV) $(MODIFIED)" ]; then echo "$(REV) $(MODIFIED)" > $(CONFIG_CACHE_VERSION); fi )
ifndef MAKEDEPEND
# The slow, but always correct, dep-check
DEP_MASK := %.d
DEPS := $(OBJS:%.o=%.d)
# Only include the deps if we are compiling everything
ifeq ($(filter $(ENDIAN_TARGETS) %.o clean mrproper, $(MAKECMDGOALS)),)
-include $(DEPS)
else
# In case we want to compile a single target, include the .d file for it
ifneq ($(filter %.o, $(MAKECMDGOALS)),)
SINGLE_DEP := $(filter %.o, $(MAKECMDGOALS))
-include $(SINGLE_DEP:%.o=%.d)
endif
endif
# Find the deps via GCC. Rarely wrong, but a bit slow
$(OBJS_C:%.o=%.d): %.d: $(SRC_DIR)/%.c $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.c=%.c)'
$(Q)$(CC_HOST) $(CC_CFLAGS) $(CFLAGS) -MM $< | sed 's~^$(@F:%.d=%.o):~$@ $(@:%.d=%.o):~' > $@
$(OBJS_CPP:%.o=%.d): %.d: $(SRC_DIR)/%.cpp $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) -MM $< | sed 's~^$(@F:%.d=%.o):~$@ $(@:%.d=%.o):~' > $@
$(OBJS_MM:%.o=%.d): %.d: $(SRC_DIR)/%.mm $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)$(CC_HOST) $(CFLAGS) -MM $< | sed 's~^$(@F:%.d=%.o):~$@ $(@:%.d=%.o):~' > $@
$(OBJS_RC:%.o=%.d): %.d: $(SRC_DIR)/%.rc $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)touch $@
else
# The much faster, but can be wrong, dep-check
DEP_MASK :=
DEPS := Makefile.dep
# Only include the deps if we are not cleaning
ifeq ($(filter $(ENDIAN_TARGETS) depend clean mrproper, $(MAKECMDGOALS)),)
-include Makefile.dep
endif
# Make sure that only 'make depend' ALWAYS triggers a recheck
ifeq ($(filter depend, $(MAKECMDGOALS)),)
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(CONFIG_CACHE_SOURCE)
else
Makefile.dep: FORCE
endif
$(E) '$(STAGE) DEP CHECK (all files)'
$(Q)rm -f Makefile.dep.tmp
$(Q)touch Makefile.dep.tmp
# Calculate the deps via makedepend
$(Q)$(MAKEDEPEND) -f$(SRC_OBJS_DIR)/Makefile.dep.tmp -o.o -Y -v -- $(CFLAGS_MAKEDEP) -- $(SRCS:%=$(SRC_DIR)/%) 2>/dev/null
# Convert x:/... paths to /x/... for mingw
ifeq ($(OS), MINGW)
@cat Makefile.dep.tmp | sed 's~\([a-zA-Z]\):\/~\/\1\/~g' > Makefile.dep.tmp.mingw
@cp Makefile.dep.tmp.mingw Makefile.dep.tmp
@rm -f Makefile.dep.tmp.mingw
endif
# Remove all comments and includes that don't start with $(SRC_DIR)
# Remove $(SRC_DIR) from object-file-name
@$(AWK) ' \
/^# DO NOT/ { print $$0 ; next} \
/^#/ {next} \
/:/ { \
left = NF - 1; \
for (n = 2; n <= NF; n++) { \
if (match($$n, "^$(ROOT_DIR)") == 0) { \
$$n = ""; \
left--; \
} \
} \
gsub("$(SRC_DIR)/", "", $$1); \
if (left > 0) { \
print $$0; \
$$1 = "Makefile.dep:"; \
print $$0; \
} \
next \
} \
{ \
print $$0 \
} \
' < Makefile.dep.tmp | sed 's~ *~ ~g;s~ $$~~' | $(SORT) > Makefile.dep
$(Q)rm -f Makefile.dep.tmp Makefile.dep.tmp.bak
endif
# Avoid problems with deps if a .h/.hpp/.hpp.sq file is deleted without the deps
# being updated. Now the Makefile continues, the deps are recreated
# and all will be fine.
%.h %.hpp %.hpp.sq:
@true
# Compile all the files according to the targets
$(OBJS_C): %.o: $(SRC_DIR)/%.c $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.c=%.c)'
$(Q)$(CC_HOST) $(CC_CFLAGS) $(CFLAGS) -c -o $@ $<
$(OBJS_CPP): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
ifeq ($(GCC295), 1)
$(Q)$(CXX_HOST) -E $(CFLAGS) $< | $(GCC295_FIX) | $(GCC295_FIX_2) | $(CXX_HOST) $(CFLAGS) -c -o $@ -x c++ -
else
$(Q)$(CXX_HOST) $(CFLAGS) -c -o $@ $<
endif
$(OBJS_MM): %.o: $(SRC_DIR)/%.mm $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
$(OBJS_RC): %.o: $(SRC_DIR)/%.rc $(FILE_DEP)
$(E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
$(Q)$(WINDRES) -o $@ -I $(MEDIA_DIR) $<
$(BIN_DIR)/$(TTD): $(TTD)
$(Q)cp $< $@
$(TTD): $(OBJS) $(CONFIG_CACHE_LINKER)
$(E) '$(STAGE) Linking $@'
ifeq ($(OS), PSP)
# Because of a bug in the PSP GCC tools, linking via CXX results
# in total chaos and more problems then you can handle. So we need
# CC to link OpenTTD for PSP
$(Q)$(CC_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
else
$(Q)$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
endif
ifdef STRIP
$(Q)$(STRIP) $@
ifeq ($(OS), DOS)
$(E) '$(STAGE) Adding CWSDPMI stub to $@'
$(Q)$(ROOT_DIR)/os/dos/make_dos_binary_selfcontained.sh $(SRC_OBJS_DIR)/$@
endif
endif
# The targets to compile the endian-code
endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN)
$(E) '$(STAGE) Testing endianness for target'
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
# Revision files
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s~@@REVISION@@~$(REV_NR)~g;s~@@VERSION@@~$(REV)~g;s~@@MODIFIED@@~$(MODIFIED)~g;s~@@DATE@@~`date +%d.%m.%y`~g" > $(SRC_DIR)/rev.cpp
$(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in
$(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s~@@REVISION@@~$(REV_NR)~g;s~@@VERSION@@~$(REV)~g;s~@@DATE@@~`date +%d.%m.%y`~g" > $(SRC_DIR)/ottdres.rc
FORCE:
depend: $(DEPS)
clean:
$(E) '$(STAGE) Cleaning up object files'
$(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(TTD:%=$(BIN_DIR)/%) $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS)
mrproper: clean
$(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/ottdres.rc
%.o:
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
.PHONY: all mrproper depend clean FORCE

247
ai/ai.c Normal file
View File

@@ -0,0 +1,247 @@
/* $Id$ */
#include "../stdafx.h"
#include "../openttd.h"
#include "../variables.h"
#include "../command.h"
#include "../network.h"
#include "ai.h"
#include "default/default.h"
/**
* Dequeues commands put in the queue via AI_PutCommandInQueue.
*/
static void AI_DequeueCommands(PlayerID player)
{
AICommand *com, *entry_com;
entry_com = _ai_player[player].queue;
/* It happens that DoCommandP issues a new DoCommandAI which adds a new command
* to this very same queue (don't argue about this, if it currently doesn't
* happen I can tell you it will happen with AIScript -- TrueLight). If we
* do not make the queue NULL, that commands will be dequeued immediatly.
* Therefor we safe the entry-point to entry_com, and make the queue NULL, so
* the new queue can be safely built up. */
_ai_player[player].queue = NULL;
_ai_player[player].queue_tail = NULL;
/* Dequeue all commands */
while ((com = entry_com) != NULL) {
_current_player = player;
_cmd_text = com->text;
DoCommandP(com->tile, com->p1, com->p2, com->callback, com->procc);
/* Free item */
entry_com = com->next;
free(com->text);
free(com);
}
}
/**
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
* will make infinite loops (AIScript).
*/
static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCallback* callback)
{
AICommand *com;
if (_ai_player[player].queue_tail == NULL) {
/* There is no item in the queue yet, create the queue */
_ai_player[player].queue = malloc(sizeof(AICommand));
_ai_player[player].queue_tail = _ai_player[player].queue;
} else {
/* Add an item at the end */
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
}
/* This is our new item */
com = _ai_player[player].queue_tail;
/* Assign the info */
com->tile = tile;
com->p1 = p1;
com->p2 = p2;
com->procc = procc;
com->callback = callback;
com->next = NULL;
com->text = NULL;
/* Copy the cmd_text, if needed */
if (_cmd_text != NULL) {
com->text = strdup(_cmd_text);
_cmd_text = NULL;
}
}
/**
* Executes a raw DoCommand for the AI.
*/
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
{
PlayerID old_lp;
int32 res = 0;
const char* tmp_cmdtext;
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
* person.. should we check for those funny jokes?
*/
/* The test already resets _cmd_text, so backup the pointer */
tmp_cmdtext = _cmd_text;
/* First, do a test-run to see if we can do this */
res = DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc);
/* The command failed, or you didn't want to execute, or you are quering, return */
if (CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
return res;
}
/* Restore _cmd_text */
_cmd_text = tmp_cmdtext;
/* If we did a DC_EXEC, and the command did not return an error, execute it
* over the network */
if (flags & DC_AUTO) procc |= CMD_AUTO;
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
/* NetworkSend_Command needs _local_player to be set correctly, so
* adjust it, and put it back right after the function */
old_lp = _local_player;
_local_player = _current_player;
#ifdef ENABLE_NETWORK
/* Send the command */
if (_networking) {
/* Network is easy, send it to his handler */
NetworkSend_Command(tile, p1, p2, procc, callback);
} else {
#else
{
#endif
/* If we execute BuildCommands directly in SP, we have a big problem with events
* so we need to delay is for 1 tick */
AI_PutCommandInQueue(_current_player, tile, p1, p2, procc, callback);
}
/* Set _local_player back */
_local_player = old_lp;
return res;
}
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
}
/**
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
*/
static void AI_RunTick(PlayerID player)
{
extern void AiNewDoGameLoop(Player *p);
Player *p = GetPlayer(player);
_current_player = player;
if (_patches.ainew_active) {
AiNewDoGameLoop(p);
} else {
/* Enable all kind of cheats the old AI needs in order to operate correctly... */
_is_old_ai_player = true;
AiDoGameLoop(p);
_is_old_ai_player = false;
}
}
/**
* The gameloop for AIs.
* Handles one tick for all the AIs.
*/
void AI_RunGameLoop(void)
{
/* Don't do anything if ai is disabled */
if (!_ai.enabled) return;
/* Don't do anything if we are a network-client, or the AI has been disabled */
if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
/* New tick */
_ai.tick++;
/* Make sure the AI follows the difficulty rule.. */
assert(_opt.diff.competitor_speed <= 4);
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
/* Check for AI-client (so joining a network with an AI) */
if (!_networking || _network_server) {
/* Check if we want to run AIs (server or SP only) */
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) {
/* This should always be true, else something went wrong... */
assert(_ai_player[p->index].active);
/* Run the script */
AI_DequeueCommands(p->index);
AI_RunTick(p->index);
}
}
}
_current_player = OWNER_NONE;
}
/**
* A new AI sees the day of light. You can do here what ever you think is needed.
*/
void AI_StartNewAI(PlayerID player)
{
assert(IsValidPlayer(player));
/* Called if a new AI is booted */
_ai_player[player].active = true;
}
/**
* This AI player died. Give it some chance to make a final puf.
*/
void AI_PlayerDied(PlayerID player)
{
/* Called if this AI died */
_ai_player[player].active = false;
}
/**
* Initialize some AI-related stuff.
*/
void AI_Initialize(void)
{
/* First, make sure all AIs are DEAD! */
AI_Uninitialize();
memset(&_ai, 0, sizeof(_ai));
memset(&_ai_player, 0, sizeof(_ai_player));
_ai.enabled = true;
}
/**
* Deinitializer for AI-related stuff.
*/
void AI_Uninitialize(void)
{
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
}
}

111
ai/ai.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef AI_H
#define AI_H
#include "../functions.h"
#include "../network.h"
#include "../player.h"
#include "../command.h"
/* How DoCommands look like for an AI */
typedef struct AICommand {
uint32 tile;
uint32 p1;
uint32 p2;
uint32 procc;
CommandCallback* callback;
char *text;
uint uid;
struct AICommand *next;
} AICommand;
/* The struct for an AIScript Player */
typedef struct AIPlayer {
bool active; ///< Is this AI active?
AICommand *queue; ///< The commands that he has in his queue
AICommand *queue_tail; ///< The tail of this queue
} AIPlayer;
/* The struct to keep some data about the AI in general */
typedef struct AIStruct {
/* General */
bool enabled; ///< Is AI enabled?
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
} AIStruct;
VARDEF AIStruct _ai;
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
// ai.c
void AI_StartNewAI(PlayerID player);
void AI_PlayerDied(PlayerID player);
void AI_RunGameLoop(void);
void AI_Initialize(void);
void AI_Uninitialize(void);
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
/** Is it allowed to start a new AI.
* This function checks some boundries to see if we should launch a new AI.
* @return True if we can start a new AI.
*/
static inline bool AI_AllowNewAI(void)
{
/* If disabled, no AI */
if (!_ai.enabled)
return false;
/* If in network, but no server, no AI */
if (_networking && !_network_server)
return false;
/* If in network, and server, possible AI */
if (_networking && _network_server) {
/* Do we want AIs in multiplayer? */
if (!_patches.ai_in_multiplayer)
return false;
/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
* system, because all commands are delayed by at least 1 tick, which causes
* a big problem, because it uses variables that are only set AFTER the command
* is really executed... */
if (!_patches.ainew_active)
return false;
}
return true;
}
#define AI_CHANCE16(a,b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
#define AI_CHANCE16R(a,b,r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint AI_RandomRange(uint max)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandomRange(max);
else
return RandomRange(max);
}
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint32 AI_Random(void)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandom();
else
return Random();
}
#endif /* AI_H */

3941
ai/default/default.c Normal file

File diff suppressed because it is too large Load Diff

8
ai/default/default.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id$ */
#ifndef DEFAULT_H
#define DEFAULT_H
void AiDoGameLoop(Player*);
#endif

324
ai/trolly/build.c Normal file
View File

@@ -0,0 +1,324 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../functions.h"
#include "../../map.h"
#include "../../road_map.h"
#include "../../tile.h"
#include "../../vehicle.h"
#include "../../command.h"
#include "trolly.h"
#include "../../engine.h"
#include "../../station.h"
#include "../../variables.h"
#include "../../bridge.h"
#include "../ai.h"
// Build HQ
// Params:
// tile : tile where HQ is going to be build
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
{
if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
return false;
AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
return true;
}
// Build station
// Params:
// type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
// tile : tile where station is going to be build
// length : in case of AI_TRAIN: length of station
// numtracks : in case of AI_TRAIN: tracks of station
// direction : the direction of the station
// flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
{
if (type == AI_TRAIN)
return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
if (type == AI_BUS)
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return AI_DoCommand(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
// Params:
// tile_a : starting point
// tile_b : end point
// flag : flag passed to DoCommand
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
{
int bridge_type, bridge_len, type, type2;
// Find a good bridgetype (the best money can buy)
bridge_len = GetBridgeLength(tile_a, tile_b);
type = type2 = 0;
for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
type2 = type;
type = bridge_type;
// We found two bridges, exit
if (type2 != 0) break;
}
}
// There is only one bridge that can be built
if (type2 == 0 && type != 0) type2 = type;
// Now, simply, build the bridge!
if (p->ainew.tbt == AI_TRAIN) {
return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
} else {
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
}
}
// Build the route part by part
// Basicly what this function do, is build that amount of parts of the route
// that go in the same direction. It sets 'part' to the last part of the route builded.
// The return value is the cost for the builded parts
//
// Params:
// PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
// part : Which part we need to build
//
// TODO: skip already builded road-pieces (e.g.: cityroad)
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
{
int part = PathFinderInfo->position;
byte *route_extra = PathFinderInfo->route_extra;
TileIndex *route = PathFinderInfo->route;
int dir;
int old_dir = -1;
int cost = 0;
int res;
// We need to calculate the direction with the parent of the parent.. so we skip
// the first pieces and the last piece
if (part < 1) part = 1;
// When we are done, stop it
if (part >= PathFinderInfo->route_length - 1) {
PathFinderInfo->position = -2;
return 0;
}
if (PathFinderInfo->rail_or_road) {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
return 0;
}
return cost;
}
// Bridge code
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
return 0;
}
return cost;
}
// Build normal rail
// Keep it doing till we go an other way
if (route_extra[part - 1] == 0 && route_extra[part] == 0) {
while (route_extra[part] == 0) {
// Get the current direction
dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
// Is it the same as the last one?
if (old_dir != -1 && old_dir != dir) break;
old_dir = dir;
// Build the tile
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(res)) {
// Problem.. let's just abort it all!
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
cost += res;
// Go to the next tile
part++;
// Check if it is still in range..
if (part >= PathFinderInfo->route_length - 1) break;
}
part--;
}
// We want to return the last position, so we go back one
PathFinderInfo->position = part;
} else {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
return 0;
}
return cost;
}
// Bridge code
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
return 0;
}
return cost;
}
// Build normal road
// Keep it doing till we go an other way
// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
// it will wait till the vehicle is gone..
if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
// Get the current direction
dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
// Is it the same as the last one?
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 (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
// Build the tile
res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
// Currently, we ignore CMD_ERRORs!
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 built.. aborting!");
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
if (!CmdFailed(res)) cost += res;
}
// Go to the next tile
part++;
// Check if it is still in range..
if (part >= PathFinderInfo->route_length - 1) break;
}
part--;
// We want to return the last position, so we go back one
}
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
PathFinderInfo->position = part;
}
return cost;
}
// This functions tries to find the best vehicle for this type of cargo
// It returns INVALID_ENGINE if not suitable engine is found
EngineID AiNew_PickVehicle(Player *p)
{
if (p->ainew.tbt == AI_TRAIN) {
// Not supported yet
return INVALID_ENGINE;
} else {
EngineID best_veh_index = INVALID_ENGINE;
int32 best_veh_rating = 0;
EngineID start = ROAD_ENGINES_INDEX;
EngineID end = ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES;
EngineID i;
/* Loop through all road vehicles */
for (i = start; i != end; i++) {
const RoadVehicleInfo *rvi = RoadVehInfo(i);
const Engine* e = GetEngine(i);
int32 rating;
int32 ret;
/* Skip vehicles which can't take our cargo type */
if (rvi->cargo_type != p->ainew.cargo && !CanRefitTo(i, p->ainew.cargo)) continue;
// Is it availiable?
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
if (!HASBIT(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
/* Rate and compare the engine by speed & capacity */
rating = rvi->max_speed * rvi->capacity;
if (rating <= best_veh_rating) continue;
// Can we build it?
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (CmdFailed(ret)) continue;
best_veh_rating = rating;
best_veh_index = i;
}
return best_veh_index;
}
}
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
Player* p = GetPlayer(_current_player);
if (success) {
p->ainew.state = AI_STATE_GIVE_ORDERS;
p->ainew.veh_id = _new_vehicle_id;
if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
/* Cargo type doesn't match, so refit it */
if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
/* Refit failed, so sell the vehicle */
DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
p->ainew.state = AI_STATE_NOTHING;
}
}
} else {
/* XXX this should be handled more gracefully */
p->ainew.state = AI_STATE_NOTHING;
}
}
// Builds the best vehicle possible
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
{
EngineID i = AiNew_PickVehicle(p);
if (i == INVALID_ENGINE) return CMD_ERROR;
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
if (flag & DC_EXEC) {
return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
} else {
return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
}
}
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
{
int ret, ret2;
if (p->ainew.tbt == AI_TRAIN) {
return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
} else {
ret = AI_DoCommand(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 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
// If it fails, ignore it..
if (CmdFailed(ret2)) return ret;
return ret + ret2;
}
}

510
ai/trolly/pathfinder.c Normal file
View File

@@ -0,0 +1,510 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../bridge_map.h"
#include "../../debug.h"
#include "../../functions.h"
#include "../../map.h"
#include "../../tile.h"
#include "../../command.h"
#include "trolly.h"
#include "../../depot.h"
#include "../../tunnel_map.h"
#include "../../bridge.h"
#include "../ai.h"
#define TEST_STATION_NO_DIR 0xFF
// Tests if a station can be build on the given spot
// TODO: make it train compatible
static bool TestCanBuildStationHere(TileIndex tile, byte dir)
{
Player *p = GetPlayer(_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) && (
(IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) ||
(IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD)
));
}
// Checks if a tile 'a' is between the tiles 'b' and '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
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
{
const Ai_PathFinderInfo* 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 (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)
static uint AiPathFinder_Hash(uint key1, uint key2)
{
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
}
// Clear the memory of all the things
static void AyStar_AiPathFinder_Free(AyStar *aystar)
{
AyStarMain_Free(aystar);
free(aystar);
}
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
// This creates the AiPathFinder
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
{
PathNode start_node;
uint x;
uint y;
// Create AyStar
AyStar *result = malloc(sizeof(AyStar));
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
// Set the function pointers
result->CalculateG = AyStar_AiPathFinder_CalculateG;
result->CalculateH = AyStar_AiPathFinder_CalculateH;
result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
result->free = AyStar_AiPathFinder_Free;
// Set some information
result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
result->max_path_cost = 0;
result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
// Set the user_data to the PathFinderInfo
result->user_target = PathFinderInfo;
// Set the start node
start_node.parent = NULL;
start_node.node.direction = 0;
start_node.node.user_data[0] = 0;
// Now we add all the starting tiles
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 = TileXY(x, y);
result->addstart(result, &start_node.node, 0);
}
}
return result;
}
// To reuse AyStar we sometimes have to clean all the memory
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
{
PathNode start_node;
uint x;
uint y;
aystar->clear(aystar);
// Set the user_data to the PathFinderInfo
aystar->user_target = PathFinderInfo;
// Set the start node
start_node.parent = NULL;
start_node.node.direction = 0;
start_node.node.user_data[0] = 0;
start_node.node.tile = PathFinderInfo->start_tile_tl;
// Now we add all the starting tiles
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++) {
TileIndex tile = TileXY(x, y);
if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
start_node.node.tile = tile;
aystar->addstart(aystar, &start_node.node, 0);
}
}
}
// The h-value, simple calculation
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
const Ai_PathFinderInfo* 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 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDiagDir(PathFinderInfo->end_direction));
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
} else {
// No direction, so just get the fastest route to the station
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
}
// 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)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
uint i = 0;
PathNode *parent = &current->path;
do {
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 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));
}
// What tiles are around us.
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
{
uint i;
int ret;
int dir;
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
aystar->num_neighbours = 0;
// 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 + TileOffsByDiagDir(i); // Adjacent tile
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!
// 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)) {
if (IsTunnel(atile)) {
if (GetTunnelDirection(atile) != i) continue;
} else {
if ((_m[atile].m5 & 1U) != DiagDirToAxis(i)) 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 ((_m[ctile].m5 & 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 = AI_DoCommand(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, ctile);
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
continue;
}
}
#endif
} 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 ((_m[ctile].m5 & dir) != dir) {
// We do miss some pieces :(
dir &= ~_m[ctile].m5;
} else {
dir = 0;
}
}
}
// Only destruct things if it is MP_CLEAR of MP_TREES
if (dir != 0) {
ret = AI_DoCommand(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 = 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) {
// First we get the dir from this tile and his parent
DiagDirection 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;
Slope tileh = GetTileSlope(tile, NULL);
// Bridges can only be build on land that is not flat
// And if there is a road or rail blocking
if (tileh != SLOPE_FLAT ||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_STREET)) ||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
for (;;) {
new_tile += TileOffsByDiagDir(dir);
// 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;
// Try building the bridge..
ret = AI_DoCommand(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 built on slopes corresponding to the direction
// For now, we check both sides for this tile.. terraforming gives fuzzy result
if ((dir == DIAGDIR_NE && tileh == SLOPE_NE) ||
(dir == DIAGDIR_SE && tileh == SLOPE_SE) ||
(dir == DIAGDIR_SW && tileh == SLOPE_SW) ||
(dir == DIAGDIR_NW && tileh == SLOPE_NW)) {
// Now simply check if a tunnel can be build
ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
tileh = GetTileSlope(_build_tunnel_endtile, NULL);
if (!CmdFailed(ret) && (tileh == SLOPE_SW || tileh == SLOPE_SE || tileh == SLOPE_NW || tileh == SLOPE_NE)) {
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(Slope tileh, TrackBits bits); // XXX function declaration in .c
extern uint GetRoadFoundation(Slope tileh, uint bits); // XXX function declaration in .c
extern uint GetBridgeFoundation(Slope tileh, Axis); // XXX function declaration in .c
enum {
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)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
int r, res = 0;
Slope tileh = GetTileSlope(current->tile, NULL);
Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
// Check if we hit the end-tile
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
return AYSTAR_INVALID_NODE;
}
// If it was valid, drop out.. we don't build on the endtile
return 0;
}
// Give everything a small penalty
res += AI_PATHFINDER_PENALTY;
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 (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.
// 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_tileh != SLOPE_FLAT && 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) {
if (PathFinderInfo->rail_or_road) {
r = GetRailFoundation(parent_tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
if (r >= 15 || (r == 0 && HASBIT(BRIDGE_NO_FOUNDATION, tileh))) {
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
} else {
res += AI_PATHFINDER_FOUNDATION_PENALTY;
}
} else {
if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
r = GetRoadFoundation(parent_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;
}
}
}
}
}
// Are we part of a tunnel?
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
// Tunnels are very expensive when build on long routes..
// Ironicly, we are using BridgeCode here ;)
r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
res += r + (r >> 8);
}
// Are we part of a bridge?
if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
// That means for every length a penalty
res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
// Check if we are going up or down, first for the starting point
// In user_data[0] is at the 8th bit the direction
if (!HASBIT(BRIDGE_NO_FOUNDATION, parent_tileh)) {
if (GetBridgeFoundation(parent_tileh, (current->user_data[0] >> 8) & 1) < 15) {
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
}
// Second for the end point
if (!HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
if (GetBridgeFoundation(tileh, (current->user_data[0] >> 8) & 1) < 15) {
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
}
if (parent_tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
if (tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
// To prevent the AI from taking the fastest way in tiles, but not the fastest way
// in speed, we have to give a good penalty to direction changing
// This way, we get almost the fastest way in tiles, and a very good speed on the track
if (!PathFinderInfo->rail_or_road) {
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 (IsRoad(parent->path.node.tile)) {
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
} else {
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
}
}
} else {
// For rail we have 1 exeption: diagonal rail..
// So we fetch 2 raildirection. That of the current one, and of the one before that
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 than straight path
if (dir1 > 1) res -= AI_PATHFINDER_DIAGONAL_BONUS;
// First see if they are different
if (dir1 != dir2) {
// dir 2 and 3 are 1 diagonal track, and 4 and 5.
if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
// It is not, so we changed of direction
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
}
if (parent->path.parent->parent->parent != NULL) {
int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
res += AI_PATHFINDER_CURVE_PENALTY;
}
}
}
}
}
return (res < 0) ? 0 : res;
}

118
ai/trolly/shared.c Normal file
View File

@@ -0,0 +1,118 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../map.h"
#include "trolly.h"
#include "../../vehicle.h"
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
{
// 0 = vert
// 1 = horz
// 2 = dig up-left
// 3 = dig down-right
// 4 = dig down-left
// 5 = dig up-right
uint x1 = TileX(tile_a);
uint x2 = TileX(tile_b);
uint x3 = TileX(tile_c);
uint y1 = TileY(tile_a);
uint y2 = TileY(tile_b);
uint y3 = TileY(tile_c);
if (y1 == y2 && y2 == y3) return 0;
if (x1 == x2 && x2 == x3) return 1;
if (y2 > y1) return x2 > x3 ? 2 : 4;
if (x2 > x1) return y2 > y3 ? 2 : 5;
if (y1 > y2) return x2 > x3 ? 5 : 3;
if (x1 > x2) return y2 > y3 ? 4 : 3;
return 0;
}
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
{
int x1, x2, x3;
int y1, y2, y3;
int r;
x1 = TileX(tile_a);
x2 = TileX(tile_b);
x3 = TileX(tile_c);
y1 = TileY(tile_a);
y2 = TileY(tile_b);
y3 = TileY(tile_c);
r = 0;
if (x1 < x2) r += 8;
if (y1 < y2) r += 1;
if (x1 > x2) r += 2;
if (y1 > y2) r += 4;
if (x2 < x3) r += 2;
if (y2 < y3) r += 4;
if (x2 > x3) r += 8;
if (y2 > y3) r += 1;
return r;
}
// Get's the direction between 2 tiles seen from tile_a
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b)
{
if (TileY(tile_a) < TileY(tile_b)) return DIAGDIR_SE;
if (TileY(tile_a) > TileY(tile_b)) return DIAGDIR_NW;
if (TileX(tile_a) < TileX(tile_b)) return DIAGDIR_SW;
return DIAGDIR_NE;
}
// This functions looks up if this vehicle is special for this AI
// and returns his flag
uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
{
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (p->ainew.special_vehicles[i].veh_id == v->index) {
return p->ainew.special_vehicles[i].flag;
}
}
// Not found :(
return 0;
}
bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
{
int new_id = -1;
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (p->ainew.special_vehicles[i].veh_id == v->index) {
p->ainew.special_vehicles[i].flag |= flag;
return true;
}
if (new_id == -1 &&
p->ainew.special_vehicles[i].veh_id == 0 &&
p->ainew.special_vehicles[i].flag == 0) {
new_id = i;
}
}
// Out of special_vehicle spots :s
if (new_id == -1) {
DEBUG(ai, 1)("special_vehicles list is too small :(");
return false;
}
p->ainew.special_vehicles[new_id].veh_id = v->index;
p->ainew.special_vehicles[new_id].flag = flag;
return true;
}

1356
ai/trolly/trolly.c Normal file

File diff suppressed because it is too large Load Diff

262
ai/trolly/trolly.h Normal file
View File

@@ -0,0 +1,262 @@
/* $Id$ */
#ifndef AI_TROLLY_H
#define AI_TROLLY_H
#include "../../aystar.h"
#include "../../player.h"
/*
* These defines can be altered to change the behavoir of the AI
*
* WARNING:
* This can also alter the AI in a negative way. I will never claim these settings
* are perfect, but don't change them if you don't know what the effect is.
*/
// How many times it the H multiplied. The higher, the more it will go straight to the
// end point. The lower, how more it will find the route with the lowest cost.
// also: the lower, the longer it takes before route is calculated..
#define AI_PATHFINDER_H_MULTIPLER 100
// How many loops may AyStar do before it stops
// 0 = infinite
#define AI_PATHFINDER_LOOPS_PER_TICK 5
// How long may the AI search for one route?
// 0 = infinite
// This number is the number of tiles tested.
// It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
// to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
// (that is: if the AI is on VERY FAST! :p
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
// If you enable this, the AI is not allowed to make 90degree turns
#define AI_PATHFINDER_NO_90DEGREES_TURN
// Below are defines for the g-calculation
// Standard penalty given to a tile
#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
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
// a bonus for using diagonal track
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
#define AI_PATHFINDER_DIAGONAL_BONUS 95
#else
#define AI_PATHFINDER_DIAGONAL_BONUS 75
#endif
// If a roadblock already exists, it gets a bonus
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
#define AI_PATHFINDER_CURVE_PENALTY 200
// Penalty a bridge gets per length
#define AI_PATHFINDER_BRIDGE_PENALTY 180
// The penalty for a bridge going up
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
// Tunnels are expensive...
// Because of that, every tile the cost is increased with 1/8th of his value
// This is also true if you are building a tunnel yourself
#define AI_PATHFINDER_TUNNEL_PENALTY 350
/*
* Ai_New defines
*/
// How long may we search cities and industry for a new route?
#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 than 4 months.
#define AI_CHECKCITY_DATE_BETWEEN 180
// How many cargo is needed for one station in a city?
#define AI_CHECKCITY_CARGO_PER_STATION 60
// How much cargo must there not be used in a city before we can build a new station?
#define AI_CHECKCITY_NEEDED_CARGO 50
// When there is already a station which takes the same good and the rating of that
// city is higher then this numer, we are not going to attempt to build anything
// there
#define AI_CHECKCITY_CARGO_RATING 50
// But, there is a chance of 1 out of this number, that we do ;)
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
// If a city is too small to contain a station, there is a small chance
// that we still do so.. just to make the city bigger!
#define AI_CHECKCITY_CITY_CHANCE 5
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
// from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
// of the cargo in the other station, both stations can be 96 units away from eachother, if the
// next number is 0.4.
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
// In whole tiles, the minimum distance for a truck route
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
// The amount of tiles in a square from -X to +X that is scanned for a station spot
// (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
// Safe values are between 15 and 5
#define AI_FINDSTATION_TILE_RANGE 10
// Building on normal speed goes very fast. Idle this amount of ticks between every
// building part. It is calculated like this: (4 - competitor_speed) * num + 1
// where competitor_speed is between 0 (very slow) to 4 (very fast)
#define AI_BUILDPATH_PAUSE 10
// Minimum % of reliabilty a vehicle has to have before the AI buys it
#define AI_VEHICLE_MIN_RELIABILTY 60
// The minimum amount of money a player should always have
#define AI_MINIMUM_MONEY 15000
// If the most cheap route is build, how much is it going to cost..
// This is to prevent the AI from trying to build a route which can not be paid for
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
// The minimum amount of money before we are going to repay any money
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
// How many repays do we do if we have enough money to do so?
// Every repay is 10000
#define AI_LOAN_REPAY 2
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
// If there is <num> time as much cargo in the station then the vehicle can handle
// reuse the station instead of building a new one!
#define AI_STATION_REUSE_MULTIPLER 2
// No more than this amount of vehicles per station..
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
// How many thick between building 2 vehicles
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS
// How many days must there between vehicle checks
// The more often, the less non-money-making lines there will be
// but the unfair it may seem to a human player
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30
// How money profit does a vehicle needs to make to stay in order
// This is the profit of this year + profit of last year
// But also for vehicles that are just one year old. In other words:
// Vehicles of 2 years do easier meet this setting then vehicles
// of one year. This is a very good thing. New vehicles are filtered,
// 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 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
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8
/*
* End of defines
*/
// This stops 90degrees curves
static const byte _illegal_curves[6] = {
255, 255, // Horz and vert, don't have the effect
5, // upleft and upright are not valid
4, // downright and downleft are not valid
2, // downleft and upleft are not valid
3, // upright and downright are not valid
};
enum {
AI_STATE_STARTUP = 0,
AI_STATE_FIRST_TIME,
AI_STATE_NOTHING,
AI_STATE_WAKE_UP,
AI_STATE_LOCATE_ROUTE,
AI_STATE_FIND_STATION,
AI_STATE_FIND_PATH,
AI_STATE_FIND_DEPOT,
AI_STATE_VERIFY_ROUTE,
AI_STATE_BUILD_STATION,
AI_STATE_BUILD_PATH,
AI_STATE_BUILD_DEPOT,
AI_STATE_BUILD_VEHICLE,
AI_STATE_WAIT_FOR_BUILD,
AI_STATE_GIVE_ORDERS,
AI_STATE_START_VEHICLE,
AI_STATE_REPAY_MONEY,
AI_STATE_CHECK_ALL_VEHICLES,
AI_STATE_ACTION_DONE,
AI_STATE_STOP, // Temporary function to stop the AI
};
// Used for tbt (train/bus/truck)
enum {
AI_TRAIN = 0,
AI_BUS,
AI_TRUCK,
};
enum {
AI_ACTION_NONE = 0,
AI_ACTION_BUS_ROUTE,
AI_ACTION_TRUCK_ROUTE,
AI_ACTION_REPAY_LOAN,
AI_ACTION_CHECK_ALL_VEHICLES,
};
// Used for from_type/to_type
enum {
AI_NO_TYPE = 0,
AI_CITY,
AI_INDUSTRY,
};
// Flags for in the vehicle
enum {
AI_VEHICLEFLAG_SELL = 1,
// Remember, flags must be in power of 2
};
#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 TileXY(MapMaxX(), MapMaxY())
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
// Flags used in user_data
#define AI_PATHFINDER_FLAG_BRIDGE 1
#define AI_PATHFINDER_FLAG_TUNNEL 2
typedef void AiNew_StateFunction(Player *p);
// ai_new.c
void AiNewDoGameLoop(Player *p);
// ai_pathfinder.c
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
// ai_shared.c
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag);
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
// ai_build.c
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
EngineID AiNew_PickVehicle(Player *p);
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
#endif /* AI_TROLLY_H */

26
aircraft.h Normal file
View File

@@ -0,0 +1,26 @@
/* $Id$ */
#ifndef AIRCRAFT_H
#define AIRCRAFT_H
#include "station_map.h"
#include "vehicle.h"
static inline bool IsAircraftInHangar(const Vehicle* v)
{
assert(v->type == VEH_Aircraft);
return v->vehstatus & VS_HIDDEN && IsHangarTile(v->tile);
}
static inline bool IsAircraftInHangarStopped(const Vehicle* v)
{
return IsAircraftInHangar(v) && v->vehstatus & VS_STOPPED;
}
uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type);
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2);
void HandleAircraftEnterHangar(Vehicle *v);
#endif /* AIRCRAFT_H */

2146
aircraft_cmd.c Normal file

File diff suppressed because it is too large Load Diff

350
aircraft_gui.c Normal file
View File

@@ -0,0 +1,350 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "aircraft.h"
#include "debug.h"
#include "functions.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "vehicle.h"
#include "gfx.h"
#include "command.h"
#include "engine.h"
#include "viewport.h"
#include "player.h"
#include "depot.h"
#include "vehicle_gui.h"
#include "newgrf_engine.h"
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) ShowAircraftViewWindow(GetVehicle(_new_vehicle_id));
}
static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
SetWindowWidgetDisabledState(w, 2, v->owner != _local_player);
/* Disable service-scroller when interval is set to disabled */
SetWindowWidgetDisabledState(w, 5, !_patches.servint_aircraft);
SetWindowWidgetDisabledState(w, 6, !_patches.servint_aircraft);
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
DrawWindowWidgets(w);
/* Draw running cost */
{
int year = v->age / 366;
SetDParam(1, year);
SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED);
SetDParam(2, v->max_age / 366);
SetDParam(3, _price.aircraft_running * AircraftVehInfo(v->engine_type)->running_cost >> 8);
DrawString(2, 15, STR_A00D_AGE_RUNNING_COST_YR, 0);
}
/* Draw max speed */
{
SetDParam(0, v->max_speed * 128 / 10);
DrawString(2, 25, STR_A00E_MAX_SPEED, 0);
}
/* Draw profit */
{
SetDParam(0, v->profit_this_year);
SetDParam(1, v->profit_last_year);
DrawString(2, 35, STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR, 0);
}
/* Draw breakdown & reliability */
{
SetDParam(0, v->reliability * 100 >> 16);
SetDParam(1, v->breakdowns_since_last_service);
DrawString(2, 45, STR_A010_RELIABILITY_BREAKDOWNS, 0);
}
/* Draw service interval text */
{
SetDParam(0, v->service_interval);
SetDParam(1, v->date_of_last_service);
DrawString(13, 103, _patches.servint_ispercent?STR_SERVICING_INTERVAL_PERCENT:STR_883C_SERVICING_INTERVAL_DAYS, 0);
}
DrawAircraftImage(v, 3, 57, INVALID_VEHICLE);
{
const Vehicle *u;
int y = 57;
do {
if (v->subtype <= 2) {
SetDParam(0, GetCustomEngineName(v->engine_type));
SetDParam(1, v->build_year);
SetDParam(2, v->value);
DrawString(60, y, STR_A011_BUILT_VALUE, 0);
y += 10;
SetDParam(0, v->cargo_type);
SetDParam(1, v->cargo_cap);
u = v->next;
SetDParam(2, u->cargo_type);
SetDParam(3, u->cargo_cap);
DrawString(60, y, (u->cargo_cap != 0) ? STR_A019_CAPACITY : STR_A01A_CAPACITY, 0);
y += 14;
}
if (v->cargo_count != 0) {
/* Cargo names (fix pluralness) */
SetDParam(0, v->cargo_type);
SetDParam(1, v->cargo_count);
SetDParam(2, v->cargo_source);
DrawString(60, y, STR_8813_FROM, 0);
y += 10;
}
} while ( (v=v->next) != NULL);
}
} break;
case WE_CLICK: {
int mod;
const Vehicle *v;
switch (e->we.click.widget) {
case 2: /* rename */
v = GetVehicle(w->window_number);
SetDParam(0, v->unitnumber);
ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
break;
case 5: /* increase int */
mod = _ctrl_pressed? 5 : 10;
goto do_change_service_int;
case 6: /* decrease int */
mod = _ctrl_pressed?- 5 : -10;
do_change_service_int:
v = GetVehicle(w->window_number);
mod = GetServiceIntervalClamped(mod + v->service_interval);
if (mod == v->service_interval) return;
DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
break;
}
} break;
case WE_ON_EDIT_TEXT:
if (e->we.edittext.str[0] != '\0') {
_cmd_text = e->we.edittext.str;
DoCommandP(0, w->window_number, 0, NULL,
CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
}
break;
}
}
static const Widget _aircraft_details_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 349, 0, 13, STR_A00C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 350, 389, 0, 13, STR_01AA_NAME, STR_A032_NAME_AIRCRAFT },
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 14, 55, 0x0, STR_NULL },
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 56, 101, 0x0, STR_NULL },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 102, 107, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 108, 113, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL },
{ WWT_PANEL, RESIZE_NONE, 14, 11, 389, 102, 113, 0x0, STR_NULL },
{ WIDGETS_END},
};
static const WindowDesc _aircraft_details_desc = {
WDP_AUTO, WDP_AUTO, 390, 114,
WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_aircraft_details_widgets,
AircraftDetailsWndProc
};
static void ShowAircraftDetailsWindow(const Vehicle *v)
{
Window *w;
VehicleID veh = v->index;
DeleteWindowById(WC_VEHICLE_ORDERS, veh);
DeleteWindowById(WC_VEHICLE_DETAILS, veh);
w = AllocateWindowDescFront(&_aircraft_details_desc, veh);
w->caption_color = v->owner;
// w->vscroll.cap = 6;
// w->traindetails_d.tab = 0;
}
static const Widget _aircraft_view_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 237, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_STICKYBOX, RESIZE_LR, 14, 238, 249, 0, 13, 0x0, STR_STICKY_BUTTON },
{ WWT_PANEL, RESIZE_RB, 14, 0, 231, 14, 103, 0x0, STR_NULL },
{ WWT_INSET, RESIZE_RB, 14, 2, 229, 16, 101, 0x0, STR_NULL },
{ WWT_PUSHBTN, RESIZE_RTB, 14, 0, 237, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 14, 31, SPR_CENTRE_VIEW_VEHICLE, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_SEND_AIRCRAFT_TODEPOT,STR_A02A_SEND_AIRCRAFT_TO_HANGAR },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 50, 67, SPR_REFIT_VEHICLE, STR_A03B_REFIT_AIRCRAFT_TO_CARRY },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 68, 85, SPR_SHOW_ORDERS, STR_A028_SHOW_AIRCRAFT_S_ORDERS },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 86, 103, SPR_SHOW_VEHICLE_DETAILS, STR_A02B_SHOW_AIRCRAFT_DETAILS },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_CLONE_AIRCRAFT, STR_CLONE_AIRCRAFT_INFO },
{ WWT_PANEL, RESIZE_LRB, 14, 232, 249, 104, 103, 0x0, STR_NULL },
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 238, 249, 104, 115, 0x0, STR_NULL },
{ WIDGETS_END},
};
static void AircraftViewWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
StringID str;
bool is_localplayer = v->owner == _local_player;
SetWindowWidgetDisabledState(w, 7, !is_localplayer);
SetWindowWidgetDisabledState(w, 8, !IsAircraftInHangarStopped(v) || !is_localplayer);
SetWindowWidgetDisabledState(w, 11, !is_localplayer);
/* draw widgets & caption */
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
DrawWindowWidgets(w);
if (v->vehstatus & VS_CRASHED) {
str = STR_8863_CRASHED;
} else if (v->vehstatus & VS_STOPPED) {
str = STR_8861_STOPPED;
} else {
switch (v->current_order.type) {
case OT_GOTO_STATION: {
SetDParam(0, v->current_order.dest);
SetDParam(1, v->cur_speed * 128 / 10);
str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
} break;
case OT_GOTO_DEPOT: {
/* Aircrafts always go to a station, even if you say depot */
SetDParam(0, v->current_order.dest);
SetDParam(1, v->cur_speed * 128 / 10);
if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) {
str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed;
} else {
str = STR_HEADING_FOR_HANGAR_SERVICE + _patches.vehicle_speed;
}
} break;
case OT_LOADING:
str = STR_882F_LOADING_UNLOADING;
break;
default:
if (v->num_orders == 0) {
str = STR_NO_ORDERS + _patches.vehicle_speed;
SetDParam(0, v->cur_speed * 128 / 10);
} else {
str = STR_EMPTY;
}
break;
}
}
/* draw the flag plus orders */
DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, 2, w->widget[5].top + 1);
DrawStringCenteredTruncated(w->widget[5].left + 8, w->widget[5].right, w->widget[5].top + 1, str, 0);
DrawWindowViewport(w);
} break;
case WE_CLICK: {
const Vehicle *v = GetVehicle(w->window_number);
switch (e->we.click.widget) {
case 5: /* start stop */
DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT));
break;
case 6: /* center main view */
ScrollMainWindowTo(v->x_pos, v->y_pos);
break;
case 7: /* goto hangar */
DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_MSG(STR_A012_CAN_T_SEND_AIRCRAFT_TO));
break;
case 8: /* refit */
ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
break;
case 9: /* show orders */
ShowOrdersWindow(v);
break;
case 10: /* show details */
ShowAircraftDetailsWindow(v);
break;
case 11:
/* clone vehicle */
DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneAircraft, CMD_CLONE_VEHICLE | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
break;
}
} break;
case WE_RESIZE:
w->viewport->width += e->we.sizing.diff.x;
w->viewport->height += e->we.sizing.diff.y;
w->viewport->virtual_width += e->we.sizing.diff.x;
w->viewport->virtual_height += e->we.sizing.diff.y;
break;
case WE_DESTROY:
DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number);
break;
case WE_MOUSELOOP: {
const Vehicle *v = GetVehicle(w->window_number);
bool plane_stopped = IsAircraftInHangarStopped(v);
/* Widget 7 (send to hangar) must be hidden if the plane is already stopped in hangar.
* Widget 11 (clone) should then be shown, since cloning is allowed only while in hangar and stopped.
* This sytem allows to have two buttons, on top of each other*/
if (plane_stopped != IsWindowWidgetHidden(w, 7) || plane_stopped == IsWindowWidgetHidden(w, 11)) {
SetWindowWidgetHiddenState(w, 7, plane_stopped); // send to hangar
SetWindowWidgetHiddenState(w, 11, !plane_stopped); // clone
SetWindowDirty(w);
}
} break;
}
}
static const WindowDesc _aircraft_view_desc = {
WDP_AUTO, WDP_AUTO, 250, 116,
WC_VEHICLE_VIEW ,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_aircraft_view_widgets,
AircraftViewWndProc
};
void ShowAircraftViewWindow(const Vehicle *v)
{
Window *w = AllocateWindowDescFront(&_aircraft_view_desc, v->index);
if (w != NULL) {
w->caption_color = v->owner;
AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
}
}

View File

@@ -1,15 +1,14 @@
/* $Id$ */
/** @file airport.cpp Functions related to airports. */
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
#include "map.h"
#include "airport.h"
#include "macros.h"
#include "variables.h"
#include "airport_movement.h"
#include "core/bitmath_func.hpp"
#include "core/alloc_func.hpp"
#include "date_func.h"
#include "settings_type.h"
#include "date.h"
/* Uncomment this to print out a full report of the airport-structure
* You should either use
@@ -18,7 +17,6 @@
* - false: give a summarized report which only shows current and next position */
//#define DEBUG_AIRPORT false
static AirportFTAClass *DummyAirport;
static AirportFTAClass *CountryAirport;
static AirportFTAClass *CityAirport;
static AirportFTAClass *Oilrig;
@@ -30,275 +28,256 @@ static AirportFTAClass *HeliDepot;
static AirportFTAClass *IntercontinentalAirport;
static AirportFTAClass *HeliStation;
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *apFA,
const TileIndexDiffC *depots, const byte nof_depots,
uint size_x, uint size_y
);
static void AirportFTAClass_Destructor(AirportFTAClass *apc);
void InitializeAirports()
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA);
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
static byte AirportTestFTA(const AirportFTAClass *apc);
#ifdef DEBUG_AIRPORT
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report);
#endif /* DEBUG_AIRPORT */
void InitializeAirports(void)
{
DummyAirport = new AirportFTAClass(
_airport_moving_data_dummy,
NULL,
NULL,
_airport_entries_dummy,
AirportFTAClass::ALL,
_airport_fta_dummy,
NULL,
0,
0, 0, 0,
0,
0
);
// country airport
CountryAirport = malloc(sizeof(AirportFTAClass));
CountryAirport = new AirportFTAClass(
_airport_moving_data_country,
AirportFTAClass_Constructor(
CountryAirport,
_airport_terminal_country,
NULL,
_airport_entries_country,
AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
16,
ALL,
_airport_fta_country,
_airport_depots_country,
lengthof(_airport_depots_country),
4, 3, 3,
0,
4
4, 3
);
CityAirport = new AirportFTAClass(
_airport_moving_data_town,
// city airport
CityAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
CityAirport,
_airport_terminal_city,
NULL,
_airport_entries_city,
AirportFTAClass::ALL,
19,
ALL,
_airport_fta_city,
_airport_depots_city,
lengthof(_airport_depots_city),
6, 6, 5,
0,
5
6, 6
);
MetropolitanAirport = new AirportFTAClass(
_airport_moving_data_metropolitan,
// metropolitan airport
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
MetropolitanAirport,
_airport_terminal_metropolitan,
NULL,
_airport_entries_metropolitan,
AirportFTAClass::ALL,
20,
ALL,
_airport_fta_metropolitan,
_airport_depots_metropolitan,
lengthof(_airport_depots_metropolitan),
6, 6, 8,
0,
6
6, 6
);
InternationalAirport = new AirportFTAClass(
_airport_moving_data_international,
// international airport
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
InternationalAirport,
_airport_terminal_international,
_airport_helipad_international,
_airport_entries_international,
AirportFTAClass::ALL,
37,
ALL,
_airport_fta_international,
_airport_depots_international,
lengthof(_airport_depots_international),
7, 7, 17,
0,
8
7, 7
);
IntercontinentalAirport = new AirportFTAClass(
_airport_moving_data_intercontinental,
// intercontintental airport
IntercontinentalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
IntercontinentalAirport,
_airport_terminal_intercontinental,
_airport_helipad_intercontinental,
_airport_entries_intercontinental,
AirportFTAClass::ALL,
43,
ALL,
_airport_fta_intercontinental,
_airport_depots_intercontinental,
lengthof(_airport_depots_intercontinental),
9, 11, 25,
0,
10
9,11
);
Heliport = new AirportFTAClass(
_airport_moving_data_heliport,
// heliport, oilrig
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
Heliport,
NULL,
_airport_helipad_heliport_oilrig,
_airport_entries_heliport_oilrig,
AirportFTAClass::HELICOPTERS,
7,
HELICOPTERS_ONLY,
_airport_fta_heliport_oilrig,
NULL,
0,
1, 1, 1,
60,
4
1, 1
);
Oilrig = new AirportFTAClass(
_airport_moving_data_oilrig,
NULL,
_airport_helipad_heliport_oilrig,
_airport_entries_heliport_oilrig,
AirportFTAClass::HELICOPTERS,
_airport_fta_heliport_oilrig,
NULL,
0,
1, 1, 0,
54,
3
);
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
CommuterAirport = new AirportFTAClass(
_airport_moving_data_commuter,
// commuter airport
CommuterAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
CommuterAirport,
_airport_terminal_commuter,
_airport_helipad_commuter,
_airport_entries_commuter,
AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
22,
ALL,
_airport_fta_commuter,
_airport_depots_commuter,
lengthof(_airport_depots_commuter),
5, 4, 4,
0,
4
5,4
);
HeliDepot = new AirportFTAClass(
_airport_moving_data_helidepot,
// helidepot airport
HeliDepot = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
HeliDepot,
NULL,
_airport_helipad_helidepot,
_airport_entries_helidepot,
AirportFTAClass::HELICOPTERS,
4,
HELICOPTERS_ONLY,
_airport_fta_helidepot,
_airport_depots_helidepot,
lengthof(_airport_depots_helidepot),
2, 2, 2,
0,
4
2,2
);
HeliStation = new AirportFTAClass(
_airport_moving_data_helistation,
// helistation airport
HeliStation = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
HeliStation,
NULL,
_airport_helipad_helistation,
_airport_entries_helistation,
AirportFTAClass::HELICOPTERS,
25,
HELICOPTERS_ONLY,
_airport_fta_helistation,
_airport_depots_helistation,
lengthof(_airport_depots_helistation),
4, 2, 3,
0,
4
4,2
);
}
void UnInitializeAirports()
void UnInitializeAirports(void)
{
delete DummyAirport;
delete CountryAirport;
delete CityAirport;
delete Heliport;
delete MetropolitanAirport;
delete InternationalAirport;
delete CommuterAirport;
delete HeliDepot;
delete IntercontinentalAirport;
delete HeliStation;
AirportFTAClass_Destructor(CountryAirport);
AirportFTAClass_Destructor(CityAirport);
AirportFTAClass_Destructor(Heliport);
AirportFTAClass_Destructor(MetropolitanAirport);
AirportFTAClass_Destructor(InternationalAirport);
AirportFTAClass_Destructor(CommuterAirport);
AirportFTAClass_Destructor(HeliDepot);
AirportFTAClass_Destructor(IntercontinentalAirport);
AirportFTAClass_Destructor(HeliStation);
}
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
#ifdef DEBUG_AIRPORT
static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
#endif
AirportFTAClass::AirportFTAClass(
const AirportMovingData *moving_data_,
const byte *terminals_,
const byte *helipads_,
const byte *entry_points_,
Flags flags_,
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *apFA,
const TileIndexDiffC *depots_,
const byte nof_depots_,
uint size_x_,
uint size_y_,
byte noise_level_,
byte delta_z_,
byte catchment_
) :
moving_data(moving_data_),
terminals(terminals_),
helipads(helipads_),
airport_depots(depots_),
flags(flags_),
nof_depots(nof_depots_),
nofelements(AirportGetNofElements(apFA)),
entry_points(entry_points_),
size_x(size_x_),
size_y(size_y_),
noise_level(noise_level_),
delta_z(delta_z_),
catchment(catchment_)
const TileIndexDiffC *depots, const byte nof_depots,
uint size_x, uint size_y
)
{
byte nofterminals, nofhelipads;
byte nofterminalgroups, nofhelipadgroups;
apc->size_x = size_x;
apc->size_y = size_y;
/* Set up the terminal and helipad count for an airport.
* TODO: If there are more than 10 terminals or 4 helipads, internal variables
* need to be changed, so don't allow that for now */
uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
if (nofterminals > MAX_TERMINALS) {
DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d terminals are supported (you wanted %d)", MAX_TERMINALS, nofterminals);
assert(nofterminals <= MAX_TERMINALS);
}
apc->terminals = terminals;
uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
if (nofhelipads > MAX_HELIPADS) {
DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d helipads are supported (you wanted %d)", MAX_HELIPADS, nofhelipads);
assert(nofhelipads <= MAX_HELIPADS);
}
apc->helipads = helipads;
/* Get the number of elements from the source table. We also double check this
* with the entry point which must be within bounds and use this information
* later on to build and validate the state machine */
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
if (entry_points[i] >= nofelements) {
DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
assert(entry_points[i] < nofelements);
}
apc->nofelements = AirportGetNofElements(apFA);
if (entry_point >= apc->nofelements) {
DEBUG(misc, 0) ("[Ap] Entry (%d) must be within the airport (maximum %d)", entry_point, apc->nofelements);
assert(entry_point < apc->nofelements);
}
apc->acc_planes = acc_planes;
apc->entry_point = entry_point;
apc->airport_depots = depots;
apc->nof_depots = nof_depots;
/* Build the state machine itself */
layout = AirportBuildAutomata(nofelements, apFA);
DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
AirportBuildAutomata(apc, apFA);
DEBUG(misc, 1) ("[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entry %3d",
apc->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, apc->entry_point);
/* Test if everything went allright. This is only a rude static test checking
* the symantic correctness. By no means does passing the test mean that the
* airport is working correctly or will not deadlock for example */
uint ret = AirportTestFTA(nofelements, layout, terminals);
if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
assert(ret == MAX_ELEMENTS);
{ byte ret = AirportTestFTA(apc);
if (ret != MAX_ELEMENTS) DEBUG(misc, 0) ("[Ap] ERROR with element: %d", ret - 1);
assert(ret == MAX_ELEMENTS);
}
#ifdef DEBUG_AIRPORT
AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
AirportPrintOut(apc, DEBUG_AIRPORT);
#endif
}
AirportFTAClass::~AirportFTAClass()
static void AirportFTAClass_Destructor(AirportFTAClass *apc)
{
for (uint i = 0; i < nofelements; i++) {
AirportFTA *current = layout[i].next;
int i;
AirportFTA *current, *next;
for (i = 0; i < apc->nofelements; i++) {
current = apc->layout[i].next;
while (current != NULL) {
AirportFTA *next = current->next;
next = current->next;
free(current);
current = next;
};
}
free(layout);
free(apc->layout);
free(apc);
}
/** Get the number of elements of a source Airport state automata
@@ -306,10 +285,11 @@ AirportFTAClass::~AirportFTAClass()
* know one element from the other by differing 'position' identifiers */
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
{
int i;
uint16 nofelements = 0;
int temp = apFA[0].position;
for (uint i = 0; i < MAX_ELEMENTS; i++) {
for (i = 0; i < MAX_ELEMENTS; i++) {
if (temp != apFA[i].position) {
nofelements++;
temp = apFA[i].position;
@@ -319,16 +299,17 @@ static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
return nofelements;
}
/** We calculate the terminal/helipod count based on the data passed to us
/* We calculate the terminal/helipod count based on the data passed to us
* This data (terminals) contains an index as a first element as to how many
* groups there are, and then the number of terminals for each group */
static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
{
byte i;
byte nof_terminals = 0;
*groups = 0;
if (terminals != NULL) {
uint i = terminals[0];
i = terminals[0];
*groups = i;
while (i-- > 0) {
terminals++;
@@ -339,56 +320,58 @@ static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
return nof_terminals;
}
static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA)
{
AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
AirportFTA *current;
AirportFTA *FAutomata = malloc(sizeof(AirportFTA) * apc->nofelements);
uint16 internalcounter = 0;
uint16 i;
for (uint i = 0; i < nofelements; i++) {
AirportFTA *current = &FAutomata[i];
apc->layout = FAutomata;
for (i = 0; i < apc->nofelements; i++) {
current = &apc->layout[i];
current->position = apFA[internalcounter].position;
current->heading = apFA[internalcounter].heading;
current->block = apFA[internalcounter].block;
current->next_position = apFA[internalcounter].next;
/* outgoing nodes from the same position, create linked list */
// outgoing nodes from the same position, create linked list
while (current->position == apFA[internalcounter + 1].position) {
AirportFTA *newNode = MallocT<AirportFTA>(1);
AirportFTA *newNode = malloc(sizeof(AirportFTA));
newNode->position = apFA[internalcounter + 1].position;
newNode->heading = apFA[internalcounter + 1].heading;
newNode->block = apFA[internalcounter + 1].block;
newNode->next_position = apFA[internalcounter + 1].next;
/* create link */
// create link
current->next = newNode;
current = current->next;
internalcounter++;
}
} // while
current->next = NULL;
internalcounter++;
}
return FAutomata;
}
static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
static byte AirportTestFTA(const AirportFTAClass *apc)
{
uint next_position = 0;
byte position, i, next_position;
AirportFTA *current, *first;
next_position = 0;
for (uint i = 0; i < nofelements; i++) {
uint position = layout[i].position;
for (i = 0; i < apc->nofelements; i++) {
position = apc->layout[i].position;
if (position != next_position) return i;
const AirportFTA *first = &layout[i];
current = first = &apc->layout[i];
for (const AirportFTA *current = first; current != NULL; current = current->next) {
for (; current != NULL; current = current->next) {
/* A heading must always be valid. The only exceptions are
* - multiple choices as start, identified by a special value of 255
* - terminal group which is identified by a special value of 255 */
if (current->heading > MAX_HEADINGS) {
if (current->heading != 255) return i;
if (current == first && current->next == NULL) return i;
if (current != first && current->next_position > terminals[0]) return i;
if (current != first && current->next_position > apc->terminals[0]) return i;
}
/* If there is only one choice, it must be at the end */
@@ -396,7 +379,7 @@ static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byt
/* Obviously the elements of the linked list must have the same identifier */
if (position != current->position) return i;
/* A next position must be within bounds */
if (current->next_position >= nofelements) return i;
if (current->next_position >= apc->nofelements) return i;
}
next_position++;
}
@@ -404,7 +387,7 @@ static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byt
}
#ifdef DEBUG_AIRPORT
static const char * const _airport_heading_strings[] = {
static const char* const _airport_heading_strings[] = {
"TO_ALL",
"HANGAR",
"TERM1",
@@ -431,17 +414,32 @@ static const char * const _airport_heading_strings[] = {
"DUMMY" // extra heading for 255
};
static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
static uint AirportBlockToString(uint32 block)
{
uint i = 0;
if (block & 0xffff0000) { block >>= 16; i += 16; }
if (block & 0x0000ff00) { block >>= 8; i += 8; }
if (block & 0x000000f0) { block >>= 4; i += 4; }
if (block & 0x0000000c) { block >>= 2; i += 2; }
if (block & 0x00000002) { i += 1; }
return i;
}
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report)
{
uint16 i;
if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
for (uint i = 0; i < nofelements; i++) {
for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
for (i = 0; i < apc->nofelements; i++) {
AirportFTA *current = &apc->layout[i];
for (; current != NULL; current = current->next) {
if (full_report) {
byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
current->next_position, _airport_heading_strings[heading],
FindLastBit(current->block));
AirportBlockToString(current->block));
} else {
printf("P:%2d NP:%2d", current->position, current->next_position);
}
@@ -453,8 +451,8 @@ static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool ful
const AirportFTAClass *GetAirport(const byte airport_type)
{
/* FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
* needs constant change if more airports are added */
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
// needs constant change if more airports are added
switch (airport_type) {
default: NOT_REACHED();
case AT_SMALL: return CountryAirport;
@@ -467,23 +465,25 @@ const AirportFTAClass *GetAirport(const byte airport_type)
case AT_HELIDEPOT: return HeliDepot;
case AT_INTERCON: return IntercontinentalAirport;
case AT_HELISTATION: return HeliStation;
case AT_DUMMY: return DummyAirport;
}
}
uint32 GetValidAirports()
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position)
{
uint32 mask = 0;
if (_cur_year < 1960 || _settings_game.station.always_small_airport) SetBit(mask, 0); // small airport
if (_cur_year >= 1955) SetBit(mask, 1); // city airport
if (_cur_year >= 1963) SetBit(mask, 2); // heliport
if (_cur_year >= 1980) SetBit(mask, 3); // metropolitan airport
if (_cur_year >= 1990) SetBit(mask, 4); // international airport
if (_cur_year >= 1983) SetBit(mask, 5); // commuter airport
if (_cur_year >= 1976) SetBit(mask, 6); // helidepot
if (_cur_year >= 2002) SetBit(mask, 7); // intercontinental airport
if (_cur_year >= 1980) SetBit(mask, 8); // helistation
return mask;
assert(airport_type < lengthof(_airport_moving_datas));
assert(position < GetAirport(airport_type)->nofelements);
return &_airport_moving_datas[airport_type][position];
}
uint32 GetValidAirports(void)
{
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
if (_cur_year >= 1980) SETBIT(bytemask, 3); // metropolitan airport
if (_cur_year >= 1990) SETBIT(bytemask, 4); // international airport
if (_cur_year >= 1983) SETBIT(bytemask, 5); // commuter airport
if (_cur_year >= 1976) SETBIT(bytemask, 6); // helidepot
if (_cur_year >= 2002) SETBIT(bytemask, 7); // intercontinental airport
if (_cur_year >= 1980) SETBIT(bytemask, 8); // helistation
return bytemask;
}

163
airport.h Normal file
View File

@@ -0,0 +1,163 @@
/* $Id$ */
#ifndef AIRPORT_H
#define AIRPORT_H
enum {MAX_TERMINALS = 10};
enum {MAX_HELIPADS = 4};
enum {MAX_ELEMENTS = 255};
enum {MAX_HEADINGS = 22};
// Airport types
enum {
AT_SMALL = 0,
AT_LARGE = 1,
AT_HELIPORT = 2,
AT_METROPOLITAN = 3,
AT_INTERNATIONAL = 4,
AT_COMMUTER = 5,
AT_HELIDEPOT = 6,
AT_INTERCON = 7,
AT_HELISTATION = 8,
AT_OILRIG = 15
};
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
enum {
AIRCRAFT_ONLY = 0,
ALL = 1,
HELICOPTERS_ONLY = 2,
};
enum {
AMED_NOSPDCLAMP = 1 << 0,
AMED_TAKEOFF = 1 << 1,
AMED_SLOWTURN = 1 << 2,
AMED_LAND = 1 << 3,
AMED_EXACTPOS = 1 << 4,
AMED_BRAKE = 1 << 5,
AMED_HELI_RAISE = 1 << 6,
AMED_HELI_LOWER = 1 << 7,
};
/* Movement States on Airports (headings target) */
enum {
TO_ALL = 0,
HANGAR = 1,
TERM1 = 2,
TERM2 = 3,
TERM3 = 4,
TERM4 = 5,
TERM5 = 6,
TERM6 = 7,
HELIPAD1 = 8,
HELIPAD2 = 9,
TAKEOFF = 10,
STARTTAKEOFF = 11,
ENDTAKEOFF = 12,
HELITAKEOFF = 13,
FLYING = 14,
LANDING = 15,
ENDLANDING = 16,
HELILANDING = 17,
HELIENDLANDING = 18,
TERM7 = 19,
TERM8 = 20,
HELIPAD3 = 21,
HELIPAD4 = 22
};
// this maps the terminal to its corresponding state and block flag
// currently set for 10 terms, 4 helipads
static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
static const byte _airport_terminal_flag[] = {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25};
/* Movement Blocks on Airports */
// blocks (eg_airport_flags)
enum {
TERM1_block = 1 << 0,
TERM2_block = 1 << 1,
TERM3_block = 1 << 2,
TERM4_block = 1 << 3,
TERM5_block = 1 << 4,
TERM6_block = 1 << 5,
HELIPAD1_block = 1 << 6,
HELIPAD2_block = 1 << 7,
RUNWAY_IN_OUT_block = 1 << 8,
RUNWAY_IN_block = 1 << 8,
AIRPORT_BUSY_block = 1 << 8,
RUNWAY_OUT_block = 1 << 9,
TAXIWAY_BUSY_block = 1 << 10,
OUT_WAY_block = 1 << 11,
IN_WAY_block = 1 << 12,
AIRPORT_ENTRANCE_block = 1 << 13,
TERM_GROUP1_block = 1 << 14,
TERM_GROUP2_block = 1 << 15,
HANGAR2_AREA_block = 1 << 16,
TERM_GROUP2_ENTER1_block = 1 << 17,
TERM_GROUP2_ENTER2_block = 1 << 18,
TERM_GROUP2_EXIT1_block = 1 << 19,
TERM_GROUP2_EXIT2_block = 1 << 20,
PRE_HELIPAD_block = 1 << 21,
// blocks for new airports
TERM7_block = 1 << 22,
TERM8_block = 1 << 23,
TERM9_block = 1 << 24,
HELIPAD3_block = 1 << 24,
TERM10_block = 1 << 25,
HELIPAD4_block = 1 << 25,
HANGAR1_AREA_block = 1 << 26,
OUT_WAY2_block = 1 << 27,
IN_WAY2_block = 1 << 28,
RUNWAY_IN2_block = 1 << 29,
RUNWAY_OUT2_block = 1 << 10, // note re-uses TAXIWAY_BUSY
HELIPAD_GROUP_block = 1 << 13, // note re-uses AIRPORT_ENTRANCE
OUT_WAY_block2 = 1 << 31,
// end of new blocks
NOTHING_block = 1 << 30
};
typedef struct AirportMovingData {
int x,y;
byte flag;
byte direction;
} AirportMovingData;
// Finite sTate mAchine --> FTA
typedef struct AirportFTAClass {
byte nofelements; // number of positions the airport consists of
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 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
byte size_x;
byte size_y;
} AirportFTAClass;
// internal structure used in openttd - Finite sTate mAchine --> FTA
typedef struct AirportFTA {
byte position; // the position that an airplane is at
byte next_position; // next position from this position
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
byte heading; // heading (current orders), guiding an airplane to its target on an airport
struct AirportFTA *next; // possible extra movement choices from this position
} AirportFTA;
void InitializeAirports(void);
void UnInitializeAirports(void);
const AirportFTAClass *GetAirport(const byte airport_type);
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position);
/** 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
*/
uint32 GetValidAirports(void);
#endif /* AIRPORT_H */

286
airport_gui.c Normal file
View File

@@ -0,0 +1,286 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "functions.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(void);
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) {
SndPlayTileFx(SND_1F_SPLAT, tile);
ResetObjectToPlace();
}
}
static void PlaceAirport(TileIndex tile)
{
DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
}
static void PlaceAir_DemolishArea(TileIndex tile)
{
VpStartPlaceSizing(tile, 4);
}
enum {
ATW_AIRPORT = 3,
ATW_DEMOLISH = 4
};
static void BuildAirClick_Airport(Window *w)
{
if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
}
static void BuildAirClick_Demolish(Window *w)
{
HandlePlacePushButton(w, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
}
static void BuildAirClick_Landscaping(Window *w)
{
ShowTerraformToolbar();
}
typedef void OnButtonClick(Window *w);
static OnButtonClick * const _build_air_button_proc[] = {
BuildAirClick_Airport,
BuildAirClick_Demolish,
BuildAirClick_Landscaping,
};
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT:
DrawWindowWidgets(w);
break;
case WE_CLICK:
if (e->we.click.widget - 3 >= 0)
_build_air_button_proc[e->we.click.widget - 3](w);
break;
case WE_KEYPRESS: {
switch (e->we.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->we.place.tile);
break;
case WE_PLACE_DRAG:
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
break;
case WE_PLACE_MOUSEUP:
if (e->we.place.pt.x != -1) {
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
}
break;
case WE_ABORT_PLACE_OBJ:
RaiseWindowButtons(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != 0)
WP(w,def_d).close = true;
break;
case WE_DESTROY:
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
break;
}
}
static const Widget _air_toolbar_widgets[] = {
{ 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_IMGBTN, RESIZE_NONE, 7, 0, 41, 14, 35, SPR_IMG_AIRPORT, STR_A01E_BUILD_AIRPORT },
{ WWT_IMGBTN, RESIZE_NONE, 7, 42, 63, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC },
{ WWT_IMGBTN, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP },
{ WIDGETS_END},
};
static const WindowDesc _air_toolbar_desc = {
WDP_ALIGN_TBR, 22, 86, 36,
WC_BUILD_TOOLBAR, 0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
_air_toolbar_widgets,
BuildAirToolbWndProc
};
void ShowBuildAirToolbar(void)
{
if (!IsValidPlayer(_current_player)) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
AllocateWindowDescFront(&_air_toolbar_desc, 0);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
}
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE:
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
LowerWindowWidget(w, _selected_airport_type + 7);
break;
case WE_PAINT: {
int i; // airport enabling loop
int rad = 4; // default catchment radious
uint32 avail_airports;
const AirportFTAClass *airport;
if (WP(w,def_d).close) return;
avail_airports = GetValidAirports();
RaiseWindowWidget(w, _selected_airport_type + 7);
if (!HASBIT(avail_airports, 0) && _selected_airport_type == AT_SMALL) _selected_airport_type = AT_LARGE;
if (!HASBIT(avail_airports, 1) && _selected_airport_type == AT_LARGE) _selected_airport_type = AT_SMALL;
LowerWindowWidget(w, _selected_airport_type + 7);
/* 'Country Airport' starts at widget 7, and if its bit is set, it is
* available, so take its opposite value to set the disabled state.
* There are 9 buildable airports
* XXX TODO : all airports should be held in arrays, with all relevant data.
* This should be part of newgrf-airports, i suppose
*/
for (i = 0; i < 9; i++) SetWindowWidgetDisabledState(w, i + 7, !HASBIT(avail_airports, i));
// select default the coverage area to 'Off' (16)
airport = GetAirport(_selected_airport_type);
SetTileSelectSize(airport->size_x, airport->size_y);
if (_patches.modified_catchment) {
switch (_selected_airport_type) {
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;
case AT_COMMUTER: rad = CA_AIR_COMMUTER; break;
case AT_HELIDEPOT: rad = CA_AIR_HELIDEPOT; break;
case AT_INTERCON: rad = CA_AIR_INTERCON; break;
case AT_HELISTATION: rad = CA_AIR_HELISTATION; break;
}
}
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
DrawWindowWidgets(w);
// strings such as 'Size' and 'Coverage Area'
// 'Coverage Area'
DrawStationCoverageAreaText(2, 206, (uint)-1, rad);
break;
}
case WE_CLICK: {
switch (e->we.click.widget) {
case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
RaiseWindowWidget(w, _selected_airport_type + 7);
_selected_airport_type = e->we.click.widget - 7;
LowerWindowWidget(w, _selected_airport_type + 7);
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
case 16: case 17:
_station_show_coverage = e->we.click.widget - 16;
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
}
} break;
case WE_MOUSELOOP: {
if (WP(w,def_d).close) {
DeleteWindow(w);
return;
}
CheckRedrawStationCoverage(w);
} break;
case WE_DESTROY:
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
static const Widget _build_airport_picker_widgets[] = {
{ 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, 52, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 53, 89, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 90, 127, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 128, 177, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 178, 239, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 27, 38, STR_SMALL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 65, 76, STR_CITY_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 141, 152, STR_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 77, 88, STR_METRO_AIRPORT , STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 103, 114, STR_INTERNATIONAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_COMMUTER_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 165, 176, STR_HELIDEPOT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 115, 126, STR_INTERCONTINENTAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 153, 164, STR_HELISTATION, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 191, 202, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 191, 202, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 14, 27, STR_SMALL_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 52, 65, STR_LARGE_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 90, 103, STR_HUB_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 128, 141, STR_HELIPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 178, 191, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
{ WIDGETS_END},
};
static const WindowDesc _build_airport_desc = {
WDP_AUTO, WDP_AUTO, 148, 240,
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_airport_picker_widgets,
BuildAirportPickerWndProc
};
static void ShowBuildAirportPicker(void)
{
AllocateWindowDesc(&_build_airport_desc);
}
void InitializeAirportGui(void)
{
_selected_airport_type = AT_SMALL;
}

794
airport_movement.h Normal file
View File

@@ -0,0 +1,794 @@
/* $Id$ */
#ifndef AIRPORT_MOVEMENT_H
#define AIRPORT_MOVEMENT_H
// state machine input struct (from external file, etc.)
// Finite sTate mAchine --> FTA
typedef struct AirportFTAbuildup {
byte position; // the position that an airplane is at
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
uint32 block; // the block this position is on on the airport (st->airport_flags)
byte next; // next position from this position
} AirportFTAbuildup;
///////////////////////////////////////////////////////////////////////
/////*********Movement Positions on Airports********************///////
// Country Airfield (small) 4x3
static const AirportMovingData _airport_moving_data_country[22] = {
{ 53, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 53, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 32, 23, AMED_EXACTPOS, 7 }, // 02 Terminal 1
{ 10, 23, AMED_EXACTPOS, 7 }, // 03 Terminal 2
{ 43, 37, 0, 0 }, // 04 Going towards terminal 2
{ 24, 37, 0, 0 }, // 05 Going towards terminal 2
{ 53, 37, 0, 0 }, // 06 Going for takeoff
{ 61, 40, AMED_EXACTPOS, 1 }, // 07 Taxi to start of runway (takeoff)
{ 3, 40, AMED_NOSPDCLAMP, 0 }, // 08 Accelerate to end of runway
{ -79, 40, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 09 Take off
{ 177, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 10 Fly to landing position in air
{ 56, 40, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 11 Going down for land
{ 3, 40, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 12 Just landed, brake until end of runway
{ 7, 40, 0, 0 }, // 13 Just landed, turn around and taxi 1 square
{ 53, 40, 0, 0 }, // 14 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (south)
{ 44, 37, AMED_HELI_RAISE, 0 }, // 19 Helicopter takeoff
{ 44, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 In position above landing spot helicopter
{ 44, 40, AMED_HELI_LOWER, 0 }, // 21 Helicopter landing
};
// Commuter Airfield (small) 5x4
static const AirportMovingData _airport_moving_data_commuter[37] = {
{ 69, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 72, 22, 0, 0 }, // 01 Taxi to right outside depot
{ 8, 22, AMED_EXACTPOS, 5 }, // 01 Taxi to right outside depot
{ 24, 36, AMED_EXACTPOS, 3 }, // 03 Terminal 1
{ 40, 36, AMED_EXACTPOS, 3 }, // 04 Terminal 2
{ 56, 36, AMED_EXACTPOS, 3 }, // 05 Terminal 3
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
{ 24, 22, 0, 5 }, // 08 Taxiing
{ 40, 22, 0, 5 }, // 09 Taxiing
{ 56, 22, 0, 5 }, // 10 Taxiing
{ 72, 40, 0, 3 }, // 11 Airport OUTWAY
{ 72, 54, AMED_EXACTPOS, 1 }, // 12 Accelerate to end of runway
{ 7, 54, AMED_NOSPDCLAMP, 0 }, // 13 Release control of runway, for smoother movement
{ 5, 54, AMED_NOSPDCLAMP, 0 }, // 14 End of runway
{ -79, 54, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 15 Take off
{ 145, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly to landing position in air
{ 73, 54, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 17 Going down for land
{ 3, 54, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 18 Just landed, brake until end of runway
{ 12, 54, 0, 7 }, // 19 Just landed, turn around and taxi
{ 8, 32, 0, 7 }, // 20 Taxi from runway to crossing
{ -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (north-east)
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (north-west)
{ 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Fly around waiting for a landing spot (south-west)
{ 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 24 Fly around waiting for a landing spot (south)
// Helicopter
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Bufferspace before helipad
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Bufferspace before helipad
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Get in position for Helipad1
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Get in position for Helipad2
{ 32, 8, AMED_HELI_LOWER, 0 }, // 29 Land at Helipad1
{ 48, 8, AMED_HELI_LOWER, 0 }, // 30 Land at Helipad2
{ 32, 8, AMED_HELI_RAISE, 0 }, // 31 Takeoff Helipad1
{ 48, 8, AMED_HELI_RAISE, 0 }, // 32 Takeoff Helipad2
{ 64, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 33 Go to position for Hangarentrance in air
{ 64, 22, AMED_HELI_LOWER, 0 }, // 34 Land in front of hangar
{ 40, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 1
{ 56, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 2
};
// City Airport (large) 6x6
static const AirportMovingData _airport_moving_data_town[25] = {
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
{ 80, 27, 0, 0 }, // 06 Taxiway terminals 2-3
{ 44, 63, 0, 0 }, // 07 Taxi to Airport center
{ 58, 71, 0, 0 }, // 08 Towards takeoff
{ 72, 85, 0, 0 }, // 09 Taxi to runway (takeoff)
{ 89, 85, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
{ 3, 85, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
{ -79, 85, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
{ 20, 87, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
{ 36, 71, 0, 0 }, // 17 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south)
{ 44, 63, AMED_HELI_RAISE, 0 }, // 22 Helicopter takeoff
{ 28, 74, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 In position above landing spot helicopter
{ 28, 74, AMED_HELI_LOWER, 0 }, // 24 Helicopter landing
};
// Metropolitan Airport (metropolitan) - 2 runways
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
{ 70, 33, 0, 0 }, // 06 Taxiway terminals 2-3
{ 44, 58, 0, 0 }, // 07 Taxi to Airport center
{ 72, 58, 0, 0 }, // 08 Towards takeoff
{ 72, 69, 0, 0 }, // 09 Taxi to runway (takeoff)
{ 89, 69, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
{ 3, 69, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
{ -79, 69, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
{ 21, 85, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
{ 21, 69, 0, 0 }, // 17 On Runway-out taxiing to In-Way
{ 21, 54, AMED_EXACTPOS, 5 }, // 18 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (south)
{ 44, 58, 0, 0 }, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
{ 44, 63, AMED_HELI_RAISE, 0 }, // 24 Helicopter takeoff
{ 15, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Get in position above landing spot helicopter
{ 15, 54, AMED_HELI_LOWER, 0 }, // 26 Helicopter landing
};
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
static const AirportMovingData _airport_moving_data_international[51] = {
{ 7, 55, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
{ 100, 21, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
{ 7, 70, 0, 0 }, // 02 Taxi to right outside depot
{ 100, 36, 0, 0 }, // 03 Taxi to right outside depot
{ 38, 70, AMED_EXACTPOS, 5 }, // 04 Terminal 1
{ 38, 54, AMED_EXACTPOS, 5 }, // 05 Terminal 2
{ 38, 38, AMED_EXACTPOS, 5 }, // 06 Terminal 3
{ 70, 70, AMED_EXACTPOS, 1 }, // 07 Terminal 4
{ 70, 54, AMED_EXACTPOS, 1 }, // 08 Terminal 5
{ 70, 38, AMED_EXACTPOS, 1 }, // 09 Terminal 6
{ 104, 71, AMED_EXACTPOS, 1 }, // 10 Helipad 1
{ 104, 55, AMED_EXACTPOS, 1 }, // 11 Helipad 2
{ 22, 87, 0, 0 }, // 12 Towards Terminals 4/5/6, Helipad 1/2
{ 60, 87, 0, 0 }, // 13 Towards Terminals 4/5/6, Helipad 1/2
{ 66, 87, 0, 0 }, // 14 Towards Terminals 4/5/6, Helipad 1/2
{ 86, 87, AMED_EXACTPOS, 7 }, // 15 Towards Terminals 4/5/6, Helipad 1/2
{ 86, 70, 0, 0 }, // 16 In Front of Terminal 4 / Helipad 1
{ 86, 54, 0, 0 }, // 17 In Front of Terminal 5 / Helipad 2
{ 86, 38, 0, 0 }, // 18 In Front of Terminal 6
{ 86, 22, 0, 0 }, // 19 Towards Terminals Takeoff (Taxiway)
{ 66, 22, 0, 0 }, // 20 Towards Terminals Takeoff (Taxiway)
{ 60, 22, 0, 0 }, // 21 Towards Terminals Takeoff (Taxiway)
{ 38, 22, 0, 0 }, // 22 Towards Terminals Takeoff (Taxiway)
{ 22, 70, 0, 0 }, // 23 In Front of Terminal 1
{ 22, 58, 0, 0 }, // 24 In Front of Terminal 2
{ 22, 38, 0, 0 }, // 25 In Front of Terminal 3
{ 22, 22, AMED_EXACTPOS, 7 }, // 26 Going for Takeoff
{ 22, 6, 0, 0 }, // 27 On Runway-out, prepare for takeoff
{ 3, 6, AMED_EXACTPOS, 5 }, // 28 Accelerate to end of runway
{ 60, 6, AMED_NOSPDCLAMP, 0 }, // 29 Release control of runway, for smoother movement
{ 105, 6, AMED_NOSPDCLAMP, 0 }, // 30 End of runway
{ 190, 6, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 31 Take off
{ 193, 104, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly to landing position in air
{ 105, 104, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 33 Going down for land
{ 3, 104, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 34 Just landed, brake until end of runway
{ 12, 104, 0, 0 }, // 35 Just landed, turn around and taxi 1 square
{ 7, 84, 0, 0 }, // 36 Taxi from runway to crossing
{ -31, 209, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 37 Fly around waiting for a landing spot (north-east)
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 38 Fly around waiting for a landing spot (north-west)
{ 273, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 39 Fly around waiting for a landing spot (south-west)
{ 305, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 40 Fly around waiting for a landing spot (south)
// Helicopter
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 41 Bufferspace before helipad
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 42 Bufferspace before helipad
{ 96, 71, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Get in position for Helipad1
{ 96, 55, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Get in position for Helipad2
{ 96, 71, AMED_HELI_LOWER, 0 }, // 45 Land at Helipad1
{ 96, 55, AMED_HELI_LOWER, 0 }, // 46 Land at Helipad2
{ 104, 71, AMED_HELI_RAISE, 0 }, // 47 Takeoff Helipad1
{ 104, 55, AMED_HELI_RAISE, 0 }, // 48 Takeoff Helipad2
{ 104, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Go to position for Hangarentrance in air
{ 104, 32, AMED_HELI_LOWER, 0} // 50 Land in HANGAR2_AREA to go to hangar
};
// Intercontinental Airport - 4 runways, 8 terminals, 2 dedicated helipads
static const AirportMovingData _airport_moving_data_intercontinental[77] = {
{ 7, 87, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
{ 135, 72, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
{ 7, 104, 0, 0 }, // 02 Taxi to right outside depot 1
{ 135, 88, 0, 0 }, // 03 Taxi to right outside depot 2
{ 56, 120, AMED_EXACTPOS, 6 }, // 04 Terminal 1
{ 56, 104, AMED_EXACTPOS, 5 }, // 05 Terminal 2
{ 56, 88, AMED_EXACTPOS, 5 }, // 06 Terminal 3
{ 56, 72, AMED_EXACTPOS, 5 }, // 07 Terminal 4
{ 88, 120, AMED_EXACTPOS, 0 }, // 08 Terminal 5
{ 88, 104, AMED_EXACTPOS, 1 }, // 09 Terminal 6
{ 88, 88, AMED_EXACTPOS, 1 }, // 10 Terminal 7
{ 88, 72, AMED_EXACTPOS, 1 }, // 11 Terminal 8
{ 88, 56, AMED_EXACTPOS, 3 }, // 12 Helipad 1
{ 72, 56, AMED_EXACTPOS, 1 }, // 13 Helipad 2
{ 40, 136, 0, 0 }, // 14 Term group 2 enter 1 a
{ 56, 136, 0, 0 }, // 15 Term group 2 enter 1 b
{ 88, 136, 0, 0 }, // 16 Term group 2 enter 2 a
{ 104, 136, 0, 0 }, // 17 Term group 2 enter 2 b
{ 104, 120, 0, 0 }, // 18 Term group 2 - opp term 5
{ 104, 104, 0, 0 }, // 19 Term group 2 - opp term 6 & exit2
{ 104, 88, 0, 0 }, // 20 Term group 2 - opp term 7 & hangar area 2
{ 104, 72, 0, 0 }, // 21 Term group 2 - opp term 8
{ 104, 56, 0, 0 }, // 22 Taxi Term group 2 exit a
{ 104, 40, 0, 0 }, // 23 Taxi Term group 2 exit b
{ 56, 40, 0, 0 }, // 24 Term group 2 exit 2a
{ 40, 40, 0, 0 }, // 25 Term group 2 exit 2b
{ 40, 120, 0, 0 }, // 26 Term group 1 - opp term 1
{ 40, 104, 0, 0 }, // 27 Term group 1 - opp term 2 & hangar area 1
{ 40, 88, 0, 0 }, // 28 Term group 1 - opp term 3
{ 40, 72, 0, 0 }, // 29 Term group 1 - opp term 4
{ 18, 72, 0, 7 }, // 30 Outway 1
{ 8, 40, 0, 7 }, // 31 Airport OUTWAY
{ 8, 24, AMED_EXACTPOS, 5 }, // 32 Accelerate to end of runway
{ 119, 24, AMED_NOSPDCLAMP, 0 }, // 33 Release control of runway, for smoother movement
{ 117, 24, AMED_NOSPDCLAMP, 0 }, // 34 End of runway
{ 197, 24, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 35 Take off
{ 254, 84, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 36 Flying to landing position in air
{ 117, 168, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 37 Going down for land
{ 3, 168, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 38 Just landed, brake until end of runway
{ 8, 168, 0, 0 }, // 39 Just landed, turn around and taxi
{ 8, 144, 0, 7 }, // 40 Taxi from runway
{ 8, 128, 0, 7 }, // 41 Taxi from runway
{ 8, 120, AMED_EXACTPOS, 5 }, // 42 Airport entrance
{ 56, 344, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Fly around waiting for a landing spot (north-east)
{ -200, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Fly around waiting for a landing spot (north-west)
{ 56, -168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 45 Fly around waiting for a landing spot (south-west)
{ 312, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 46 Fly around waiting for a landing spot (south)
// Helicopter
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 47 Bufferspace before helipad
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 48 Bufferspace before helipad
{ 82, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Get in position for Helipad1
{ 64, 56, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 50 Get in position for Helipad2
{ 81, 55, AMED_HELI_LOWER, 0 }, // 51 Land at Helipad1
{ 64, 56, AMED_HELI_LOWER, 0 }, // 52 Land at Helipad2
{ 80, 56, AMED_HELI_RAISE, 0 }, // 53 Takeoff Helipad1
{ 64, 56, AMED_HELI_RAISE, 0 }, // 54 Takeoff Helipad2
{ 136, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 55 Go to position for Hangarentrance in air
{ 136, 96, AMED_HELI_LOWER, 0 }, // 56 Land in front of hangar2
{ 126, 104, 0, 3 }, // 57 Outway 2
{ 136, 136, 0, 1 }, // 58 Airport OUTWAY 2
{ 136, 152, AMED_EXACTPOS, 1 }, // 59 Accelerate to end of runway2
{ 16, 152, AMED_NOSPDCLAMP, 0 }, // 60 Release control of runway2, for smoother movement
{ 20, 152, AMED_NOSPDCLAMP, 0 }, // 61 End of runway2
{ -56, 152, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 62 Take off2
{ 24, 8, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 63 Going down for land2
{ 136, 8, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 64 Just landed, brake until end of runway2in
{ 136, 8, 0, 0 }, // 65 Just landed, turn around and taxi
{ 136, 24, 0, 3 }, // 66 Taxi from runway 2in
{ 136, 40, 0, 3 }, // 67 Taxi from runway 2in
{ 136, 56, AMED_EXACTPOS, 1 }, // 68 Airport entrance2
{ -56, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 69 Fly to landing position in air2
{ 88, 40, 0, 0 }, // 70 Taxi Term group 2 exit - opp heli1
{ 72, 40, 0, 0 }, // 71 Taxi Term group 2 exit - opp heli2
{ 88, 57, AMED_EXACTPOS, 3 }, // 72 pre-helitakeoff helipad 1
{ 71, 56, AMED_EXACTPOS, 1 }, // 73 pre-helitakeoff helipad 2
{ 8, 120, AMED_HELI_RAISE, 0 }, // 74 Helitakeoff outside depot 1
{ 136, 104, AMED_HELI_RAISE, 0 }, // 75 Helitakeoff outside depot 2
{ 197, 168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0} // 76 Fly to landing position in air1
};
// Heliport (heliport)
static const AirportMovingData _airport_moving_data_heliport[9] = {
{ 5, 9, AMED_EXACTPOS, 1 }, // 0 - At heliport terminal
{ 2, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
{ -3, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
{ -3, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
{ 2, 9, 0, 0 }, // 4 - Goto terminal on ground
{ -31, 59, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #1 (north-east)
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #2 (north-west)
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - Circle #3 (south-west)
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - Circle #4 (south)
};
// HeliDepot 2x2 (heliport)
static const AirportMovingData _airport_moving_data_helidepot[18] = {
{ 24, 4, AMED_EXACTPOS, 1 }, // 0 - At depot
{ 24, 28, 0, 0 }, // 1 Taxi to right outside depot
{ 5, 38, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 Flying
{ -15, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 3 - Circle #1 (north-east)
{ -15, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 4 - Circle #2 (north-west)
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #3 (south-west)
{ 49, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #4 (south-east)
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 7 - PreHelipad
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 8 - Helipad
{ 8, 16, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 9 - Land
{ 8, 16, AMED_HELI_LOWER, 7 }, // 10 - Land
{ 8, 24, AMED_HELI_RAISE, 0 }, // 11 - Take off (play sound)
{ 32, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 12 Air to above hangar area
{ 32, 24, AMED_HELI_LOWER, 7 }, // 13 Taxi to right outside depot
{ 8, 24, AMED_EXACTPOS, 7 }, // 14 - on helipad1
{ 24, 28, AMED_HELI_RAISE, 0 }, // 15 Takeoff right outside depot
{ 8, 24, AMED_HELI_RAISE, 5 }, // 16 - Take off (play sound)
{ 8, 24, AMED_SLOWTURN | AMED_EXACTPOS, 2 }, // 17 - turn on helipad1 for takeoff
};
// HeliDepot 2x2 (heliport)
static const AirportMovingData _airport_moving_data_helistation[33] = {
{ 8, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar2
{ 8, 22, 0, 0 }, // 01 outside hangar 2
{ 116, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 02 Fly to landing position in air
{ 14, 22, AMED_HELI_RAISE, 0 }, // 03 Helitakeoff outside hangar1(play sound)
{ 24, 22, 0, 0 }, // 04 taxiing
{ 40, 22, 0, 0 }, // 05 taxiing
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
{ 56, 24, AMED_EXACTPOS, 1 }, // 08 Helipad 3
{ 40, 8, AMED_EXACTPOS, 0 }, // 09 pre-helitakeoff helipad 1
{ 56, 8, AMED_EXACTPOS, 0 }, // 10 pre-helitakeoff helipad 2
{ 56, 24, AMED_EXACTPOS, 0 }, // 11 pre-helitakeoff helipad 3
{ 32, 8, AMED_HELI_RAISE, 0 }, // 12 Takeoff Helipad1
{ 48, 8, AMED_HELI_RAISE, 0 }, // 13 Takeoff Helipad2
{ 48, 24, AMED_HELI_RAISE, 0 }, // 14 Takeoff Helipad3
{ 84, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Bufferspace before helipad
{ 68, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Bufferspace before helipad
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Get in position for Helipad1
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Get in position for Helipad2
{ 48, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 1 }, // 19 Get in position for Helipad3
{ 40, 8, AMED_HELI_LOWER, 0 }, // 20 Land at Helipad1
{ 48, 8, AMED_HELI_LOWER, 0 }, // 21 Land at Helipad2
{ 48, 24, AMED_HELI_LOWER, 0 }, // 22 Land at Helipad3
{ 0, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Go to position for Hangarentrance in air
{ 0, 22, AMED_HELI_LOWER, 0 }, // 24 Land in front of hangar
{ 148, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Fly around waiting for a landing spot (south-east)
{ 148, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Fly around waiting for a landing spot (south-west)
{ 132, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Fly around waiting for a landing spot (south-west)
{ 100, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Fly around waiting for a landing spot (north-east)
{ 84, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 29 Fly around waiting for a landing spot (south-east)
{ 84, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 30 Fly around waiting for a landing spot (south-west)
{ 100, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 31 Fly around waiting for a landing spot (north-west)
{ 132, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly around waiting for a landing spot (north-east)
};
// Oilrig
static const AirportMovingData _airport_moving_data_oilrig[9] = {
{ 31, 9, AMED_EXACTPOS, 1 }, // 0 - At oilrig terminal
{ 28, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
{ 23, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
{ 23, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
{ 28, 9, 0, 0 }, // 4 - Goto terminal on ground
{ -31, 69, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - circle #1 (north-east)
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - circle #2 (north-west)
{ 69, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - circle #3 (south-west)
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - circle #4 (south)
};
///////////////////////////////////////////////////////////////////////
/////**********Movement Machine on Airports*********************///////
/* First element of terminals 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 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 },
{ 2, TERM1, TERM1_block, 1 },
{ 3, TERM2, TERM2_block, 5 },
{ 4, 255, AIRPORT_BUSY_block, 0 }, { 4, TERM2, 0, 5 }, { 4, HANGAR, 0, 1 }, { 4, TAKEOFF, 0, 6 }, { 4, HELITAKEOFF, 0, 1 },
{ 5, 255, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, 0, 0, 4 },
{ 6, 0, AIRPORT_BUSY_block, 7 },
// takeoff
{ 7, TAKEOFF, AIRPORT_BUSY_block, 8 },
{ 8, STARTTAKEOFF, NOTHING_block, 9 },
{ 9, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 10, FLYING, NOTHING_block, 15 }, { 10, LANDING, 0, 11 }, { 10, HELILANDING, 0, 20 },
{ 11, LANDING, AIRPORT_BUSY_block, 12 },
{ 12, 0, AIRPORT_BUSY_block, 13 },
{ 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 },
{ 14, 0, AIRPORT_BUSY_block, 1 },
// In air
{ 15, 0, NOTHING_block, 16 },
{ 16, 0, NOTHING_block, 17 },
{ 17, 0, NOTHING_block, 18 },
{ 18, 0, NOTHING_block, 10 },
{ 19, HELITAKEOFF, NOTHING_block, 0 },
{ 20, HELILANDING, AIRPORT_BUSY_block, 21 },
{ 21, HELIENDLANDING, AIRPORT_BUSY_block, 1 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const TileIndexDiffC _airport_depots_commuter[] = { { 4, 0 } };
static const byte _airport_terminal_commuter[] = { 1, 3 };
static const byte _airport_helipad_commuter[] = { 1, 2 };
static const AirportFTAbuildup _airport_fta_commuter[] = {
{ 0, HANGAR, NOTHING_block, 1 }, { 0, HELITAKEOFF, HELIPAD2_block, 1 }, { 0, 0, 0, 1 },
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TAKEOFF, 0, 11 }, { 1, TERM1, TAXIWAY_BUSY_block, 10 }, { 1, TERM2, TAXIWAY_BUSY_block, 10 }, { 1, TERM3, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD1, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD2, TAXIWAY_BUSY_block, 10 }, { 1, HELITAKEOFF, TAXIWAY_BUSY_block, 10 }, { 1, 0, 0, 0 },
{ 2, 255, AIRPORT_ENTRANCE_block, 2 }, { 2, HANGAR, 0, 8 }, { 2, TERM1, 0, 8 }, { 2, TERM2, 0, 8 }, { 2, TERM3, 0, 8 }, { 2, HELIPAD1, 0, 8 }, { 2, HELIPAD2, 0, 8 }, { 2, HELITAKEOFF, 0, 8 }, { 2, 0, 0, 2 },
{ 3, TERM1, TERM1_block, 8 }, { 3, HANGAR, 0, 8 }, { 3, TAKEOFF, 0, 8 }, { 3, 0, 0, 3 },
{ 4, TERM2, TERM2_block, 9 }, { 4, HANGAR, 0, 9 }, { 4, TAKEOFF, 0, 9 }, { 4, 0, 0, 4 },
{ 5, TERM3, TERM3_block, 10 }, { 5, HANGAR, 0, 10 }, { 5, TAKEOFF, 0, 10 }, { 5, 0, 0, 5 },
{ 6, HELIPAD1, HELIPAD1_block, 6 }, { 6, HANGAR, TAXIWAY_BUSY_block, 9 }, { 6, HELITAKEOFF, 0, 35 },
{ 7, HELIPAD2, HELIPAD2_block, 7 }, { 7, HANGAR, TAXIWAY_BUSY_block, 10 }, { 7, HELITAKEOFF, 0, 36 },
{ 8, 255, TAXIWAY_BUSY_block, 8 }, { 8, TAKEOFF, TAXIWAY_BUSY_block, 9 }, { 8, HANGAR, TAXIWAY_BUSY_block, 9 }, { 8, TERM1, TERM1_block, 3 }, { 8, 0, TAXIWAY_BUSY_block, 9 },
{ 9, 255, TAXIWAY_BUSY_block, 9 }, { 9, TAKEOFF, TAXIWAY_BUSY_block, 10 }, { 9, HANGAR, TAXIWAY_BUSY_block, 10 }, { 9, TERM2, TERM2_block, 4 }, { 9, HELIPAD1, HELIPAD1_block, 6 }, { 9, HELITAKEOFF, HELIPAD1_block, 6 }, { 9, TERM1, TAXIWAY_BUSY_block, 8 }, { 9, 0, TAXIWAY_BUSY_block, 10 },
{ 10, 255, TAXIWAY_BUSY_block, 10 }, { 10, TERM3, TERM3_block, 5 }, { 10, HELIPAD1, 0, 9 }, { 10, HELIPAD2, HELIPAD2_block, 7 }, { 10, HELITAKEOFF, HELIPAD2_block, 7 }, { 10, TAKEOFF, TAXIWAY_BUSY_block, 1 }, { 10, HANGAR, TAXIWAY_BUSY_block, 1 }, { 10, 0, TAXIWAY_BUSY_block, 9 },
{ 11, 0, OUT_WAY_block, 12 },
// takeoff
{ 12, TAKEOFF, RUNWAY_IN_OUT_block, 13 },
{ 13, 0, RUNWAY_IN_OUT_block, 14 },
{ 14, STARTTAKEOFF, RUNWAY_IN_OUT_block, 15 },
{ 15, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 16, FLYING, NOTHING_block, 21 }, { 16, LANDING, IN_WAY_block, 17 }, { 16, HELILANDING, 0, 25 },
{ 17, LANDING, RUNWAY_IN_OUT_block, 18 },
{ 18, 0, RUNWAY_IN_OUT_block, 19 },
{ 19, 0, RUNWAY_IN_OUT_block, 20 },
{ 20, ENDLANDING, IN_WAY_block, 2 },
// In Air
{ 21, 0, NOTHING_block, 22 },
{ 22, 0, NOTHING_block, 23 },
{ 23, 0, NOTHING_block, 24 },
{ 24, 0, NOTHING_block, 16 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 25, HELILANDING, PRE_HELIPAD_block, 26 },
{ 26, HELIENDLANDING, PRE_HELIPAD_block, 26 }, { 26, HELIPAD1, 0, 27 }, { 26, HELIPAD2, 0, 28 }, { 26, HANGAR, 0, 33 },
{ 27, 0, NOTHING_block, 29 }, //helipad1 approach
{ 28, 0, NOTHING_block, 30 },
// landing
{ 29, 255, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
{ 30, 255, NOTHING_block, 0 }, { 30, HELIPAD2, HELIPAD2_block, 7 },
// Helicopter -- takeoff
{ 31, HELITAKEOFF, NOTHING_block, 0 },
{ 32, HELITAKEOFF, NOTHING_block, 0 },
{ 33, 0, TAXIWAY_BUSY_block, 34 }, // need to go to hangar when waiting in air
{ 34, 0, TAXIWAY_BUSY_block, 1 },
{ 35, 0, HELIPAD1_block, 31 },
{ 36, 0, HELIPAD2_block, 32 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
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
{ 2, TERM1, TERM1_block, 7 }, { 2, TAKEOFF, OUT_WAY_block, 7 }, { 2, 0, 0, 7 },
{ 3, TERM2, TERM2_block, 5 }, { 3, TAKEOFF, OUT_WAY_block, 5 }, { 3, 0, 0, 5 },
{ 4, TERM3, TERM3_block, 5 }, { 4, TAKEOFF, OUT_WAY_block, 5 }, { 4, 0, 0, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, OUT_WAY_block, 8 }, { 7, HELITAKEOFF, 0, 22 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_IN_OUT_block, 10 },
// takeoff
{ 10, TAKEOFF, RUNWAY_IN_OUT_block, 11 },
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 13, FLYING, NOTHING_block, 18 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 23 },
{ 14, LANDING, RUNWAY_IN_OUT_block, 15 },
{ 15, 0, RUNWAY_IN_OUT_block, 16 },
{ 16, 0, RUNWAY_IN_OUT_block, 17 },
{ 17, ENDLANDING, IN_WAY_block, 7 },
// In Air
{ 18, 0, NOTHING_block, 19 },
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 13 },
// helicopter
{ 22, HELITAKEOFF, NOTHING_block, 0 },
{ 23, HELILANDING, IN_WAY_block, 24 },
{ 24, HELIENDLANDING, IN_WAY_block, 17 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
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
{ 2, TERM1, TERM1_block, 7 },
{ 3, TERM2, TERM2_block, 5 },
{ 4, TERM3, TERM3_block, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, 0, 8 }, { 7, HELITAKEOFF, 0, 23 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_OUT_block, 10 },
// takeoff
{ 10, TAKEOFF, RUNWAY_OUT_block, 11 },
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 13, FLYING, NOTHING_block, 19 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 25 },
{ 14, LANDING, RUNWAY_IN_block, 15 },
{ 15, 0, RUNWAY_IN_block, 16 },
{ 16, 255, RUNWAY_IN_block, 0 }, { 16, ENDLANDING, IN_WAY_block, 17 },
{ 17, 255, RUNWAY_OUT_block, 0 }, { 17, ENDLANDING, IN_WAY_block, 18 },
{ 18, ENDLANDING, IN_WAY_block, 7 },
// In Air
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 22 },
{ 22, 0, NOTHING_block, 13 },
// helicopter
{ 23, 0, NOTHING_block, 24 },
{ 24, HELITAKEOFF, NOTHING_block, 0 },
{ 25, HELILANDING, IN_WAY_block, 26 },
{ 26, HELIENDLANDING, IN_WAY_block, 18 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
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 },
{ 2, 255, AIRPORT_ENTRANCE_block, 0 }, { 2, HANGAR, 0, 0 }, { 2, TERM4, 0, 12 }, { 2, TERM5, 0, 12 }, { 2, TERM6, 0, 12 }, { 2, HELIPAD1, 0, 12 }, { 2, HELIPAD2, 0, 12 }, { 2, HELITAKEOFF, 0, 12 }, { 2, 0, 0, 23 },
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, 0, 0, 18 },
{ 4, TERM1, TERM1_block, 23 }, { 4, HANGAR, AIRPORT_ENTRANCE_block, 23 }, { 4, 0, 0, 23 },
{ 5, TERM2, TERM2_block, 24 }, { 5, HANGAR, AIRPORT_ENTRANCE_block, 24 }, { 5, 0, 0, 24 },
{ 6, TERM3, TERM3_block, 25 }, { 6, HANGAR, AIRPORT_ENTRANCE_block, 25 }, { 6, 0, 0, 25 },
{ 7, TERM4, TERM4_block, 16 }, { 7, HANGAR, HANGAR2_AREA_block, 16 }, { 7, 0, 0, 16 },
{ 8, TERM5, TERM5_block, 17 }, { 8, HANGAR, HANGAR2_AREA_block, 17 }, { 8, 0, 0, 17 },
{ 9, TERM6, TERM6_block, 18 }, { 9, HANGAR, HANGAR2_AREA_block, 18 }, { 9, 0, 0, 18 },
{ 10, HELIPAD1, HELIPAD1_block, 10 }, { 10, HANGAR, HANGAR2_AREA_block, 16 }, { 10, HELITAKEOFF, 0, 47 },
{ 11, HELIPAD2, HELIPAD2_block, 11 }, { 11, HANGAR, HANGAR2_AREA_block, 17 }, { 11, HELITAKEOFF, 0, 48 },
{ 12, 0, TERM_GROUP2_ENTER1_block, 13 },
{ 13, 0, TERM_GROUP2_ENTER1_block, 14 },
{ 14, 0, TERM_GROUP2_ENTER2_block, 15 },
{ 15, 0, TERM_GROUP2_ENTER2_block, 16 },
{ 16, 255, TERM_GROUP2_block, 0 }, { 16, TERM4, TERM4_block, 7 }, { 16, HELIPAD1, HELIPAD1_block, 10 }, { 16, HELITAKEOFF, HELIPAD1_block, 10 }, { 16, 0, 0, 17 },
{ 17, 255, TERM_GROUP2_block, 0 }, { 17, TERM5, TERM5_block, 8 }, { 17, TERM4, 0, 16 }, { 17, HELIPAD1, 0, 16 }, { 17, HELIPAD2, HELIPAD2_block, 11 }, { 17, HELITAKEOFF, HELIPAD2_block, 11 }, { 17, 0, 0, 18 },
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM6, TERM6_block, 9 }, { 18, TAKEOFF, 0, 19 }, { 18, HANGAR, HANGAR2_AREA_block, 3 }, { 18, 0, 0, 17 },
{ 19, 0, TERM_GROUP2_EXIT1_block, 20 },
{ 20, 0, TERM_GROUP2_EXIT1_block, 21 },
{ 21, 0, TERM_GROUP2_EXIT2_block, 22 },
{ 22, 0, TERM_GROUP2_EXIT2_block, 26 },
{ 23, 255, TERM_GROUP1_block, 0 }, { 23, TERM1, TERM1_block, 4 }, { 23, HANGAR, AIRPORT_ENTRANCE_block, 2 }, { 23, 0, 0, 24 },
{ 24, 255, TERM_GROUP1_block, 0 }, { 24, TERM2, TERM2_block, 5 }, { 24, TERM1, 0, 23 }, { 24, HANGAR, 0, 23 }, { 24, 0, 0, 25 },
{ 25, 255, TERM_GROUP1_block, 0 }, { 25, TERM3, TERM3_block, 6 }, { 25, TAKEOFF, 0, 26 }, { 25, 0, 0, 24 },
{ 26, 255, TAXIWAY_BUSY_block, 0 }, { 26, TAKEOFF, 0, 27 }, { 26, 0, 0, 25 },
{ 27, 0, OUT_WAY_block, 28 },
// takeoff
{ 28, TAKEOFF, OUT_WAY_block, 29 },
{ 29, 0, RUNWAY_OUT_block, 30 },
{ 30, STARTTAKEOFF, NOTHING_block, 31 },
{ 31, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 32, FLYING, NOTHING_block, 37 }, { 32, LANDING, 0, 33 }, { 32, HELILANDING, 0, 41 },
{ 33, LANDING, RUNWAY_IN_block, 34 },
{ 34, 0, RUNWAY_IN_block, 35 },
{ 35, 0, RUNWAY_IN_block, 36 },
{ 36, ENDLANDING, IN_WAY_block, 36 }, { 36, 255, TERM_GROUP1_block, 0 }, { 36, 255, TERM_GROUP2_ENTER1_block, 1 }, { 36, TERM4, 0, 12 }, { 36, TERM5, 0, 12 }, { 36, TERM6, 0, 12 }, { 36, 0, 0, 2 },
// In Air
{ 37, 0, NOTHING_block, 38 },
{ 38, 0, NOTHING_block, 39 },
{ 39, 0, NOTHING_block, 40 },
{ 40, 0, NOTHING_block, 32 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 41, HELILANDING, PRE_HELIPAD_block, 42 },
{ 42, HELIENDLANDING, PRE_HELIPAD_block, 42 }, { 42, HELIPAD1, 0, 43 }, { 42, HELIPAD2, 0, 44 }, { 42, HANGAR, 0, 49 },
{ 43, 0, NOTHING_block, 45 },
{ 44, 0, NOTHING_block, 46 },
// landing
{ 45, 255, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
{ 46, 255, NOTHING_block, 0 }, { 46, HELIPAD2, HELIPAD2_block, 11 },
// Helicopter -- takeoff
{ 47, HELITAKEOFF, NOTHING_block, 0 },
{ 48, HELITAKEOFF, NOTHING_block, 0 },
{ 49, 0, HANGAR2_AREA_block, 50 }, // need to go to hangar when waiting in air
{ 50, 0, HANGAR2_AREA_block, 3 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// intercontinental
static const TileIndexDiffC _airport_depots_intercontinental[] = { { 0, 5 }, { 8, 4 } };
static const byte _airport_terminal_intercontinental[] = { 2, 4, 4 };
static const byte _airport_helipad_intercontinental[] = { 1, 2 };
static const AirportFTAbuildup _airport_fta_intercontinental[] = {
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 0 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 1 }, { 0, TAKEOFF, HANGAR1_AREA_block | TERM_GROUP1_block, 2 }, { 0, 0, 0, 2 },
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, 255, HANGAR2_AREA_block, 0 }, { 1, 0, 0, 3 },
{ 2, 255, HANGAR1_AREA_block, 0 }, { 2, 255, TERM_GROUP1_block, 0 }, { 2, 255, TERM_GROUP1_block, 1 }, { 2, HANGAR, 0, 0 }, { 2, TAKEOFF, TERM_GROUP1_block, 27 }, { 2, TERM5, 0, 26 }, { 2, TERM6, 0, 26 }, { 2, TERM7, 0, 26 }, { 2, TERM8, 0, 26 }, { 2, HELIPAD1, 0, 26 }, { 2, HELIPAD2, 0, 26 }, { 2, HELITAKEOFF, 0, 74 }, { 2, 0, 0, 27 },
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 75 }, { 3, 0, 0, 20 },
{ 4, TERM1, TERM1_block, 26 }, { 4, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 26 }, { 4, 0, 0, 26 },
{ 5, TERM2, TERM2_block, 27 }, { 5, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 27 }, { 5, 0, 0, 27 },
{ 6, TERM3, TERM3_block, 28 }, { 6, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 28 }, { 6, 0, 0, 28 },
{ 7, TERM4, TERM4_block, 29 }, { 7, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 7, 0, 0, 29 },
{ 8, TERM5, TERM5_block, 18 }, { 8, HANGAR, HANGAR2_AREA_block, 18 }, { 8, 0, 0, 18 },
{ 9, TERM6, TERM6_block, 19 }, { 9, HANGAR, HANGAR2_AREA_block, 19 }, { 9, 0, 0, 19 },
{ 10, TERM7, TERM7_block, 20 }, { 10, HANGAR, HANGAR2_AREA_block, 20 }, { 10, 0, 0, 20 },
{ 11, TERM8, TERM8_block, 21 }, { 11, HANGAR, HANGAR2_AREA_block, 21 }, { 11, 0, 0, 21 },
{ 12, HELIPAD1, HELIPAD1_block, 12 }, { 12, HANGAR, 0, 70 }, { 12, HELITAKEOFF, 0, 72 },
{ 13, HELIPAD2, HELIPAD2_block, 13 }, { 13, HANGAR, 0, 71 }, { 13, HELITAKEOFF, 0, 73 },
{ 14, 0, TERM_GROUP2_ENTER1_block, 15 },
{ 15, 0, TERM_GROUP2_ENTER1_block, 16 },
{ 16, 0, TERM_GROUP2_ENTER2_block, 17 },
{ 17, 0, TERM_GROUP2_ENTER2_block, 18 },
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM5, TERM5_block, 8 }, { 18, TAKEOFF, 0, 19 }, { 18, HELITAKEOFF, HELIPAD1_block, 19 }, { 18, 0, TERM_GROUP2_EXIT1_block, 19 },
{ 19, 255, TERM_GROUP2_block, 0 }, { 19, TERM6, TERM6_block, 9 }, { 19, TERM5, 0, 18 }, { 19, TAKEOFF, 0, 57 }, { 19, HELITAKEOFF, HELIPAD1_block, 20 }, { 19, 0, TERM_GROUP2_EXIT1_block, 20 }, // add exit to runway out 2
{ 20, 255, TERM_GROUP2_block, 0 }, { 20, TERM7, TERM7_block, 10 }, { 20, TERM5, 0, 19 }, { 20, TERM6, 0, 19 }, { 20, HANGAR, HANGAR2_AREA_block, 3 }, { 20, TAKEOFF, 0, 19 }, { 20, 0, TERM_GROUP2_EXIT1_block, 21 },
{ 21, 255, TERM_GROUP2_block, 0 }, { 21, TERM8, TERM8_block, 11 }, { 21, HANGAR, HANGAR2_AREA_block, 20 }, { 21, TERM5, 0, 20 }, { 21, TERM6, 0, 20 }, { 21, TERM7, 0, 20 }, { 21, TAKEOFF, 0, 20 }, { 21, 0, TERM_GROUP2_EXIT1_block, 22 },
{ 22, 255, TERM_GROUP2_block, 0 }, { 22, HANGAR, 0, 21 }, { 22, TERM5, 0, 21 }, { 22, TERM6, 0, 21 }, { 22, TERM7, 0, 21 }, { 22, TERM8, 0, 21 }, { 22, TAKEOFF, 0, 21 }, { 22, 0, 0, 23 },
{ 23, 0, TERM_GROUP2_EXIT1_block, 70 },
{ 24, 0, TERM_GROUP2_EXIT2_block, 25 },
{ 25, 255, TERM_GROUP2_EXIT2_block, 0 }, { 25, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 25, 0, 0, 29 },
{ 26, 255, TERM_GROUP1_block, 0 }, { 26, TERM1, TERM1_block, 4 }, { 26, HANGAR, HANGAR1_AREA_block, 27 }, { 26, TERM5, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM6, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM7, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM8, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD1, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD2, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELITAKEOFF, TERM_GROUP2_ENTER1_block, 14 }, { 26, 0, 0, 27 },
{ 27, 255, TERM_GROUP1_block, 0 }, { 27, TERM2, TERM2_block, 5 }, { 27, HANGAR, HANGAR1_AREA_block, 2 }, { 27, TERM1, 0, 26 }, { 27, TERM5, 0, 26 }, { 27, TERM6, 0, 26 }, { 27, TERM7, 0, 26 }, { 27, TERM8, 0, 26 }, { 27, HELIPAD1, 0, 14 }, { 27, HELIPAD2, 0, 14 }, { 27, 0, 0, 28 },
{ 28, 255, TERM_GROUP1_block, 0 }, { 28, TERM3, TERM3_block, 6 }, { 28, HANGAR, HANGAR1_AREA_block, 27 }, { 28, TERM1, 0, 27 }, { 28, TERM2, 0, 27 }, { 28, TERM4, 0, 29 }, { 28, TERM5, 0, 14 }, { 28, TERM6, 0, 14 }, { 28, TERM7, 0, 14 }, { 28, TERM8, 0, 14 }, { 28, HELIPAD1, 0, 14 }, { 28, HELIPAD2, 0, 14 }, { 28, 0, 0, 29 },
{ 29, 255, TERM_GROUP1_block, 0 }, { 29, TERM4, TERM4_block, 7 }, { 29, HANGAR, HANGAR1_AREA_block, 27 }, { 29, TAKEOFF, 0, 30 }, { 29, 0, 0, 28 },
{ 30, 0, OUT_WAY_block2, 31 },
{ 31, 0, OUT_WAY_block, 32 },
// takeoff
{ 32, TAKEOFF, RUNWAY_OUT_block, 33 },
{ 33, 0, RUNWAY_OUT_block, 34 },
{ 34, STARTTAKEOFF, NOTHING_block, 35 },
{ 35, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 36, 0, 0, 0 },
{ 37, LANDING, RUNWAY_IN_block, 38 },
{ 38, 0, RUNWAY_IN_block, 39 },
{ 39, 0, RUNWAY_IN_block, 40 },
{ 40, ENDLANDING, RUNWAY_IN_block, 41 },
{ 41, 0, IN_WAY_block, 42 },
{ 42, 255, IN_WAY_block, 0 }, { 42, 255, TERM_GROUP1_block, 0 }, { 42, 255, TERM_GROUP1_block, 1 }, { 42, HANGAR, 0, 2 }, { 42, 0, 0, 26 },
// In Air
{ 43, 0, 0, 44 },
{ 44, FLYING, 0, 45 }, { 44, HELILANDING, 0, 47 }, { 44, LANDING, 0, 69 }, { 44, 0, 0, 45 },
{ 45, 0, 0, 46 },
{ 46, FLYING, 0, 43 }, { 46, LANDING, 0, 76 }, { 46, 0, 0, 43 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 47, HELILANDING, PRE_HELIPAD_block, 48 },
{ 48, HELIENDLANDING, PRE_HELIPAD_block, 48 }, { 48, HELIPAD1, 0, 49 }, { 48, HELIPAD2, 0, 50 }, { 48, HANGAR, 0, 55 },
{ 49, 0, NOTHING_block, 51 },
{ 50, 0, NOTHING_block, 52 },
// landing
{ 51, 255, NOTHING_block, 0 }, { 51, HELIPAD1, HELIPAD1_block, 12 }, { 51, HANGAR, 0, 55 }, { 51, 0, 0, 12 },
{ 52, 255, NOTHING_block, 0 }, { 52, HELIPAD2, HELIPAD2_block, 13 }, { 52, HANGAR, 0, 55 }, { 52, 0, 0, 13 },
// Helicopter -- takeoff
{ 53, HELITAKEOFF, NOTHING_block, 0 },
{ 54, HELITAKEOFF, NOTHING_block, 0 },
{ 55, 0, HANGAR2_AREA_block, 56 }, // need to go to hangar when waiting in air
{ 56, 0, HANGAR2_AREA_block, 3 },
// runway 2 out support
{ 57, 255, OUT_WAY2_block, 0 }, { 57, TAKEOFF, 0, 58 }, { 57, 0, 0, 58 },
{ 58, 0, OUT_WAY2_block, 59 },
{ 59, TAKEOFF, RUNWAY_OUT2_block, 60 }, // takeoff
{ 60, 0, RUNWAY_OUT2_block, 61 },
{ 61, STARTTAKEOFF, NOTHING_block, 62 },
{ 62, ENDTAKEOFF, NOTHING_block, 0 },
// runway 2 in support
{ 63, LANDING, RUNWAY_IN2_block, 64 },
{ 64, 0, RUNWAY_IN2_block, 65 },
{ 65, 0, RUNWAY_IN2_block, 66 },
{ 66, ENDLANDING, RUNWAY_IN2_block, 0 }, { 66, 255, 0, 1 }, { 66, 255, 0, 0 }, { 66, 0, 0, 67 },
{ 67, 0, IN_WAY2_block, 68 },
{ 68, 255, IN_WAY2_block, 0 }, { 68, 255, TERM_GROUP2_block, 1 }, { 68, 255, TERM_GROUP1_block, 0 }, { 68, HANGAR, HANGAR2_AREA_block, 22 }, { 68, 0, 0, 22 },
{ 69, 255, RUNWAY_IN2_block, 0 }, { 69, 0, RUNWAY_IN2_block, 63 },
{ 70, 255, TERM_GROUP2_EXIT1_block, 0 }, { 70, HELIPAD1, HELIPAD1_block, 12 }, { 70, HELITAKEOFF, HELIPAD1_block, 12 }, { 70, 0, 0, 71 },
{ 71, 255, TERM_GROUP2_EXIT1_block, 0 }, { 71, HELIPAD2, HELIPAD2_block, 13 }, { 71, HELITAKEOFF, HELIPAD1_block, 12 }, { 71, 0, 0, 24 },
{ 72, 0, HELIPAD1_block, 53 },
{ 73, 0, HELIPAD2_block, 54 },
{ 74, HELITAKEOFF, NOTHING_block, 0 },
{ 75, HELITAKEOFF, NOTHING_block, 0 },
{ 76, 255, RUNWAY_IN_block, 0 }, { 76, 0, RUNWAY_IN_block, 37 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// 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
{ 2, 255, AIRPORT_BUSY_block, 0 }, { 2, HELILANDING, 0, 3 }, { 2, HELITAKEOFF, 0, 1 },
{ 3, HELILANDING, AIRPORT_BUSY_block, 4 },
{ 4, HELIENDLANDING, AIRPORT_BUSY_block, 4 }, { 4, HELIPAD1, HELIPAD1_block, 0 }, { 4, HELITAKEOFF, 0, 2 },
// In Air
{ 5, 0, NOTHING_block, 6 },
{ 6, 0, NOTHING_block, 7 },
{ 7, 0, NOTHING_block, 8 },
{ 8, FLYING, NOTHING_block, 5 }, { 8, HELILANDING, HELIPAD1_block, 2 }, // landing
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// helidepots
static const TileIndexDiffC _airport_depots_helidepot[] = { { 1, 0 } };
static const byte _airport_helipad_helidepot[] = { 1, 1 };
static const AirportFTAbuildup _airport_fta_helidepot[] = {
{ 0, HANGAR, NOTHING_block, 1 },
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELIPAD1, HELIPAD1_block, 14 }, { 1, HELITAKEOFF, 0, 15 }, { 1, 0, 0, 0 },
{ 2, FLYING, NOTHING_block, 3 }, { 2, HELILANDING, PRE_HELIPAD_block, 7 }, { 2, HANGAR, 0, 12 }, { 2, HELITAKEOFF, NOTHING_block, 16 },
// In Air
{ 3, 0, NOTHING_block, 4 },
{ 4, 0, NOTHING_block, 5 },
{ 5, 0, NOTHING_block, 6 },
{ 6, 0, NOTHING_block, 2 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 7, HELILANDING, PRE_HELIPAD_block, 8 },
{ 8, HELIENDLANDING, PRE_HELIPAD_block, 8 }, { 8, HELIPAD1, 0, 9 }, { 8, HANGAR, 0, 12 }, { 8, 0, 0, 2 },
{ 9, 0, NOTHING_block, 10 },
// landing
{ 10, 255, NOTHING_block, 10 }, { 10, HELIPAD1, HELIPAD1_block, 14 }, { 10, HANGAR, 0, 1 }, { 10, 0, 0, 14 },
// Helicopter -- takeoff
{ 11, HELITAKEOFF, NOTHING_block, 0 },
{ 12, 0, HANGAR2_AREA_block, 13 }, // need to go to hangar when waiting in air
{ 13, 0, HANGAR2_AREA_block, 1 },
{ 14, HELIPAD1, HELIPAD1_block, 14 }, { 14, HANGAR, 0, 1 }, { 14, HELITAKEOFF, 0, 17 },
{ 15, HELITAKEOFF, NOTHING_block, 0 }, // takeoff outside depot
{ 16, HELITAKEOFF, 0, 14 },
{ 17, 0, NOTHING_block, 11 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// helistation
static const TileIndexDiffC _airport_depots_helistation[] = { { 0, 0 } };
static const byte _airport_helipad_helistation[] = { 1, 3 };
static const AirportFTAbuildup _airport_fta_helistation[] = {
{ 0, HANGAR, NOTHING_block, 8 }, { 0, HELIPAD1, 0, 1 }, { 0, HELIPAD2, 0, 1 }, { 0, HELIPAD3, 0, 1 }, { 0, HELITAKEOFF, 0, 1 }, { 0, 0, 0, 0 },
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELITAKEOFF, 0, 3 }, { 1, 0, 0, 4 },
// landing
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, 0, 0, 28 },
// helicopter side
{ 3, HELITAKEOFF, NOTHING_block, 0 }, // helitakeoff outside hangar2
{ 4, 255, TAXIWAY_BUSY_block, 0 }, { 4, HANGAR, HANGAR2_AREA_block, 1 }, { 4, HELITAKEOFF, 0, 1 }, { 4, 0, 0, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, HELIPAD1, HELIPAD1_block, 6 }, { 5, HELIPAD2, HELIPAD2_block, 7 }, { 5, HELIPAD3, HELIPAD3_block, 8 }, { 5, 0, 0, 4 },
{ 6, HELIPAD1, HELIPAD1_block, 5 }, { 6, HANGAR, HANGAR2_AREA_block, 5 }, { 6, HELITAKEOFF, 0, 9 }, { 6, 0, 0, 6 },
{ 7, HELIPAD2, HELIPAD2_block, 5 }, { 7, HANGAR, HANGAR2_AREA_block, 5 }, { 7, HELITAKEOFF, 0, 10 }, { 7, 0, 0, 7 },
{ 8, HELIPAD3, HELIPAD3_block, 5 }, { 8, HANGAR, HANGAR2_AREA_block, 5 }, { 8, HELITAKEOFF, 0, 11 }, { 8, 0, 0, 8 },
{ 9, 0, HELIPAD1_block, 12 },
{ 10, 0, HELIPAD2_block, 13 },
{ 11, 0, HELIPAD3_block, 14 },
{ 12, HELITAKEOFF, NOTHING_block, 0 },
{ 13, HELITAKEOFF, NOTHING_block, 0 },
{ 14, HELITAKEOFF, NOTHING_block, 0 },
// heli - in flight moves
{ 15, HELILANDING, PRE_HELIPAD_block, 16 },
{ 16, HELIENDLANDING, PRE_HELIPAD_block, 16 }, { 16, HELIPAD1, 0, 17 }, { 16, HELIPAD2, 0, 18 }, { 16, HELIPAD3, 0, 19 }, { 16, HANGAR, 0, 23 },
{ 17, 0, NOTHING_block, 20 },
{ 18, 0, NOTHING_block, 21 },
{ 19, 0, NOTHING_block, 22 },
// heli landing
{ 20, 255, NOTHING_block, 0 }, { 20, HELIPAD1, HELIPAD1_block, 6 }, { 20, HANGAR, 0, 23 }, { 20, 0, 0, 6 },
{ 21, 255, NOTHING_block, 0 }, { 21, HELIPAD2, HELIPAD2_block, 7 }, { 21, HANGAR, 0, 23 }, { 21, 0, 0, 7 },
{ 22, 255, NOTHING_block, 0 }, { 22, HELIPAD3, HELIPAD3_block, 8 }, { 22, HANGAR, 0, 23 }, { 22, 0, 0, 8 },
{ 23, 0, HANGAR2_AREA_block, 24 }, // need to go to helihangar when waiting in air
{ 24, 0, HANGAR2_AREA_block, 1 },
{ 25, 0, NOTHING_block, 26 },
{ 26, 0, NOTHING_block, 27 },
{ 27, 0, NOTHING_block, 2 },
{ 28, 0, NOTHING_block, 29 },
{ 29, 0, NOTHING_block, 30 },
{ 30, 0, NOTHING_block, 31 },
{ 31, 0, NOTHING_block, 32 },
{ 32, 0, NOTHING_block, 25 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
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
_airport_moving_data_commuter, // Commuter Airfield (small) 5x4
_airport_moving_data_helidepot, // Helidepot
_airport_moving_data_intercontinental, // Intercontinental Airport (xxlarge) - 4 runways
_airport_moving_data_helistation, // Helistation
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
_airport_moving_data_oilrig // Oilrig
};
#endif /* AIRPORT_MOVEMENT_H */

View File

@@ -1,7 +1,5 @@
/* $Id$ */
/** @file aystar.cpp Implementation of A*. */
/*
* This file has the core function for AyStar
* AyStar is a fast pathfinding routine and is used for things like
@@ -19,15 +17,15 @@
*/
#include "stdafx.h"
#include "openttd.h"
#include "aystar.h"
#include "core/alloc_func.hpp"
int _aystar_stats_open_size;
int _aystar_stats_closed_size;
// This looks in the Hash if a node exists in ClosedList
// If so, it returns the PathNode, else NULL
static PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
static PathNode* AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
{
return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
}
@@ -37,7 +35,7 @@ static PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode
static void AyStarMain_ClosedList_Add(AyStar *aystar, const PathNode *node)
{
// Add a node to the ClosedList
PathNode *new_node = MallocT<PathNode>(1);
PathNode *new_node = malloc(sizeof(*new_node));
*new_node = *node;
Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
}
@@ -68,7 +66,7 @@ static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, const AyStarNode *node, int f, int g)
{
// Add a new Node to the OpenList
OpenListNode *new_node = MallocT<OpenListNode>(1);
OpenListNode *new_node = malloc(sizeof(*new_node));
new_node->g = g;
new_node->path.parent = parent;
new_node->path.node = *node;

View File

@@ -1,6 +1,6 @@
/* $Id$ */
/** @file aystar.h
/*
* This file has the header for AyStar
* AyStar is a fast pathfinding routine and is used for things like
* AI_pathfinding and Train_pathfinding.
@@ -12,8 +12,6 @@
#define AYSTAR_H
#include "queue.h"
#include "tile_type.h"
#include "track_type.h"
//#define AYSTAR_DEBUG
enum {
@@ -29,13 +27,15 @@ enum{
AYSTAR_INVALID_NODE = -1,
};
typedef struct AyStarNode AyStarNode;
struct AyStarNode {
TileIndex tile;
Trackdir direction;
uint direction;
uint user_data[2];
};
// The resulting path has nodes looking like this.
typedef struct PathNode PathNode;
struct PathNode {
AyStarNode node;
// The parent of this item
@@ -45,12 +45,13 @@ struct PathNode {
// For internal use only
// We do not save the h-value, because it is only needed to calculate the f-value.
// h-value should _always_ be the distance left to the end-tile.
typedef struct OpenListNode OpenListNode;
struct OpenListNode {
int g;
PathNode path;
};
struct AyStar;
typedef struct AyStar AyStar;
/*
* This function is called to check if the end-tile is found
* return values can be:

View File

@@ -1,69 +0,0 @@
#!/bin/sh
# $Id$
if ! [ -f ai/regression/regression.nut ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
cat ai/regression/regression.nut | tr ';' '\n' | awk '
/^function/ {
for (local in locals) {
delete locals[local]
}
if (match($0, "function Regression::Start") || match($0, "function Regression::Stop")) next
locals["this"] = "AIControllerSquirrel"
}
/local/ {
gsub(".*local", "local")
if (match($4, "^AI")) {
sub("\\(.*", "", $4)
locals[$2] = $4
}
}
/Valuate/ {
gsub(".*Valuate\\(", "")
gsub("\\).*", "")
gsub(",.*", "")
gsub("\\.", "::")
print $0
}
/\./ {
for (local in locals) {
if (match($0, local ".")) {
fname = substr($0, index($0, local "."))
sub("\\(.*", "", fname)
sub("\\.", "::", fname)
sub(local, locals[local], fname)
print fname
if (match(locals[local], "List")) {
sub(locals[local], "AIAbstractList", fname)
print fname
}
}
}
# We want to remove everything before the FIRST occurence of AI.
# If we do not remove any other occurences of AI from the string
# we will remove everything before the LAST occurence of AI, so
# do some little magic to make it work the way we want.
sub("AI", "AXXXXY")
gsub("AI", "AXXXXX")
sub(".*AXXXXY", "AI")
if (match($0, "^AI") && match($0, ".")) {
sub("\\(.*", "", $0)
sub("\\.", "::", $0)
print $0
}
}
' | sed 's/ //g' | sort | uniq > tmp.in_regression
grep 'DefSQ.*Method' ../src/ai/api/*.hpp.sq | grep -v 'AIError::' | grep -v 'AIAbstractList::Valuate' | grep -v '::GetClassName' | sed 's/^[^,]*, &//g;s/,[^,]*//g' | sort > tmp.in_api
diff -u tmp.in_regression tmp.in_api | grep -v '^+++' | grep '^+' | sed 's/^+//'
rm -f tmp.in_regression tmp.in_api

View File

@@ -1,17 +0,0 @@
[misc]
display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|WAYPOINTS
language = english.lng
[gui]
autosave = off
[game_creation]
town_name = english
[ai_players]
none =
regression =
[vehicle]
road_side = right
plane_speed = 2

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
/* $Id$ */
class Regression extends AIInfo {
function GetAuthor() { return "OpenTTD NoAI Developers Team"; }
function GetName() { return "Regression"; }
function GetShortName() { return "REGR"; }
function GetDescription() { return "This runs regression-tests on all commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; }
}
RegisterAI(Regression());

View File

@@ -1,4 +0,0 @@
/* $Id$ */
print(" Required this file");

View File

@@ -1,51 +0,0 @@
#!/bin/sh
# $Id$
if ! [ -f ai/regression/regression.nut ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
cp ai/regression/regression.nut ai/regression/main.nut
cp ai/regression/regression_info.nut ai/regression/info.nut
if [ -f scripts/game_start.scr ]; then
mv scripts/game_start.scr scripts/game_start.scr.regression
fi
params=""
gdb=""
if [ "$1" != "-r" ]; then
params="-snull -mnull -vnull:ticks=30000"
fi
if [ "$1" = "-g" ]; then
gdb="gdb --ex run --args "
fi
if [ -n "$gdb" ]; then
$gdb ./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.sav
else
./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.sav -d ai=2 2>&1 | awk '{ gsub("0x(\\(nil\\)|0+)", "0x00000000", $0); gsub("^dbg: \\[ai\\]", "", $0); gsub("^ ", "ERROR: ", $0); gsub("ERROR: \\[1\\] ", "", $0); gsub("\\[P\\] ", "", $0); print $0; }' > tmp.regression
fi
if [ -z "$gdb" ]; then
res="`diff -ub ai/regression/regression.txt tmp.regression`"
if [ -z "$res" ]; then
echo "Regression test passed!"
else
echo "Regression test failed! Difference:"
echo "$res"
fi
echo ""
echo "Regression test done"
fi
rm -f ai/regression/main.nut ai/regression/info.nut
if [ -f scripts/game_start.scr.regression ]; then
mv scripts/game_start.scr.regression scripts/game_start.scr
fi
if [ "$1" != "-k" ]; then
rm -f tmp.regression
fi

Binary file not shown.

Binary file not shown.

View File

@@ -1,31 +0,0 @@
; $Id$
;
; This represents the original graphics as on the non-German Transport
; Tycoon Deluxe DOS CD.
;
[metadata]
name = original_dos
shortname = TTDD
version = 1
description = Original Transport Tycoon Deluxe DOS edition graphics
palette = DOS
[files]
base = TRG1.GRF
logos = TRGI.GRF
arctic = TRGC.GRF
tropical = TRGH.GRF
toyland = TRGT.GRF
extra = OPENTTDD.GRF
[md5s]
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
TRGC.GRF = ed446637e034104c5559b32c18afe78d
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
TRGT.GRF = e30e8a398ae86c03dc534a8ac7dfb3b6
OPENTTDD.GRF = c886c7d5b38a93f2cb1cdc0d33472eb8
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTDD.GRF = This file was part of your installation.

View File

@@ -1,31 +0,0 @@
; $Id$
;
; This represents the original graphics as on the German Transport
; Tycoon Deluxe DOS CD. It contains one broken sprite.
;
[metadata]
name = original_dos_de
shortname = TTDD
version = 0
description = Original Transport Tycoon Deluxe DOS (German) edition graphics
palette = DOS
[files]
base = TRG1.GRF
logos = TRGI.GRF
arctic = TRGC.GRF
tropical = TRGH.GRF
toyland = TRGT.GRF
extra = OPENTTDD.GRF
[md5s]
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
TRGC.GRF = ed446637e034104c5559b32c18afe78d
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
OPENTTDD.GRF = c886c7d5b38a93f2cb1cdc0d33472eb8
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTDD.GRF = This file was part of your installation.

View File

@@ -1,31 +0,0 @@
; $Id$
;
; This represents the original graphics as on the Transport
; Tycoon Deluxe for Windows.
;
[metadata]
name = original_windows
shortname = TTDW
version = 0
description = Original Transport Tycoon Deluxe Windows edition graphics
palette = Windows
[files]
base = TRG1R.GRF
logos = TRGIR.GRF
arctic = TRGCR.GRF
tropical = TRGHR.GRF
toyland = TRGTR.GRF
extra = OPENTTDW.GRF
[md5s]
TRG1R.GRF = b04ce593d8c5016e07473a743d7d3358
TRGIR.GRF = 0c2484ff6be49fc63a83be6ab5c38f32
TRGCR.GRF = 3668f410c761a050b5e7095a2b14879b
TRGHR.GRF = 06bf2b7a31766f048baac2ebe43457b1
TRGTR.GRF = de53650517fe661ceaa3138c6edb0eb8
OPENTTDW.GRF = b6689105405fa3ea34cb8a5543633d29
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTDW.GRF = This file was part of your installation.

View File

@@ -1,2 +0,0 @@
start_ai MyAI

View File

@@ -1,2 +0,0 @@
# Show a MOTD
say "Welcome..."

View File

@@ -1,14 +1,12 @@
/* $Id$ */
/** @file bmp.cpp Read and write support for bmps. */
#include "stdafx.h"
#include "openttd.h"
#include "gfx.h"
#include "bmp.h"
#include "core/bitmath_func.hpp"
#include "core/alloc_func.hpp"
#include "macros.h"
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
{
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file) {
buffer->pos = -1;
buffer->file = file;
buffer->read = 0;
@@ -322,15 +320,15 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
if (info->bpp <= 8) {
uint i;
/* Reads number of colours if available in info header */
/* Reads number of colors if available in info header */
if (header_size >= 16) {
SkipBytes(buffer, 12); // skip image size and resolution
info->palette_size = ReadDword(buffer); // number of colours in palette
info->palette_size = ReadDword(buffer); // number of colors in palette
SkipBytes(buffer, header_size - 16); // skip the end of info header
}
if (info->palette_size == 0) info->palette_size = 1 << info->bpp;
data->palette = CallocT<Colour>(info->palette_size);
data->palette = calloc(info->palette_size, sizeof(*(data->palette)));
if (data->palette == NULL) return false;
for (i = 0; i < info->palette_size; i++) {
@@ -352,7 +350,7 @@ bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
assert(info != NULL && data != NULL);
data->bitmap = CallocT<byte>(info->width * info->height * ((info->bpp == 24) ? 3 : 1));
data->bitmap = calloc(info->width * info->height, ((info->bpp == 24) ? 3 : 1) * sizeof(byte));
if (data->bitmap == NULL) return false;
/* Load image */

View File

@@ -1,36 +1,32 @@
/* $Id$ */
/** @file bmp.h Read and write support for bmps. */
#ifndef BMP_H
#define BMP_H
#include "gfx_type.h"
struct BmpInfo {
typedef struct {
uint32 offset; ///< offset of bitmap data from .bmp file begining
uint32 width; ///< bitmap width
uint32 height; ///< bitmap height
bool os2_bmp; ///< true if OS/2 1.x or windows 2.x bitmap
uint16 bpp; ///< bits per pixel
uint32 compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
uint32 palette_size; ///< number of colours in palette
};
uint32 palette_size; ///< number of colors in palette
} BmpInfo;
struct BmpData {
typedef struct {
Colour *palette;
byte *bitmap;
};
} BmpData;
#define BMP_BUFFER_SIZE 1024
struct BmpBuffer {
typedef struct {
byte data[BMP_BUFFER_SIZE];
int pos;
int read;
FILE *file;
uint real_pos;
};
} BmpBuffer;
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file);
bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data);

32
bridge.h Normal file
View File

@@ -0,0 +1,32 @@
/* $Id$ */
/** @file bridge.h Header file for bridges */
#ifndef BRIDGE_H
#define BRIDGE_H
enum {
MAX_BRIDGES = 13
};
/** Struct containing information about a single bridge type
*/
typedef struct Bridge {
Year avail_year; ///< the year in which the bridge becomes available
byte min_length; ///< the minimum length of the bridge (not counting start and end tile)
byte max_length; ///< the maximum length of the bridge (not counting start and end tile)
uint16 price; ///< the relative price of the bridge
uint16 speed; ///< maximum travel speed
PalSpriteID sprite; ///< the sprite which is used in the GUI (possibly with a recolor sprite)
StringID material; ///< the string that contains the bridge description
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
byte flags; ///< bit 0 set: disable drawing of far pillars.
} Bridge;
extern const Bridge orig_bridge[MAX_BRIDGES];
extern Bridge _bridge[MAX_BRIDGES];
uint GetBridgeFoundation(Slope tileh, Axis axis);
uint GetBridgeHeightRamp(TileIndex t);
#endif /* BRIDGE_H */

167
bridge_gui.c Normal file
View File

@@ -0,0 +1,167 @@
/* $Id$ */
/** @file bridge_gui.c Graphical user interface for bridge construction*/
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "viewport.h"
#include "gfx.h"
#include "command.h"
#include "sound.h"
#include "variables.h"
#include "bridge.h"
static struct BridgeData {
uint count;
TileIndex start_tile;
TileIndex end_tile;
byte type;
byte indexes[MAX_BRIDGES];
int32 costs[MAX_BRIDGES];
} _bridgedata;
void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
}
static void BuildBridge(Window *w, int i)
{
DeleteWindow(w);
DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
_bridgedata.indexes[i] | (_bridgedata.type << 8), CcBuildBridge,
CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
}
static void BuildBridgeWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
uint i;
DrawWindowWidgets(w);
for (i = 0; i < 4 && i + w->vscroll.pos < _bridgedata.count; i++) {
const Bridge *b = &_bridge[_bridgedata.indexes[i + w->vscroll.pos]];
SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
SetDParam(1, b->speed);
SetDParam(0, b->material);
DrawSprite(b->sprite, 3, 15 + i * 22);
DrawString(44, 15 + i * 22 , STR_500D, 0);
}
} break;
case WE_KEYPRESS: {
uint i = e->we.keypress.keycode - '1';
if (i < 9 && i < _bridgedata.count) {
e->we.keypress.cont = false;
BuildBridge(w, i);
}
break;
}
case WE_CLICK:
if (e->we.click.widget == 2) {
uint ind = ((int)e->we.click.pt.y - 14) / 22;
if (ind < 4 && (ind += w->vscroll.pos) < _bridgedata.count)
BuildBridge(w, ind);
}
break;
}
}
static const Widget _build_bridge_widgets[] = {
{ 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},
};
static const WindowDesc _build_bridge_desc = {
WDP_AUTO, WDP_AUTO, 200, 102,
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_bridge_widgets,
BuildBridgeWndProc
};
static const Widget _build_road_bridge_widgets[] = {
{ 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},
};
static const WindowDesc _build_road_bridge_desc = {
WDP_AUTO, WDP_AUTO, 200, 102,
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_road_bridge_widgets,
BuildBridgeWndProc
};
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, byte bridge_type)
{
uint j = 0;
int32 ret;
StringID errmsg;
DeleteWindowById(WC_BUILD_BRIDGE, 0);
_bridgedata.type = bridge_type;
_bridgedata.start_tile = start;
_bridgedata.end_tile = end;
errmsg = INVALID_STRING_ID;
// only query bridge building possibility once, result is the same for all bridges!
// returns CMD_ERROR on failure, and price on success
ret = DoCommand(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
if (CmdFailed(ret)) {
errmsg = _error_message;
} else {
// check which bridges can be built
int bridge_len; // length of the middle parts of the bridge
int tot_bridgedata_len; // total length of bridge
// get absolute bridge length
bridge_len = GetBridgeLength(start, end);
tot_bridgedata_len = bridge_len + 2;
tot_bridgedata_len = CalcBridgeLenCostFactor(tot_bridgedata_len);
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
const Bridge *b = &_bridge[bridge_type];
// bridge is accepted, add to list
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
_bridgedata.costs[j] = ret + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
_bridgedata.indexes[j] = bridge_type;
j++;
}
}
}
_bridgedata.count = j;
if (j != 0) {
Window *w = AllocateWindowDesc((_bridgedata.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
w->vscroll.cap = 4;
w->vscroll.count = (byte)j;
} else {
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
}
}

37
bridge_map.c Normal file
View File

@@ -0,0 +1,37 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "bridge_map.h"
TileIndex GetBridgeEnd(TileIndex tile, DiagDirection dir)
{
TileIndexDiff delta = TileOffsByDiagDir(dir);
assert(DiagDirToAxis(dir) == GetBridgeAxis(tile));
do {
tile += delta;
} while (!IsBridgeRamp(tile));
return tile;
}
TileIndex GetSouthernBridgeEnd(TileIndex t)
{
return GetBridgeEnd(t, AxisToDiagDir(GetBridgeAxis(t)));
}
TileIndex GetOtherBridgeEnd(TileIndex tile)
{
TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
do {
tile += delta;
} while (!IsBridgeRamp(tile));
return tile;
}

235
bridge_map.h Normal file
View File

@@ -0,0 +1,235 @@
/* $Id$ */
#ifndef BRIDGE_MAP_H
#define BRIDGE_MAP_H
#include "direction.h"
#include "macros.h"
#include "map.h"
#include "rail.h"
#include "road_map.h"
#include "tile.h"
static inline bool IsBridge(TileIndex t)
{
assert(IsTileType(t, MP_TUNNELBRIDGE));
return HASBIT(_m[t].m5, 7);
}
static inline bool IsBridgeTile(TileIndex t)
{
return IsTileType(t, MP_TUNNELBRIDGE) && IsBridge(t);
}
static inline bool IsBridgeRamp(TileIndex t)
{
assert(IsBridgeTile(t));
return !HASBIT(_m[t].m5, 6);
}
static inline bool IsBridgeMiddle(TileIndex t)
{
assert(IsBridgeTile(t));
return HASBIT(_m[t].m5, 6);
}
/**
* Determines which piece of a bridge is contained in the current tile
* @param tile The tile to analyze
* @return the piece
*/
static inline uint GetBridgePiece(TileIndex t)
{
assert(IsBridgeMiddle(t));
return GB(_m[t].m2, 0, 4);
}
/**
* Determines the type of bridge on a tile
* @param tile The tile to analyze
* @return The bridge type
*/
static inline uint GetBridgeType(TileIndex t)
{
assert(IsBridgeTile(t));
return GB(_m[t].m2, 4, 4);
}
/**
* Get the direction pointing onto the bridge
*/
static inline DiagDirection GetBridgeRampDirection(TileIndex t)
{
assert(IsBridgeRamp(t));
return ReverseDiagDir(XYNSToDiagDir((Axis)GB(_m[t].m5, 0, 1), GB(_m[t].m5, 5, 1)));
}
static inline Axis GetBridgeAxis(TileIndex t)
{
assert(IsBridgeMiddle(t));
return (Axis)GB(_m[t].m5, 0, 1);
}
static inline TransportType GetBridgeTransportType(TileIndex t)
{
assert(IsBridgeTile(t));
return (TransportType)GB(_m[t].m5, 1, 2);
}
static inline bool IsClearUnderBridge(TileIndex t)
{
assert(IsBridgeMiddle(t));
return GB(_m[t].m5, 3, 3) == 0;
}
static inline bool IsWaterUnderBridge(TileIndex t)
{
assert(IsBridgeMiddle(t));
return GB(_m[t].m5, 3, 3) == 1;
}
static inline bool IsTransportUnderBridge(TileIndex t)
{
assert(IsBridgeMiddle(t));
return HASBIT(_m[t].m5, 5);
}
static inline TransportType GetTransportTypeUnderBridge(TileIndex t)
{
assert(IsTransportUnderBridge(t));
return (TransportType)GB(_m[t].m5, 3, 2);
}
static inline RoadBits GetRoadBitsUnderBridge(TileIndex t)
{
assert(GetTransportTypeUnderBridge(t) == TRANSPORT_ROAD);
return GetBridgeAxis(t) == AXIS_X ? ROAD_Y : ROAD_X;
}
static inline Track GetRailUnderBridge(TileIndex t)
{
assert(GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL);
return AxisToTrack(OtherAxis(GetBridgeAxis(t)));
}
static inline TrackBits GetRailBitsUnderBridge(TileIndex t)
{
return TrackToTrackBits(GetRailUnderBridge(t));
}
/**
* Finds the end of a bridge in the specified direction starting at a middle tile
*/
TileIndex GetBridgeEnd(TileIndex, DiagDirection);
/**
* Finds the southern end of a bridge starting at a middle tile
*/
TileIndex GetSouthernBridgeEnd(TileIndex t);
/**
* Starting at one bridge end finds the other bridge end
*/
TileIndex GetOtherBridgeEnd(TileIndex);
uint GetBridgeHeight(TileIndex t);
static inline void SetClearUnderBridge(TileIndex t)
{
assert(IsBridgeMiddle(t));
SetTileOwner(t, OWNER_NONE);
SB(_m[t].m5, 3, 3, 0 << 2 | 0);
SB(_m[t].m3, 0, 4, 0);
}
static inline void SetWaterUnderBridge(TileIndex t)
{
assert(IsBridgeMiddle(t));
SetTileOwner(t, OWNER_WATER);
SB(_m[t].m5, 3, 3, 0 << 2 | 1);
SB(_m[t].m3, 0, 4, 0);
}
static inline void SetCanalUnderBridge(TileIndex t, Owner o)
{
assert(IsBridgeMiddle(t));
SetTileOwner(t, o);
SB(_m[t].m5, 3, 3, 0 << 2 | 1);
SB(_m[t].m3, 0, 4, 0);
}
static inline void SetRailUnderBridge(TileIndex t, Owner o, RailType r)
{
assert(IsBridgeMiddle(t));
SetTileOwner(t, o);
SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_RAIL);
SB(_m[t].m3, 0, 4, r);
}
static inline void SetRoadUnderBridge(TileIndex t, Owner o)
{
assert(IsBridgeMiddle(t));
SetTileOwner(t, o);
SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_ROAD);
SB(_m[t].m3, 0, 4, 0);
}
static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt)
{
uint northsouth = (d == DIAGDIR_NE || d == DIAGDIR_NW);
SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, o);
_m[t].m2 = bridgetype << 4;
_m[t].m4 = 0;
_m[t].m5 = 1 << 7 | 0 << 6 | northsouth << 5 | tt << 1 | DiagDirToAxis(d);
}
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d)
{
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD);
_m[t].m3 = 0;
}
static inline void MakeRailBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RailType r)
{
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL);
_m[t].m3 = r;
}
static inline void MakeBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, TransportType tt)
{
SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, OWNER_NONE);
_m[t].m2 = bridgetype << 4 | piece;
_m[t].m3 = 0;
_m[t].m4 = 0;
_m[t].m5 = 1 << 7 | 1 << 6 | 0 << 5 | 0 << 3 | tt << 1 | a;
}
static inline void MakeRoadBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a)
{
MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_ROAD);
}
static inline void MakeRailBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, RailType r)
{
MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_RAIL);
SB(_m[t].m3, 4, 4, r);
}
#endif /* BRIDGE_MAP_H */

492
build_vehicle_gui.c Normal file
View File

@@ -0,0 +1,492 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "aircraft.h"
#include "debug.h"
#include "functions.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "window.h"
#include "gui.h"
#include "vehicle.h"
#include "gfx.h"
#include "station.h"
#include "command.h"
#include "engine.h"
#include "player.h"
#include "depot.h"
#include "airport.h"
#include "vehicle_gui.h"
#include "newgrf_engine.h"
#include "date.h"
#include "strings.h"
enum BuildVehicleWidgets {
BUILD_VEHICLE_WIDGET_CLOSEBOX = 0,
BUILD_VEHICLE_WIDGET_CAPTION,
BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING,
BUILD_VEHICLE_WIDGET_SORT_TEXT,
BUILD_VEHICLE_WIDGET_SORT_DROPDOWN,
BUILD_VEHICLE_WIDGET_LIST,
BUILD_VEHICLE_WIDGET_SCROLLBAR,
BUILD_VEHICLE_WIDGET_PANEL,
BUILD_VEHICLE_WIDGET_BUILD,
BUILD_VEHICLE_WIDGET_RENAME,
BUILD_VEHICLE_WIDGET_RESIZE,
};
static const Widget _build_vehicle_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 239, 0, 13, STR_A005_NEW_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP},
{ WWT_PANEL, RESIZE_NONE, 14, 81, 227, 14, 25, 0x0, STR_SORT_CRITERIA_TIP},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 228, 239, 14, 25, STR_0225, STR_SORT_CRITERIA_TIP},
{ WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 227, 26, 121, 0x401, STR_A025_AIRCRAFT_SELECTION_LIST },
{ WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 228, 239, 26, 121, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST },
{ WWT_PANEL, RESIZE_TB, 14, 0, 239, 122, 213, 0x0, STR_NULL },
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 114, 214, 225, STR_A006_BUILD_AIRCRAFT, STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT },
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 115, 227, 214, 225, STR_A037_RENAME, STR_A038_RENAME_AIRCRAFT_TYPE },
{ WWT_RESIZEBOX, RESIZE_TB, 14, 228, 239, 214, 225, 0x0, STR_RESIZE_BUTTON },
{ WIDGETS_END},
};
static bool _internal_sort_order; // descending/ascending
static byte _last_sort_criteria = 0;
static bool _last_sort_order = false;
static int CDECL EngineNumberSorter(const void *a, const void *b)
{
const EngineID va = *(const EngineID*)a;
const EngineID vb = *(const EngineID*)b;
int r = va - vb;
return _internal_sort_order ? -r : r;
}
static int CDECL EngineIntroDateSorter(const void *a, const void *b)
{
const int va = GetEngine(*(const EngineID*)a)->intro_date;
const int vb = GetEngine(*(const EngineID*)b)->intro_date;
const int r = va - vb;
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
static int CDECL EngineNameSorter(const void *a, const void *b)
{
static EngineID last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE };
static char last_name[2][64] = { "\0", "\0" };
const EngineID va = *(const EngineID*)a;
const EngineID vb = *(const EngineID*)b;
int r;
if (va != last_engine[0]) {
last_engine[0] = va;
GetString(last_name[0], GetCustomEngineName(va), lastof(last_name[0]));
}
if (vb != last_engine[1]) {
last_engine[1] = vb;
GetString(last_name[1], GetCustomEngineName(vb), lastof(last_name[1]));
}
r = strcmp(last_name[0], last_name[1]); // sort by name
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
static int CDECL EngineReliabilitySorter(const void *a, const void *b)
{
const int va = GetEngine(*(const EngineID*)a)->reliability;
const int vb = GetEngine(*(const EngineID*)b)->reliability;
const int r = va - vb;
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
/* Aircraft sorting functions */
static int CDECL AircraftEngineCostSorter(const void *a, const void *b)
{
const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost;
const int vb = AircraftVehInfo(*(const EngineID*)b)->base_cost;
int r = va - vb;
return _internal_sort_order ? -r : r;
}
static int CDECL AircraftEngineSpeedSorter(const void *a, const void *b)
{
const int va = AircraftVehInfo(*(const EngineID*)a)->max_speed;
const int vb = AircraftVehInfo(*(const EngineID*)b)->max_speed;
const int r = va - vb;
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
static int CDECL AircraftEngineRunningCostSorter(const void *a, const void *b)
{
const int va = AircraftVehInfo(*(const EngineID*)a)->running_cost;
const int vb = AircraftVehInfo(*(const EngineID*)b)->running_cost;
const int r = va - vb;
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
static int CDECL AircraftEngineCargoSorter(const void *a, const void *b)
{
const int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity;
const int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity;
const int r = va - vb;
if (r == 0) {
/* Use EngineID to sort instead since we want consistent sorting */
return EngineNumberSorter(a, b);
}
return _internal_sort_order ? -r : r;
}
static EngList_SortTypeFunction * const _aircraft_sorter[] = {
&EngineNumberSorter,
&AircraftEngineCostSorter,
&AircraftEngineSpeedSorter,
&EngineIntroDateSorter,
&EngineNameSorter,
&AircraftEngineRunningCostSorter,
&EngineReliabilitySorter,
&AircraftEngineCargoSorter,
};
static const StringID _aircraft_sort_listing[] = {
STR_ENGINE_SORT_ENGINE_ID,
STR_ENGINE_SORT_COST,
STR_SORT_BY_MAX_SPEED,
STR_ENGINE_SORT_INTRO_DATE,
STR_SORT_BY_DROPDOWN_NAME,
STR_ENGINE_SORT_RUNNING_COST,
STR_SORT_BY_RELIABILITY,
STR_ENGINE_SORT_CARGO_CAPACITY,
INVALID_STRING_ID
};
/**
* Draw the purchase info details of an aircraft at a given location.
* @param x,y location where to draw the info
* @param engine_number the engine of which to draw the info of
*/
void DrawAircraftPurchaseInfo(int x, int y, uint w, EngineID engine_number)
{
const AircraftVehicleInfo *avi = AircraftVehInfo(engine_number);
const Engine *e = GetEngine(engine_number);
CargoID cargo;
YearMonthDay ymd;
ConvertDateToYMD(e->intro_date, &ymd);
/* Purchase cost - Max speed */
SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
SetDParam(1, avi->max_speed * 128 / 10);
DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
y += 10;
/* Cargo capacity */
cargo = FindFirstRefittableCargo(engine_number);
if (cargo == CT_INVALID || cargo == CT_PASSENGERS) {
SetDParam(0, avi->passenger_capacity);
SetDParam(1, avi->mail_capacity);
DrawString(x, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY, 0);
} else {
/* Note, if the default capacity is selected by the refit capacity
* callback, then the capacity shown is likely to be incorrect. */
SetDParam(0, cargo);
SetDParam(1, AircraftDefaultCargoCapacity(cargo, engine_number));
SetDParam(2, STR_9842_REFITTABLE);
DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
}
y += 10;
/* Running cost */
SetDParam(0, avi->running_cost * _price.aircraft_running >> 8);
DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
y += 10;
/* Design date - Life length */
SetDParam(0, ymd.year);
SetDParam(1, e->lifelength);
DrawString(x, y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0);
y += 10;
/* Reliability */
SetDParam(0, e->reliability * 100 >> 16);
DrawString(x, y, STR_PURCHASE_INFO_RELIABILITY, 0);
y += 10;
/* Additional text from NewGRF */
y += ShowAdditionalText(x, y, w, engine_number);
y += ShowRefitOptionsList(x, y, w, engine_number);
}
void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection)
{
PalSpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(GetAircraftImage(v, DIR_W) | pal, x + 25, y + 10);
if (v->subtype == 0) {
SpriteID rotor_sprite = GetCustomRotorSprite(v, true);
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
DrawSprite(rotor_sprite, x + 25, y + 5);
}
if (v->index == selection) {
DrawFrameRect(x - 1, y - 1, x + 58, y + 21, 0xF, FR_BORDERONLY);
}
}
void CcBuildAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) {
const Vehicle *v = GetVehicle(_new_vehicle_id);
if (v->tile == _backup_orders_tile) {
_backup_orders_tile = 0;
RestoreVehicleOrders(v, _backup_orders_data);
}
ShowAircraftViewWindow(v);
}
}
static void GenerateBuildAircraftList(Window *w)
{
EngineID eid, sel_id;
buildvehicle_d *bv = &WP(w, buildvehicle_d);
EngList_RemoveAll(&bv->eng_list);
/* Make list of all available planes.
* Also check to see if the previously selected plane is still available,
* and if not, reset selection to INVALID_ENGINE. This could be the case
* when planes become obsolete and are removed */
sel_id = INVALID_ENGINE;
for (eid = AIRCRAFT_ENGINES_INDEX; eid < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; eid++) {
if (IsEngineBuildable(eid, VEH_Aircraft, _local_player)) {
const AircraftVehicleInfo *avi = AircraftVehInfo(eid);
switch (bv->filter.acc_planes) {
case HELICOPTERS_ONLY:
if (avi->subtype != 0) continue; // if not helicopter
break;
case AIRCRAFT_ONLY:
if (avi->subtype == 0) continue; // if helicopter
break;
case ALL: break;
}
EngList_Add(&bv->eng_list, eid);
if (eid == bv->sel_engine) sel_id = eid;
}
}
bv->sel_engine = sel_id;
}
static void GenerateBuildList(Window *w)
{
buildvehicle_d *bv = &WP(w, buildvehicle_d);
switch (bv->vehicle_type) {
case VEH_Aircraft:
GenerateBuildAircraftList(w);
_internal_sort_order = bv->descending_sort_order;
EngList_Sort(&bv->eng_list, _aircraft_sorter[bv->sort_criteria]);
break;
default: NOT_REACHED();
}
}
static void DrawBuildAircraftWindow(Window *w)
{
const buildvehicle_d *bv = &WP(w, buildvehicle_d);
SetWindowWidgetDisabledState(w, BUILD_VEHICLE_WIDGET_BUILD, w->window_number == 0);
SetVScrollCount(w, EngList_Count(&bv->eng_list));
DrawWindowWidgets(w);
{
int x = 2;
int y = 27;
EngineID selected_id = bv->sel_engine;
EngineID eid = w->vscroll.pos;
uint16 max = min(w->vscroll.pos + w->vscroll.cap, EngList_Count(&bv->eng_list));
for (; eid < max; eid++) {
const EngineID engine = bv->eng_list[eid];
DrawString(x + 62, y + 7, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10);
DrawAircraftEngine(x + 29, y + 10, engine, GetEnginePalette(engine, _local_player));
y += 24;
}
if (selected_id != INVALID_ENGINE) {
const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
DrawAircraftPurchaseInfo(x, wi->top + 1, wi->right - wi->left - 2, selected_id);
}
}
DrawString(85, 15, _aircraft_sort_listing[bv->sort_criteria], 0x10);
DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10);
}
static void BuildAircraftClickEvent(Window *w, WindowEvent *e)
{
buildvehicle_d *bv = &WP(w, buildvehicle_d);
switch (e->we.click.widget) {
case BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING:
bv->descending_sort_order ^= true;
_last_sort_order = bv->descending_sort_order;
GenerateBuildList(w);
SetWindowDirty(w);
break;
case BUILD_VEHICLE_WIDGET_LIST: {
uint i = (e->we.click.pt.y - 26) / 24 + w->vscroll.pos;
uint num_items = EngList_Count(&bv->eng_list);
bv->sel_engine = (i < num_items) ? bv->eng_list[i] : INVALID_ENGINE;
SetWindowDirty(w);
break;
}
case BUILD_VEHICLE_WIDGET_SORT_TEXT: case BUILD_VEHICLE_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */
ShowDropDownMenu(w, _aircraft_sort_listing, bv->sort_criteria, BUILD_VEHICLE_WIDGET_SORT_DROPDOWN, 0, 0);
return;
case BUILD_VEHICLE_WIDGET_BUILD: {
EngineID sel_eng = bv->sel_engine;
if (sel_eng != INVALID_ENGINE) {
DoCommandP(w->window_number, sel_eng, 0, CcBuildAircraft, CMD_BUILD_AIRCRAFT | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
}
break;
}
case BUILD_VEHICLE_WIDGET_RENAME: {
EngineID sel_eng = bv->sel_engine;
if (sel_eng != INVALID_ENGINE) {
bv->rename_engine = sel_eng;
ShowQueryString(GetCustomEngineName(sel_eng), STR_A039_RENAME_AIRCRAFT_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
}
break;
}
}
}
static void NewAircraftWndProc(Window *w, WindowEvent *e)
{
buildvehicle_d *bv = &WP(w, buildvehicle_d);
switch (e->event) {
case WE_INVALIDATE_DATA:
GenerateBuildList(w);
break;
case WE_DESTROY:
EngList_Destroy(&bv->eng_list);
break;
case WE_PAINT:
DrawBuildAircraftWindow(w);
break;
case WE_CLICK:
BuildAircraftClickEvent(w, e);
break;
case WE_ON_EDIT_TEXT: {
if (e->we.edittext.str[0] != '\0') {
_cmd_text = e->we.edittext.str;
DoCommandP(0, bv->rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
}
break;
}
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
if (bv->sort_criteria != e->we.dropdown.index) {
bv->sort_criteria = _last_sort_criteria = e->we.dropdown.index;
GenerateBuildList(w);
}
SetWindowDirty(w);
break;
case WE_RESIZE:
w->vscroll.cap += e->we.sizing.diff.y / 24;
w->widget[BUILD_VEHICLE_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
break;
}
}
static const WindowDesc _build_vehicle_desc = {
WDP_AUTO, WDP_AUTO, 240, 226,
WC_BUILD_VEHICLE,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_build_vehicle_widgets,
NewAircraftWndProc
};
void ShowBuildVehicleWindow(TileIndex tile, byte type)
{
buildvehicle_d *bv;
Window *w;
DeleteWindowById(WC_BUILD_VEHICLE, tile);
w = AllocateWindowDescFront(&_build_vehicle_desc, tile);
if (w == NULL) return;
w->caption_color = (tile != 0) ? GetTileOwner(tile) : _local_player;
w->resize.step_height = GetVehicleListHeight(type);
w->vscroll.cap = 4;
w->widget[BUILD_VEHICLE_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
bv = &WP(w, buildvehicle_d);
EngList_Create(&bv->eng_list);
bv->sel_engine = INVALID_ENGINE;
bv->sort_criteria = _last_sort_criteria;
bv->descending_sort_order = _last_sort_order;
bv->vehicle_type = type;
switch (type) {
case VEH_Aircraft: {
byte acc_planes = (tile == 0) ? ALL : GetAirport(GetStationByTile(tile)->airport_type)->acc_planes;
bv->filter.acc_planes = acc_planes;
break;
}
default: NOT_REACHED();
}
GenerateBuildList(w);
/* Select the first plane in the list as default when opening the window */
if (EngList_Count(&bv->eng_list) > 0) bv->sel_engine = bv->eng_list[0];
}

View File

@@ -1,60 +1,61 @@
/* $Id$ */
/** @file callback_table.cpp All command callbacks. */
#include "stdafx.h"
#include "openttd.h"
#include "callback_table.h"
#include "command_type.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!! */
// 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.cpp */
/* aircraft_gui.c */
CommandCallback CcBuildAircraft;
CommandCallback CcCloneAircraft;
/* airport_gui.cpp */
/* airport_gui.c */
CommandCallback CcBuildAirport;
/* bridge_gui.cpp */
/* bridge_gui.c */
CommandCallback CcBuildBridge;
/* dock_gui.cpp */
/* dock_gui.c */
CommandCallback CcBuildDocks;
CommandCallback CcBuildCanal;
/* depot_gui.cpp */
/* depot_gui.c */
CommandCallback CcCloneVehicle;
/* main_gui.cpp */
/* main_gui.c */
CommandCallback CcPlaySound10;
CommandCallback CcPlaceSign;
CommandCallback CcTerraform;
CommandCallback CcBuildTown;
CommandCallback CcGiveMoney;
/* rail_gui.cpp */
/* rail_gui.c */
CommandCallback CcPlaySound1E;
CommandCallback CcRailDepot;
CommandCallback CcStation;
CommandCallback CcBuildRailTunnel;
/* road_gui.cpp */
/* road_gui.c */
CommandCallback CcPlaySound1D;
CommandCallback CcBuildRoadTunnel;
CommandCallback CcRoadDepot;
/* roadveh_gui.cpp */
/* roadveh_gui.c */
CommandCallback CcBuildRoadVeh;
CommandCallback CcCloneRoadVeh;
/* ship_gui.cpp */
/* ship_gui.c */
CommandCallback CcBuildShip;
CommandCallback CcCloneShip;
/* train_gui.cpp */
/* train_gui.c */
CommandCallback CcBuildWagon;
CommandCallback CcBuildLoco;
CommandCallback CcCloneTrain;
/* ai/ai_core.cpp */
CommandCallback CcAI;
CommandCallback *_callback_table[] = {
@@ -79,9 +80,12 @@ CommandCallback *_callback_table[] = {
/* 0x12 */ CcPlaySound1E,
/* 0x13 */ CcStation,
/* 0x14 */ CcTerraform,
/* 0x15 */ CcAI,
/* 0x16 */ CcCloneVehicle,
/* 0x17 */ CcGiveMoney,
/* 0x15 */ CcCloneAircraft,
/* 0x16 */ CcCloneRoadVeh,
/* 0x17 */ CcCloneShip,
/* 0x18 */ CcCloneTrain,
/* 0x19 */ CcAI,
/* 0x1A */ CcCloneVehicle
};
const int _callback_table_count = lengthof(_callback_table);

View File

@@ -1,11 +1,9 @@
/* $Id$ */
/** @file callback_table.h Table with all command callbacks. */
#ifndef CALLBACK_TABLE_H
#define CALLBACK_TABLE_H
#include "command_type.h"
#include "command.h"
extern CommandCallback *_callback_table[];
extern const int _callback_table_count;

View File

@@ -1,899 +1,3 @@
0.7.0-beta1 (2009-02-16)
------------------------------------------------------------------------
- Feature: Make it possible to have multiple windows with edit box open simultaniously (r15424)
- Feature: Add ability to select which base graphics set is used from the Game Options window. The change takes effect when the window is closed. This option can only be used from the intro menu, as reloading graphics during a game may cause issues (r15389)
- Feature: Do not draw superfluous catenary wires [FS#1761] (r15347)
- Feature: Add option to group and subtotal expenses list in the company finance window (r15301)
- Feature: Allow moving clients between companies/spectators by the server and the clients themselves (r15242)
- Feature: Native support for Transport Tycoon (Original) savegames (r15216)
- Feature: Allow terraforming of the tiles at the edges of the map (r15190)
- Feature: [NewGRF] Allow a grf to customize house name via callback 0x14D, during Tile Inquiry process (r15172)
- Feature: Downloading content from a central server (content.openttd.org) where authors can upload their NewGRFS/AI etc. This should make joining servers that use only NewGRFs that are distributed via this system easier as the players can download the NewGRFs from within the game. It should also make it easier to see whether there are updates for NewGRFs and make the necessary updates (r15126)
- Feature: Add support for IP range bans using CIDR notation (r15094)
- Feature: An AI framework so people can write their own AIs. This also removes the old cheating and heavily broken AI (r15027)
- Feature: [NewGRF] Support var 0x45 (curvature info) also for road vehicles (r14945)
- Feature: [NewGRF] Automatically set last engine ageing year to the last 'introduction year plus half model life', to allow engines later than 2050 to appear (r14926)
- Feature: Distant joining of stations (r14919)
- Feature: Advanced setting to keep various building tools active, which are usually closed after placing an object (r14902)
- Feature: Remove the window limit, but leave a configurable limit on the number of non-sticky non-vital windows (r14899)
- Feature: Allow road vehicles to move multiple steps in a tick (code based on train movement code) and add support for RV prop 15. This gives RVs a maximum speed of 318mph instead 79mph. This only implements higher speeds, not 'realistic acceleration' (r14869)
- Feature: Automatic reversing in front of block signals can now be disabled by setting pf.wait_oneway_signal respectively pf.wait_twoway_signal to 255 (r14852)
- Feature: Few (optional) optimisations to making (initial) orders; like keeping goto selected [FS#1984] (r14827)
- Feature: Make the road grids of town match, when all are using the same road layout ofcourse [FS#2390] (r14821)
- Feature: Pressing CTRL while dragging to build a bridge builds the last built bridge type if possible [FS#2238] (r14805)
- Feature: Make the date format for default savegame/screenshot names configurable (r14792)
- Feature: Allow scrolling with the left mouse button pressed (if enabled). Primarily useful for systems with touch screen (r14789)
- Feature: Allow up to 15 companies (r14735)
- Feature: Allow up to 255 clients in multiplayer games (r14730)
- Feature: When the chosen language is not supported by the current font, try to find a font that does and use that instead (r14618)
- Feature: [NewGRF] Action0Industries property 24 (industry supplies default name for nearby station) (r14598)
- Feature: Non-destructive autofill with option to keep waiting times [FS#1124] (r14592)
- Feature: Stop-in-depot order; after this order you have to manually start the vehicle again (or sell it) (r14524)
- Feature: Arrow key scrolling in the server list (r14517)
- Feature: Initial support for handling bidirectional scripts and connecting Arabic characters (r14479)
- Feature: Allow sorting vehicles by remaining life time (r14352)
- Feature: Ability to reset name to default/automatic value (for vehicles, engines, towns, groups, stations, waypoints, managers and companies) (r14334)
- Feature: [NewGRF] Add Variational Action 2 Variable 0x47 for houses, Coordinates of the house tile (r14294)
- Feature: Allow overriding the palette of the base GRFs. This way you can play with NewGRFs made for the Windows palette with the DOS palettes base GRFs (and vice versa). Note that for this to work correctly ALL NewGRFs must use the same palette; mix and match is not yet supported (r14229)
- Feature: Double click to join selected server/company (r14209)
- Feature: Allow both the German as well as non-German toyland graphics as "correct" and official graphics (r14197)
- Feature: Allow people to create their own base graphics easily and without requiring code changes (r14197)
- Feature: [NewGRF]: Add support for property 0x13 for Bridges. In other words, one can now specifies a 16 bits cost multiplier (r14172)
- Feature: Make it possible to choose between the DOS and Windows graphics packs while retaining the possibility to override the palette (r14151)
- Feature: Increase the size of the console backlog. Now it'll only remove backlog items when there are more than a threshold and when they are there longer than (another) threshold (r14056)
- Feature: Make it possible to filter list_patches output like it's done for other list_* console commands (r14041)
- Feature: Path based signalling (r13926-13967)
- Feature: Show [total-]cargo info in depot when [ctrl-]right-clicking on vehicle (r13923)
- Feature: NewGRF presets, selected by a drop down list in the NewGRF window. Presets are saved in the config file (r13781)
- Feature: Add a few extra columns with information to the server list (r13732)
- Feature: [NewGRF] Add var 65 in Variational Action 2 Variables for Houses (r13603)
- Feature: [NewGRF] Implement var 63, variational action2 variable for Houses. Or, in more simple terms, the check for the animation frame of nearby house (r13519)
- Feature: Aqueducts (r13464)
- Feature: [NewGRF] Add var 0x69 for industries, long format construction date (r13443)
- Feature: [NewGRF] Add long format introduction and maximum construction year for house (r13437)
- Feature: [NewGRF] Add access to current long year and date from Action 7/9/D and VarAction2 (23/24 or A3/A4), and add access to (long format) building year, in Variational Action2 Variable 49 for Vehicles (r13376)
- Feature: Splitting of the main toolbar when the resolution becomes very low so the buttons are still visible and useable (r13339)
- Feature: Make news messages use a linked list instead of a moving circular buffer. This makes it possible to store more news messages in the history (r13317)
- Feature: The number of news messages is reduced by removing every news message that is a configurable amount older than when it would not be shown in the newspaper popup/ticker, which is e.g. a month for industry production changes and half a year for subsidy offers. As a result the more important messages will stay longer in the message history (if longer than 30 messages) (r13317)
- Feature: Allow to have more than only two airports per town. The number of airports is now controlled by the noise each of them generates, the distance from town's center and how tolerant the town is (13226)
- Feature: Introducing the so called 'engine pool' which primarily removes the fixed engine type limits and also happens to allow (with the patch option 'dynamic_engines') multiple NewGRF vehicle sets to coexist (r12924)
- Feature: [NewGRF] The ability to play NewGRF sounds for industries and stations (r12817)
- Feature: [NewGRF] Add some support for NewGRF station animation (r12798)
- Feature: Sorting vehicle lists by road vehicle/train length (r12766)
- Feature: Conditional 'skip/jump' orders (r12667)
- Feature: Ability to send a vehicle (using default orders) to the nearest depot (r12661)
- Feature: Ability to force a vehicle to not load or to not unload at a station (r12650)
- Feature: Four different non-stop types, individually selectable per order. Replaces "TTDP compatible order" setting (r12648)
- Feature: Three different load type in a single game instead of two. One can choose full load all and full load any instead of full load being governed by the "full load any" patch setting (r12648)
- Feature: Financial and Player Selection Face windows are now remembering their position when toggling sizes (r12634)
- Feature: Show what cargos a station could be supplied with (r12596)
- Feature: [NewGRF] Add random action 2 type 84. For vehicles only (r12452)
- Feature: [NewGRF] Add support for var A2/22 for action 7/9/D: Difficulty level (r12449)
- Feature: Add +/- toggle buttons to station cargo waiting list to show/hide the detailed transferred cargo information (r12446)
- Feature: Open the time table when pressing the order button while pressing the CTRL key (r12441)
- Feature: On Screen Keyboard for input fields so someone without a keyboard can enter text too [FS#1846] (r12425)
- Change: When checking for unique names, compare only with manually set names [FS#1923] (r14958)
- Change: Apply the 'warn if train's income is negative' setting to other vehicle types, too (r14835)
- Change: When loading games in "network" mode use the start date of the save game for the server and all clients when loading the NewGRFs instead of the current date. Prevents desyncs caused by action 7/9s skipping parts of the GRF based on the date or some other variables that can differ at NewGRF load time (r14769)
- Change: Only say a engine/vehicle is refittable when it can be refitted to at least two cargo type or when it has subcargos (r14683)
- Change: [NewGRF] Since our NewGRF handling is better than it used to be, disable a NewGRF if unexpected sprites are reached (r14184)
- Fix: A town could build a statue under a bridge [FS#2618] (r15397)
- Fix: Multiple vehicles could be filling the timetable and only the data from one vehicle would be taken. Now only allow one to be filling at a time [FS#2466] (r15382)
- Fix: When testing for parallel road two tiles away, do not move more than one tile along the road (r15381)
- Fix: [NewGRF] The subcargo returned by vehicle variable 0x42 should be the most-common-subcargo of the most-common-cargo. If nothing is transported 0x..FFFF00 should be returned (r15378)
- Fix: A tram circling around in a depot did never actually 'enter' the depot [FS#2605] (r15375)
- Fix: Changing town road layout in-game caused ugly road networks [FS#2121] (r15340)
- Fix: Company could never have auto-assigned colour 0 (dark blue) (r15281)
- Fix: Deadlock (with wide fonts) or desync when generating manager name (r15279)
- Fix: Close all windows *before* starting a new game/loading a game instead of doing that as one of the latest steps of loading the game. This caused, in some cases, the NewGRF settings to be reset when the game was already loaded resulting in instant desyncs when joining a network game [FS#2577] (r15256)
- Fix: Aircraft could be 'loading in the air' or have zero speed while in air after converting old savegames [FS#2571] (r15230, r15227)
- Fix: Tile error location not reset when leveling land causing a tile to be highlighted when there was nothing to flatten [FS#2542] (r15138)
- Fix: Signs with sign 'Sign' were lost when converting from TTD savegames (r15137)
- Fix: [NewGRF] Add support for 8 byte action7/9 data, used as a mask for GRFID checks (r15114)
- Fix: [NewGRF] Keep industry variables 8E and 8F in sync with 93, when changing production using results 0D, 0E or 0F of callback 29 or 35 (r15103)
- Fix: [NewGRF] Disable a NewGRF from loading if it contains multiple Action 8s (r14979)
- Fix: Wrong defaults for service interval when switching between service interval in days and service interval in percentages [FS#2508] (r14959)
- Fix: [NewGRF] Building new station parts did not allocate a new station spec effectively breaking variable 41. This was due to the limited number of station specs that we can have per station. This fix makes newly build station parts create a new spec until one cannot allocate new station specs anymore and it'll revert to the old behaviour (sharing station specs) [FS#1832] (r14956)
- Fix: [NewGRF] Station specs did not get deallocated when building a new station part over them (r14955)
- Fix: Sharing/cloning/inserting of orders that the/a vehicle (in the shared list) cannot go to (wrong station type etc) [FS#1890] (r14954)
- Fix: The "animation state" of the bubbles was stored in a variable that was not stored in the savegame. Using a variable that gets saved in the savegame solves the desync and makes it a bit clearer [FS#2512] (r14931)
- Fix: Abort dragging of vehicles in the group window when they are deleted [FS#2500] (r14925)
- Fix: Do not unnecessarily reset the cursor, when a different vehicle is dragged (r14924)
- Fix: [NewGRF] First create all articulated parts of roadvehicles, then call callback 36 capacity, also call it for all articulated parts (r14903)
- Fix: Overflow of number of orders per vehicle [FS#2495] (r14830)
- Fix: Off-by-one causing possible out-of-bounds reads (r14811)
- Fix: In an MP game in SP mode no company would go bankrupt. Furthermore companies that passed the "bankrupt" period (4 quarters) would not go bankrupt when loading the game back in MP. Now any company that is in MP or not "currently controlled by the player" in SP will bankrupt [FS#1993] (r14750)
- Fix: Do not let any disaster vehicle (Helicopter or Airplane) target invalid industry (r14746)
- Fix: Memory leak in Action 0x0F (new town names) (r14737)
- Fix: Writing a single char to the config file caused reading outside a buffer (r14729)
- Fix: First transfer the whole load of a vehicle chain to industries before triggering any processing. This reduces callback usage and resolves critical rounding errors when using input-cargo-multipliers instead of production callbacks [FS#2460] (r14705)
- Fix: Zeppeliner (disaster) should target st->airport_tile, not st->xy (r14694)
- Fix: [NewGRF] Gradual filling graphics were not chosen according to the NewGRF spec [FS#2435] (r14678)
- Fix: [NewGRF] Check sprite size when executing action 6 (r14674)
- Fix: [NewGRF] Property 7 and callback 12 were broken for aircraft. Now callback 12 is properly called also for 'mail'. If the callback is not used, 'mail' uses 1/4 of property 7 (rounded up) [FS#2444] (r14672)
- Fix: Possible stack corruption when reading corrupted sprites [FS#2415] (r14610)
- Fix: [NewGRF] Return the current year as construction year for unfinished houses (r14608)
- Fix: [NewGRF] When callback 1E fails, use the standard random colour (r14605)
- Fix: The company ID is off-by-one with respect to the rest of the GUI in the cheat window [FS#2422] (r14603)
- Fix: The range for kicking/banning clients is based on the maximum number of clients, not the maximum number of companies [FS#2414] (r14588)
- Fix: Allow capacity callbacks (15, 36) to return zero capacity (r14578)
- Fix: Crashes when a NewGRF sends an invalid string [FS#2395] (r14563)
- Fix: Order pool seemed to look full when it was not as it only checked whether it was possible to allocate a new block of pool items instead of checking for free pool items (r14547)
- Fix: Do not deliver cargo to industries not inside station catchment area [FS#2138] (r14530)
- Fix: Allocate stub (empty) sound entries when loading an empty/corrupt/incorrectly sized sample.cat instead of making valid NewGRFs fail to load (r14527)
- Fix: Make sure trains stop at the end of a station; a 3/8th length train did stop 2/8th of it's length too early causing a 63/8th long train not to fit in a 4 tile station [FS#2379] (r14526)
- Fix: Small possible chance of desync due to sorting on pointer instead of by (station) index [FS#2348] (r14463)
- Fix: When a road stop gets moved make sure to update the destination of RVs going to that road stop [FS#2330] (r14446)
- Fix: Support for spaces in directories passed to ./configure [FS#1802] (r14440)
- Fix: Trains would sometimes move one time too often/little when moving from diagonal<->non-diagonal tracks [FS#1793] (r14436)
- Fix: Balance the monthly random industry changes, by introducing a daily random industry change [FS#1885] (r14332)
- Fix: Save the palette of the loaded NewGRFs in the savegame, so joining with a server using Windows palette will make a client with the DOS palette do palette conversion and (thus) not cause a desync (r14233)
- Fix: Glitches (alignment issues/inconsistent vehicle graphics) in original graphics (r14214, r14211)
- Fix: One could not get a list of vehicles sharing an order when the number of orders was 0; you could see that the vehicles had a shared order though [FS#2085] (r14097)
- Fix: Various assorted autoreplace issues/malbehaviours [FS#1264, FS#2037, FS#2038, FS#2110] (r14083)
- Fix: The autoreplace gui showed vehicle types for replacement which CmdSetAutoReplace() did not accept (r14037)
- Fix: Automatically recalculate inflation if NewGRFs are changed and cargo types are added, so that cargo payment rates are correct [FS#2074] (r13836)
0.6.3 (2008-10-01)
------------------------------------------------------------------------
- Fix: NewGRF VarAction 2 variable 43 for industries saw MP_VOID tiles as land tiles and was inefficient (r14417, r14416, r14415)
- Fix: Possible buffer overrun/wrong parameter type passed to printf (r14414, r14397)
- Fix: Generation seed set using -G was always overwritten by -g (r14408)
- Fix: Do not allow extending signals by dragging in any direction other than the track direction [FS#2202] (r14013)
0.6.3-RC1 (2008-09-22)
------------------------------------------------------------------------
- Fix: Invalid v->u.air.targetairport could cause crashes at several places [FS#2300] (r14383, r14344, r14343)
- Fix: Moving the first vehicle of a train elsewhere might require a new unitnumber for the remaining chain which might not be available (r14384)
- Fix: Trams jumping when reversing on a single trambit (like caused during road construction reworks) or when (manually) reversing in a corner [FS#1852] (r14371)
- Fix: Multiheaded parts in free wagon chains weren't connected (could cause desyncs) (r14366, r14362)
- Fix: [Win32] Some keypress combinations could be handled twice [FS#2206] (r14363)
- Fix: The ownership of roadtiles was not properly set for very old savegames (including TTD's) making it impossible to remove some pieces of road [FS#2311] (r14359)
- Fix: Desync due to randomly ordered vehicle hash by flooding and road vehicle overtake/following (r14356, r14258)
- Fix: Signs were not updated on company bankrupcy/sell, and thus could have the colour of invalid player (r14348)
- Fix: Delete the RenameSignWindow when 'its' sign is deleted (r14345)
- Fix: Signs from old savegames were lost (causing little memory leaks) (r14340)
- Fix: When a company was renamed and then manager was renamed before building anything, company name changed (r14328)
- Fix: When you rename a town before building something and build something near that town your company would be called "<old townname> Transport" [FS#2251] (r14327)
- Fix: Free any blocks that a helicopter may have on an oilrig when the helicopter gets forcefully removed (bankruptcy). For other airports this isn't needed as they can't be used by multiple companies [FS#2241] (r14324)
- Fix: Possible assert when renaming removed waypoint (r14322)
- Fix: Properly delete orders so the pool doesn't fill up (r14319)
- Fix: Do not allow building road over level crossings and drive-through road stops in the wrong direction; do not allow adding roadtypes to non-drive through road stops; pay for all added road bits [FS#2268] (r14316, r14315, r14314, r14308)
- Fix: Aircraft frozen above oil rig when the next order is invalid [FS#2244] (r14309)
- Fix: [YAPF] Only reserve road slots for multistop when they are really reachable [FS#2294] (r14305)
- Fix: One could be trying to get the station name of a station that is outside of the pool (r14297)
- Fix: Default for sound effects and music volume should be in the valid range for that setting [FS#2286] (r14289)
- Fix: Make small UFO aware of articulated RVs so they crash the complete vehicle instead of a small part of it (r14270)
- Fix: Desyncs after deleting a waypoint because of explicit destructor call instead of using operator delete (r14265)
- Fix: Merge keycode for "normal" 0-9 keys and keypad 0-9 keys so people do not get confused that the keypad does not work as expected [FS#2277] (r14260)
- Fix: Clicking on the smallmap didn't break the "follow vehicle in main viewport" [FS#2269] (r14243)
- Fix: The engine-purchase-list-sorter doubled running-cost and halfed capacity of double-headed engines [FS#2267] (r14239)
- Fix: Feeder share was computed wrong when splitting cargo packet (r14234)
- Fix: Signs (town name, station name, ...) could be too long for 8bit width in pixels (r14221)
- Fix: 10 days != 6*2.5 days, effectively causing the payment graph to show the wrong data (r14219)
- Fix: When determining length of a string with limited size, first check if we are not out of bounds already (r14204)
- Fix: Properly update the current timetable's travel/wait times instead of only doing it for one vehicle in the shared order chain and only when some bit has not been set [FS#2236] (r14192)
- Fix: Sprite payload skipping would not skip enough bytes in a very small subset of compressed sprites (r14191)
- Fix: After applying NewGRF settings, all rail and road types were available as the engine availability check was performed too early (r14182)
- Fix: Close all related vehicle lists when closing a station window (and not only the train list) (r14180)
- Fix: RemoveOrderFromAllVehicles() did not mark enough windows dirty (r14179)
- Fix: Incorrect cargo weights (r14144)
- Fix: GetSlopeZ() gets a virtual coordinate, not a tile (r14139)
- Fix: Close the 'manage vehicles' dropdown once the number of vehicles in the list reaches 0 [FS#2249] (r14133)
- Fix: [strgen] Changing order of parameters {X:...} did not work for strings including some {StringY} (r14111)
- Fix: Desync due to bubbles in toyland (r14110)
- Fix: Make NewGRF action 0x06's changes persistent over the several loading stages [FS#1986] (r14102)
- Fix: Make the 'Transfer Credit' display aware of the entire consist, not only the first vehicle (r14098)
- Fix: Do not flood a NewGRF industry when it implicitly tells that it wants to be build on water (land shape flags bit 5) [FS#2230] (r14093)
- Fix: The vehicle window of articulated road vehicles would show the clone/refit button when the vehicle was not completely stopped in the depot (r14090)
- Fix: Flawed parsing of words (as in 2 bytes) in GRF strings due to sign extension [FS#2228] (r14087)
- Fix: Division by 0 in NewAI [FS#2226] (r14062)
- Fix: NewGRF callback 23 did not use the NewGRF compatible text stack [FS#2224] (r14058)
- Fix: NewGRF text stack's "push word" didn't move the data around properly (r14057)
- Fix: Long strings in the edit box would cause OpenTTD to stop drawing the string. This is especially noticable with low resolutions and the chat input box (r14054)
- Fix: [OSX] changed the condition for selecting 8 or 32 bpp blitter by default. Now we will pick 32 bpp if no 8 bpp fullscreen resolutions are available on the main display (the one with the dock) (r14032)
- Fix: Crash when the AI tries to find the depot of an airport that doesn't have a depot [FS#2190] (r13999)
- Fix: MSVC cannot handle changed files in the prebuild event, so make the version determination a separate subproject [FS#2004] (r13998)
- Fix: The dedicated console removed any character that was not a printable ASCII character instead. Now it allows UTF8 formated strings too [FS#2189] (r13992)
- Fix: Resetting construction stage counter reset more than it should (r13981)
- Fix: Wrong tooltip for the industry directory's list [FS#2178] (r13917)
0.6.2 (2008-08-01)
------------------------------------------------------------------------
- Fix: Custom vehicle names from TTD(Patch) games were lost (r13884)
- Fix: NewGRF Callback 10 (visual effect and powered wagons setting) and powered wagons operation were not performed for articulated wagons [FS#2167] (r13870)
- Fix: In some cases the sprite cache could be filled with unremovable items [FS#2153] (r13869)
- Fix: Return of wrong parent scope of (NewGRF) industry variables (r13868)
- Fix: Loading of TTD(Patch) savegames from the command line did not work (r13859)
- Fix: Buffer overflow for too long filename supplied as '-g' parameter (r13858)
- Fix: Cargo type lookup was incorrect for NewGRF version 7 files without a translation table [FS#2157] (r13855)
- Fix: GetTownByTile() is only valid for houses and roads (r13851)
- Fix: Power, running cost and capacity of multiheaded engines were (too often) doubled in newspaper resp. offer window (r13844)
- Fix: FreeType may return a bitmap glyph even if a grey-scale glyph was requested [FS#2152] (r13832)
0.6.2-RC2 (2008-07-25)
------------------------------------------------------------------------
- Fix: Building through the wrong side of a drive through station was allowed [FS#2166] (r13822)
- Fix: Check for vehicle length changes outside a depot (callback 0x11) and give a warning about that [FS#2150] (r13816)
- Fix: Several minor memory leaks. They only happened once per game (r13809, 13810)
- Fix: Checking for train waiting at other side of two-way signal was broken [FS#2162] (r13806)
- Fix: Some revision checking code was unintentionally disabled (r13776)
- Fix: Enforce the validity of a NetworkAction (chat packet) issued by a client (r13775)
- Fix: Selecting non-full length vehicles in the depot gui would place the "mouse pointer" out of the center of the vehicle making it hard to "aim" [FS#2147] (r13759)
- Fix: NewGRF rail continuation would always mark a tunnel on the same axis as connected, even when the tunnel faces the wrong direction (r13734)
- Fix: Assumption that non-north tiles of a house do not have the 1x1 building bit set was flawed with some NewGRFs. This caused the amount of houses to differ, which causes the town radii to differ, which causes desyncs when towns are expanded (r13729)
- Fix: Possible desync on the autorenew settings 20+ game years (i.e. 4.5+ hours) after a company was started (r13718)
- Fix: Any player could construct new companies [FS#2144] (r13716)
- Fix: Remove the unique_id from the message that a client has joined as it is only exposes the unique_id more than needed (r13714)
- Fix: Possible crash on creating a network packet (r13713)
- Fix: Enforce the length restrictions of company and president name in the commands too (r13712)
0.6.2-RC1 (2008-07-16)
------------------------------------------------------------------------
- Fix: Possible buffer overflow in string truncation code (r13700)
- Fix: Handle SETX(Y) properly when truncating a string instead of ignoring it and returning a too long string (r13699)
- Fix: In some cases the (sound) mixer could overflow causing artefacts in the sound [FS#2120] (r13695)
- Fix: Do not rely on .tar files always ending with a block of zeros (r13693)
- Fix: Make sure a command is ran in the context of autoreplace or not (r13691)
- Fix: In the case that elrails and 'realistic' acceleration are disabled all electrified engines would have no power on load, until the vehicle got turned around, loaded or got into a depot [FS#2102]- Fix: Saving TTD imported games in recession failed due to wrong (and unneeded) type conversions in the saveload code [FS#2131] (r13679)
- Fix: Inactive companies from old (TTD) saves could be marked active in some cases, which then loads garbage in their statistics and such [FS#2126] (r13676)
- Fix: Memory leak when NewGRFs got forcefully disabled and they defined GOTO labels (r13675)
- Fix: Crash when drawing a non-real sprite caused by NewGRF interference [FS#2127] (r13674)
- Fix: Desync when building electrified trains on a dedicated server that was started with electrification disabled [FS#2122] (r13673)
- Fix: Bus/truck forgetting go-to-depot order when entering a non-drivethrough road stop [FS#2117] (r13664)
- Fix: Server crashing when banning the rconning client (r13661)
- Fix: Signals were not updated correctly when a player removed a non-existing track piece (r13626)
- Fix: Crash when one tries to raise the nothern corner of MP_VOID tiles (i.e. the southern corner of the tiles on the southern map edge) in the scenario editor [FS#2106] (r13624)
- Fix: Only the front of a RV would be considered when determining to what cargos a vehicle can be refitted instead of all cargos [FS#2109] (r13622)
- Fix: If the first bridge can not be build for a given length, then none of the other bridges can. Effectively meaning that if someone replaces the first bridge with a bridge that can be only 3 tiles longs then only other bridges that can be 3 tiles long will be buildable, but only if they are 3 tiles long [FS#2100] (r13611)
- Fix: Signal states could be propagated through waypoints built in orthogonal axis (r13589)
- Fix: [OSX] 10.5 failed to switch to fullscreen (r13584)
- Fix: RVs continueing onto next DT station when they are build adjacent to them [FS#2040] (r13581)
- Fix: Disable static NewGRFs when non-static NewGRFs query them in the context of network games. This makes it impossible for static NewGRFs to disable non-static NewGRFs and 'bad' things happening because the non-static NewGRF doesn't know about the static NewGRF (r13576)
- Fix: Properly count number of non-north housetiles [FS#2083] (r13518)
- Fix: Incorrect usage of strtoul (r13508)
- Fix: Clear the memory for the new AI during the loading of a savegame so it does not try to execute commands generated in a different savegame, which could be resulting in the AI trying to give orders to stations that do not exist (r13505)
- Fix: Drawing of zoomed out partial sprites could cause deadlocks or crashes (r13502)
- Fix: First determine where to *exactly* build a house before asking a NewGRF whether the location is good instead of possibly moving the house a tile after the NewGRF said the location is good (r13489)
- Fix: Track was not removed on company bankrupcy when there was a ship on lower halftile (r13488)
- Fix: Let ships also navigate on half-tile sloped watery rail tiles (r13485)
- Fix: Division by zero when one would press 'd' (skip order) when there's no order (r13409)
- Fix: Do not crash when resolving vehicle sprite groups with zero sprites (r13397)
- Fix: In the purchase list, CB36 for capacity was not called for the first part of rail and road vehicles (r13385)
- Fix: Loading of very old OpenTTD savegames was broken (r13373)
0.6.1 (2008-06-01)
------------------------------------------------------------------------
- Fix: Industry tiles would sometimes tell they need a 'level' slope when they do not want the slope (r13348)
- Fix: Attempts to make the old AI perform better (r13217, r13221, r13222)
0.6.1-RC2 (2008-05-21)
------------------------------------------------------------------------
- Fix: Do not send rcon commands of the server to the first client but do directly execute those on the server (r13137)
- Fix: For multiheaded engines, halve power and running cost when used instead of when loading, to allow callback values to work properly (r13074)
- Fix: Loading of TTDP savegames with rivers in them [FS#2005] (r13066)
- Fix: Update build industry window when raw_industry_construction setting is modified (r13060)
- Fix: Revert changes to multihead engine weight -- the original values were correct (r13023)
- Fix: Debugging was not possible with MSVC 2008 (r12996)
- Fix: List used for sorting GRFs was not freed (r12993)
- Fix: Default difficulty settings were different to TTD's original settings [FS#1977] (r12951)
- Fix: All vehicles would be available when an original scenario would be played [FS#1982] (r12948)
- Fix: Keep only first 15 bits for non failed callback results (r12947)
- Fix: Reading/modifying invalid data under some circumstances (r12943)
- Fix: Minor errors related to industries accepted/produced cargo (r12933)
- Fix: Town rating was affected even after the test run (r12920)
- Fix: Flood road tiles even when there are road works in progress [FS#1965] (r12919)
- Fix: Do not initialize Station struct with tile=0, buoys will never change that value [FS#1960] (r12915)
- Fix: Game crash when a spectator/server tried to show an engine with no owner when a NewGRF requested a specific variable (r12914)
- Fix: Report reverse sprite status (FD/FE) to NewGRF for manually toggled vehicles (r12910)
- Fix: Vehicles going twice to a depot when the automatic service interfered with the current order [FS#1985] (r12629)
0.6.1-RC1 (2008-04-26)
------------------------------------------------------------------------
- Fix: Vehicle groups, engine replacement rules and player/company names were not properly reset/freed after bankrupt (r12906)
- Fix: Remove trams from savegames saved in OTTD without tram support, it is better than to simply crash [FS#1953] (r12904)
- Fix: GCC on FreeBSD does not support -dumpmachine causing configure to fail. Use g++ instead [FS#1928] (r12876)
- Fix: Make the town rating tests use less memory and much quicker (r12859)
- Fix: Usage of AutoPtr made (trying to) build stuff very (time) expensive (r12857, r12855)
- Fix: Ensure that prop 25 is set for all vehicles in the consist before other properties as it could cause desyncs (r12856)
- Fix: Too much catenary was drawn about tunnel entrances, middle bridge pieces and non-rail station tiles (r12853, r12852)
- Fix: Use YAPF for fairly old savegames from before YAPF was introduced (r12845)
- Fix: The industry tick trigger should only be triggered once every 256 ticks, not every tick... Also bail out of the triggers a little earlier if you know they are not going to happen anyway (r12844)
- Fix: Inconsistent use of 8/15-bitness of NewGRF callback results with respect to TTDP's implementation of the specification (r12819, r12818, r12759)
- Fix: Possible out of bounds array access (r12809)
- Fix: Enforce autorenew values range in command (r12808)
- Fix: Vehicles could break down during loading and keep loading. The intention of the break down code is not to break down when having zero speed, therefor break downs now do not happen when loading [FS#1938] (r12795)
- Fix: [OSX] In some rare cases when using an uncalibrated monitor the system colour space could not be retrieved. Show an error when this happens instead of just trying an assertion (r12776)
- Fix: Slope checking for NewGRFs failed (r12759)
- Fix: Check the TILE_NOT_SLOPED flag of the _north_ tile of multi-tile houses to decide if autoslope is allowed (r12717)
- Fix: Do not move windows below the toolbar on resizes unless they would go behind the toolbar [FS#1904] (r12714)
- Fix: Increase default sound buffer size only for Vista [FS#1914] (r12708)
- Fix: Do not crash very hard on unrecognised savegames, just go back to the intro menu instead (r12707)
- Fix: In some cases a news messages would not be shown [FS#1906] (r12683)
- Fix: Removing road pieces from a town gave you twice the intended penalty [FS#1920] (r12682)
- Fix: When a road vehicle has a tram only stop multiple times in a row in it's orders, only the first one would be skipped [FS#1918] (r12678)
- Fix: Colour remaps on station sprites only worked for company colours [FS#1902] (r12674)
- Fix: Remove buggy buoys at tile 0 from old TTDP savegames (r12642)
- Fix: Possible NULL pointer dereference when reading some NewGRF data [FS#1913] (r12637)
- Fix: Infinite loop in case your compiler decides that enums are unsigned by default (r12622)
- Fix: The convert signal button disallowed signal dragging when the signal GUI was closed (r12577)
- Fix: Binding to a specific IP could cause OpenTTD to not register properly with the masterserver if one has multiple external interfaces (r12574)
- Fix: min() has 32bit arguments, clamping of 64bit values did not work (r12572)
- Fix: Towns could not terraform when inflation rised terraform prices enough (r12564)
- Fix: Do not affect town rating change by the order in which we examine stations (r12561)
- Fix: Redraw the signal GUI when the signal drag density changes in the patch settings and vice versa (r12553)
- Fix: Do not install scenarios into the current user's homedir when running 'make install', that is silly. Simply always install scenarios system wide instead (r12542)
0.6.0 (2008-04-01)
------------------------------------------------------------------------
- Fix: Final formatting of some string codes from NewGRFs was not done correctly [FS#1889] (r12488)
- Fix: Timetable times for aircraft were always doubled [FS#1883] (r12477)
- Fix: Remove broken endian-dependent code and unnecessary rgb to bgr swapping [FS#1880] (r12453)
- Fix: Do not 'disable' the drawing of autorail overlays when the tile is 'error'-marked (red pulsating selection) [FS#1871] (r12439)
- Fix: Plural rule for Icelandic was wrong (r12417)
0.6.0-RC1 (2008-03-26)
------------------------------------------------------------------------
- Feature: Show whether a town is a "city" in the town description title bar (r12391)
- Feature: Increase house animation frame number from 32 to 128 (r12347)
- Fix: Loading of TTD savegames (r12399, r12401)
- Fix: Vehicle lists related to stations not closed when the station is deleted [FS#1872] (r12393)
- Fix: Trams failing to turn on bridge heads/tunnel entrances [FS#1851] (r123890)
- Fix: Train could break apart when reversed while partially in a depot [FS#1841] (r12386, r12384)
- Fix: Non-breaking spaces should not be broken (r12385)
- Fix: Check return of AfterLoadGame for success or failure when loading TTD games [FS#1860] (r12383)
- Fix: Use 'items' unit for batteries, fizzy drinks, toys and bubbles in total cargo tab [FS#1864] (r12382)
- Fix: The number of houses wasn't computed right [FS#1835, FS#1535] (r12381)
- Fix: Update train acceleration and max speed after setting cached value to ensure the correct max speed is used with disabled real acceleration (r12380)
- Fix: Refresh vehicle details window when cached values are updated (r12378)
- Fix: Set cached value for vehicle property 25 before other cached values [FS#1854] (r12377)
- Fix: Don't close a dropmenu when clicking on a dropdown widget (r12374)
- Fix: win32 music driver fails if path is too long or if containing non-latin chars [FS#1849] (r12373, r12372)
- Fix: Do not let window hide behind the main toolbar after resizing the screen [FS#1823] (r12371)
- Fix: Close language drop down when parent window is clicked/closed [FS#1853] (r12370)
- Fix: Reset train speed limits when _patches.realistic_acceleration changes (r12369)
- Fix: Commands were sent to clients waiting for map download causing 'executing command from the past' error [FS#1650] (r12367)
- Fix: Do not allow building 'zero' road bits (r12363)
- Fix: Randomize variable 8F only once per callback 28 (r12362)
- Fix: openttdd.grf was using the wrong colours for glyphs due to a grfcodec bug (fixed in grfcodec 0.9.10 r1837) (r12360)
- Fix: Some callback-results were treated as 8 bit, when they were 15 bit, and vice versa (r12352, r12358)
- Fix: Do not try to flood water tile [FS#1836] (r12350)
- Fix: NTP skipped junction just after bridge end (r12348)
- Fix: Remove duplicated and inconsistent code wrt. autoreplace with rules in both vehicles' group and ALL_GROUP [FS#1748, FS#1825] (r12346)
- Fix: Don't try to restore backupped timetable when timetabling is disabled [FS#1828] (r12345)
- Fix: Slow helicopters never got the 'chance' to finish the landing routine (r12343)
- Fix: GRM buffer for cargos was incorrect size [FS#1827] (r12341)
- Fix: Recalculate cached train data after clearing reversing flag when entering depot (r12339)
0.6.0-beta5 (2008-03-04)
------------------------------------------------------------------------
- Feature: Vehicle variable FE bit 5, 6 and 8 [FS#1812] (r12331, r12330)
- Feature: Support loading full range of 0xD0xx NewGRF strings which includes 0xD000 to 0xD3FF (r12316)
- Feature: Ability to change aircraft speed factor, from so called 'realistic' (matching other vehicles) (1/1) to original TTD speed (1/4) (r12293, r12294)
- Change: Update readme about where openttd looks for files (r12321)
- Fix: Don't pause/unpause the game when showing load/save windows when the game is paused due to missing GRFs [FS#1733] (r12336)
- Fix: Disallow building level crossings over one-way roads as this allowed competitors to remove the one-way state [FS#1819] (r12329)
- Fix: Wrong Y pillar specified for girder with arch bridge (r12328)
- Fix: Vehicles could be sorted in a wrong order when a vehicle name changed - cached name was not invalidated (r12324)
- Fix: Vehicle sorting by name was broken, it was comparing the same string (when caching was not used) [FS#1821] (r12323)
- Fix: Endian issue when saving/loading group owner (r12322)
- Fix: Wrong transparency options could be saved after toggling all [FS#1817] (r12320)
- Fix: Map string IDs that are embedded from other strings [FS#1815] (r12317)
- Fix: Include prop 25 data for all train parts, not just those that carry cargo (r12314)
- Fix: YAPF and NTP did not apply penalty for uphill tracks on steep slopes (r12313)
- Fix: Restore timetable from backupped orders and add group ID to the backup [FS#1549] (r12296)
- Fix: Do not draw trees nor lamps between tram tracks (r12290) [FS#1807]
- Fix: [Win32] Do not create save dir on install (r12269)
- Fix: Autoreplace did not update vehicle index for timetable window [FS#1805] (r12261)
- Fix: GetProductionAroundTiles() may fail if only the second production slot exists (r12258)
- Fix: Town variables 0x9E to 0xAD (company ratings) returned wrong values (r12247)
- Fix: Typo resulting in no players are given the engine preview offer (r12244)
- Fix: Mac OSX bundle display name should be 'OpenTTD' [FS#1798] (r12234)
- Fix: [NewGRF] Support using any base price for rail and road vehicles' running cost, show running cost of wagons if available (r12209)
- Fix: When loading a savegame fails, do not start creating a new game, just go straight back to the intro screen (r12202)
- Fix: Force AI to build rail or road instead of bridges if possible, so it doesn't build bridges everywhere (r12200)
- Fix: "Transparent buildings" now only toggles buildings, so show tick when buildings are transparent [FS#1789] (r12198)
- Fix: Show correct last year profit when the train had negative income [FS#1788] (r12197)
- Fix: There can be oil rigs at map borders, do not set water class for them [FS#1787] (r12195)
- Fix: Do not start overtaking if the RV reaches wrong-way one-way-road in the next tiles (r12191)
- Fix: Assert when trying to play tile sound at NW border of map (placing buyos, leveling land) [FS#1784] (r12186)
- Fix: Take into account possible loan when AI is deciding which bridge to build, so it won't build wooden bridges everytime (r12184)
0.6.0-beta4 (2008-02-18)
------------------------------------------------------------------------
- Feature: Allow buttons to resize in NewGRF settings window (r12172)
- Feature: Change colour of autorail and autoroad selection when Ctrl is pressed (r12167)
- Feature: Separate catenary transparency settings from building transparency settings (r12103)
- Feature: Allow locking individual transparency settings so they will not be changed by pressing 'x' (r12102)
- Feature: Add some missing VarAction2 variables (r12124)
- Feature: Make snow appear on rail tiles dependant on track height, not on height of the lowest part of the tile (r12098)
- Feature: [NewGRF] Specify the purchase, rail and road description of a bridge (r12069)
- Feature: [NewGRF] Add support for var 12, Variational Action 2 (r12045)
- Feature: Allow trees on shore (r12029)
- Feature: Invisible trees are now separate from the building concept (r12022)
- Feature: Add support for passenger engine designation for AI-use, NewGRF property 0x08 for trains (r12019)
- Feature: Show all cargo sources (en-route from) in the station view cargo waiting list instead of just one (r11990)
- Feature: [NewGRF] Resizable industry view window on callback 3A (r11987)
- Feature: [NewGRF] Implement var 8F (random bits) during callback 28 [FS#1697] (r11985)
- Feature: [NewGRF] Add support for Action 0D, var 13: informations about current map size (r11961)
- Feature: Support Action5 type 0D (newwater) (r11947)
- Feature: Allow building bridge heads on more slopes (r11937)
- Feature: [NewGRF] Add support for Rivers. Rivers can currently only be placed with-in the scenario editor (r11926,r11938,r11949,r12071)
- Feature: Generate.vbs script to allow project files generation for users unable to run generate bash script (r12123)
- Feature: Sort the strings in languages dropdown (r11886)
- Codechange: Drop MSVC 2003 support (r11979)
- Fix: Test purchase list loading/loaded sprites instead of unconditionally returning a possibly non-existant sprite (r12180)
- Fix: Return correct bridge price for AI when DC_QUERY_COST is set [FS#609] (r12171)
- Fix: When drag&drop mode was cancelled by keyboard input, depot/group window wasn't updated [FS#337] (r12166)
- Fix: Buffer overflow when drawing scrolling news [FS#1652, FS#1773] (r12165)
- Fix: If a train is 'stopping' when entering a depot, do not let it leave again [FS#1705] (r12163)
- Fix: Towns shouldn't build over houses owned by another town [FS#1757] (r12162)
- Fix: Towns will no longer build houses > 1x1 there where should be road (with 2x2, 3x3 grid town layouts) (r12161)
- Fix: Remove the arbitrary limit of 64 waypoints per town [FS#1744] (r12160)
- Fix: Chance16I was now biased towards zero - round to nearest now (r12156)
- Fix: Adjust aircraft slowing algorithm (r12144)
- Fix: Callback 0x3D always gets a cargobit in var 0x18, independent of grf version [FS#1766] (r12142)
- Fix: Do not allow adding tram to rail-road crossing when there is a vehicle on it (r12138)
- Fix: Show cargo capacity for articulated vehicles correctly in the purchase list. Multiple cargo types can also now been shown [FS#1769] (r12137)
- Fix: With mammoth trains disabled, maximum train length was limited to 9 (r12131)
- Fix: Use tile index 0 for planes in the air, so it cannot have an invalid tile index [FS#1745] (r12109)
- Fix: X/Y axis swap for station tiles in GetNearbyTile() was wrong way around [FS#1753]( r12108)
- Fix: Loading older savegames fixes (r12096,r12097)
- Fix: When a company bankrupts, remove drive-through road stops, ship depots and buoys too. Update owners of water and road [FS#1703] (r12095)
- Fix: Do not set station owner for buoys when merging company (r12093)
- Fix: Keep production level within delimited boundaries, while using var result 0D/0E and than multiplying/dividing it [FS#1755] (r12092)
- Fix: Assert when loading savegame with wrong tiletype at south map borders (r12088)
- Fix: Check overrides only for industries when mapping newgrf entities to 'real' entities [FS#1747] (r12086)
- Fix: Update waypoint signs when changing language (r12080)
- Fix: Use search paths when opening console scripts (r12079)
- Fix: When reusing a renamed deleted waypoint, keep the new name (r12076)
- Fix: Make docks at sea flood neighboured tiles (r12072)
- Fix: Possible deadlock when there are no houses available to build at given tile (r12062)
- Fix: Houses with zero probability could be built (r12062)
- Fix: Do not clear tiles when the town won't be able to build any buildings anyway (r12060)
- Fix: Allow building 2x2 building on slopes if not explicitly forbidden (r12060)
- Fix: It was possible to build 2x1 and 1x2 buildings on slopes even if it was not allowed (r12060)
- Fix: Teach NPF where road vehicles and trams can reverse (r12058)
- Fix: Ships can drive through opponents' ship depots (r12058)
- Fix: Slowdown train when approaching 90deg turn when 90deg turns are forbidden (r12057)
- Fix: Enable YAPF to start searching inside a wormhole [FS#1704] (r12056)
- Fix: Another way to fix AI trying to build road through depots (r12055)
- Fix: The cargo translation table was loaded at the right time, but all the other global variables were now loaded too early [FS#1737] (r12052)
- Fix: Random_func broke for desync debug (r12050)
- Fix: Memset on multibyte array with wrong byte count (r12049)
- Fix: Crash when centering on a vehicle (aircraft) that is outside of the map [FS#1741] (r12044)
- Fix: Allow building transmitters and lighthouses on tree tiles [FS#1736] (r12043)
- Fix: Reimplement how rivers and canals are stored in the map, allowing the sea/river/canal status to also be stored for buoys, docks, locks and depots. All these are now allowed on rivers and removal of them will revert to the original water type [FS#1676] (r12042)
- Fix: Change ownership of or remove statues when merging/bankrupting companies (r12038)
- Fix: For station tiles, only get road types for road stops (r12036)
- Fix: Teach YAPF where trams can reverse, and where not [FS#1702] (r12035)
- Fix: Do not show train speed as zero after loading paused game (r12033)
- Fix: When removing a statue, remove town statue flag for the statue owner, not current player (r12032)
- Fix: Prevent towns from removing or claiming ownership of player owned tiles when growing [FS#1689,FS#1719] (r12031)
- Fix: In one case trees could spread under bridges (r12024)
- Fix: Put a better suited text in the quit-dialog [FS#1690] (r12023)
- Fix: Restore initial intent on the invisible tree while transparent building patch setting [FS#1721] (r12018)
- Fix: When you have more than 9 network interfaces you'll enter the wonderfull world of overflows (r12017)
- Fix: Better work on strings in regard to gender [FS#1716] (r12015)
- Fix: Lighthouses and transmitters were never supposed to be build on a slope (r12014)
- Fix: When modifying watered tiles, mark neighboured canals and rivers dirty in more cases (r12013)
- Fix: Enable TownRatingTestMode during cost estimation with 'shift'-key (r12012)
- Fix: Do not consider one-corner-raised-shores to be watered tiles from all sides [FS#1701] (r12011)
- Fix: Avoid loading sample.cat if it 'looks' incorrect, and avoid later null pointer dereferences by moving volume lookup deeper [FS#1707] (r12009)
- Fix: Possible reading from an invalid pointer [FS#1717] (r12005)
- Fix: When skipping Action 11 or 12, also skip belonging sprites (r12001)
- Fix: Do entrance-slope-check for every tile of railstations (r11999)
- Fix: Possible remote assert by setting bit 6 of p1 for CMD_REMOVE_ROAD [FS#1692] (r11998)
- Fix: Update train statusbar when stopping from zero speed [FS#1706] (r11996)
- Fix: Resize station/roadstop/dock/airport construction windows if cargo acceptance list is too long (r11993)
- Fix: When building two rail stations close to each other (with control) so they looked like one long track trains would see them as one (r11992)
- Fix: Resize autoreplace window to fit purchase information text if it is too large (r11989)
- Fix: Build system ignored changes to table/control_codes.h which require strgen to be rebuilt (r11986)
- Fix: Also draw corner shores under rail tracks (r11984)
- Fix: Use unicode glyph mapping to fix up missing/shuffled sprites in original data files instead of shuffling or skipping sprites directly [FS#1698] (r11981)
- Fix: Industries using results 0D/0E on callback cb29/35 were a bit too eager to close down (r11976)
- Fix: Shore and sea tiles under bridges were converted to canals in old savegames [FS#1684] (r11974)
- Fix: Use grass tiles for corner shores, if shores got replaced by ActionA [FS#1683] (r11973)
- Fix: Old AI shouldn't build fast planes with a small airport in orders(r11972)
- Fix: MP_ROAD can have railbits too - OPF searching over rail of diffen t owner behind crossing (r11967)
- Fix: OPF was searching through depots and normal road stops [FS#1403, FS#1506] (r11966)
- Fix: Tropic zone data was returned incorrectly [FS#1685] (r11964)
- Fix: NewAI couldn't build any road vehicles when there were any tram grfs loaded (r11958)
- Fix: Disallow building locks and docks on rapids [FS#1675] (r11956)
- Fix: Do not allow modifying roadbits when other roadtypes would need different foundation (r11953)
- Fix: Loading of very old savegames was broken (r11951)
- Fix: Slope detection of bridge ramps. Helps YAPF and Trolly (r11946)
- Fix: FileExists() failed for non latin paths (win32) (r11945)
- Fix: Allow building drive-through road/tram stops at road/tram track that has no owner (r11944)
- Fix: 'BRIDGE_TOO_LOW_FOR_TERRAIN'-check was wrong for steep slopes (r11936)
- Fix: [Autoreplace] Single to dualhead locomotive replacefailed when player had enough money to replace and refit one but not enough to refit the last one as well [FS#1624] (r11929)
- Fix: [Autoreplace] Autoreplace could refit train engines to the wrong cargo type if the old engine had no cargo capacity and the new one had (r11928)
- Fix: Loading old, pre savegame version 2, savegames (r11925)
- Fix: AI was reading wrong tile slope while building road bridge (r11917)
- Fix: set correctly crossing state after train reversal, train leaving crossing, train crash (r11900)
- Fix: Segmentation faults/wrong frees due uninitialized memory in the AI [FS#1658] (r11887)
- Fix: Assert when trying to remove rail from a house or industry tile [FS#1663,FS#1665-6-7-8,FS#1680,FS#1686-7-8 FS#1715 FS#1742 FS#1771 FS#1776](r11883)
- Fix: Crash in MP in vehicle group window if the currently selected group is deleted by another player (r11878)
- Fix: Another way to crash competitors' train in a station (r11877)
- Fix: Automatically sending aircraft to depot for autoreplace/renew is now triggered by the correct conditions (r11875)
- Fix: EngineHasReplacementForPlayer() didn't look in ALL_GROUP (r11872)
- Fix: Do not update signals after each tile when building/removing a large block of track/signals/station [FS#1074] (r11871)
- Fix: Slow down train when approaching tile we can't enter in more cases (r11870)
- Fix: Do not make crossing red when we can't enter it in any case (r11870)
0.6.0-beta3 (2008-01-16)
------------------------------------------------------------------------
- Feature: Replaced fixed size custom name array. Names are now attached to their object directly and there is no limit to the amount of names (r11822)
- Feature: Add drag-n-drop support to the raise/lower land tools. Land is raised/lowered at the start and the rest of the area levelled to match (r11759)
- Feature: Add support for NewGRF's train 'tilt' flag. Trains with tilt capability (specific details are per NewGRF set) will be given a 20% speed limit bonus on curves (r11741)
- Feature: Added sorting for cost, running costs and speed to road vehicles and ships build windows (r11710)
- Feature: List neutral stations where the player has service in the station list too (r11670)
- Feature: Check whether (some) characters are missing in the current 'font' for the 'currently' chosen language and give a warning when that does happen (r11646)
- Feature: Support shore replacement via Action 5 (r11726)
- Fix: When two NewGRFs 'fight' to define the same cargo it could happen that the strings are defined by one cargo and the 'action2' by another and when one assumes that both come from the same NewGRF [FS#1559] (r11862)
- Fix: Recompute town population when removing a 'newhouses' grf, or when loading a game with missing 'newhouses' grfs [FS#1335] (r11855)
- Fix: Road vehicle count was incorrect in network lobby window (r11844)
- Fix: Mark dirty canal tile even in diagonal direction from flooded tile, draw correctly canal next to half flooded rail tile (r11843, r11838)
- Fix: At least one instance of dmusic driver is needed for it to be registered and usable (r11826)
- Fix: An articulated road vehicle could split up when it turned around at a corner and then would enter a drive through station at the next tile [FS#1627] (r11825)
- Fix: Switch _screen to the output buffer and disable usage of 32bpp-anim animation buffer during giant screenshots [FS#1602] (r11813)
- Fix: Do not crash trains when leaving depot to a very long track [FS#716] (r11802)
- Fix: Take town rating into account when testing if a command can be executed [FS#1616] (r11795)
- Fix: Reversing a train when loading at a station with an adjacent station in the same axis crashed [FS#1632] (r11794)
- Fix: Group names got not deallocated in the command test run [FS#1614] (r11743)
- Fix: Run window tick events when paused, so that news pop-ups and the about window still progress. For other windows the events are ignored when paused [FS#1319] (r11742)
- Fix: Modify and possibly discard key events for code points in the unicode private use area [FS#1610] (r11740)
- Fix: Set the new scroll position after zooming in instead of before, as the zoom will cancel it out [FS#1609] (r11739)
- Fix: Do not reset loading indicator IDs when only reloading NewGRFs [FS#1574] (r11735)
- Fix: Elrail merge gave elrail, monorail & maglev unintended speed bonuses for curves, as the bonus was based on the railtype index. The bonus is now specified by a property of the railtype (r11732)
- Fix: Clear sprite override data before performing NewGRF wagon attach callback. This stopped the callback working for autoreplace and when moving wagons from train to train in a depot [FS#1582] ( r11731)
- Fix: If there are no houses that can be build in a specific year yet, force the houses with the earliest introduction year to be available [FS#1577] (r11727)
- Fix: Make it impossible (for users) to circumvent the length checking of the NewGRF 'allow wagon attach' callback by moving several wagons at a time (r11724)
- Fix: Do not put more than one Random() in function calls because parameter evaluation order is not guaranteed in the C++ standard [FS#1561] (r11716)
- Fix: Do not allow player inauguration date on scenarios to be bigger than current year [FS#1569] (r11714)
- Fix: Add more house string id ranges to MapGRFStringID so NewGRFs use the proper string ids (r11712)
- Fix: Do not allow refitting flooded (destroyed) vehicles (r11707)
- Fix: Trains could have sprites with wrong direction when reversing, also was inconsistent with save/load process [FS#1557] (r11705)
- Fix: When removing buoys, return to water or canal depending on their owner (r11666)
- Fix: Animation informations should not be copied from original industry tile spec, while doing an action 00, industry tile, prop 08 (r11665)
- Fix: Do not allow modifying non-uniform stations when non-uniform stations are disabled [FS#1563] (r11659)
- Fix: 'Initialised' NewGRFs could still be deactivated in the later 'activation' pass (r11650)
- Fix: Vehicles were still followed when sold [FS#1541] (r11632)
- Fix: Many viewports could crash the scenario editor [FS#1527] (r11629)
- Fix: Popping from text reference stack must be done in a precise order. But some compiler (MSVC) over optimised it and inverted this order [FS#1532] (r11627)
- Fix: There were still some cases where one could not build a tram track, but the tram could become blocked [FS#1525] (r11621)
- Fix: Do not make crossing red behind depot the train is entering [FS#1531] (r11619)
- Fix: Buoys are just waypoints, so don't allow load/unload/transfert for them (r11618)
- Fix: Sometimes large values could go off the chart [FS#1526] (r11616)
- Fix: Temperate banks can only be built in towns (over a house) (r11615)
0.6.0-beta2 (2007-12-09)
------------------------------------------------------------------------
- Feature: Allow setting a default password for new companies in network games (r11556)
- Feature: Signal selection GUI for the ones that really like to use that over CTRL (r11547)
- Feature: Make the bridge selection window resizable (r11539)
- Feature: [OSX] Added support for using Quartz instead of Quickdraw in windowed mode on OS X 10.4 and higher (r11496)
- Feature: Allow to resize on creation the smallmap gui in order to show all the types industry available, allow to enable/disable individually or all at once, the industries shown on small map (r11474)
- Codechange: Send and store the passwords a little more secure to/in the servers (r11557)
- Fix: Wrong error messages were shown when trying to build some industries in the scenario editor [FS#1524] (r11609)
- Fix: [NewGRF] Do not trigger industries, but only the industry's tiles (r11608)
- Fix: Wrong count of Kirby trains when a ship was build [FS#1482] (r11605)
- Fix: Tiles were not marked dirty in some cases when removing a lock or flooding (r11582, r11604)
- Fix: Make price for railtype conversion more realistic; conversion should not be more expensive than removing and rebuilding [FS#1481] (r11603)
- Fix: Do not allow changing network only patches settings from console when not in network game (r11594)
- Fix: IsSlopeRefused() result was half wrong causing banks to be built on wrong places (r11590)
- Fix: When ship depots got destroyed they always returned to water, even when it should have been canals [FS#1514] (r11589)
- Fix: The one way road button wasn't reset on abort (r11587)
- Fix: Windows could get completely missing when one resized the window to something very small [FS#1484] (r11583)
- Fix: Invalidate 'list trains/roadvehs/ships/planes' widgets when station part is added/removed so it does not become glitchy (r11577)
- Fix: Flood train stations when there are no trains on border tiles too (r11574, r11570)
- Fix: Reinitialise windows system before loading a savegame because not doing so can cause crashes [FS#1494] (r11572)
- Fix: Road vehicle getting to the wrong side of a station when trying to overtake in there [FS#1493] (r11571)
- Fix: Full paths sometimes did not work correctly [FS#1480] (r11568)
- Fix: Break the chain before moving a vehicle after another in the same chain instead of causing an infinite loop [FS#1512] (r11566)
- Fix: Aircraft sometimes stopped mid-air when the airport got destroyed [FS#1503] (r11562)
- Fix: Group list was not updated when removing the last group [FS#1504] (r11561)
- Fix: Overflow when drawing graphics with high company values [FS#1505] (r11558)
- Fix: If ever the air/heliport is suddenly not available while the "chopper" is descending, just go back into flying instead of stopping mid air [FS#1496] (r11546)
- Fix: Cargo translation was sometimes done when it should not be done [FS#1501] (r11544)
- Fix: [OSX] Detect statvfs at runtime (based on OSX version) instead of compile time. This should prevent a crash on OSX 10.3 with the precompiled binaries (in the load/save windows) (r11541)
- Fix: [OSX] Do not try to compile the quartz video driver on OSX 10.3 as it will fail (r11540)
- Fix: Do not do all kinds of 'updates' for town, waypoint, station and other signs when you have not converted the map to the 'current' format as that means you are going to read data in the 'old' format when you assume that it is in the 'current' format, which is eventually going to break (r11525)
- Fix: Assertion when tram reversed at a station [FS#1485] (r11524)
- Fix: The scrollbar of the network gui could run out of bounds (r11522)
- Fix: [OSX] The cocoa video driver let the mouse cursor escape the window when using rmb scrolling (r11520)
- Fix: Signs totally illegible when transparant signs is turned on and zoomed out more than one level [FS#1463] (r11507)
- Fix: Selling vehicles could cause the window of others to scroll to that location [FS#1471] (r11506)
- Fix: Do not do standard production change if callbacks 29/35 failed, disable smooth economy for industries using callbacks 29/35 (r11502)
- Fix: Two small layout issues with the vehicle grouping GUI (r11478)
- Fix: A road vehicle must not show that it is driving max speed when it is standing still waiting for the vehicle in from of it [FS#1451] (r11477)
- Fix: OpenBSD has ALIGN already defined, causing compilation failures [FS#1450] (r11467)
- Fix: Operator priority problem resulting in problematic autoroad placement in some cases (r11466)
0.6.0-beta1 (2007-11-18)
------------------------------------------------------------------------
- Feature: Make news messages related to the industry (production) changes better configurable; you can now disable news messages popping up for industries you are not servicing (r11442)
- Feature: When sorting stations by cargo sum, only sum the cargoes that are selected in the filter (r11437)
- Feature: Show all players who have shares, not just the first two (r11435)
- Feature: Make OTTD's sprites replaceable using Action 5 and make replacing contiguous subsets of sprites in for some types possible in Action 5 (r11433)
- Feature: Allow town-bridges to be build on slopes (r11395)
- Feature: Auto-road; same as auto-rail, but for road and trams and only on X and Y direction (r11339)
- Feature: OTTD version checking for NewGRFs. This allows NewGRFs to do something different for different versions of OpenTTD, like disabling it for too low versions or loading different graphics (r11330)
- Feature: Half tile- and anti-zig-zag-foundations (r11319)
- Feature: Control-Clicking the Centre Main View button on the vehicle window allows the main viewport to follow the chosen vehicle (r11304)
- Feature: User customisable faces (r11269)
- Feature: Make more advanced rail types more expensive to build (r11265)
- Feature: Implement the "moreanimation" feature of TTDP, so we can properly support newindustries (r11228)
- Feature: [NewGRF] Add support for newindustries (r11204)
- Feature: Sort the NewGRFs by name, making searching a specific NewGRF a lot easier (r11175)
- Feature: Add possibility to show the bounding boxes of sprites using CTRL-B so one can get a better understanding of the used bounding boxes to fix the glitches that still exist. Note that showing the bounding boxes is not glitch free; it only gives you some knowledge where the bounding boxes are (r11174)
- Feature: Remove the arbitrary limit of 10 articulated parts for a vehicle (r11120)
- Feature: Autoslope, changing of slopes of tiles that already have something build on them. Does not work for tiles of houses/industries/stations that do not allow autosloping (r11107)
- Feature: Support for encapsulating files into a .tar file; you can pack all files in your data/ directory in how ever many .tar files you like, keeping the directory-structure equal to the unpacked version, and OpenTTD can handle them just like the files were unpacked (r11106)
- Feature: Allow slopes under statues (r11069)
- Feature: [OSX] Added more options for right click emulation (controlled from the interface tab in the patch window) (r10996)
- Feature: Allow building and removing tracks and signals when there is a train on a parallel diagonal track that does not interact with this one. (r10922)
- Feature: Added TileHeight to the Land Area Information tool [FS#653] (r10878)
- Feature: [OSX] OpenTTD will now pick the same language as finder is set to if no config file is found (r10851)
- Feature: Provide an infrastructure to have resizable windows that are smaller than the default window size. Useful for playing on very low resolution systems (r10704)
- Feature: Support for autosave_on_exit in the console, so dedicated servers can use it (r10658)
- Feature: Add a soft limit of 4096 "entities" in a station's waiting queue and a hard limit of 32768 so (malicious) people cannot cause a "denial of service" attack by filling cargo lists (r10555)
- Feature: Replace all the windows for Industry building by a more flexible one (r10496)
- Feature: Support for "prospecting" raw industries, i.e. you pay an amount of money and then it might (with a given chance) build a raw industry somewhere on the map (r10451)
- Feature: Automatic signal completion, enabled by pressing CTRL when dragging signals. Signals will continue following track until an existing signal, junction or station are reached. This currently replaces the existing use of CTRL-drag for changing existing signal type (r10437)
- Feature: New sign editor features including switching to previous/next sign (r10401)
- Feature: Disallow (in the GUI) the building of infrastructure you do not have available vehicles for. This means that the airport building button is disabled till you can actually build aircraft. The game itself will not disallow you to build the infrastructure and this "new" behaviour can be overridden with a patch setting [FS#669] (r10353)
- Feature: Add the possibility of automatically filling in timetables based on the times from the first (or subsequent) run-throughs (r10331)
- Feature: Option to select the "default" rail type when you start a new game or load a game. This is done either static, i.e. rail, electrified rail, monorail and maglev, or dynamic which takes either the first or last available railtype or the railtype that is used most on the map [FS#812] (r10329)
- Feature: Give a better explanation why the loading of a savegame failed and do not crash on loading savegames that were altered by patches or branches [FS#917] (r10300)
- Feature: A sticky button for the client list window [FS#885] (r10293)
- Feature: Allow double-clicking on certain places: add NewGRF window, build-vehicle and town-action (r10265, r10267)
- Feature: Loading indicator, which shows in % how full a vehicle is while loading/unloading (r10254)
- Feature: Introduce a form of timetabling for vehicles (r10236)
- Feature: [NewGRF] Add support for action 0F (town name generator) (r10211)
- Feature: Add support for personal directories on Windows. (r10182)
- Feature: Add support for anti aliased typefaces via FreeType. This is configurable for each font size in the configuration settings and requires using the 32bpp blitter and suitable fonts (r10166)
- Feature: 32 bpp sprite support and dedicated driver does not blit nor render by default. Can be overruled by user (r10121)
- Feature: Add support for articulated road vehicles (r10097)
- Feature: Allow moving of orders instead of removing them and readding them somewhere else [FS#828] (r10071)
- Feature: Replace hard coded spritecache size with a configuration option, sprite_cache_size. The default size is 2MB and the value can range from 1 to 64MB. If you experience slow-downs when scrolling the map, try increasing this setting (r10042)
- Feature: Skip to the selected order in the order list when clicking on the "skip" button while pressing CTRL [FS#760] (r10033)
- Feature: Sort the strings in server language dropdown and the town names dropdown (r10032, r10036)
- Feature: Build windows of trains, road vehicles and ships can now be sorted by cargo capacity (planes already had this option) (r10024)
- Feature: More languages flags for servers [FS#790] (r10017)
- Feature: Allow different signal types on one tile [FS#362] (r10006)
- Feature: Support for oneway roads (r9999)
- Feature: Add smooth viewport scrolling. This must be enabled with patch setting 'smooth_scroll' (r9962)
- Feature: Allow terraforming under bridges (r9950)
- Feature: Support for trams (r9923)
- Feature: Allow building new stations adjacent to existing stations by holding down control (r9905)
- Feature: Add one new zoom-out level: 8 times (r9884)
- Feature: Advanced vehicle lists a.k.a. group interface. Now you can make groups of vehicles and perform all kinds of tasks on that given group (r9874)
- Feature: Make "improved loading" a proper improved loading instead of loading one (semi-)random vehicle at a time. Furthermore fill multiple vehicles at once when there is enough cargo to do so (r9838)
- Feature: Add drag and drop removal of station tiles (r9810)
- Feature: Support for "curvature info", Action 2 for train, variable 45 (r9803)
- Feature: [NewGRF] Add action 1, 2 and 3 support for canals (r9797)
- Feature: Add the possibility to choose different road patterns for towns to use (r9779)
- Feature: Add an option to automatically pause when starting a new game (r9734)
- Feature: Add the concept of cities. A (configurable) proportion of towns can start off larger, and will grow twice as quickly as other towns (r9667)
- Feature: Add NewGRF Action 5 (Sprite Replacement) support for 2cc colour maps, airport, and road stop sprites (r9645)
- Feature: Increase cargo types from 12 to 32 and enable newcargo flag in NewGRF loader (r9638)
- Feature: Make it possible to have some control over the town growth (r9613)
- Feature: Add list_patches console command. This shows all patches along with their current values (r9565)
- Feature: Add more finer control to transparency options, including a new toolbar (r9563)
- Feature: Add support for variable snow lines in the arctic climate, supplied by NewGRF files (r9371)
- Feature: [NewGRF] Add support for newhouses (r9315)
- Feature: [NewGRF] Add support for Action 13, which allows you to translate GRF-specific texts. The translations will only be shown if you are using a language with a GRF language id and if a string has not already been set specifically for the language you are using (r9037)
- Feature: Translation dependant formatting of dates (r8906)
- Feature: If an action 7/9 leads to skipping the rest of the file, disable the NewGRF if an action 8 has not been encountered yet (r8831)
- Feature: Stop loading and disable the current NewGRF if a fatal error message in Action B is encountered. Also be more strict on the values accepted (r8830)
- Feature: Build aircraft windows will no longer show aircraft that cannot use the airport in question (r8771)
- Feature: Drive-through road stops (r8735)
- Feature: Allow upgrading bridges by building a new bridge over the top (r8567)
- Feature: Provide aircraft with vertical separation depending on their altitude and velocity (r8534)
- Feature: When linking the terraform toolbar to the build toolbars place them side by side instead of on top of each other (r8436)
- Feature: The vehicle build windows are now resizable in horizontal direction as well (r8331, r8336, r8338)
- Feature: Automatically build semaphores before a configurable date, which can be set by each network player separately (r8151)
- Feature: Increase sprite limit from 16384 sprites to 16777216 sprites (r8128, r8129)
- Feature: Add the ability to load savegames when you do not have the exact GRF files in your list. GRF files that are found based on GRF ID (but not on matching md5sum) are used instead of disabling them. This does not affect MP games, there you still need an exact match (r8106)
- Feature: Show the activated status of the GRF list after pressing 'apply' in the NewGRF window, instead of the local list (r8094)
- Feature: The station list does now remember the sort settings (r8065)
- Feature: Make it possible to override the bind address and port of a dedicated server from the command line (r7802)
- Feature: Add command line option to prevent saving of high score and configuration on exit and a console command to manually initiate a configuration save (r7801)
- Feature: Add support for tractive effort to 'realistic' acceleration (7592)
- Feature: Allow to build bridges of arbitrary rail/road combinations (including signals) (r7573)
- Codechange: Do not allow configuration changes, that NewGRFs can directly use to change their behaviour, during network games as this can cause desyncs (r11452)
- Codechange: Make opening a new toolbar not overlapping its parent one, by locating it under the parent, and aligned with the left side of it [FS#1310] (r11256)
- Codechange: Do not brute force determine the first vehicle in the chain or previous vehicle, but do it by properly accounting the previous and first pointers when updating the next pointer. This gives a performance increase of about 15% when there are a lot of vehicles in the game (r11011)
- Codechange: Cache expensive NewGRF station variables during sprite lookups/callbacks (r10509)
- Codechange: Keep track of the origin, time of travel and accumulated feeder share (transfers) of individual pieces of cargo. This means that cargo is not thrown on a big pile when it is put in a station or unloaded at a station, however the GUI does not reflect these changes yet so you will not actually see it (r10266)
- Codechange: Do not limit the cost of tunnels (r10248)
- Codechange: Add new vehicle hash table for collision detection and finding vehicles on a tile. The hash area scanned is far smaller than the old hash table, which is now used for viewport updates only. This should give a significant performance improvement for games with many vehicles (r10111)
- Codechange: Don't redraw all station tiles when cargo is added or removed if the station has no custom graphics (r10062)
- Codechange: Add some support for NewGRF var 7D, temporary storage array (r9707)
- Codechange: Add support for returning 'ttdpatch variables' (Action D) (r9701)
- Codechange: Implement NewGRF callback 36, which allows changing of various properties which were previously static (r9671 and several others)
- Codechange: Add support for multiple 'base' directories for NewGRF searching (r9560)
- Codechange: Implement actions 1/2/3 for cargoes, callback handler and custom icon sprites (rmany)
- Codechange: Rename the 'New <vehtype>' button of the global vehicle lists to 'Available <vehtype>' as it is a view-only list, not one from which you can purchase (rolling) stock (r8420)
- Codechange: Remove the landscaping button from the build toolbars (r8143)
- Codechange: [NewGRF] Do not mark as unsafe those NewGRFs that set their own parameters (via action D) and/or change only bridge sprite table layouts (action 0, property D) (r7831)
- Fix: The CHANCE16 functions were biased; a 32768 in 65536 chance was really a 32769 in 65536 chance (r11454)
- Fix: Do not create shores in canyons (r11438)
- Fix: Starting OpenTTD with DOS files made it look weird out of the box (r11433)
- Fix: Properly support genders coming from NewGRFs instead of crashing [FS#1430] (r11422)
- Fix: Do not ignore the autorenew settings for new games when creating a new game [FS#1428] (r11415)
- Fix: Do not do a 270 degree turn when 90 degrees is enough on a commuter airport [FS#1422] (r11408)
- Fix: In rare cases OpenTTD could segfault when resizing and scroll the main window (r11405)
- Fix: Manually replacing a vehicle with shared orders makes it lose it is order index and service interval [FS1384] (r11370)
- Fix: Road vehicles must not drive through each other on bridges/in tunnels [FS#1258] (r11366)
- Fix: When stopping a ship or aircraft, set their speed to 0 so they will not continue at the speed where they were stopped at [FS#1288] (r11365)
- Fix: Cloning vehicles with non-standard sub-cargotypes (i.e. livery refits) failed [FS#1380] (r11362)
- Fix: Loading too many GRFs was not handled gracefully causing crashes and such [FS#1377] (r11355)
- Fix: Add missing elrail sprites for some rail build buttons/cursors (r11350)
- Fix: Trees can now be planted on bare land without making it grassy, planting tree in desert does not make it grassy for the first tile-cycle and when a tree dies in desert, it no longer becomes a snowy tile for the first tile-cycle (r11244)
- Fix: The explosion vehicles were placed too far to the south [FS#1312] (r11234)
- Fix: One could sell vehicles that were crashed in a depot, which would still yield money/one could construct trains of crashed vehicles [FS#1307, FS#1228] (r11229, r11230)
- Fix: Electric trains were not shown as stopped in depots when converting it from elrail -> normal rail [FS#1260] (r11167)
- Fix: A lot of graphical glitches by changing some bounding boxes. It is not perfect yet, but a *very* good step into the right direction (r11128)
- Fix: When autorenew is enabled and it cannot renew the vehicle anymore (because the player cannot build the engine), the ageing warnings as if autorenew is not enabled are shown [FS#553] (r11064)
- Fix: Inconsistency between rail<->elrail conversions of different kinds of rail containing tiles (normal rail, stations, depots, etc) [FS#1182] (r11059)
- Fix: Crash when having the Finance window opened of the player you are cheating to [FS#1177] (r11028)
- Fix: Switching players (using the cheat) crashed on Big Endian machines [FS#1150] (r11023)
- Fix: The canal border determination did not take oil rigs into consideration (r11022)
- Fix: Do not display income/expenses when they do not belong to a "valid" tile, like the money cheat/giving money [FS#1175] (r11021)
- Fix: One could not give money when (s)he had too much money or rather: when casting the amount of money to an int32 becomes negative [FS#1174] (r11020)
- Fix: When determining the gender of a string, do not assume that the gender is in the front of the string when there can be case switching code at that location [FS#1104] (r10792)
- Fix: Determining whether there is a tunnel going under the lowered area is only needed in two directions instead of all four, so take the directions (one for each axis) to the nearest border (along the given axis) [FS#1058] (r10686)
- Fix: Graphical glitches when the "link landscape toolbar" patch is turned on when opening one of the construction toolbars [FS#1076] (r10685)
- Fix: Trolly AI did not know about steep slopes, and used wrong tileh in some cases [FS#1070] (r10655)
- Fix: Be consistent with the space between the company name and the player number, i.e. always put a space between them [FS#1052] (r10627)
- Fix: [YAPF] Ships received curve penalty for non-diagonal straight move (r10578)
- Fix: Do not segfault when you quit in the end-of-the-game screen [FS#1020] (r10548)
- Fix: When Cheat-Window is open and a new month happens, the window was not redrawn instantly (r10547)
- Fix: You can now have both Available Train as Available Ship window open [FS#1026] (r10546)
- Fix: Cargo payment rates overflow and cargo payment rates diverge from cost rates making it impossible to make any profit after a certain number of years. Both are solved by stopping the inflation after 170 years; there is absolutely no point in continuing the inflation after that as it only makes the game have overflows at some point that cannot be solved; using larger variables only delays the inevitable [FS#1028] (r10541)
- Fix: Error dialog was sometimes shown on all clients when a command failed instead of only the client that actually did the command [FS#1015] (r10501)
- Fix: The network protocol check for required NewGRFs sent static NewGRFs too (r10414)
- Fix: When landscape generating, allow for 200ms between screen updates instead of updating every 200ms. Previously slow screen updates would result in very slow map generation (r10396)
- Fix: One could only build a limited number of stations before one had to rename them [FS#278] (r10320)
- Fix: Acceleration not calculated properly when a train goes up a hill between tunnels [FS#786] (r10317)
- Fix: [YAPF] Now it is no longer needed to invalidate the YAPF segment cache every tick in MP (read performance increase). Segment cost now does not contain the curves between segments. As a result the cache should be now accurate (r10302)
- Fix: [YAPF] Assertion triggered in some special cases [FS#901] (r10301)
- Fix: Flush stdout on dedicated server output to ensure an update of stdout [FS#775] (r10295)
- Fix: With smooth_economy, when industry production hit 32, it stayed there for ever. Give it some chance to get out of that uber-lowness (although it is a very slim chance, at least it has one) (r10290)
- Fix: Also age engines that are not front-engines [FS#202] (r10288)
- Fix: Money overflow bugs in many locations [FS#723] (r10212)
- Fix: Fix issues related to fixed names, fixed places of files/directories and application bundles [FS#153, FS#193, FS#502, FS#816, FS#854] (r10182)
- Fix: A vehicle without visual effects is not per definition unpowered (r9802)
- Fix: Do not assume that trains running on monorail/maglev cannot smoke/spark (r9801)
- Fix: Play sound effects based on the engine class, not the rail type (r9800)
- Fix: Separate engine class and engine running cost class (r9799)
- Fix: Clone vehicles will no longer refit for free (r9689)
- Fix: Improved loading does not use a huge amount of processing power anymore when having a lot of trains [FS#423] (r9683)
- Fix: Truncate the NewGRF information text in the NewGRF GUI if it is too long (r9449)
- Fix: Cancel in password queries reduces amount of players in the network game when they have not joined the game yet [FS#688] r9378
- Fix: If all news-setting buttons show 'full', make the ALL-button show 'full' too (r9137)
- Fix: Open and close messages now have their own setting, so you can hide economy changes, but do show open/close of industries [FS#525] (r9097)
- Fix: Do not make owner signs transparent, as then you loose the information who it owns [FS#637] (r9067)
- Fix: Store the owner of a statue, so when it gets removed, the town is notified of it [FS#638] (r9066)
- Fix: Inactive connections are not automatically kicked, i.e. people who only open a telnet (or similar) connection to a server [FS#115] (r9038)
- Fix: Do not select a disabled platform length/number of track count when going out of drag-drop mode [FS#450] (r8999)
- Fix: Make an aircraft at 400 km/h go as fast as a train at 400 km/h (r8973)
- Fix: You were unable to build roads in the scenario editor when there is no town 0, even though there are other towns (r8608)
- Fix: Road Vehicles now can obtain a slot even if the station is very spread out [FS#577] (r8536)
- Fix: Allow lumber mill to cut trees only when they are full grown (r8535)
- Fix: Segmentation fault when the toolbar gets removed and you have selected one of the items in a sub menu of the toolbar (r8533)
- Fix: Remove phantom oil rigs sometimes present in old savegames (r8485)
- Fix: When a station is removed, vehicles do not get excessive payment any longer, as the origin TILE is now stored as long as the origin STATION for the transported cargoes (r8144)
- Fix: The game could crash when the chat key (<ENTER>) is pressed too vehemently during the join of the game. Your client's id does not exist in the clients list yet, and returns NULL (r8132)
- Fix: Rail vehicles can no longer enter tunnels or bridgeheads with wrong railtype (r7976)
- Fix: When path finding onto a bridge or tunnel end from previous tile (but not warping from the opposite end) check the enter direction. This fixes signal setting if a rail ends on the top of a tunnel end (r7718)
- Fix: When following path for signals, do not skip back to the previous tile, as for tunnels and bridge ends the entering direction is wrong (r7717)
- Fix: [YAPF] suppress 'Train is lost' message if path finding ended on the first two-way red signal due to YAPF.rail_firstred_twoway_eol option (r7628)
- Fix: [OPF] signal update was incorrectly propagated (r7620)
0.5.3 (2007-09-15)
------------------------------------------------------------------------
- Fix: Possible NULL pointer dereference that could be triggered remotely (r11074)
- Fix: Removing CMD_AUTO from some commands could remotely trigger an assertion [FS#1179] (r11040)
- Fix: Underflow that caused overflows in the performance rating [FS#1179] (r11039)
- Fix: [Windows] MIDI does not stop when closing openttd [FS#1164] (r11029)
- Fix: Do not unconditionally assume that a tile has a depot (r11027)
- Fix: Give a more correct error when building some things on tile 0 [FS#1173] (r11024)
- Fix: Do not display income/expenses when they do not belong to a "valid" tile, like the money cheat and giving money [FS#1175] (r11021)
- Fix: One could not give money when (s)he had too much money [FS#1174] (r11020)
- Fix: Disallow buying/selling shares in your own company or a bankrupt company [FS#1169] (r11018)
- Fix: Crash when quiting the game in one of the end score windows [FS#1218] (r11071)
0.5.3-RC3 (2007-08-30)
------------------------------------------------------------------------
- Fix: Spectators are not allowed to issue commands (r11006)
- Fix: Make the AI not crash when it has ships as the AI does not support them [FS#1133] (r10942)
- Fix: Trains would not get flooded when they are at the lower part of a tile that would become a coast tile after flooding [FS#1127] (r10892)
- Fix: Removing road with the road removal tool would also work with a negative bank account, making the bank account even more negative than it was [FS#1125] (r10890)
- Fix: Some isocodes were wrong, resulting in some NewGRF not working properly for the affected languages (r10877)
- Fix: [Windows] Do not try to minimise or restore the window when closing OpenTTD [FS#998] (r10835)
- Fix: Trains going over bridges would get the "going down hill" accelerate bonus, which causes trains to go faster on bridges than they would be going on level land [FS#1096] (r10739)
- Fix: Trains being split into two pieces when loading an old savegame [FS#1062] (r10735)
- Fix: [OS/2] Fix chdir problem with open/save dialog (r10650)
- Fix: One could not remove locks that were build in a (very) old version of OpenTTD [FS#1038] (r10593)
- Fix: One cannot navigate using arrow keys in the game name text box [FS#1038] (r10500)
- Fix: Ship's maximum speed wrongly shown [FS#1013] (r10497)
- Fix: [OSX] Of the resolution is changed to something that is too high for the monitor, then it is reduced to fit the monitor size, solving several crashes and graphical glitches [FS#458] (r10410)
- Fix: NPF was leaking memory each time it got initialized, except for the first time (r10357)
- Fix: [YAPF] 'target_seen' flag that is set prematurely in some cases (1 tile long cached segment followed by target station) which caused asserts to trigger [FS#884] (r10199)
0.5.3-RC2 (2007-07-07)
------------------------------------------------------------------------
- Fix: Visual glitches when a window is resized in the WE_CREATE callback (r10465)
- Fix: [Windows] _wnd.has_focus was not properly set after using ALT-TAB [FS#962] (r10399)
0.5.3-RC1 (2007-06-28)
------------------------------------------------------------------------
- Feature: Make the client list window (for network games) stickyable (r10293)
- Feature: console command to get the current game date (r10137)
- Fix: Waypoints could be renamed when you are not the owner (r10368)
- Fix: Smooth economy did not close primary industries and it allowed increasing of production of industries that should not have rising productions (r10348, r10347, r10290)
- Fix: Acceleration for trains on slopes is not calculated properly [FS#786] (r10344, r10317)
- Fix: The 'old' pathfinders (OPF and NPF) for road vehicles could not find a path when in a tunnel [FS#290] (r10345)
- Fix: Only add the autoreplace menu when autoreplace actually knows about the group [FS#880] (r10337)
- Fix: Signal state sometimes not properly set when the signal "pathfinder" reached the end of a line [FS#910] (r10336)
- Fix: News messages were shown over the endgame/highscore windows [FS#943] (r10333)
- Fix: Rail could be destroyed when building tunnels (r10306)
- Fix: Flush the output of the dedicated server console (r10295)
- Fix: The "pause" key did not work in the scenario editor (r10294)
- Fix: Age non-front engines too (so when you move engines around in the depot they do not get age 0 when they are much older [FS#202] (r10288)
- Fix: Do not make everyone spectator if 1 joining client failed to create new company (r10284)
- Fix: Remove invalid characters (for the file system) from savegame names [FS#916, FS#850] (r10272, r10116)
- Fix: Some old savegames could have the wrong bits unset (r10268, r10147)
- Fix: Do not look in every direction for tunnels when building one, one direction is enough (r10258)
- Fix: [Windows] Do not mess desktop when using ALT-TAB [FS#876] (r10251, r10186)
- Fix: Take the age of the front vehicle for station rating (r10246)
- Fix: Terraforming wipes out canals. Now you always have to remove the canal before terraforming, instead of "just" removing the canal [FS#594] (r10240)
- Fix: Only 2 trains could crash at one time as collision checking stopped on the first hit. This could technically cause desyncs in network games as the collision hash order is not guaranteed [FS#892] (r10222)
- Fix: Land under foundations was terraform when it shouldn't be terraformed [FS#882, FS#890] (r10219)
- Fix: Do not make a 270 degree turn on the international airport when a 90 degree turn is enough (r10187)
- Fix: Crash when trying to get the aircraft movement state of an aircraft going to a just deleted airport [FS#874] (r10165)
- Fix: Airports did not flood when there are aircraft on the airport [FS#601] (r10155)
- Fix: Some vehicles were not drawn when having a high resolution and a high zoom-out level [FS#870] (r10154)
- Fix: Vehicles disappear when crossing certain tiles [FS#869] (r10153)
- Fix: Train disconnects in some old TTD savegames [FS#862] (10151)
- Fix: OpenTTD assumes that the resolution is at least 1 by 1, so force the resolution to be always at least 1 by 1 (r10139)
- Fix: When you got a sufficiently small resolution, there is a possibility for a division by zero when a sound is played (r10138)
- Fix: When removing a dock, a ship will always try to reach the old location of the dock even when it cannot anymore because it the old location of the dock is now land instead of water [FS#810] (r10131)
- Fix: SetCurrentGrfLangID returned the wrong language ids for most languages (r10130)
- Fix: Some NewGRFs use the same (unused in the "current" climate) sprite IDs. Normally this gives some artefacts, but when one NewGRF expects it to be a sprite and another NewGRF overwrites it with a non-sprite nasty things happen (drawing a non-sprite crashes OTTD) [FS#838] (r10109)
- Fix: Multiple subsequent "give money" actions could result in duplicate messages that money has been transfered when it only happened once, or tell you paid money when you did not [FS#834, FS#839] (r10087, r10085)
- Fix: "Deactivate Electrified Railways" did not work [FS#836] (10083)
- Fix: Memory leaks in the networking code [FS#846, FS#844] (r10082, r10075)
- Fix: Coverage area highlight was still show when it was turned off for docks [FS#835] (r10068)
- Fix: Do not use override engine type for articulated wagon parts (r10048)
- Fix: Sprite resulting from '?' substitution was reloaded into the cache entry for SPR_IMG_QUERY instead of the original sprite cache entry. This resulted in unaccounted missing sprite cache memory, and was exacerbated because the original missing sprite was not cached, so it did it again and again and again. Slowdowns and boom (r10038)
- Fix: One could build on (some) slopes when building on slopes was disabled [FS#823] (r10030)
- Fix: When deleting the first engine of a train with multiple engines, only reopen the train window if the player had the original train window open. This fixes 'random' windows opening for multiple players of the same company (r10028)
- Fix: When selling trains, if there were no wagons between multiheaded engines the rear part could be checked despite having already been deleted (10023)
0.5.2 (2007-05-29)
------------------------------------------------------------------------
- Feature: Add threading support for MorphOS (r9759)
@@ -1011,7 +115,7 @@
- Fix: Draw canal edges under buoys that are in a canal (r8635)
- Fix: Buoys on canal tiles do not flood anymore (r8620)
- Fix: Store the ownership of a water tile in the buoy tile and set the ownership of the water tile when the buoy is removed. Prevents certain abuses (r8619)
- Fix: When the currently selected player in the performance details window is no longer active, choose the first active player instead of the first player as that may also be inactive [FS#582] (r8612)
- Fix: When the currently selected player in the performance details window is no longer active, choose the first active player instead of the first player as that may also be inactive [FS#582] (r8612)
- Fix: Road vehicle very close after another (slower) road vehicle gets its speed reset to 0 when entering a tunnel, which causes a traffic jam outside of the tunnel (r8609)
- Fix: Bridges do not get destroyed when the bridge head gets flooded and there is a vehicle on the bridge [FS#564] (r8593)
- Fix: Road Vehicles now can obtain a slot even if the station is very spread out [FS#577] (r8536)
@@ -1655,7 +759,7 @@
- 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: [ 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
@@ -2395,43 +1499,43 @@
0.1.3 (2004-03-18)
------------------------------------------------------------------------
- Fix: message options window
- Fix: company takeover/purchase
- Fixed message options window
- Fixed company takeover/purchase
- Feature: Improved mouse scroll zooming
- Fix: station code so it's not possible to steal another player's temporarily deleted station
- Fix: subsidy owner bug when deleting station
- Fix: crash when deleting a bridge with a train on it
- Fixed station code so it's not possible to steal another player's temporarily deleted station
- Fixed subsidy owner bug when deleting station
- Fixed crash when deleting a bridge with a train on it
- Feature: Larger stations and possibility to join stations
- Fix: missing candy initial cargo payment values
- Fix: goods and Food/FizzyDrinks subsidies
- Fix: graphical glitch in subsidies window
- Fix: take over company dialog was not shown properly
- Fix: crash if player windows were open while the company went bankrupt
- Fix: train slowness on hills
- Fixed missing candy initial cargo payment values
- Fixed Goods and Food/FizzyDrinks subsidies
- Fixed graphical glitch in subsidies window
- Take over company dialog was not shown properly
- Fixed crash if player windows were open while the company went bankrupt
- Fixed train slowness on hills
- Feature: swedish town names (patch by glottis)
- Feature: more currencies
- Feature: better window resizing/zooming
- Feature: added goto road vehicle depot for road vehicle orders
- Feature: possibility to use either semaphores or signals (Ctrl key)
- Feature: limited the scrolling rate for year selector in scenario editor
- Better window resizing/zooming
- Added goto road vehicle depot for road vehicle orders
- Possibility to use either semaphores or signals (Ctrl key)
- Limited the scrolling rate for year selector in scenario editor
0.1.2 (2004-03-15)
------------------------------------------------------------------------
- Feature: mouse wheel can be used to zoom in out on win32
- Feature: implemented some support for resizing the window dynamically in win32
- Fix: tunnel mouse icon for maglev and monorail
- Mouse wheel can be used to zoom in out on win32 (ludde)
- Implemented some support for resizing the window dynamically in win32 (ludde)
- Fixed tunnel mouse icon for maglev and monorail
0.1.1 (2004-03-14)
------------------------------------------------------------------------
- Feature: Preliminary presignal support
- Add: external MIDI driver for unix version (by robertnorris)
- Add: DirectMusic driver for Win32 version
- Fix: problem where directories weren't displayed under Linux (by Markus)
- Feature: Center windows properly in higher resolutions
- Add: "build tracks on slopes" feature
- Fix: colors in map window for routes
- Feature: Command line -g flag now optionally takes a game to load
- Fix: road drive side
- Fix: "Fund road construction" not clickable when unavailable
- Preliminary presignal support
- Added external MIDI driver for unix version (by robertnorris)
- Added DirectMusic driver for Win32 version
- Fixed problem where directories weren't displayed under Linux (by Markus)
- Center windows properly in higher resolutions
- Added "build tracks on slopes" feature
- Fixed colors in map window for routes
- Command line -g flag now optionally takes a game to load
- Fixed road drive side
- Fixed "Fund road construction" not clickable when unavailable

794
clear_cmd.c Normal file
View File

@@ -0,0 +1,794 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "clear_map.h"
#include "rail_map.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "player.h"
#include "tile.h"
#include "viewport.h"
#include "command.h"
#include "tunnel_map.h"
#include "variables.h"
#include "table/sprites.h"
#include "unmovable_map.h"
#include "genworld.h"
#include "industry.h"
typedef struct TerraformerHeightMod {
TileIndex tile;
byte height;
} TerraformerHeightMod;
typedef struct TerraformerState {
int height[4];
uint32 flags;
int direction;
int modheight_count;
int tile_table_count;
int32 cost;
TileIndex *tile_table;
TerraformerHeightMod *modheight;
} TerraformerState;
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
{
TileIndex *t;
int count;
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) return -1;
t = ts->tile_table;
for (count = ts->tile_table_count; count != 0; count--, t++) {
if (*t == tile) return 0;
}
return 1;
}
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
{
TerraformerHeightMod *mod = ts->modheight;
int count;
for (count = ts->modheight_count; count != 0; count--, mod++) {
if (mod->tile == tile) return mod->height;
}
return TileHeight(tile);
}
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
{
int count;
TileIndex *t;
count = ts->tile_table_count;
if (count >= 625) return;
for (t = ts->tile_table; count != 0; count--,t++) {
if (*t == tile) return;
}
ts->tile_table[ts->tile_table_count++] = tile;
}
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
{
TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, 0));
TerraformAddDirtyTile(ts, tile);
}
static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
{
int r;
int32 ret;
assert(tile < MapSize());
r = TerraformAllowTileProcess(ts, tile);
if (r <= 0) return r;
if (IsTileType(tile, MP_RAILWAY)) {
static const TrackBits safe_track[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
static const Slope unsafe_slope[] = { SLOPE_S, SLOPE_W, SLOPE_N, SLOPE_E };
Slope tileh;
uint z;
// 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/lower the other corner.
tileh = GetTileSlope(tile, &z);
if (tileh == unsafe_slope[mode] ||
tileh == ComplementSlope(unsafe_slope[mode])) {
_terraform_err_tile = tile;
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
return -1;
}
// If we have a single diagonal track there, the other side of
// tile can be terraformed.
if (IsPlainRailTile(tile) && GetTrackBits(tile) == safe_track[mode]) {
/* If terraforming downwards prevent damaging a potential tunnel below.
* This check is only necessary for flat tiles, because if the tile is
* non-flat, then the corner opposing the rail is raised. Only this corner
* can be lowered and this is a safe action
*/
if (tileh == SLOPE_FLAT &&
ts->direction == -1 &&
IsTunnelInWay(tile, z - TILE_HEIGHT)) {
_terraform_err_tile = tile;
_error_message = STR_1002_EXCAVATION_WOULD_DAMAGE;
return -1;
}
return 0;
}
}
ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) {
_terraform_err_tile = tile;
return -1;
}
ts->cost += ret;
if (ts->tile_table_count >= 625) return -1;
ts->tile_table[ts->tile_table_count++] = tile;
return 0;
}
static bool TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height)
{
int nh;
TerraformerHeightMod *mod;
int count;
assert(tile < MapSize());
if (height < 0) {
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
return false;
}
_error_message = STR_1004_TOO_HIGH;
if (height > 15) return false;
nh = TerraformGetHeightOfTile(ts, tile);
if (nh < 0 || height == nh) return false;
if (TerraformProc(ts, tile, 0) < 0) return false;
if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
mod = ts->modheight;
count = ts->modheight_count;
for (;;) {
if (count == 0) {
if (ts->modheight_count >= 576) return false;
ts->modheight_count++;
break;
}
if (mod->tile == tile) break;
mod++;
count--;
}
mod->tile = tile;
mod->height = (byte)height;
ts->cost += _price.terraform;
{
int direction = ts->direction, r;
const TileIndexDiffC *ttm;
static const TileIndexDiffC _terraform_tilepos[] = {
{ 1, 0},
{-2, 0},
{ 1, 1},
{ 0, -2}
};
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) {
if (!TerraformTileHeight(ts, tile, r+direction))
return false;
}
}
}
return true;
}
/** Terraform land
* @param tile tile to terraform
* @param p1 corners to terraform.
* @param p2 direction; eg up or down
*/
int32 CmdTerraformLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
TerraformerState ts;
TileIndex t;
int direction;
TerraformerHeightMod modheight_data[576];
TileIndex tile_table_data[625];
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
_terraform_err_tile = 0;
ts.direction = direction = p2 ? 1 : -1;
ts.flags = flags;
ts.modheight_count = ts.tile_table_count = 0;
ts.cost = 0;
ts.modheight = modheight_data;
ts.tile_table = tile_table_data;
/* Make an extra check for map-bounds cause we add tiles to the originating tile */
if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
if (p1 & 1) {
t = tile + TileDiffXY(1, 0);
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
return CMD_ERROR;
}
}
if (p1 & 2) {
t = tile + TileDiffXY(1, 1);
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
return CMD_ERROR;
}
}
if (p1 & 4) {
t = tile + TileDiffXY(0, 1);
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
return CMD_ERROR;
}
}
if (p1 & 8) {
t = tile + TileDiffXY(0, 0);
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
return CMD_ERROR;
}
}
if (direction == -1) {
/* Check if tunnel would take damage */
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
uint z, t;
TileIndex tile = *ti;
z = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
if (t <= z) z = t;
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
if (t <= z) z = t;
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
if (t <= z) z = t;
if (IsTunnelInWay(tile, z * TILE_HEIGHT)) {
return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
}
}
}
if (flags & DC_EXEC) {
/* Clear the landscape at the tiles */
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
DoCommand(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
}
/* change the height */
{
int count;
TerraformerHeightMod *mod;
mod = ts.modheight;
for (count = ts.modheight_count; count != 0; count--, mod++) {
TileIndex til = mod->tile;
SetTileHeight(til, mod->height);
TerraformAddDirtyTileAround(&ts, til);
}
}
/* finally mark the dirty tiles dirty */
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
MarkTileDirtyByTile(*ti);
}
}
}
return ts.cost;
}
/** Levels a selected (rectangle) area of land
* @param tile end tile of area-drag
* @param p1 start tile of area drag
* @param p2 unused
*/
int32 CmdLevelLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
int size_x, size_y;
int ex;
int ey;
int sx, sy;
uint h, curh;
int32 ret, cost, money;
if (p1 >= MapSize()) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
// remember level height
h = TileHeight(p1);
// make sure sx,sy are smaller than ex,ey
ex = TileX(tile);
ey = TileY(tile);
sx = TileX(p1);
sy = TileY(p1);
if (ex < sx) intswap(ex, sx);
if (ey < sy) intswap(ey, sy);
tile = TileXY(sx, sy);
size_x = ex-sx+1;
size_y = ey-sy+1;
money = GetAvailableMoneyForCommand();
cost = 0;
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
curh = TileHeight(tile2);
while (curh != h) {
ret = DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
if (CmdFailed(ret)) break;
cost += ret;
if (flags & DC_EXEC) {
if ((money -= ret) < 0) {
_additional_cash_required = ret;
return cost - ret;
}
DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
}
curh += (curh > h) ? -1 : 1;
}
} END_TILE_LOOP(tile2, size_x, size_y, tile)
return (cost == 0) ? CMD_ERROR : cost;
}
/** Purchase a land area. Actually you only purchase one tile, so
* the name is a bit confusing ;p
* @param tile the tile the player is purchasing
* @param p1 unused
* @param p2 unused
*/
int32 CmdPurchaseLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
int32 cost;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (IsOwnedLandTile(tile) && IsTileOwner(tile, _current_player)) {
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
}
cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(cost)) return CMD_ERROR;
if (flags & DC_EXEC) {
MakeOwnedLand(tile, _current_player);
MarkTileDirtyByTile(tile);
}
return cost + _price.purchase_land * 10;
}
static int32 ClearTile_Clear(TileIndex tile, byte flags)
{
static const int32* clear_price_table[] = {
&_price.clear_1,
&_price.purchase_land,
&_price.clear_2,
&_price.clear_3,
&_price.purchase_land,
&_price.purchase_land,
&_price.clear_2, // XXX unused?
};
int32 price;
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
price = 0;
} else {
price = *clear_price_table[GetClearGround(tile)];
}
if (flags & DC_EXEC) DoClearSquare(tile);
return price;
}
/** Sell a land area. Actually you only sell one tile, so
* the name is a bit confusing ;p
* @param tile the tile the player is selling
* @param p1 unused
* @param p2 unused
*/
int32 CmdSellLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
if (!IsOwnedLandTile(tile)) return CMD_ERROR;
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (flags & DC_EXEC) DoClearSquare(tile);
return - _price.purchase_land * 2;
}
#include "table/clear_land.h"
void DrawClearLandTile(const TileInfo *ti, byte set)
{
DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19);
}
void DrawHillyLandTile(const TileInfo *ti)
{
if (ti->tileh != SLOPE_FLAT) {
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh]);
} else {
DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)]);
}
}
void DrawClearLandFence(const TileInfo *ti)
{
byte z = ti->z;
if (ti->tileh & SLOPE_S) {
z += TILE_HEIGHT;
if (ti->tileh == SLOPE_STEEP_S) z += TILE_HEIGHT;
}
if (GetFenceSW(ti->tile) != 0) {
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
}
if (GetFenceSE(ti->tile) != 0) {
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
}
}
static void DrawTile_Clear(TileInfo *ti)
{
switch (GetClearGround(ti->tile)) {
case CLEAR_GRASS:
DrawClearLandTile(ti, GetClearDensity(ti->tile));
break;
case CLEAR_ROUGH:
DrawHillyLandTile(ti);
break;
case CLEAR_ROCKS:
DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh]);
break;
case CLEAR_FIELDS:
DrawGroundSprite(_clear_land_sprites_1[GetFieldType(ti->tile)] + _tileh_to_sprite[ti->tileh]);
break;
case CLEAR_SNOW:
DrawGroundSprite(_clear_land_sprites_2[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
break;
case CLEAR_DESERT:
DrawGroundSprite(_clear_land_sprites_3[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
break;
}
DrawClearLandFence(ti);
}
static uint GetSlopeZ_Clear(TileIndex tile, uint x, uint y)
{
uint z;
uint tileh = GetTileSlope(tile, &z);
return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
}
static Slope GetSlopeTileh_Clear(TileIndex tile, Slope tileh)
{
return tileh;
}
static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
{
/* unused */
}
static void AnimateTile_Clear(TileIndex tile)
{
/* unused */
}
void TileLoopClearHelper(TileIndex tile)
{
byte self;
byte neighbour;
TileIndex dirty = INVALID_TILE;
self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
if (GetFenceSW(tile) == 0) {
if (self != neighbour) {
SetFenceSW(tile, 3);
dirty = tile;
}
} else {
if (self == 0 && neighbour == 0) {
SetFenceSW(tile, 0);
dirty = tile;
}
}
neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
if (GetFenceSE(tile) == 0) {
if (self != neighbour) {
SetFenceSE(tile, 3);
dirty = tile;
}
} else {
if (self == 0 && neighbour == 0) {
SetFenceSE(tile, 0);
dirty = tile;
}
}
if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
}
/* convert into snowy tiles */
static void TileLoopClearAlps(TileIndex tile)
{
int k = GetTileZ(tile) - _opt.snow_line + TILE_HEIGHT;
if (k < 0) { // well below the snow line
if (!IsClearGround(tile, CLEAR_SNOW)) return;
if (GetClearDensity(tile) == 0) SetClearGroundDensity(tile, CLEAR_GRASS, 3);
} else {
if (!IsClearGround(tile, CLEAR_SNOW)) {
SetClearGroundDensity(tile, CLEAR_SNOW, 0);
} else {
uint density = min((uint)k / TILE_HEIGHT, 3);
if (GetClearDensity(tile) < density) {
AddClearDensity(tile, 1);
} else if (GetClearDensity(tile) > density) {
AddClearDensity(tile, -1);
} else {
return;
}
}
}
MarkTileDirtyByTile(tile);
}
static void TileLoopClearDesert(TileIndex tile)
{
if (IsClearGround(tile, CLEAR_DESERT)) return;
if (GetTropicZone(tile) == TROPICZONE_DESERT) {
SetClearGroundDensity(tile, CLEAR_DESERT, 3);
} else {
if (GetTropicZone(tile + TileDiffXY( 1, 0)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY(-1, 0)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY( 0, 1)) != TROPICZONE_DESERT &&
GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
return;
SetClearGroundDensity(tile, CLEAR_DESERT, 1);
}
MarkTileDirtyByTile(tile);
}
static void TileLoop_Clear(TileIndex tile)
{
TileLoopClearHelper(tile);
switch (_opt.landscape) {
case LT_DESERT: TileLoopClearDesert(tile); break;
case LT_HILLY: TileLoopClearAlps(tile); break;
}
switch (GetClearGround(tile)) {
case CLEAR_GRASS:
if (GetClearDensity(tile) == 3) return;
if (_game_mode != GM_EDITOR) {
if (GetClearCounter(tile) < 7) {
AddClearCounter(tile, 1);
return;
} else {
SetClearCounter(tile, 0);
AddClearDensity(tile, 1);
}
} else {
SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
}
break;
case CLEAR_FIELDS: {
uint field_type;
if (_game_mode == GM_EDITOR) return;
if (GetClearCounter(tile) < 7) {
AddClearCounter(tile, 1);
return;
} else {
SetClearCounter(tile, 0);
}
if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
/* This farmfield is no longer farmfield, so make it grass again */
MakeClear(tile, CLEAR_GRASS, 2);
} else {
field_type = GetFieldType(tile);
field_type = (field_type < 8) ? field_type + 1 : 0;
SetFieldType(tile, field_type);
}
break;
}
default:
return;
}
MarkTileDirtyByTile(tile);
}
void GenerateClearTile(void)
{
uint i, gi;
TileIndex tile;
/* add rough tiles */
i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
do {
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
tile = RandomTile();
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
} while (--i);
/* add rocky tiles */
i = gi;
do {
uint32 r = Random();
tile = RandomTileSeed(r);
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
uint j = GB(r, 16, 4) + 5;
for (;;) {
TileIndex tile_new;
SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
do {
if (--j == 0) goto get_out;
tile_new = tile + TileOffsByDiagDir(GB(Random(), 0, 2));
} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
tile = tile_new;
}
get_out:;
}
} while (--i);
}
static void ClickTile_Clear(TileIndex tile)
{
/* not used */
}
static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
{
return 0;
}
static const StringID _clear_land_str[] = {
STR_080D_GRASS,
STR_080B_ROUGH_LAND,
STR_080A_ROCKS,
STR_080E_FIELDS,
STR_080F_SNOW_COVERED_LAND,
STR_0810_DESERT
};
static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
{
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
td->str = STR_080C_BARE_LAND;
} else {
td->str = _clear_land_str[GetClearGround(tile)];
}
td->owner = GetTileOwner(tile);
}
static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
{
return;
}
void InitializeClearLand(void)
{
_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
}
const TileTypeProcs _tile_type_clear_procs = {
DrawTile_Clear, /* draw_tile_proc */
GetSlopeZ_Clear, /* get_slope_z_proc */
ClearTile_Clear, /* clear_tile_proc */
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
GetTileDesc_Clear, /* get_tile_desc_proc */
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
ClickTile_Clear, /* click_tile_proc */
AnimateTile_Clear, /* animate_tile_proc */
TileLoop_Clear, /* tile_loop_clear */
ChangeTileOwner_Clear, /* change_tile_owner_clear */
NULL, /* get_produced_cargo_proc */
NULL, /* vehicle_enter_tile_proc */
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
};

145
clear_map.h Normal file
View File

@@ -0,0 +1,145 @@
/* $Id$ */
#ifndef CLEAR_MAP_H
#define CLEAR_MAP_H
#include "macros.h"
#include "tile.h"
/* ground type, m5 bits 2...4
* valid densities (bits 0...1) in comments after the enum
*/
typedef enum ClearGround {
CLEAR_GRASS = 0, // 0-3
CLEAR_ROUGH = 1, // 3
CLEAR_ROCKS = 2, // 3
CLEAR_FIELDS = 3, // 3
CLEAR_SNOW = 4, // 0-3
CLEAR_DESERT = 5 // 1,3
} ClearGround;
static inline ClearGround GetClearGround(TileIndex t)
{
assert(IsTileType(t, MP_CLEAR));
return GB(_m[t].m5, 2, 3);
}
static inline bool IsClearGround(TileIndex t, ClearGround ct)
{
return GetClearGround(t) == ct;
}
static inline uint GetClearDensity(TileIndex t)
{
assert(IsTileType(t, MP_CLEAR));
return GB(_m[t].m5, 0, 2);
}
static inline void AddClearDensity(TileIndex t, int d)
{
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
_m[t].m5 += d;
}
static inline uint GetClearCounter(TileIndex t)
{
assert(IsTileType(t, MP_CLEAR));
return GB(_m[t].m5, 5, 3);
}
static inline void AddClearCounter(TileIndex t, int c)
{
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
_m[t].m5 += c << 5;
}
static inline void SetClearCounter(TileIndex t, uint c)
{
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
SB(_m[t].m5, 5, 3, c);
}
/* Sets type and density in one go, also sets the counter to 0 */
static inline void SetClearGroundDensity(TileIndex t, ClearGround type, uint density)
{
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
_m[t].m5 = 0 << 5 | type << 2 | density;
}
static inline uint GetFieldType(TileIndex t)
{
assert(GetClearGround(t) == CLEAR_FIELDS);
return GB(_m[t].m3, 0, 4);
}
static inline void SetFieldType(TileIndex t, uint f)
{
assert(GetClearGround(t) == CLEAR_FIELDS); // XXX incomplete
SB(_m[t].m3, 0, 4, f);
}
static inline uint16 GetIndustryIndexOfField(TileIndex t)
{
assert(GetClearGround(t) == CLEAR_FIELDS);
return _m[t].m2;
}
static inline void SetIndustryIndexOfField(TileIndex t, uint16 i)
{
assert(GetClearGround(t) == CLEAR_FIELDS);
_m[t].m2 = i;
}
/* Is used by tree tiles, too */
static inline uint GetFenceSE(TileIndex t)
{
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
return GB(_m[t].m4, 2, 3);
}
static inline void SetFenceSE(TileIndex t, uint h)
{
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
SB(_m[t].m4, 2, 3, h);
}
static inline uint GetFenceSW(TileIndex t)
{
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
return GB(_m[t].m4, 5, 3);
}
static inline void SetFenceSW(TileIndex t, uint h)
{
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
SB(_m[t].m4, 5, 3, h);
}
static inline void MakeClear(TileIndex t, ClearGround g, uint density)
{
SetTileType(t, MP_CLEAR);
SetTileOwner(t, OWNER_NONE);
_m[t].m2 = 0;
_m[t].m3 = 0;
_m[t].m4 = 0 << 5 | 0 << 2;
SetClearGroundDensity(t, g, density);
}
static inline void MakeField(TileIndex t, uint field_type, uint16 industry)
{
SetTileType(t, MP_CLEAR);
SetTileOwner(t, OWNER_NONE);
_m[t].m2 = industry;
_m[t].m3 = field_type;
_m[t].m4 = 0 << 5 | 0 << 2;
SetClearGroundDensity(t, CLEAR_FIELDS, 3);
}
#endif /* CLEAR_MAP_H */

566
command.c Normal file
View File

@@ -0,0 +1,566 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "gui.h"
#include "command.h"
#include "player.h"
#include "network.h"
#include "variables.h"
#include "genworld.h"
const char* _cmd_text = NULL;
#define DEF_COMMAND(yyyy) int32 yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
DEF_COMMAND(CmdBuildRailroadTrack);
DEF_COMMAND(CmdRemoveRailroadTrack);
DEF_COMMAND(CmdBuildSingleRail);
DEF_COMMAND(CmdRemoveSingleRail);
DEF_COMMAND(CmdLandscapeClear);
DEF_COMMAND(CmdBuildBridge);
DEF_COMMAND(CmdBuildRailroadStation);
DEF_COMMAND(CmdRemoveFromRailroadStation);
DEF_COMMAND(CmdConvertRail);
DEF_COMMAND(CmdBuildSingleSignal);
DEF_COMMAND(CmdRemoveSingleSignal);
DEF_COMMAND(CmdTerraformLand);
DEF_COMMAND(CmdPurchaseLandArea);
DEF_COMMAND(CmdSellLandArea);
DEF_COMMAND(CmdBuildTunnel);
DEF_COMMAND(CmdBuildTrainDepot);
DEF_COMMAND(CmdBuildTrainWaypoint);
DEF_COMMAND(CmdRenameWaypoint);
DEF_COMMAND(CmdRemoveTrainWaypoint);
DEF_COMMAND(CmdBuildRoadStop);
DEF_COMMAND(CmdBuildLongRoad);
DEF_COMMAND(CmdRemoveLongRoad);
DEF_COMMAND(CmdBuildRoad);
DEF_COMMAND(CmdRemoveRoad);
DEF_COMMAND(CmdBuildRoadDepot);
DEF_COMMAND(CmdBuildAirport);
DEF_COMMAND(CmdBuildDock);
DEF_COMMAND(CmdBuildShipDepot);
DEF_COMMAND(CmdBuildBuoy);
DEF_COMMAND(CmdPlantTree);
DEF_COMMAND(CmdBuildRailVehicle);
DEF_COMMAND(CmdMoveRailVehicle);
DEF_COMMAND(CmdStartStopTrain);
DEF_COMMAND(CmdSellRailWagon);
DEF_COMMAND(CmdSendTrainToDepot);
DEF_COMMAND(CmdForceTrainProceed);
DEF_COMMAND(CmdReverseTrainDirection);
DEF_COMMAND(CmdModifyOrder);
DEF_COMMAND(CmdSkipOrder);
DEF_COMMAND(CmdDeleteOrder);
DEF_COMMAND(CmdInsertOrder);
DEF_COMMAND(CmdChangeServiceInt);
DEF_COMMAND(CmdRestoreOrderIndex);
DEF_COMMAND(CmdBuildIndustry);
DEF_COMMAND(CmdBuildCompanyHQ);
DEF_COMMAND(CmdSetPlayerFace);
DEF_COMMAND(CmdSetPlayerColor);
DEF_COMMAND(CmdIncreaseLoan);
DEF_COMMAND(CmdDecreaseLoan);
DEF_COMMAND(CmdWantEnginePreview);
DEF_COMMAND(CmdNameVehicle);
DEF_COMMAND(CmdRenameEngine);
DEF_COMMAND(CmdChangeCompanyName);
DEF_COMMAND(CmdChangePresidentName);
DEF_COMMAND(CmdRenameStation);
DEF_COMMAND(CmdSellAircraft);
DEF_COMMAND(CmdStartStopAircraft);
DEF_COMMAND(CmdBuildAircraft);
DEF_COMMAND(CmdSendAircraftToHangar);
DEF_COMMAND(CmdRefitAircraft);
DEF_COMMAND(CmdPlaceSign);
DEF_COMMAND(CmdRenameSign);
DEF_COMMAND(CmdBuildRoadVeh);
DEF_COMMAND(CmdStartStopRoadVeh);
DEF_COMMAND(CmdSellRoadVeh);
DEF_COMMAND(CmdSendRoadVehToDepot);
DEF_COMMAND(CmdTurnRoadVeh);
DEF_COMMAND(CmdRefitRoadVeh);
DEF_COMMAND(CmdPause);
DEF_COMMAND(CmdBuyShareInCompany);
DEF_COMMAND(CmdSellShareInCompany);
DEF_COMMAND(CmdBuyCompany);
DEF_COMMAND(CmdBuildTown);
DEF_COMMAND(CmdRenameTown);
DEF_COMMAND(CmdDoTownAction);
DEF_COMMAND(CmdSetRoadDriveSide);
DEF_COMMAND(CmdChangeDifficultyLevel);
DEF_COMMAND(CmdChangePatchSetting);
DEF_COMMAND(CmdStartStopShip);
DEF_COMMAND(CmdSellShip);
DEF_COMMAND(CmdBuildShip);
DEF_COMMAND(CmdSendShipToDepot);
DEF_COMMAND(CmdRefitShip);
DEF_COMMAND(CmdOrderRefit);
DEF_COMMAND(CmdCloneOrder);
DEF_COMMAND(CmdClearArea);
DEF_COMMAND(CmdGiveMoney);
DEF_COMMAND(CmdMoneyCheat);
DEF_COMMAND(CmdBuildCanal);
DEF_COMMAND(CmdBuildLock);
DEF_COMMAND(CmdPlayerCtrl);
DEF_COMMAND(CmdLevelLand);
DEF_COMMAND(CmdRefitRailVehicle);
DEF_COMMAND(CmdBuildSignalTrack);
DEF_COMMAND(CmdRemoveSignalTrack);
DEF_COMMAND(CmdSetAutoReplace);
DEF_COMMAND(CmdCloneVehicle);
DEF_COMMAND(CmdMassStartStopVehicle);
DEF_COMMAND(CmdDepotSellAllVehicles);
DEF_COMMAND(CmdDepotMassAutoReplace);
/* The master command table */
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, 0}, /* 42 */
{CmdSkipOrder, 0}, /* 43 */
{CmdDeleteOrder, 0}, /* 44 */
{CmdInsertOrder, 0}, /* 45 */
{CmdChangeServiceInt, 0}, /* 46 */
{CmdBuildIndustry, 0}, /* 47 */
{CmdBuildCompanyHQ, 0}, /* 48 */
{CmdSetPlayerFace, 0}, /* 49 */
{CmdSetPlayerColor, 0}, /* 50 */
{CmdIncreaseLoan, 0}, /* 51 */
{CmdDecreaseLoan, 0}, /* 52 */
{CmdWantEnginePreview, 0}, /* 53 */
{CmdNameVehicle, 0}, /* 54 */
{CmdRenameEngine, 0}, /* 55 */
{CmdChangeCompanyName, 0}, /* 56 */
{CmdChangePresidentName, 0}, /* 57 */
{CmdRenameStation, 0}, /* 58 */
{CmdSellAircraft, 0}, /* 59 */
{CmdStartStopAircraft, 0}, /* 60 */
{CmdBuildAircraft, 0}, /* 61 */
{CmdSendAircraftToHangar, 0}, /* 62 */
{NULL, 0}, /* 63 */
{CmdRefitAircraft, 0}, /* 64 */
{CmdPlaceSign, 0}, /* 65 */
{CmdRenameSign, 0}, /* 66 */
{CmdBuildRoadVeh, 0}, /* 67 */
{CmdStartStopRoadVeh, 0}, /* 68 */
{CmdSellRoadVeh, 0}, /* 69 */
{CmdSendRoadVehToDepot, 0}, /* 70 */
{CmdTurnRoadVeh, 0}, /* 71 */
{CmdRefitRoadVeh, 0}, /* 72 */
{CmdPause, CMD_SERVER}, /* 73 */
{CmdBuyShareInCompany, 0}, /* 74 */
{CmdSellShareInCompany, 0}, /* 75 */
{CmdBuyCompany, 0}, /* 76 */
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
{NULL, 0}, /* 78 */
{NULL, 0}, /* 79 */
{CmdRenameTown, CMD_SERVER}, /* 80 */
{CmdDoTownAction, 0}, /* 81 */
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
{NULL, 0}, /* 83 */
{NULL, 0}, /* 84 */
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
{CmdStartStopShip, 0}, /* 86 */
{CmdSellShip, 0}, /* 87 */
{CmdBuildShip, 0}, /* 88 */
{CmdSendShipToDepot, 0}, /* 89 */
{NULL, 0}, /* 90 */
{CmdRefitShip, 0}, /* 91 */
{NULL, 0}, /* 92 */
{NULL, 0}, /* 93 */
{NULL, 0}, /* 94 */
{NULL, 0}, /* 95 */
{NULL, 0}, /* 96 */
{NULL, 0}, /* 97 */
{CmdOrderRefit, 0}, /* 98 */
{CmdCloneOrder, 0}, /* 99 */
{CmdClearArea, 0}, /* 100 */
{NULL, 0}, /* 101 */
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
{CmdBuildCanal, 0}, /* 103 */
{CmdPlayerCtrl, 0}, /* 104 */
{CmdLevelLand, 0}, /* 105 */
{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 */
{CmdSetAutoReplace, 0}, /* 115 */
{CmdCloneVehicle, 0}, /* 116 */
{CmdMassStartStopVehicle, 0}, /* 117 */
{CmdDepotSellAllVehicles, 0}, /* 118 */
{CmdDepotMassAutoReplace, 0}, /* 119 */
};
/* This function range-checks a cmd, and checks if the cmd is not NULL */
bool IsValidCommand(uint cmd)
{
cmd &= 0xFF;
return
cmd < lengthof(_command_proc_table) &&
_command_proc_table[cmd].proc != NULL;
}
byte GetCommandFlags(uint cmd)
{
return _command_proc_table[cmd & 0xFF].flags;
}
static int _docommand_recursive;
int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
int32 res;
CommandProc *proc;
/* Do not even think about executing out-of-bounds tile-commands */
if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
_cmd_text = NULL;
return CMD_ERROR;
}
proc = _command_proc_table[procc].proc;
if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
_docommand_recursive++;
// 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(tile, flags & ~DC_EXEC, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto error;
}
if (_docommand_recursive == 1 &&
!(flags & DC_QUERY_COST) &&
res != 0 &&
!CheckPlayerHasMoney(res)) {
goto error;
}
if (!(flags & DC_EXEC)) {
_docommand_recursive--;
_cmd_text = NULL;
return res;
}
}
/* 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(tile, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
error:
_docommand_recursive--;
_cmd_text = NULL;
return CMD_ERROR;
}
// if toplevel, subtract the money.
if (--_docommand_recursive == 0) {
SubtractMoneyFromPlayer(res);
// XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player
if (tile != 0 && IsValidPlayer(_current_player)) {
GetPlayer(_current_player)->last_build_coordinate = tile;
}
}
_cmd_text = NULL;
return res;
}
int32 GetAvailableMoneyForCommand(void)
{
PlayerID pid = _current_player;
if (!IsValidPlayer(pid)) return 0x7FFFFFFF; // max int
return GetPlayer(pid)->player_money;
}
// toplevel network safe docommand function for the current player. must not be called recursively.
// the callback is called when the command succeeded or failed.
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
{
int32 res = 0,res2;
CommandProc *proc;
uint32 flags;
bool notest;
StringID error_part1;
int x = TileX(tile) * TILE_SIZE;
int y = TileY(tile) * TILE_SIZE;
/* Do not even think about executing out-of-bounds tile-commands */
if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
_cmd_text = NULL;
return false;
}
assert(_docommand_recursive == 0);
_error_message = INVALID_STRING_ID;
error_part1 = GB(cmd, 16, 16);
_additional_cash_required = 0;
/** Spectator has no rights except for the (dedicated) server which
* is/can be a spectator but as the server it can do anything */
if (_current_player == PLAYER_SPECTATOR && !_network_server) {
ShowErrorMessage(_error_message, error_part1, x, y);
_cmd_text = NULL;
return false;
}
flags = 0;
if (cmd & CMD_AUTO) flags |= DC_AUTO;
if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
// get pointer to command handler
assert((cmd & 0xFF) < lengthof(_command_proc_table));
proc = _command_proc_table[cmd & 0xFF].proc;
if (proc == NULL) {
_cmd_text = NULL;
return false;
}
// 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_REMOVE_ROAD ||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
_docommand_recursive = 1;
// cost estimation only?
if (!IsGeneratingWorld() &&
_shift_pressed &&
IsLocalPlayer() &&
!(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) &&
(cmd & 0xFF) != CMD_PAUSE) {
// estimate the cost.
res = proc(tile, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
ShowErrorMessage(_error_message, error_part1, x, y);
} else {
ShowEstimatedCostOrIncome(res, x, y);
}
_docommand_recursive = 0;
_cmd_text = NULL;
return false;
}
if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
// first test if the command can be executed.
res = proc(tile, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto show_error;
}
// no money? Only check if notest is off
if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
}
#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.
* We also need to do this if the server's company has gone bankrupt
* @todo Rewrite (dedicated) server to something more than a dirty hack!
*/
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
PlayerID pbck = _local_player;
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = 0;
NetworkSend_Command(tile, p1, p2, cmd, callback);
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
_docommand_recursive = 0;
_cmd_text = NULL;
return true;
}
#endif /* ENABLE_NETWORK */
// update last build coordinate of player.
if (tile != 0 && IsValidPlayer(_current_player)) {
GetPlayer(_current_player)->last_build_coordinate = tile;
}
/* Actually try and execute the command. If no cost-type is given
* use the construction one */
_yearly_expenses_type = EXPENSES_CONSTRUCTION;
res2 = proc(tile, flags | DC_EXEC, p1, p2);
// 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 (CmdFailed(res2)) {
if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
goto show_error;
}
}
SubtractMoneyFromPlayer(res2);
if (IsLocalPlayer() && _game_mode != GM_EDITOR) {
if (res2 != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
if (_additional_cash_required) {
SetDParam(0, _additional_cash_required);
ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y);
if (res2 == 0) goto callb_err;
}
}
_docommand_recursive = 0;
if (callback) callback(true, tile, p1, p2);
_cmd_text = NULL;
return true;
show_error:
// show error message if the command fails?
if (IsLocalPlayer() && error_part1 != 0) {
ShowErrorMessage(_error_message, error_part1, x,y);
}
callb_err:
_docommand_recursive = 0;
if (callback) callback(false, tile, p1, p2);
_cmd_text = NULL;
return false;
}

213
command.h Normal file
View File

@@ -0,0 +1,213 @@
/* $Id$ */
#ifndef COMMAND_H
#define COMMAND_H
enum {
CMD_BUILD_RAILROAD_TRACK = 0,
CMD_REMOVE_RAILROAD_TRACK = 1,
CMD_BUILD_SINGLE_RAIL = 2,
CMD_REMOVE_SINGLE_RAIL = 3,
CMD_LANDSCAPE_CLEAR = 4,
CMD_BUILD_BRIDGE = 5,
CMD_BUILD_RAILROAD_STATION = 6,
CMD_BUILD_TRAIN_DEPOT = 7,
CMD_BUILD_SIGNALS = 8,
CMD_REMOVE_SIGNALS = 9,
CMD_TERRAFORM_LAND = 10,
CMD_PURCHASE_LAND_AREA = 11,
CMD_SELL_LAND_AREA = 12,
CMD_BUILD_TUNNEL = 13,
CMD_REMOVE_FROM_RAILROAD_STATION = 14,
CMD_CONVERT_RAIL = 15,
CMD_BUILD_TRAIN_WAYPOINT = 16,
CMD_RENAME_WAYPOINT = 17,
CMD_REMOVE_TRAIN_WAYPOINT = 18,
CMD_BUILD_ROAD_STOP = 21,
CMD_BUILD_LONG_ROAD = 23,
CMD_REMOVE_LONG_ROAD = 24,
CMD_BUILD_ROAD = 25,
CMD_REMOVE_ROAD = 26,
CMD_BUILD_ROAD_DEPOT = 27,
CMD_BUILD_AIRPORT = 29,
CMD_BUILD_DOCK = 30,
CMD_BUILD_SHIP_DEPOT = 31,
CMD_BUILD_BUOY = 32,
CMD_PLANT_TREE = 33,
CMD_BUILD_RAIL_VEHICLE = 34,
CMD_MOVE_RAIL_VEHICLE = 35,
CMD_START_STOP_TRAIN = 36,
CMD_SELL_RAIL_WAGON = 38,
CMD_SEND_TRAIN_TO_DEPOT = 39,
CMD_FORCE_TRAIN_PROCEED = 40,
CMD_REVERSE_TRAIN_DIRECTION = 41,
CMD_MODIFY_ORDER = 42,
CMD_SKIP_ORDER = 43,
CMD_DELETE_ORDER = 44,
CMD_INSERT_ORDER = 45,
CMD_CHANGE_SERVICE_INT = 46,
CMD_BUILD_INDUSTRY = 47,
CMD_BUILD_COMPANY_HQ = 48,
CMD_SET_PLAYER_FACE = 49,
CMD_SET_PLAYER_COLOR = 50,
CMD_INCREASE_LOAN = 51,
CMD_DECREASE_LOAN = 52,
CMD_WANT_ENGINE_PREVIEW = 53,
CMD_NAME_VEHICLE = 54,
CMD_RENAME_ENGINE = 55,
CMD_CHANGE_COMPANY_NAME = 56,
CMD_CHANGE_PRESIDENT_NAME = 57,
CMD_RENAME_STATION = 58,
CMD_SELL_AIRCRAFT = 59,
CMD_START_STOP_AIRCRAFT = 60,
CMD_BUILD_AIRCRAFT = 61,
CMD_SEND_AIRCRAFT_TO_HANGAR = 62,
CMD_REFIT_AIRCRAFT = 64,
CMD_PLACE_SIGN = 65,
CMD_RENAME_SIGN = 66,
CMD_BUILD_ROAD_VEH = 67,
CMD_START_STOP_ROADVEH = 68,
CMD_SELL_ROAD_VEH = 69,
CMD_SEND_ROADVEH_TO_DEPOT = 70,
CMD_TURN_ROADVEH = 71,
CMD_REFIT_ROAD_VEH = 72,
CMD_PAUSE = 73,
CMD_BUY_SHARE_IN_COMPANY = 74,
CMD_SELL_SHARE_IN_COMPANY = 75,
CMD_BUY_COMPANY = 76,
CMD_BUILD_TOWN = 77,
CMD_RENAME_TOWN = 80,
CMD_DO_TOWN_ACTION = 81,
CMD_SET_ROAD_DRIVE_SIDE = 82,
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
CMD_START_STOP_SHIP = 86,
CMD_SELL_SHIP = 87,
CMD_BUILD_SHIP = 88,
CMD_SEND_SHIP_TO_DEPOT = 89,
CMD_REFIT_SHIP = 91,
CMD_ORDER_REFIT = 98,
CMD_CLONE_ORDER = 99,
CMD_CLEAR_AREA = 100,
CMD_MONEY_CHEAT = 102,
CMD_BUILD_CANAL = 103,
CMD_PLAYER_CTRL = 104, // used in multiplayer to create a new player etc.
CMD_LEVEL_LAND = 105, // level land
CMD_REFIT_RAIL_VEHICLE = 106,
CMD_RESTORE_ORDER_INDEX = 107,
CMD_BUILD_LOCK = 108,
CMD_BUILD_SIGNAL_TRACK = 110,
CMD_REMOVE_SIGNAL_TRACK = 111,
CMD_GIVE_MONEY = 113,
CMD_CHANGE_PATCH_SETTING = 114,
CMD_SET_AUTOREPLACE = 115,
CMD_CLONE_VEHICLE = 116,
CMD_MASS_START_STOP = 117,
CMD_DEPOT_SELL_ALL_VEHICLES = 118,
CMD_DEPOT_MASS_AUTOREPLACE = 119,
};
enum {
DC_EXEC = 0x01,
DC_AUTO = 0x02, // don't allow building on structures
DC_QUERY_COST = 0x04, // query cost only, don't build.
DC_NO_WATER = 0x08, // don't allow building on water
DC_NO_RAIL_OVERLAP = 0x10, // don't allow overlap of rails (used in buildrail)
DC_AI_BUILDING = 0x20, // special building rules for AI
DC_NO_TOWN_RATING = 0x40, // town rating does not disallow you from building
DC_FORCETEST = 0x80, // force test too.
CMD_ERROR = ((int32)0x80000000),
};
#define CMD_MSG(x) ((x)<<16)
enum {
CMD_AUTO = 0x0200,
CMD_NO_WATER = 0x0400,
CMD_NETWORK_COMMAND = 0x0800, // 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 int32 CommandProc(TileIndex tile, uint32 flags, uint32 p1, uint32 p2);
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 */
typedef void CommandCallback(bool success, TileIndex tile, uint32 p1, uint32 p2);
int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd);
#ifdef ENABLE_NETWORK
void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
#endif /* ENABLE_NETWORK */
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 */

2843
config.lib

File diff suppressed because it is too large Load Diff

440
configure vendored
View File

@@ -1,137 +1,323 @@
#!/bin/sh
CONFIGURE_EXECUTABLE="$_"
# On *nix systems those two are equal when ./configure is done
if [ "$0" != "$CONFIGURE_EXECUTABLE" ]; then
# On some systems, when ./configure is triggered from 'make'
# the $_ is filled with 'make'. So if that is true, skip 'make'
# and use $0 (and hope that is correct ;))
if [ -n "`echo $CONFIGURE_EXECUTABLE | grep make`" ]; then
CONFIGURE_EXECUTABLE="$0"
else
CONFIGURE_EXECUTABLE="$CONFIGURE_EXECUTABLE $0"
# This 'configure' script is a very easy wrapper around 'make updateconf'
# It allows cross-compilers to do their job much more easy.
showhelp() {
echo "Configure for OpenTTD"
echo ""
echo "Usage:"
echo " $0 --your_options"
echo ""
echo "Params:"
echo " --debug Create debug-release [no]"
echo " --profile Create profile-release [no]"
echo " --dedicated Make a dedicated build [no]"
echo " --revision Set the revision of the compilation [detected]"
echo " --target-cc Sets the target-compiler [\$CC]"
echo " --target-cxx Sets the C++ target-compiler []"
echo " --host-cc Sets the host-compiler [\$CC]"
echo " --host-cxx Sets the C++ host-compiler []"
echo " --os Sets the OS. Listens to: [detected]"
echo " UNIX, OSX, FREEBSD, MORPHOS"
echo " BEOS, SUNOS, CYGWIN, MINGW, OS2"
echo " --windres Sets the windres (Windows) [windres]"
echo " --force-le Force LE platform [no]"
echo " --force-be Force BE platform [no]"
echo ""
echo "Params that can be used with --with or --without"
echo " (e.g.: --without-static disables static (default))"
echo " static Do you want a static build? [no]"
echo " directmusic Do you want direct-music? [no]"
echo " zlib Do you want zlib-support? [yes]"
echo " sdl Do you want SDL-support? [yes]"
echo " png Do you want PNG-support? [yes]"
echo " iconv Do you want iconv-support? [no]"
echo " network Do you want network-support? [yes]"
echo " cocoa Do you want cocoa-support? (MacOSX) [no]"
echo " freetype Do you want freetype-support? [yes]"
echo " fontconfig Do you want fontconfig-support? [yes]"
echo ""
echo "Params used to configure external libs:"
echo " --static-zlib-path Set the path to your static zlib []"
echo " --sdl-config Where is your sdl-config [sdl-config]"
echo " --libpng-config Where is your libpng-config [libpng-config]"
echo " --freetype-config Where is your freetype-config [freetype-config]"
echo " --fontconfig-config Where is your fontconfig-config [pkg-config fontconfig]"
echo " --with-iconv Set the path to your iconv headers []"
echo " "
}
handle() {
PARAM="$PARAM \"$1=`awk 'BEGIN { FS="="; $0="'"$2"'"; print $2;}'`\""
}
# The things you can use inside this case:
# handle NAME VALUE - Sets the value to give the 'make upgradeconf'
# Value is in form: tag=REAL_VALUE
# ITEM="NAME" - Will set the value as above, only with the next param
# SITEM="NAME" - Will set the var $NAME to the next param
for n in "$@"
do
case "$n" in
--help | -h)
showhelp
exit 0
;;
--debug)
DEBUG_SET=1
ITEM="DEBUG"
;;
--debug=*)
handle "DEBUG" "$n"
;;
--profile)
PARAM="$PARAM PROFILE=1"
;;
--dedicated)
PARAM="$PARAM DEDICATED=1"
;;
--revision=*)
RELEASE=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
;;
--revision)
SITEM="RELEASE"
;;
--target-cc=*)
handle "CC_TARGET" "$n"
;;
--target-cc)
ITEM="CC_TARGET"
;;
--target-cxx=*)
handle "CXX_TARGET" "$n"
;;
--target-cxx)
SITEM="CXX_TARGET"
;;
--host-cc=*)
handle "CC_HOST" "$n"
;;
--host-cc)
ITEM="CC_HOST"
;;
--host-cxx=*)
handle "CXX_HOST" "$n"
;;
--host-cxx)
ITEM="CXX_HOST"
;;
--host-cflags=*)
handle CFLAGS_HOST "$n"
;;
--host-cflags)
ITEM="CFLAGS_HOST"
;;
--os=*)
TARGET_OS=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
;;
--os)
SITEM="TARGET_OS"
;;
--windres=*)
handle WINDRES "$n"
;;
--windres)
ITEM="WINDRES"
;;
--force-le)
PARAM="$PARAM ENDIAN_FORCE=LE"
;;
--force-be)
PARAM="$PARAM ENDIAN_FORCE=BE"
;;
--with-static)
PARAM="$PARAM STATIC=1"
;;
--without-static)
PARAM="$PARAM STATIC="
;;
--with-directmusic)
PARAM="$PARAM WITH_DIRECTMUSIC=1"
;;
--without-directmusic)
PARAM="$PARAM WITH_DIRECTMUSIC="
;;
--with-zlib)
PARAM="$PARAM WITH_ZLIB=1"
;;
--without-zlib)
PARAM="$PARAM WITH_ZLIB="
;;
--with-sdl)
PARAM="$PARAM WITH_SDL=1"
;;
--without-sdl)
PARAM="$PARAM WITH_SDL="
;;
--with-png)
PARAM="$PARAM WITH_PNG=1"
;;
--without-png)
PARAM="$PARAM WITH_PNG="
;;
--with-iconv)
PARAM="$PARAM WITH_ICONV=1"
;;
--with-iconv=*)
PARAM="$PARAM WITH_ICONV=1"
handle WITH_ICONV_PATH "$n"
;;
--without-iconv)
PARAM="$PARAM WITH_ICONV="
;;
--with-cocoa)
PARAM="$PARAM WITH_COCOA=1"
;;
--with-network)
PARAM="$PARAM WITH_NETWORK=1"
;;
--without-network)
PARAM="$PARAM WITH_NETWORK="
;;
--without-cocoa)
PARAM="$PARAM WITH_COCOA="
;;
--with-freetype)
PARAM="$PARAM WITH_FREETYPE=1"
;;
--without-freetype)
PARAM="$PARAM WITH_FREETYPE="
;;
--with-fontconfig)
PARAM="$PARAM WITH_FONTCONFIG=1"
;;
--without-fontconfig)
PARAM="$PARAM WITH_FONTCONFIG="
;;
--static-zlib-path=*)
handle STATIC_ZLIB_PATH "$n"
;;
--static-zlib-path)
ITEM="STATIC_ZLIB_PATH"
;;
--sdl-config=*)
handle SDL_CONFIG "$n"
;;
--sdl-config)
ITEM="SDL_CONFIG"
;;
--libpng-config=*)
handle LIBPNG_CONFIG "$n"
;;
--libpng-config)
ITEM="LIBPNG_CONFIG"
;;
--freetype-config=*)
handle FREETYPE_CONFIG "$n"
;;
--freetype-config)
ITEM="FREETYPE_CONFIG"
;;
--fontconfig-config=*)
handle FONTCONFIG_CONFIG "$n"
;;
--fontconfig-config)
ITEM="FONTCONFIG_CONFIG"
;;
--*=*)
echo -n "Unknown switch "
echo `awk 'BEGIN { FS="="; $0="'"$n"'"; print $1;}'`
exit 1
;;
-*)
echo "Unknown switch $n"
exit 1
;;
*)
if ! test -z "$ITEM"
then
PARAM="$PARAM $ITEM=\"$n\""
ITEM="";
elif ! test -z "$SITEM"
then
export $SITEM="$n"
SITEM=""
else
echo "Unknown switch $n"
exit 1
fi
;;
esac
done
if ! test -z "$TARGET_OS"
then
TARGET_OS=`echo $TARGET_OS | tr '[:lower:]' '[:upper:]'`
case "$TARGET_OS" in
WIN32)
PARAM="$PARAM WIN32=1"
;;
UNIX)
PARAM="$PARAM UNIX=1"
;;
OSX)
PARAM="$PARAM OSX=1 UNIX=1"
;;
FREEBSD)
PARAM="$PARAM FREEBSD=1"
;;
MORPHOS)
PARAM="$PARAM MORPHOS=1 UNIX=1"
;;
BEOS)
PARAM="$PARAM BEOS=1 UNIX=1"
;;
OS2)
PARAM="$PARAM OS2=1 UNIX=1"
;;
SUNOS)
PARAM="$PARAM SUNOS=1 UNIX=1"
;;
CYGWIN)
PARAM="$PARAM CYGWIN=1 WIN32=1"
;;
MINGW)
PARAM="$PARAM MINGW=1 WIN32=1"
;;
*)
echo "Unknown OS: $TARGET_OS"
exit 1
;;
esac
PARAM="$PARAM BYPASS_OS_DETECT=1"
fi
if ! test -z "$DEBUG_SET"
then
if test -z "`echo $PARAM | grep "DEBUG="`"
then
# Someone did --debug, without assigning a value, assume 1
PARAM="$PARAM DEBUG=1"
fi
fi
# Find out where configure is (in what dir)
ROOT_DIR="`dirname $0`"
ROOT_DIR="`cd $ROOT_DIR && pwd`"
PWD="`pwd`"
PREFIX="$PWD/bin"
# First remove the Makefile.config, else you can have double entries
rm -f Makefile.config
. $ROOT_DIR/config.lib
echo "make upgradeconf $PARAM" > ./Makefile.run
. ./Makefile.run
rm -f ./Makefile.run
# Set default dirs
OBJS_DIR="$PWD/objs"
BASE_SRC_OBJS_DIR="$OBJS_DIR"
LANG_OBJS_DIR="$OBJS_DIR/lang"
BIN_DIR="$PREFIX"
SRC_DIR="$ROOT_DIR/src"
LANG_DIR="$SRC_DIR/lang"
MEDIA_DIR="$ROOT_DIR/media"
SOURCE_LIST="$ROOT_DIR/source.list"
# Makefile.config currently doesn't support custom RELEASE (revision), so, we add the line
# yourself!
if [ "$1" = "--reconfig" ] || [ "$1" = "--reconfigure" ]; then
if [ ! -f "config.cache" ]; then
echo "can't reconfigure, because never configured before"
exit 1
fi
# Make sure we don't lock config.cache
cat config.cache | sed 's~\\ ~\\\\ ~g' > cache.tmp
sh cache.tmp
rm -f cache.tmp
exit $?
if ! test -z "$RELEASE"
then
echo "RELEASE=$RELEASE" >> Makefile.config
fi
set_default
detect_params "$@"
check_params
save_params
make_cflags_and_ldflags
EXE=""
if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ] || [ "$os" = "WINCE" ]; then
EXE=".exe"
fi
TTD="openttd$EXE"
STRGEN="strgen$EXE"
ENDIAN_CHECK="endian_check$EXE"
if [ -z "$sort" ]; then
PIPE_SORT="sed s~a~a~"
else
PIPE_SORT="$sort"
fi
if [ ! -f "$LANG_DIR/english.txt" ]; then
echo "Languages not found in $LANG_DIR. Can't continue without it."
echo "Please make sure the dir exists and contains at least english.txt"
fi
# Read the source.list and process it
SRCS="`< $ROOT_DIR/source.list tr '\r' '\n' | $awk '
{ }
/^( *)#end/ { if (deep == skip) { skip -= 1; } deep -= 1; next; }
/^( *)#else/ { if (deep == skip) { skip -= 1; } else if (deep - 1 == skip) { skip += 1; } next; }
/^( *)#if/ {
gsub(" ", "", $0);
gsub("^#if ", "", $0);
if (deep != skip) { deep += 1; next; }
deep += 1;
if ($0 == "ALLEGRO" && "'$allegro_config'" == "") { next; }
if ($0 == "SDL" && "'$sdl_config'" == "") { next; }
if ($0 == "PNG" && "'$png_config'" == "") { next; }
if ($0 == "OSX" && "'$os'" != "OSX") { next; }
if ($0 == "OS2" && "'$os'" != "OS2") { next; }
if ($0 == "PSP" && "'$os'" != "PSP") { next; }
if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; }
if ($0 == "COCOA" && "'$with_cocoa'" == "0") { next; }
if ($0 == "DOS" && "'$os'" != "DOS") { next; }
if ($0 == "BEOS" && "'$os'" != "BEOS") { next; }
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
"'$os'" != "CYGWIN" && "'$os'" != "MSVC" ) { next; }
if ($0 == "MORPHOS" && "'$os'" != "MORPHOS") { next; }
if ($0 == "WINCE" && "'$os'" != "WINCE") { next; }
if ($0 == "MSVC" && "'$os'" != "MSVC") { next; }
if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; }
if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; }
if ($0 == "HAVE_THREAD" && "'$with_threads'" == "0") { next; }
skip += 1;
next;
}
/^( *)#/ { next }
/^$/ { next }
/\.h$/ { next }
/\.hpp$/ { next }
{
if (deep == skip) {
gsub(" ", "", $0);
print $0;
}
}
' | $PIPE_SORT`"
OBJS_C="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.c$/ { gsub(".c$", ".o", $0); print $0; }'`"
OBJS_CPP="`echo \"$SRCS\" | $awk ' { ORS = " " } /\.cpp$/ { gsub(".cpp$", ".o", $0); print $0; }'`"
OBJS_MM="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.mm$/ { gsub(".mm$", ".o", $0); print $0; }'`"
OBJS_RC="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.rc$/ { gsub(".rc$", ".o", $0); print $0; }'`"
SRCS="` echo \"$SRCS\" | $awk ' { ORS = " " } { print $0; }'`"
# In makefiles, we always use -u for sort
if [ -z "$sort" ]; then
sort="sed s~a~a~"
else
sort="$sort -u"
fi
CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in"
generate_main
generate_lang
generate_src

View File

@@ -1,16 +1,21 @@
/* $Id$ */
/** @file console.cpp Handling of the in-game console. */
#include "stdafx.h"
#include "core/alloc_func.hpp"
#include "core/math_func.hpp"
#include "string_func.h"
#include "console_internal.h"
#include "network/network.h"
#include "network/network_func.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "window.h"
#include "gui.h"
#include "gfx.h"
#include "player.h"
#include "variables.h"
#include "string.h"
#include <stdarg.h>
#include <string.h>
#include "console.h"
#include "network.h"
#include "network_data.h"
#include "network_server.h"
#define ICON_BUFFER 79
#define ICON_HISTORY_SIZE 20
@@ -20,45 +25,244 @@
#define ICON_MAX_ALIAS_LINES 40
#define ICON_TOKEN_COUNT 20
/* console parser */
IConsoleCmd *_iconsole_cmds; ///< list of registred commands
IConsoleVar *_iconsole_vars; ///< list of registred vars
IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
// ** main console ** //
static char *_iconsole_buffer[ICON_BUFFER + 1];
static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
static Textbuf _iconsole_cmdline;
/* ** stdlib ** */
// ** stdlib ** //
byte _stdlib_developer = 1;
bool _stdlib_con_developer = false;
FILE *_iconsole_output_file;
void IConsoleInit()
// ** main console cmd buffer
static char *_iconsole_history[ICON_HISTORY_SIZE];
static byte _iconsole_historypos;
/* *************** */
/* end of header */
/* *************** */
static void IConsoleClearCommand(void)
{
memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
_iconsole_cmdline.length = 0;
_iconsole_cmdline.width = 0;
_iconsole_cmdline.caretpos = 0;
_iconsole_cmdline.caretxoffs = 0;
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
}
static inline void IConsoleResetHistoryPos(void) {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
static void IConsoleHistoryAdd(const char *cmd);
static void IConsoleHistoryNavigate(int direction);
// ** console window ** //
static void IConsoleWndProc(Window *w, WindowEvent *e)
{
static byte iconsole_scroll = ICON_BUFFER;
switch (e->event) {
case WE_PAINT: {
int i = iconsole_scroll;
int max = (w->height / ICON_LINE_HEIGHT) - 1;
int delta = 0;
GfxFillRect(w->left, w->top, w->width, w->height - 1, 0);
while ((i > 0) && (i > iconsole_scroll - max) && (_iconsole_buffer[i] != NULL)) {
DoDrawString(_iconsole_buffer[i], 5,
w->height - (iconsole_scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
i--;
}
/* If the text is longer than the window, don't show the starting ']' */
delta = w->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
if (delta > 0) {
DoDrawString("]", 5, w->height - ICON_LINE_HEIGHT, _icolour_cmd);
delta = 0;
}
DoDrawString(_iconsole_cmdline.buf, 10 + delta, w->height - ICON_LINE_HEIGHT, _icolour_cmd);
if (_iconsole_cmdline.caret)
DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, 12);
break;
}
case WE_MOUSELOOP:
if (HandleCaret(&_iconsole_cmdline))
SetWindowDirty(w);
break;
case WE_DESTROY:
_iconsole_mode = ICONSOLE_CLOSED;
break;
case WE_KEYPRESS:
e->we.keypress.cont = false;
switch (e->we.keypress.keycode) {
case WKC_UP:
IConsoleHistoryNavigate(+1);
SetWindowDirty(w);
break;
case WKC_DOWN:
IConsoleHistoryNavigate(-1);
SetWindowDirty(w);
break;
case WKC_SHIFT | WKC_PAGEUP:
if (iconsole_scroll - (w->height / ICON_LINE_HEIGHT) - 1 < 0) {
iconsole_scroll = 0;
} else {
iconsole_scroll -= (w->height / ICON_LINE_HEIGHT) - 1;
}
SetWindowDirty(w);
break;
case WKC_SHIFT | WKC_PAGEDOWN:
if (iconsole_scroll + (w->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
iconsole_scroll = ICON_BUFFER;
} else {
iconsole_scroll += (w->height / ICON_LINE_HEIGHT) - 1;
}
SetWindowDirty(w);
break;
case WKC_SHIFT | WKC_UP:
if (iconsole_scroll <= 0) {
iconsole_scroll = 0;
} else {
--iconsole_scroll;
}
SetWindowDirty(w);
break;
case WKC_SHIFT | WKC_DOWN:
if (iconsole_scroll >= ICON_BUFFER) {
iconsole_scroll = ICON_BUFFER;
} else {
++iconsole_scroll;
}
SetWindowDirty(w);
break;
case WKC_BACKQUOTE:
IConsoleSwitch();
break;
case WKC_RETURN: case WKC_NUM_ENTER:
IConsolePrintF(_icolour_cmd, "] %s", _iconsole_cmdline.buf);
IConsoleHistoryAdd(_iconsole_cmdline.buf);
IConsoleCmdExec(_iconsole_cmdline.buf);
IConsoleClearCommand();
break;
case WKC_CTRL | WKC_RETURN:
_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
IConsoleResize(w);
MarkWholeScreenDirty();
break;
case (WKC_CTRL | 'V'):
if (InsertTextBufferClipboard(&_iconsole_cmdline)) {
IConsoleResetHistoryPos();
SetWindowDirty(w);
}
break;
case (WKC_CTRL | 'L'):
IConsoleCmdExec("clear");
break;
case (WKC_CTRL | 'U'):
DeleteTextBufferAll(&_iconsole_cmdline);
SetWindowDirty(w);
break;
case WKC_BACKSPACE: case WKC_DELETE:
if (DeleteTextBufferChar(&_iconsole_cmdline, e->we.keypress.keycode)) {
IConsoleResetHistoryPos();
SetWindowDirty(w);
}
break;
case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
if (MoveTextBufferPos(&_iconsole_cmdline, e->we.keypress.keycode)) {
IConsoleResetHistoryPos();
SetWindowDirty(w);
}
break;
default:
if (IsValidChar(e->we.keypress.key, CS_ALPHANUMERAL)) {
iconsole_scroll = ICON_BUFFER;
InsertTextBufferChar(&_iconsole_cmdline, e->we.keypress.key);
IConsoleResetHistoryPos();
SetWindowDirty(w);
} else {
e->we.keypress.cont = true;
}
break;
}
}
}
static const Widget _iconsole_window_widgets[] = {
{WIDGETS_END}
};
static const WindowDesc _iconsole_window_desc = {
0, 0, 2, 2,
WC_CONSOLE, 0,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_iconsole_window_widgets,
IConsoleWndProc,
};
void IConsoleInit(void)
{
extern const char _openttd_revision[];
_iconsole_output_file = NULL;
_icolour_def = 1;
_icolour_err = 3;
_icolour_warn = 13;
_icolour_dbg = 5;
_icolour_cmd = 2;
_iconsole_historypos = ICON_HISTORY_SIZE - 1;
_iconsole_mode = ICONSOLE_CLOSED;
#ifdef ENABLE_NETWORK /* Initialize network only variables */
_redirect_console_to_client = INVALID_CLIENT_ID;
_redirect_console_to_client = 0;
#endif
IConsoleGUIInit();
memset(_iconsole_history, 0, sizeof(_iconsole_history));
memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
_iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it
_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
IConsolePrint(12, "------------------------------------");
IConsolePrint(12, "use \"help\" for more information");
IConsolePrint(12, "");
IConsoleStdLibRegister();
IConsoleClearCommand();
IConsoleHistoryAdd("");
}
void IConsoleClearBuffer(void)
{
uint i;
for (i = 0; i <= ICON_BUFFER; i++) {
free(_iconsole_buffer[i]);
_iconsole_buffer[i] = NULL;
}
}
static void IConsoleClear(void)
{
free(_iconsole_cmdline.buf);
IConsoleClearBuffer();
}
static void IConsoleWriteToLogFile(const char *string)
{
if (_iconsole_output_file != NULL) {
/* if there is an console output file ... also print it there */
if (fwrite(string, strlen(string), 1, _iconsole_output_file) != 1 ||
fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
fclose(_iconsole_output_file);
_iconsole_output_file = NULL;
IConsolePrintF(CC_DEFAULT, "cannot write to log file");
}
// if there is an console output file ... also print it there
fwrite(string, strlen(string), 1, _iconsole_output_file);
fwrite("\n", 1, 1, _iconsole_output_file);
}
}
bool CloseConsoleLogIfActive()
bool CloseConsoleLogIfActive(void)
{
if (_iconsole_output_file != NULL) {
IConsolePrintF(CC_DEFAULT, "file output complete");
IConsolePrintF(_icolour_def, "file output complete");
fclose(_iconsole_output_file);
_iconsole_output_file = NULL;
return true;
@@ -67,28 +271,109 @@ bool CloseConsoleLogIfActive()
return false;
}
void IConsoleFree()
void IConsoleFree(void)
{
IConsoleGUIFree();
IConsoleClear();
CloseConsoleLogIfActive();
}
void IConsoleResize(Window *w)
{
switch (_iconsole_mode) {
case ICONSOLE_OPENED:
w->height = _screen.height / 3;
w->width = _screen.width;
break;
case ICONSOLE_FULL:
w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
w->width = _screen.width;
break;
default: return;
}
MarkWholeScreenDirty();
}
void IConsoleSwitch(void)
{
switch (_iconsole_mode) {
case ICONSOLE_CLOSED: {
Window *w = AllocateWindowDesc(&_iconsole_window_desc);
w->height = _screen.height / 3;
w->width = _screen.width;
_iconsole_mode = ICONSOLE_OPENED;
SETBIT(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
} break;
case ICONSOLE_OPENED: case ICONSOLE_FULL:
DeleteWindowById(WC_CONSOLE, 0);
_iconsole_mode = ICONSOLE_CLOSED;
CLRBIT(_no_scroll, SCROLL_CON);
break;
}
MarkWholeScreenDirty();
}
void IConsoleClose(void) {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
void IConsoleOpen(void) {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
/**
* Add the entered line into the history so you can look it back
* scroll, etc. Put it to the beginning as it is the latest text
* @param cmd Text to be entered into the 'history'
*/
static void IConsoleHistoryAdd(const char *cmd)
{
free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
_iconsole_history[0] = strdup(cmd);
IConsoleResetHistoryPos();
}
/**
* Navigate Up/Down in the history of typed commands
* @param direction Go further back in history (+1), go to recently typed commands (-1)
*/
static void IConsoleHistoryNavigate(int direction)
{
int i = _iconsole_historypos + direction;
// watch out for overflows, just wrap around
if (i < 0) i = ICON_HISTORY_SIZE - 1;
if (i >= ICON_HISTORY_SIZE) i = 0;
if (direction > 0)
if (_iconsole_history[i] == NULL) i = 0;
if (direction < 0) {
while (i > 0 && _iconsole_history[i] == NULL) i--;
}
_iconsole_historypos = i;
IConsoleClearCommand();
// copy history to 'command prompt / bash'
assert(_iconsole_history[i] != NULL && IS_INT_INSIDE(i, 0, ICON_HISTORY_SIZE));
ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
UpdateTextBufferSize(&_iconsole_cmdline);
}
/**
* Handle the printing of text entered into the console or redirected there
* by any other means. Text can be redirected to other clients in a network game
* by any other means. Text can be redirected to other players in a network game
* as well as to a logfile. If the network server is a dedicated server, all activities
* are also logged. All lines to print are added to a temporary buffer which can be
* used as a history to print them onscreen
* @param colour_code the colour of the command. Red in case of errors, etc.
* @param color_code the colour of the command. Red in case of errors, etc.
* @param string the message entered or output on the console (notice, error, etc.)
*/
void IConsolePrint(ConsoleColour colour_code, const char *string)
void IConsolePrint(uint16 color_code, const char *string)
{
char *str;
#ifdef ENABLE_NETWORK
if (_redirect_console_to_client != INVALID_CLIENT_ID) {
if (_redirect_console_to_client != 0) {
/* Redirect the string to the client */
NetworkServerSendRcon(_redirect_console_to_client, colour_code, string);
SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string);
return;
}
#endif
@@ -100,23 +385,32 @@ void IConsolePrint(ConsoleColour colour_code, const char *string)
str_validate(str);
if (_network_dedicated) {
fprintf(stdout, "%s\n", str);
fflush(stdout);
printf("%s\n", str);
IConsoleWriteToLogFile(str);
free(str); // free duplicated string since it's not used anymore
return;
}
IConsoleWriteToLogFile(str);
IConsoleGUIPrint(colour_code, str);
/* move up all the strings in the buffer one place and do the same for colour
* to accomodate for the new command/message */
free(_iconsole_buffer[0]);
memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
_iconsole_buffer[ICON_BUFFER] = str;
memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
_iconsole_cbuffer[ICON_BUFFER] = color_code;
IConsoleWriteToLogFile(_iconsole_buffer[ICON_BUFFER]);
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
}
/**
* Handle the printing of text entered into the console or redirected there
* by any other means. Uses printf() style format, for more information look
* at IConsolePrint()
* at @IConsolePrint()
*/
void CDECL IConsolePrintF(ConsoleColour colour_code, const char *s, ...)
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
{
va_list va;
char buf[ICON_MAX_STREAMSIZE];
@@ -125,21 +419,19 @@ void CDECL IConsolePrintF(ConsoleColour colour_code, const char *s, ...)
vsnprintf(buf, sizeof(buf), s, va);
va_end(va);
IConsolePrint(colour_code, buf);
IConsolePrint(color_code, buf);
}
/**
* It is possible to print debugging information to the console,
* which is achieved by using this function. Can only be used by
* debug() in debug.cpp. You need at least a level 2 (developer) for debugging
* @debug() in debug.c. You need at least a level 2 (developer) for debugging
* messages to show up
* @param dbg debugging category
* @param string debugging message
*/
void IConsoleDebug(const char *dbg, const char *string)
void IConsoleDebug(const char *string)
{
if (_stdlib_developer > 1)
IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string);
IConsolePrintF(_icolour_dbg, "dbg: %s", string);
}
/**
@@ -150,7 +442,7 @@ void IConsoleDebug(const char *dbg, const char *string)
void IConsoleWarning(const char *string)
{
if (_stdlib_developer > 0)
IConsolePrintF(CC_WARNING, "WARNING: %s", string);
IConsolePrintF(_icolour_warn, "WARNING: %s", string);
}
/**
@@ -159,13 +451,13 @@ void IConsoleWarning(const char *string)
*/
void IConsoleError(const char *string)
{
IConsolePrintF(CC_ERROR, "ERROR: %s", string);
IConsolePrintF(_icolour_err, "ERROR: %s", string);
}
/**
* Change a string into its number representation. Supports
* decimal and hexadecimal numbers as well as 'on'/'off' 'true'/'false'
* @param *value the variable a successful conversion will be put in
* @param *value the variable a successfull conversion will be put in
* @param *arg the string to be converted
* @return Return true on success or false on failure
*/
@@ -186,13 +478,12 @@ bool GetArgumentInteger(uint32 *value, const char *arg)
return arg != endptr;
}
/* * *************************
* hooking code *
* *************************/
// * ************************* * //
// * hooking code * //
// * ************************* * //
/**
* General internal hooking code that is the same for both commands and variables
* @param hooks IConsoleHooks structure that will be set according to
* @param hooks @IConsoleHooks structure that will be set according to
* @param type type access trigger
* @param proc function called when the hook criteria is met
*/
@@ -217,9 +508,9 @@ static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConso
/**
* Handle any special hook triggers. If the hook type is met check if
* there is a function associated with that and if so, execute it
* @param hooks IConsoleHooks structure that will be checked
* @param hooks @IConsoleHooks structure that will be checked
* @param type type of hook, trigger that needs to be activated
* @return true on a successful execution of the hook command or if there
* @return true on a successfull execution of the hook command or if there
* is no hook/trigger present at all. False otherwise
*/
static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
@@ -319,7 +610,7 @@ void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
{
char *new_cmd = strdup(name);
IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
IConsoleCmd *item_new = malloc(sizeof(IConsoleCmd));
item_new->next = NULL;
item_new->proc = proc;
@@ -356,7 +647,7 @@ void IConsoleAliasRegister(const char *name, const char *cmd)
{
char *new_alias = strdup(name);
char *cmd_aliased = strdup(cmd);
IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);
IConsoleAlias *item_new = malloc(sizeof(IConsoleAlias));
item_new->next = NULL;
item_new->cmdline = cmd_aliased;
@@ -372,7 +663,7 @@ void IConsoleAliasRegister(const char *name, const char *cmd)
*/
IConsoleAlias *IConsoleAliasGet(const char *name)
{
IConsoleAlias *item;
IConsoleAlias* item;
for (item = _iconsole_aliases; item != NULL; item = item->next) {
if (strcmp(item->name, name) == 0) return item;
@@ -384,9 +675,8 @@ IConsoleAlias *IConsoleAliasGet(const char *name)
/** copy in an argument into the aliasstream */
static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
{
/* len is the amount of bytes to add excluding the '\0'-termination */
int len = min(ICON_MAX_STREAMSIZE - bufpos - 1, (uint)strlen(src));
strecpy(dst, src, dst + len);
int len = min(ICON_MAX_STREAMSIZE - bufpos, (uint)strlen(src));
strncpy(dst, src, len);
return len;
}
@@ -409,25 +699,25 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
memset(&aliasstream, 0, sizeof(aliasstream));
if (_stdlib_con_developer)
IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing...");
IConsolePrintF(_icolour_dbg, "condbg: requested command is an alias; parsing...");
aliases[0] = aliasstream;
for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) {
if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
switch (*cmdptr) {
case '\'': // ' will double for ""
case '\'': /* ' will double for "" */
aliasstream[astream_i++] = '"';
break;
case ';': // Cmd seperator, start new command
case ';': /* Cmd seperator, start new command */
aliasstream[astream_i] = '\0';
aliases[++a_index] = &aliasstream[++astream_i];
cmdptr++;
break;
case '%': // Some or all parameters
case '%': /* Some or all parameters */
cmdptr++;
switch (*cmdptr) {
case '+': { // All parameters seperated: "[param 1]" "[param 2]"
case '+': { /* All parameters seperated: "[param 1]" "[param 2]" */
for (i = 0; i != tokencount; i++) {
aliasstream[astream_i++] = '"';
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
@@ -435,7 +725,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
aliasstream[astream_i++] = ' ';
}
} break;
case '!': { // Merge the parameters to one: "[param 1] [param 2] [param 3...]"
case '!': { /* Merge the parameters to one: "[param 1] [param 2] [param 3...]" */
aliasstream[astream_i++] = '"';
for (i = 0; i != tokencount; i++) {
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
@@ -444,12 +734,12 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
aliasstream[astream_i++] = '"';
} break;
default: { // One specific parameter: %A = [param 1] %B = [param 2] ...
default: { /* One specific parameter: %A = [param 1] %B = [param 2] ... */
int param = *cmdptr - 'A';
if (param < 0 || param >= tokencount) {
IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline);
IConsolePrintF(_icolour_warn, "Usage of alias '%s': %s", alias->name, alias->cmdline);
return;
}
@@ -471,11 +761,8 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
/**
* Special function for adding string-type variables. They in addition
* also need a 'size' value saying how long their string buffer is.
* @param name name of the variable that will be used
* @param addr memory location the variable will point to
* @param size the length of the string buffer
* @param help the help string shown for the variable
* For more information see IConsoleVarRegister()
* For more information see @IConsoleVarRegister()
*/
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
{
@@ -495,7 +782,7 @@ void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
{
char *new_cmd = strdup(name);
IConsoleVar *item_new = MallocT<IConsoleVar>(1);
IConsoleVar *item_new = malloc(sizeof(IConsoleVar));
item_new->help = (help != NULL) ? strdup(help) : NULL;
@@ -572,7 +859,7 @@ static void IConsoleVarSetStringvalue(const IConsoleVar *var, const char *value)
if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
ttd_strlcpy((char*)var->addr, value, var->size);
ttd_strlcpy(var->addr, value, var->size);
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
return;
@@ -662,7 +949,7 @@ void IConsoleVarPrintGetValue(const IConsoleVar *var)
}
value = IConsoleVarGetStringValue(var);
IConsolePrintF(CC_WARNING, "Current value for '%s' is: %s", var->name, value);
IConsolePrintF(_icolour_warn, "Current value for '%s' is: %s", var->name, value);
}
/**
@@ -672,7 +959,7 @@ void IConsoleVarPrintGetValue(const IConsoleVar *var)
void IConsoleVarPrintSetValue(const IConsoleVar *var)
{
char *value = IConsoleVarGetStringValue(var);
IConsolePrintF(CC_WARNING, "'%s' changed to: %s", var->name, value);
IConsolePrintF(_icolour_warn, "'%s' changed to: %s", var->name, value);
}
/**
@@ -689,7 +976,7 @@ void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_T
uint32 value;
if (_stdlib_con_developer)
IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable");
IConsolePrintF(_icolour_dbg, "condbg: requested command is a variable");
if (tokencount == 0) { /* Just print out value */
IConsoleVarPrintGetValue(var);
@@ -766,13 +1053,13 @@ void IConsoleCmdExec(const char *cmdstr)
for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
IConsoleError("command contains malformed characters, aborting");
IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr);
IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr);
return;
}
}
if (_stdlib_con_developer)
IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr);
IConsolePrintF(_icolour_dbg, "condbg: executing cmdline: '%s'", cmdstr);
memset(&tokens, 0, sizeof(tokens));
memset(&tokenstream, 0, sizeof(tokenstream));
@@ -796,16 +1083,16 @@ void IConsoleCmdExec(const char *cmdstr)
tstream_i++;
break;
case '"': // Tokens enclosed in "" are one token
case '"': /* Tokens enclosed in "" are one token */
longtoken = !longtoken;
break;
case '\\': // Escape character for ""
case '\\': /* Escape character for "" */
if (cmdptr[1] == '"' && tstream_i + 1 < lengthof(tokenstream)) {
tokenstream[tstream_i++] = *++cmdptr;
break;
}
/* fallthrough */
default: // Normal character
default: /* Normal character */
tokenstream[tstream_i++] = *cmdptr;
if (!foundtoken) {
@@ -820,7 +1107,7 @@ void IConsoleCmdExec(const char *cmdstr)
uint i;
for (i = 0; tokens[i] != NULL; i++) {
IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]);
IConsolePrintF(_icolour_dbg, "condbg: token %d is: '%s'", i, tokens[i]);
}
}

View File

@@ -1,18 +1,14 @@
/* $Id$ */
/** @file console_internal.h Internally used functions for the console. */
#ifndef CONSOLE_H
#define CONSOLE_H
#ifndef CONSOLE_INTERNAL_H
#define CONSOLE_INTERNAL_H
// maximum length of a typed in command
#define ICON_CMDLN_SIZE 255
// maximum length of a totally expanded command
#define ICON_MAX_STREAMSIZE 1024
#include "console_func.h"
enum {
ICON_CMDLN_SIZE = 1024, ///< maximum length of a typed in command
ICON_MAX_STREAMSIZE = 2048, ///< maximum length of a totally expanded command
};
enum IConsoleVarTypes {
typedef enum IConsoleVarTypes {
ICONSOLE_VAR_BOOLEAN,
ICONSOLE_VAR_BYTE,
ICONSOLE_VAR_UINT16,
@@ -20,25 +16,31 @@ enum IConsoleVarTypes {
ICONSOLE_VAR_INT16,
ICONSOLE_VAR_INT32,
ICONSOLE_VAR_STRING
};
} IConsoleVarTypes;
enum IConsoleHookTypes {
typedef enum IConsoleModes {
ICONSOLE_FULL,
ICONSOLE_OPENED,
ICONSOLE_CLOSED
} IConsoleModes;
typedef enum IConsoleHookTypes {
ICONSOLE_HOOK_ACCESS,
ICONSOLE_HOOK_PRE_ACTION,
ICONSOLE_HOOK_POST_ACTION
};
} IConsoleHookTypes;
/** --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();
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
};
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;
/** --Commands--
* Commands are commands, or functions. They get executed once and any
@@ -49,13 +51,14 @@ struct IConsoleHooks{
*/
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
struct IConsoleCmd {
char *name; ///< name of command
IConsoleCmd *next; ///< next command in list
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
};
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
@@ -66,17 +69,18 @@ struct IConsoleCmd {
* - '++' to increase value by one
* - '--' to decrease value by one
*/
struct IConsoleVar {
char *name; ///< name of the variable
IConsoleVar *next; ///< next variable in list
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
};
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,
@@ -89,21 +93,42 @@ struct IConsoleVar {
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
* - ";" allows for combining commands (see example 'ng')
*/
struct IConsoleAlias {
char *name; ///< name of the alias
IConsoleAlias *next; ///< next alias in list
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
};
char *cmdline; // command(s) that is/are being aliased
} IConsoleAlias;
/* console parser */
extern IConsoleCmd *_iconsole_cmds; ///< list of registred commands
extern IConsoleVar *_iconsole_vars; ///< list of registred vars
extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
VARDEF IConsoleCmd *_iconsole_cmds; // list of registred commands
VARDEF IConsoleVar *_iconsole_vars; // list of registred vars
VARDEF IConsoleAlias *_iconsole_aliases; // list of registred aliases
/* 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 IConsoleClearBuffer();
void IConsoleOpen();
void IConsoleInit(void);
void IConsoleFree(void);
void IConsoleClearBuffer(void);
void IConsoleResize(Window *w);
void IConsoleSwitch(void);
void IConsoleClose(void);
void IConsoleOpen(void);
/* console output */
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 char *name, IConsoleCmdProc *proc);
@@ -114,15 +139,16 @@ IConsoleAlias *IConsoleAliasGet(const char *name);
/* Variables */
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);
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[]);
/* console std lib (register ingame commands/aliases/variables) */
void IConsoleStdLibRegister();
void IConsoleStdLibRegister(void);
/* Hooking code */
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
@@ -131,9 +157,4 @@ void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
/* Supporting functions */
bool GetArgumentInteger(uint32 *value, const char *arg);
void IConsoleGUIInit();
void IConsoleGUIFree();
void IConsoleGUIPrint(ConsoleColour colour_code, char *string);
#endif /* CONSOLE_INTERNAL_H */
#endif /* CONSOLE_H */

1628
console_cmds.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +1,46 @@
/* $Id$ */
/** @file currency.cpp Support for different currencies. */
#include "stdafx.h"
#include "openttd.h"
#include "currency.h"
#include "news_func.h"
#include "settings_type.h"
#include "date_func.h"
#include "news.h"
#include "variables.h"
#include "table/strings.h"
#include "date.h"
// exchange rate prefix symbol_pos
// | separator | postfix |
// | | Euro year | | | name
// | | | | | | |
static const CurrencySpec origin_currency_specs[NUM_CURRENCY] = {
{ 1, ',', CF_NOEURO, "£", "", 0, STR_CURR_GBP }, ///< british pounds
{ 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, ///< us dollars
{ 2, ',', CF_ISEURO, "", "", 0, STR_CURR_EUR }, ///< Euro
{ 220, ',', CF_NOEURO, "¥", "", 0, STR_CURR_YEN }, ///< yen
{ 20, ',', 2002, "", " S.", 1, STR_CURR_ATS }, ///< austrian schilling
{ 59, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, ///< belgian franc
{ 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, ///< swiss franc
{ 41, ',', CF_NOEURO, "", "", 1, STR_CURR_CZK }, ///< czech koruna
{ 3, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, ///< deutsche mark
{ 11, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, ///< danish krone
{ 245, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, ///< spanish pesetas
{ 9, ',', 2002, "", " mk", 1, STR_CURR_FIM }, ///< finnish markka
{ 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, ///< french francs
{ 500, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, ///< greek drachma
{ 378, ',', CF_NOEURO, "", " Ft", 1, STR_CURR_HUF }, ///< hungarian forint
{ 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, ///< icelandic krona
{ 2850, ',', 2002, "", " L.", 1, STR_CURR_ITL }, ///< italian lira
{ 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, ///< dutch gulden
{ 12, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, ///< norwegian krone
{ 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, ///< polish zloty
{ 5, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, ///< romanian Lei
{ 50, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, ///< russian rouble
{ 352, '.', 2007, "", " SIT", 1, STR_CURR_SIT }, ///< slovenian tolar
{ 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, ///< swedish krona
{ 3, '.', CF_NOEURO, "", " TL", 1, STR_CURR_TRY }, ///< turkish lira
{ 52, ',', 2009, "", " Sk", 1, STR_CURR_SKK }, ///< slovak koruna
{ 4, ',', CF_NOEURO, "R$ ", "", 0, STR_CURR_BRL }, ///< brazil real
{ 20, '.', CF_NOEURO, "", " EEK", 1, STR_CURR_EEK }, ///< estonian krooni
{ 1, ' ', CF_NOEURO, "", "", 2, STR_CURR_CUSTOM }, ///< custom currency
{ 1, ',', CF_NOEURO, "£", "", 0, STR_CURR_GBP }, // british pounds
{ 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, // us dollars
{ 2, ',', CF_ISEURO, "", "", 0, STR_CURR_EUR }, // Euro
{ 220, ',', CF_NOEURO, "¥", "", 0, STR_CURR_YEN }, // yen
{ 20, ',', 2002, "", " S.", 1, STR_CURR_ATS }, // austrian schilling
{ 59, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, // belgian franc
{ 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, // swiss franc
{ 41, ',', CF_NOEURO, "", "", 1, STR_CURR_CZK }, // czech koruna
{ 3, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, // deutsche mark
{ 11, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, // danish krone
{ 245, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, // spanish pesetas
{ 9, ',', 2002, "", " mk", 1, STR_CURR_FIM }, // finnish markka
{ 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, // french francs
{ 500, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, // greek drachma
{ 378, ',', 2010, "", " Ft", 1, STR_CURR_HUF }, // hungarian forint
{ 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, // icelandic krona
{ 2850, ',', 2002, "", " L.", 1, STR_CURR_ITL }, // italian lira
{ 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, // dutch gulden
{ 12, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, // norwegian krone
{ 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, // polish zloty
{ 5, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, // romanian Lei
{ 50, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, // russian rouble
{ 352, '.', CF_NOEURO, "", " SIT", 1, STR_CURR_SIT }, // slovenian tolar
{ 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, // swedish krona
{ 3, '.', CF_NOEURO, "", " YTL", 1, STR_CURR_YTL }, // turkish lira
{ 52, ',', CF_NOEURO, "", " Sk", 1, STR_CURR_SKK }, // slovak koruna
{ 4, ',', CF_NOEURO, "R$ ", "", 0, STR_CURR_BRR }, // brazil real
{ 1, ' ', CF_NOEURO, "", "", 2, STR_CURR_CUSTOM }, // custom currency
};
/* Array of currencies used by the system */
@@ -81,9 +78,6 @@ enum {
CURR_SIT,
CURR_SEK,
CURR_YTL,
CURR_SKK,
CURR_BRL,
CURR_EEK,
};
/**
@@ -117,9 +111,9 @@ const byte TTDPatch_To_OTTDIndex[] =
/**
* Will return the ottd's index correspondance to
* the ttdpatch's id. If the id is bigger than the array,
* it is a grf written for ottd, thus returning the same id.
* Only called from newgrf.cpp
* the ttdpatch's id. If the id is bigger then the array,
* it is a grf written for ottd, thus returning the same id.
* Only called from newgrf.c
* @param grfcurr_id currency id coming from newgrf
* @return the corrected index
**/
@@ -128,11 +122,8 @@ byte GetNewgrfCurrencyIdConverted(byte grfcurr_id)
return (grfcurr_id >= lengthof(TTDPatch_To_OTTDIndex)) ? grfcurr_id : TTDPatch_To_OTTDIndex[grfcurr_id];
}
/**
* get a mask of the allowed currencies depending on the year
* @return mask of currencies
*/
uint GetMaskOfAllowedCurrencies()
/* get a mask of the allowed currencies depending on the year */
uint GetMaskOfAllowedCurrencies(void)
{
uint mask = 0;
uint i;
@@ -151,25 +142,25 @@ uint GetMaskOfAllowedCurrencies()
/**
* Verify if the currency chosen by the user is about to be converted to Euro
**/
void CheckSwitchToEuro()
void CheckSwitchToEuro(void)
{
if (_currency_specs[_settings_game.locale.currency].to_euro != CF_NOEURO &&
_currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO &&
_cur_year >= _currency_specs[_settings_game.locale.currency].to_euro) {
_settings_game.locale.currency = 2; // this is the index of euro above.
AddNewsItem(STR_EURO_INTRODUCE, NS_ECONOMY, 0, 0);
if (_currency_specs[_opt.currency].to_euro != CF_NOEURO &&
_currency_specs[_opt.currency].to_euro != CF_ISEURO &&
_cur_year >= _currency_specs[_opt.currency].to_euro) {
_opt.currency = 2; // this is the index of euro above.
AddNewsItem(STR_EURO_INTRODUCE, NEWS_FLAGS(NM_NORMAL, 0, NT_ECONOMY, 0), 0, 0);
}
}
/**
* Will fill _currency_specs array with
* default values from origin_currency_specs
* Called only from newgrf.cpp and settings.cpp.
* Called only from newgrf.c and settings.c.
* @param preserve_custom will not reset custom currency (the latest one on the list)
* if ever it is flagged to true. In which case, the total size of the memory to move
* will be one currency spec less, thus preserving the custom curreny from been
* overwritten.
**/
* overwritten.void ResetCurrencies(bool preserve_custom)
*/
void ResetCurrencies(bool preserve_custom)
{
memcpy(&_currency_specs, &origin_currency_specs, sizeof(origin_currency_specs) - (preserve_custom ? sizeof(_custom_currency) : 0));
@@ -179,7 +170,7 @@ void ResetCurrencies(bool preserve_custom)
* Build a list of currency names StringIDs to use in a dropdown list
* @return Pointer to a (static) array of StringIDs
*/
StringID *BuildCurrencyDropdown()
StringID* BuildCurrencyDropdown(void)
{
/* Allow room for all currencies, plus a terminator entry */
static StringID names[NUM_CURRENCY + 1];

View File

@@ -1,21 +1,16 @@
/* $Id$ */
/** @file currency.h Functions to handle different currencies. */
#ifndef CURRENCY_H
#define CURRENCY_H
#include "date_type.h"
#include "strings_type.h"
enum {
CF_NOEURO = 0,
CF_ISEURO = 1,
NUM_CURRENCY = 29,
NUM_CURRENCY = 28,
CUSTOM_CURRENCY_ID = NUM_CURRENCY - 1
};
struct CurrencySpec {
typedef struct {
uint16 rate;
char separator;
Year to_euro;
@@ -32,19 +27,19 @@ struct CurrencySpec {
*/
byte symbol_pos;
StringID name;
};
} CurrencySpec;
extern CurrencySpec _currency_specs[NUM_CURRENCY];
// XXX small hack, but makes the rest of the code a bit nicer to read
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
#define _currency ((const CurrencySpec*)&_currency_specs[_game_mode == GM_MENU ? _settings_newgame.locale.currency : _settings_game.locale.currency])
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
uint GetMaskOfAllowedCurrencies();
void CheckSwitchToEuro();
void ResetCurrencies(bool preserve_custom = true);
StringID *BuildCurrencyDropdown();
uint GetMaskOfAllowedCurrencies(void);
void CheckSwitchToEuro(void);
void ResetCurrencies(bool preserve_custom);
StringID* BuildCurrencyDropdown(void);
byte GetNewgrfCurrencyIdConverted(byte grfcurr_id);
#endif /* CURRENCY_H */

BIN
data/2ccmap.grf Normal file

Binary file not shown.

BIN
data/airports.grf Normal file

Binary file not shown.

BIN
data/autorail.grf Normal file

Binary file not shown.

BIN
data/canalsw.grf Normal file

Binary file not shown.

BIN
data/dosdummy.grf Normal file

Binary file not shown.

BIN
data/elrailsw.grf Normal file

Binary file not shown.

BIN
data/nsignalsw.grf Normal file

Binary file not shown.

BIN
data/openttd.grf Normal file

Binary file not shown.

BIN
data/trkfoundw.grf Normal file

Binary file not shown.

View File

@@ -1,25 +1,20 @@
/* $Id$ */
/** @file date.cpp Handling of dates in our native format and transforming them to something human readable. */
#include "stdafx.h"
#include "openttd.h"
#include "date.h"
#include "variables.h"
#include "settings_type.h"
#include "network/network.h"
#include "network/network_func.h"
#include "currency.h"
#include "window_func.h"
#include "macros.h"
#include "vehicle.h"
#include "network.h"
#include "network_data.h"
#include "network_server.h"
#include "functions.h"
#include "date_func.h"
#include "vehicle_base.h"
#include "debug.h"
#include "rail_gui.h"
#include "saveload/saveload.h"
#include "currency.h"
Year _cur_year; ///< Current year, starting at 0
Month _cur_month; ///< Current month (0..11)
Date _date; ///< Current date in days (day counter)
Year _cur_year;
Month _cur_month;
Date _date;
DateFract _date_fract;
@@ -31,6 +26,10 @@ void SetDate(Date date)
ConvertDateToYMD(date, &ymd);
_cur_year = ymd.year;
_cur_month = ymd.month;
#ifdef ENABLE_NETWORK
_network_last_advertise_frame = 0;
_network_need_advertise = true;
#endif /* ENABLE_NETWORK */
}
#define M(a, b) ((a << 5) | b)
@@ -71,6 +70,11 @@ static const uint16 _accum_days_for_month[] = {
ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
};
static inline bool IsLeapYear(Year yr)
{
return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0);
}
/**
* Converts a Date to a Year, Month & Day.
* @param date the date to convert from
@@ -84,35 +88,35 @@ void ConvertDateToYMD(Date date, YearMonthDay *ymd)
*/
/* There are 97 leap years in 400 years */
Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
int rem = date % (DAYS_IN_YEAR * 400 + 97);
Year yr = 400 * (date / (365 * 400 + 97));
int rem = date % (365 * 400 + 97);
uint16 x;
if (rem >= DAYS_IN_YEAR * 100 + 25) {
if (rem >= 365 * 100 + 25) {
/* There are 25 leap years in the first 100 years after
* every 400th year, as every 400th year is a leap year */
yr += 100;
rem -= DAYS_IN_YEAR * 100 + 25;
rem -= 365 * 100 + 25;
/* There are 24 leap years in the next couple of 100 years */
yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
rem = (rem % (DAYS_IN_YEAR * 100 + 24));
yr += 100 * (rem / (365 * 100 + 24));
rem = (rem % (365 * 100 + 24));
}
if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
if (!IsLeapYear(yr) && rem >= 365 * 4) {
/* The first 4 year of the century are not always a leap year */
yr += 4;
rem -= DAYS_IN_YEAR * 4;
rem -= 365 * 4;
}
/* There is 1 leap year every 4 years */
yr += 4 * (rem / (DAYS_IN_YEAR * 4 + 1));
rem = rem % (DAYS_IN_YEAR * 4 + 1);
yr += 4 * (rem / (365 * 4 + 1));
rem = rem % (365 * 4 + 1);
/* The last (max 3) years to account for; the first one
* can be, but is not necessarily a leap year */
while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
while (rem >= (IsLeapYear(yr) ? 366 : 365)) {
rem -= IsLeapYear(yr) ? 366 : 365;
yr++;
}
@@ -149,34 +153,55 @@ Date ConvertYMDToDate(Year year, Month month, Day day)
/* Account for the missing of the 29th of February in non-leap years */
if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
return year * DAYS_IN_YEAR + nr_of_leap_years + days;
return year * 365 + nr_of_leap_years + days;
}
/** Functions used by the IncreaseDate function */
extern void WaypointsDailyLoop();
extern void EnginesDailyLoop();
extern void DisasterDailyLoop();
extern void IndustryDailyLoop();
extern void CompaniesMonthlyLoop();
extern void EnginesMonthlyLoop();
extern void TownsMonthlyLoop();
extern void IndustryMonthlyLoop();
extern void StationMonthlyLoop();
extern void OnNewDay_Train(Vehicle *v);
extern void OnNewDay_RoadVeh(Vehicle *v);
extern void OnNewDay_Aircraft(Vehicle *v);
extern void OnNewDay_Ship(Vehicle *v);
static void OnNewDay_EffectVehicle(Vehicle *v) { /* empty */ }
extern void OnNewDay_DisasterVehicle(Vehicle *v);
extern void CompaniesYearlyLoop();
extern void VehiclesYearlyLoop();
extern void TownsYearlyLoop();
typedef void OnNewVehicleDayProc(Vehicle *v);
extern void ShowEndGameChart();
static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = {
OnNewDay_Train,
OnNewDay_RoadVeh,
OnNewDay_Ship,
OnNewDay_Aircraft,
OnNewDay_EffectVehicle,
OnNewDay_DisasterVehicle,
};
extern void WaypointsDailyLoop(void);
extern void TextMessageDailyLoop(void);
extern void EnginesDailyLoop(void);
extern void DisasterDailyLoop(void);
extern void PlayersMonthlyLoop(void);
extern void EnginesMonthlyLoop(void);
extern void TownsMonthlyLoop(void);
extern void IndustryMonthlyLoop(void);
extern void StationMonthlyLoop(void);
extern void PlayersYearlyLoop(void);
extern void TrainsYearlyLoop(void);
extern void RoadVehiclesYearlyLoop(void);
extern void AircraftYearlyLoop(void);
extern void ShipsYearlyLoop(void);
extern void ShowEndGameChart(void);
static const Month _autosave_months[] = {
0, ///< never
1, ///< every month
3, ///< every 3 months
6, ///< every 6 months
12, ///< every 12 months
0, // never
1, // every month
3, // every 3 months
6, // every 6 months
12, // every 12 months
};
/**
@@ -190,15 +215,11 @@ static void RunVehicleDayProc(uint daytick)
for (i = daytick; i < total; i += DAY_TICKS) {
Vehicle *v = GetVehicle(i);
if (v->IsValid()) {
/* Call the 32-day callback if needed */
CheckVehicle32Day(v);
v->OnNewDay();
}
if (IsValidVehicle(v)) _on_new_vehicle_day_proc[v->type - 0x10](v);
}
}
void IncreaseDate()
void IncreaseDate(void)
{
YearMonthDay ymd;
@@ -219,13 +240,10 @@ void IncreaseDate()
/* yeah, increase day counter and call various daily loops */
_date++;
#ifdef ENABLE_NETWORK
NetworkChatMessageDailyLoop();
#endif /* ENABLE_NETWORK */
TextMessageDailyLoop();
DisasterDailyLoop();
WaypointsDailyLoop();
IndustryDailyLoop();
if (_game_mode != GM_MENU) {
InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
@@ -239,26 +257,17 @@ void IncreaseDate()
/* yes, call various monthly loops */
if (_game_mode != GM_MENU) {
if (_debug_desync_level > 2) {
char name[MAX_PATH];
snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
}
if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) {
_do_autosave = true;
RedrawAutosave();
}
InvalidateWindowClasses(WC_CHEATS);
CompaniesMonthlyLoop();
PlayersMonthlyLoop();
EnginesMonthlyLoop();
TownsMonthlyLoop();
IndustryMonthlyLoop();
StationMonthlyLoop();
#ifdef ENABLE_NETWORK
if (_network_server) NetworkServerMonthlyLoop();
#endif /* ENABLE_NETWORK */
}
/* check if we entered a new year? */
@@ -266,34 +275,30 @@ void IncreaseDate()
_cur_year = ymd.year;
/* yes, call various yearly loops */
CompaniesYearlyLoop();
VehiclesYearlyLoop();
TownsYearlyLoop();
#ifdef ENABLE_NETWORK
PlayersYearlyLoop();
TrainsYearlyLoop();
RoadVehiclesYearlyLoop();
AircraftYearlyLoop();
ShipsYearlyLoop();
if (_network_server) NetworkServerYearlyLoop();
#endif /* ENABLE_NETWORK */
if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
/* check if we reached end of the game */
if (_cur_year == ORIGINAL_END_YEAR) {
ShowEndGameChart();
if (_cur_year == _patches.ending_year) {
ShowEndGameChart();
/* check if we reached the maximum year, decrement dates by a year */
} else if (_cur_year == MAX_YEAR + 1) {
Vehicle *v;
uint days_this_year;
_cur_year--;
days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
days_this_year = IsLeapYear(_cur_year) ? 366 : 365;
_date -= days_this_year;
FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
#ifdef ENABLE_NETWORK
/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
* all of them if the date is set back, else those messages will hang for ever */
NetworkInitChatMessage();
#endif /* ENABLE_NETWORK */
InitTextMessage();
}
if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
if (_patches.auto_euro) CheckSwitchToEuro();
}

View File

@@ -1,9 +1,7 @@
/* $Id$ */
/** @file date_type.h Types related to the dates in OpenTTD. */
#ifndef DATE_TYPE_H
#define DATE_TYPE_H
#ifndef DATE_H
#define DATE_H
/**
* 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On
@@ -11,11 +9,7 @@
* 1 tick is approximately 30 ms.
* 1 day is thus about 2 seconds (74 * 30 = 2220) on a machine that can run OpenTTD normally
*/
enum {
DAY_TICKS = 74, ///< ticks per day
DAYS_IN_YEAR = 365, ///< days per year
DAYS_IN_LEAP_YEAR = 366, ///< sometimes, you need one day more...
};
#define DAY_TICKS 74
/*
* ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR and DAYS_TILL_ORIGINAL_BASE_YEAR are
@@ -26,8 +20,6 @@ enum {
/** The minimum starting year/base year of the original TTD */
#define ORIGINAL_BASE_YEAR 1920
/** The original ending year */
#define ORIGINAL_END_YEAR 2051
/** The maximum year of the original TTD */
#define ORIGINAL_MAX_YEAR 2090
@@ -35,7 +27,7 @@ enum {
* The offset in days from the '_date == 0' till
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
*/
#define DAYS_TILL_ORIGINAL_BASE_YEAR (DAYS_IN_YEAR * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400)
#define DAYS_TILL_ORIGINAL_BASE_YEAR (365 * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400)
/* The absolute minimum & maximum years in OTTD */
#define MIN_YEAR 0
@@ -43,24 +35,25 @@ enum {
* be encoded in a single 32 bits date, about 2^31 / 366 years. */
#define MAX_YEAR 5000000
typedef int32 Date;
typedef uint16 DateFract;
typedef int32 Year;
/* Year and Date are defined elsewhere */
typedef uint8 Month;
typedef uint8 Day;
typedef uint16 DateFract;
/**
* Data structure to convert between Date and triplet (year, month, and day).
* @see ConvertDateToYMD(), ConvertYMDToDate()
*/
struct YearMonthDay {
Year year; ///< Year (0...)
Month month; ///< Month (0..11)
Day day; ///< Day (1..31)
};
typedef struct YearMonthDay {
Year year;
Month month;
Day day;
} YearMonthDay;
static const Year INVALID_YEAR = -1;
static const Date INVALID_DATE = -1;
extern Year _cur_year;
extern Month _cur_month;
extern Date _date;
extern DateFract _date_fract;
#endif /* DATE_TYPE_H */
void SetDate(Date date);
void ConvertDateToYMD(Date date, YearMonthDay *ymd);
Date ConvertYMDToDate(Year year, Month month, Day day);
#endif /* DATE_H */

View File

@@ -1,19 +1,13 @@
/* $Id$ */
/** @file debug.cpp Handling of printing debug messages. */
#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include "console_func.h"
#include "openttd.h"
#include "console.h"
#include "debug.h"
#include "string_func.h"
#include "network/core/core.h"
#include "fileio_func.h"
#if defined(ENABLE_NETWORK)
SOCKET _debug_socket = INVALID_SOCKET;
#endif /* ENABLE_NETWORK */
#include "functions.h"
#include "string.h"
int _debug_ai_level;
int _debug_driver_level;
@@ -22,22 +16,30 @@ int _debug_map_level;
int _debug_misc_level;
int _debug_ms_level;
int _debug_net_level;
int _debug_sprite_level;
int _debug_spritecache_level;
int _debug_oldloader_level;
int _debug_ntp_level;
int _debug_npf_level;
int _debug_yapf_level;
int _debug_freetype_level;
int _debug_sl_level;
int _debug_station_level;
int _debug_gamelog_level;
int _debug_desync_level;
struct DebugLevel {
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[] = {
@@ -48,72 +50,22 @@ struct DebugLevel {
DEBUG_LEVEL(misc),
DEBUG_LEVEL(ms),
DEBUG_LEVEL(net),
DEBUG_LEVEL(sprite),
DEBUG_LEVEL(spritecache),
DEBUG_LEVEL(oldloader),
DEBUG_LEVEL(ntp),
DEBUG_LEVEL(npf),
DEBUG_LEVEL(yapf),
DEBUG_LEVEL(freetype),
DEBUG_LEVEL(sl),
DEBUG_LEVEL(station),
DEBUG_LEVEL(gamelog),
DEBUG_LEVEL(desync),
DEBUG_LEVEL(freetype)
};
#undef DEBUG_LEVEL
#if !defined(NO_DEBUG_MESSAGES)
static void debug_print(const char *dbg, const char *buf)
{
#if defined(ENABLE_NETWORK)
if (_debug_socket != INVALID_SOCKET) {
char buf2[1024 + 32];
snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
send(_debug_socket, buf2, (int)strlen(buf2), 0);
} else
#endif /* ENABLE_NETWORK */
if (strcmp(dbg, "desync") != 0) {
#if defined(WINCE)
/* We need to do OTTD2FS twice, but as it uses a static buffer, we need to store one temporary */
TCHAR tbuf[512];
_sntprintf(tbuf, sizeof(tbuf), _T("%s"), OTTD2FS(dbg));
NKDbgPrintfW(_T("dbg: [%s] %s\n"), tbuf, OTTD2FS(buf));
#else
fprintf(stderr, "dbg: [%s] %s\n", dbg, buf);
#endif
IConsoleDebug(dbg, buf);
} else {
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
if (f == NULL) return;
fprintf(f, "%s", buf);
fflush(f);
}
}
void CDECL debug(const char *dbg, ...)
{
va_list va;
va_start(va, dbg);
const char *s;
char buf[1024];
s = va_arg(va, const char*);
vsnprintf(buf, lengthof(buf), s, va);
va_end(va);
debug_print(dbg, buf);
}
#endif /* NO_DEBUG_MESSAGES */
void SetDebugString(const char *s)
{
int v;
char *end;
const char *t;
/* global debugging level? */
// global debugging level?
if (*s >= '0' && *s <= '9') {
const DebugLevel *i;
@@ -123,19 +75,19 @@ void SetDebugString(const char *s)
for (i = debug_level; i != endof(debug_level); ++i) *i->level = v;
}
/* individual levels */
// individual levels
for (;;) {
const DebugLevel *i;
int *p;
/* skip delimiters */
// skip delimiters
while (*s == ' ' || *s == ',' || *s == '\t') s++;
if (*s == '\0') break;
t = s;
while (*s >= 'a' && *s <= 'z') s++;
/* check debugging levels */
// 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) {
@@ -159,10 +111,10 @@ void SetDebugString(const char *s)
* Just return a string with the values of all the debug categorites
* @return string with debug-levels
*/
const char *GetDebugString()
const char *GetDebugString(void)
{
const DebugLevel *i;
static char dbgstr[150];
static char dbgstr[100];
char dbgval[20];
memset(dbgstr, 0, sizeof(dbgstr));
@@ -171,7 +123,7 @@ const char *GetDebugString()
for (i++; i != endof(debug_level); i++) {
snprintf(dbgval, sizeof(dbgval), ", %s=%d", i->name, *i->level);
strecat(dbgstr, dbgval, lastof(dbgstr));
ttd_strlcat(dbgstr, dbgval, sizeof(dbgstr));
}
return dbgstr;

54
debug.h Normal file
View File

@@ -0,0 +1,54 @@
/* $Id$ */
#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_driver_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_ntp_level;
extern int _debug_npf_level;
extern int _debug_yapf_level;
extern int _debug_freetype_level;
#endif
void CDECL debug(const char *s, ...);
void SetDebugString(const char *s);
const char *GetDebugString(void);
/* MSVCRT of course has to have a different syntax for long long *sigh* */
#if defined(_MSC_VER) || defined(__MINGW32__)
# define OTTD_PRINTF64 "I64"
#else
# define OTTD_PRINTF64 "ll"
#endif
// Used for profiling
#define TIC() {\
extern uint64 _rdtsc(void);\
uint64 _xxx_ = _rdtsc();\
static uint64 __sum__ = 0;\
static uint32 __i__ = 0;
#define TOC(str, count)\
__sum__ += _rdtsc() - _xxx_;\
if (++__i__ == count) {\
printf("[%s]: %" OTTD_PRINTF64 "u [avg: %.1f]\n", str, __sum__, __sum__/(double)__i__);\
__i__ = 0;\
__sum__ = 0;\
}\
}
#endif /* DEBUG_H */

View File

@@ -1,26 +1,18 @@
/* $Id$ */
/** @file dedicated.cpp Forking support for dedicated servers. */
#include "stdafx.h"
#ifdef ENABLE_NETWORK
#if defined(UNIX) && !defined(__MORPHOS__)
#include "openttd.h"
#include "variables.h"
#include <sys/types.h>
#include <unistd.h>
#if defined(SUNOS) && !defined(_LP64) && !defined(_I32LPx)
/* Solaris has, in certain situation, pid_t defined as long, while in other
* cases it has it defined as int... this handles all cases nicely. */
# define PRINTF_PID_T "%ld"
#else
# define PRINTF_PID_T "%d"
#endif
void DedicatedFork()
void DedicatedFork(void)
{
/* Fork the program */
pid_t pid = fork();
@@ -30,7 +22,7 @@ void DedicatedFork()
exit(1);
case 0: { // We're the child
FILE *f;
FILE* f;
/* Open the log-file to log all stuff too */
f = fopen(_log_file, "a");
@@ -51,9 +43,9 @@ void DedicatedFork()
}
default:
/* We're the parent */
// We're the parent
printf("Loading dedicated server...\n");
printf(" - Forked to background with pid " PRINTF_PID_T "\n", pid);
printf(" - Forked to background with pid %d\n", pid);
exit(0);
}
}
@@ -61,7 +53,6 @@ void DedicatedFork()
#else
/** Empty helper function call for NOT(UNIX and not MORPHOS) systems */
void DedicatedFork() {}
void DedicatedFork(void) {}
#endif /* ENABLE_NETWORK */

127
depot.c Normal file
View File

@@ -0,0 +1,127 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "depot.h"
#include "functions.h"
#include "tile.h"
#include "map.h"
#include "table/strings.h"
#include "saveload.h"
#include "order.h"
/**
* Called if a new block is added to the depot-pool
*/
static void DepotPoolNewBlock(uint start_item)
{
Depot *d;
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
* TODO - This is just a temporary stage, this will be removed. */
for (d = GetDepot(start_item); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) d->index = start_item++;
}
DEFINE_OLD_POOL(Depot, Depot, DepotPoolNewBlock, NULL)
/**
* Gets a depot from a tile
*
* @return Returns the depot if the tile had a depot, else it returns NULL
*/
Depot *GetDepotByTile(TileIndex tile)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (depot->xy == tile) return depot;
}
return NULL;
}
/**
* Allocate a new depot
*/
Depot *AllocateDepot(void)
{
Depot *d;
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
* TODO - This is just a temporary stage, this will be removed. */
for (d = GetDepot(0); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) {
if (!IsValidDepot(d)) {
DepotID index = d->index;
memset(d, 0, sizeof(Depot));
d->index = index;
return d;
}
}
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_Depot_pool)) return AllocateDepot();
return NULL;
}
/**
* Clean up a depot
*/
void DestroyDepot(Depot *depot)
{
/* Clear the tile */
DoClearSquare(depot->xy);
/* Clear the depot from all order-lists */
RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, depot->index);
/* Delete the depot-window */
DeleteWindowById(WC_VEHICLE_DEPOT, depot->xy);
}
void InitializeDepots(void)
{
CleanPool(&_Depot_pool);
AddBlockToPool(&_Depot_pool);
}
static const SaveLoad _depot_desc[] = {
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, SL_MAX_VERSION),
SLE_VAR(Depot, town_index, SLE_UINT16),
SLE_END()
};
static void Save_DEPT(void)
{
Depot *depot;
FOR_ALL_DEPOTS(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},
};

112
depot.h Normal file
View File

@@ -0,0 +1,112 @@
/* $Id$ */
#ifndef DEPOT_H
#define DEPOT_H
/** @file depot.h Header files for depots (not hangars)
* @see depot.c */
#include "direction.h"
#include "oldpool.h"
#include "tile.h"
#include "variables.h"
struct Depot {
TileIndex xy;
TownID town_index;
DepotID index;
};
DECLARE_OLD_POOL(Depot, Depot, 3, 8000)
/**
* Check if a depot really exists.
*/
static inline bool IsValidDepot(const Depot *depot)
{
return depot != NULL && depot->xy != 0;
}
static inline bool IsValidDepotID(uint index)
{
return index < GetDepotPoolSize() && IsValidDepot(GetDepot(index));
}
void DestroyDepot(Depot *depot);
static inline void DeleteDepot(Depot *depot)
{
DestroyDepot(depot);
depot->xy = 0;
}
void ShowDepotWindow(TileIndex tile, byte type);
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) if (IsValidDepot(d))
#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 Date GetServiceIntervalClamped(uint index)
{
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
}
/**
* 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) && (_m[tile].m5 & 0xFC) == 0xC0;
case TRANSPORT_ROAD:
return IsTileType(tile, MP_STREET) && (_m[tile].m5 & 0xF0) == 0x20;
case TRANSPORT_WATER:
return IsTileType(tile, MP_WATER) && (_m[tile].m5 & ~3) == 0x80;
default:
assert(0);
return false;
}
}
/**
* Find out if the slope of the tile is suitable to build a depot of given direction
* @param direction The direction in which the depot's exit points. Starts with 0 as NE and goes Clockwise
* @param tileh The slope of the tile in question
* @return true if the construction is possible
* This is checked by the ugly 0x4C >> direction magic, which does the following:
* 0x4C is 0100 1100 and tileh has only bits 0..3 set (steep tiles are ruled out)
* So: for direction (only the significant bits are shown)<p>
* 00 (exit towards NE) we need either bit 2 or 3 set in tileh: 0x4C >> 0 = 1100<p>
* 01 (exit towards SE) we need either bit 1 or 2 set in tileh: 0x4C >> 1 = 0110<p>
* 02 (exit towards SW) we need either bit 0 or 1 set in tileh: 0x4C >> 2 = 0011<p>
* 03 (exit towards NW) we need either bit 0 or 4 set in tileh: 0x4C >> 3 = 1001<p>
* So ((0x4C >> direction) & tileh) determines whether the depot can be built on the current tileh
*/
static inline bool CanBuildDepotByTileh(uint32 direction, Slope tileh)
{
return ((0x4C >> direction) & tileh) != 0;
}
Depot *GetDepotByTile(TileIndex tile);
void InitializeDepots(void);
Depot *AllocateDepot(void);
void DeleteDepotHighlightOfVehicle(const Vehicle *v);
#endif /* DEPOT_H */

1016
depot_gui.c Normal file

File diff suppressed because it is too large Load Diff

147
direction.h Normal file
View File

@@ -0,0 +1,147 @@
/* $Id$ */
#ifndef DIRECTION_H
#define DIRECTION_H
/* Direction as commonly used in v->direction, 8 way. */
typedef enum Direction {
DIR_N = 0,
DIR_NE = 1, /* Northeast, upper right on your monitor */
DIR_E = 2,
DIR_SE = 3,
DIR_S = 4,
DIR_SW = 5,
DIR_W = 6,
DIR_NW = 7,
DIR_END,
INVALID_DIR = 0xFF,
} Direction;
static inline Direction ReverseDir(Direction d)
{
return (Direction)(4 ^ d);
}
typedef enum DirDiff {
DIRDIFF_SAME = 0,
DIRDIFF_45RIGHT = 1,
DIRDIFF_90RIGHT = 2,
DIRDIFF_REVERSE = 4,
DIRDIFF_90LEFT = 6,
DIRDIFF_45LEFT = 7
} DirDiff;
static inline DirDiff DirDifference(Direction d0, Direction d1)
{
return (DirDiff)((d0 + 8 - d1) % 8);
}
static inline DirDiff ChangeDirDiff(DirDiff d, DirDiff delta)
{
return (DirDiff)((d + delta) % 8);
}
static inline Direction ChangeDir(Direction d, DirDiff delta)
{
return (Direction)((d + delta) % 8);
}
/* Direction commonly used as the direction of entering and leaving tiles, 4-way */
typedef enum DiagDirection {
DIAGDIR_NE = 0, /* Northeast, upper right on your monitor */
DIAGDIR_SE = 1,
DIAGDIR_SW = 2,
DIAGDIR_NW = 3,
DIAGDIR_END,
INVALID_DIAGDIR = 0xFF,
} DiagDirection;
static inline DiagDirection ReverseDiagDir(DiagDirection d)
{
return (DiagDirection)(2 ^ d);
}
typedef enum DiagDirDiff {
DIAGDIRDIFF_SAME = 0,
DIAGDIRDIFF_90RIGHT = 1,
DIAGDIRDIFF_REVERSE = 2,
DIAGDIRDIFF_90LEFT = 3
} DiagDirDiff;
static inline DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
{
return (DiagDirection)((d + delta) % 4);
}
static inline DiagDirection DirToDiagDir(Direction dir)
{
return (DiagDirection)(dir >> 1);
}
static inline Direction DiagDirToDir(DiagDirection dir)
{
return (Direction)(dir * 2 + 1);
}
/* the 2 axis */
typedef enum Axis {
AXIS_X = 0,
AXIS_Y = 1,
AXIS_END
} Axis;
static inline Axis OtherAxis(Axis a)
{
return (Axis)(a ^ 1);
}
static inline Axis DiagDirToAxis(DiagDirection d)
{
return (Axis)(d & 1);
}
/*
* Converts an Axis to a DiagDirection
* Points always in the positive direction, i.e. S[EW]
*/
static inline DiagDirection AxisToDiagDir(Axis a)
{
return (DiagDirection)(2 - a);
}
/**
* Convert an axis and a flag for north/south into a DiagDirection
* @param ns north -> 0, south -> 1
*/
static inline DiagDirection XYNSToDiagDir(Axis xy, uint ns)
{
return (DiagDirection)(xy * 3 ^ ns * 2);
}
static inline bool IsValidDiagDirection(DiagDirection d)
{
return d < DIAGDIR_END;
}
static inline bool IsValidDirection(Direction d)
{
return d < DIR_END;
}
static inline bool IsValidAxis(Axis d)
{
return d < AXIS_END;
}
#endif /* DIRECTION_H */

1001
disaster_cmd.c Normal file

File diff suppressed because it is too large Load Diff

378
dock_gui.c Normal file
View File

@@ -0,0 +1,378 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "functions.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"
#include "variables.h"
static void ShowBuildDockStationPicker(void);
static void ShowBuildDocksDepotPicker(void);
static Axis _ship_depot_direction;
void CcBuildDocks(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) {
SndPlayTileFx(SND_02_SPLAT, tile);
ResetObjectToPlace();
}
}
void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
}
static void PlaceDocks_Dock(TileIndex tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
}
static void PlaceDocks_Depot(TileIndex tile)
{
DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_AUTO | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT));
}
static void PlaceDocks_Buoy(TileIndex tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
}
static void PlaceDocks_DemolishArea(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
}
static void PlaceDocks_BuildCanal(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_OR_Y);
}
static void PlaceDocks_BuildLock(TileIndex tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
}
enum {
DTW_CANAL = 3,
DTW_LOCK = 4,
DTW_DEMOLISH = 6,
DTW_DEPOT = 7,
DTW_STATION = 8,
DTW_BUOY = 9
};
static void BuildDocksClick_Canal(Window *w)
{
HandlePlacePushButton(w, DTW_CANAL, SPR_CURSOR_CANAL, 1, PlaceDocks_BuildCanal);
}
static void BuildDocksClick_Lock(Window *w)
{
HandlePlacePushButton(w, DTW_LOCK, SPR_CURSOR_LOCK, 1, PlaceDocks_BuildLock);
}
static void BuildDocksClick_Demolish(Window *w)
{
HandlePlacePushButton(w, DTW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
}
static void BuildDocksClick_Depot(Window *w)
{
if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
}
static void BuildDocksClick_Dock(Window *w)
{
if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
}
static void BuildDocksClick_Buoy(Window *w)
{
HandlePlacePushButton(w, DTW_BUOY, SPR_CURSOR_BOUY, 1, PlaceDocks_Buoy);
}
static void BuildDocksClick_Landscaping(Window *w)
{
ShowTerraformToolbar();
}
typedef void OnButtonClick(Window *w);
static OnButtonClick * const _build_docks_button_proc[] = {
BuildDocksClick_Canal,
BuildDocksClick_Lock,
NULL,
BuildDocksClick_Demolish,
BuildDocksClick_Depot,
BuildDocksClick_Dock,
BuildDocksClick_Buoy,
BuildDocksClick_Landscaping,
};
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT:
DrawWindowWidgets(w);
break;
case WE_CLICK:
if (e->we.click.widget - 3 >= 0 && e->we.click.widget != 5) _build_docks_button_proc[e->we.click.widget - 3](w);
break;
case WE_KEYPRESS:
switch (e->we.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:
_place_proc(e->we.place.tile);
break;
case WE_PLACE_DRAG: {
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
return;
}
case WE_PLACE_MOUSEUP:
if (e->we.place.pt.x != -1) {
if ((e->we.place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
GUIPlaceProcDragXY(e);
} else if (e->we.place.userdata == VPM_X_OR_Y) {
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
}
}
break;
case WE_ABORT_PLACE_OBJ:
RaiseWindowButtons(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != NULL) WP(w,def_d).close = true;
w = FindWindowById(WC_BUILD_DEPOT, 0);
if (w != NULL) WP(w,def_d).close = true;
break;
case WE_PLACE_PRESIZE: {
TileIndex tile_from;
TileIndex tile_to;
tile_from = tile_to = e->we.place.tile;
switch (GetTileSlope(tile_from, NULL)) {
case SLOPE_SW: tile_to += TileDiffXY(-1, 0); break;
case SLOPE_SE: tile_to += TileDiffXY( 0, -1); break;
case SLOPE_NW: tile_to += TileDiffXY( 0, 1); break;
case SLOPE_NE: tile_to += TileDiffXY( 1, 0); break;
default: break;
}
VpSetPresizeRange(tile_from, tile_to);
} break;
case WE_DESTROY:
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
break;
}
}
static const Widget _build_docks_toolb_widgets[] = {
{ 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_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
{ WWT_IMGBTN, 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_IMGBTN, RESIZE_NONE, 7, 48, 69, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_SHIP_DEPOT, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_SHIP_DOCK, STR_981D_BUILD_SHIP_DOCK},
{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_BOUY, STR_9834_POSITION_BUOY_WHICH_CAN},
{ WWT_IMGBTN, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
{ WIDGETS_END},
};
static const WindowDesc _build_docks_toolbar_desc = {
WDP_ALIGN_TBR, 22, 158, 36,
WC_BUILD_TOOLBAR, 0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
_build_docks_toolb_widgets,
BuildDocksToolbWndProc
};
void ShowBuildDocksToolbar(void)
{
if (!IsValidPlayer(_current_player)) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
AllocateWindowDesc(&_build_docks_toolbar_desc);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
}
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE: LowerWindowWidget(w, _station_show_coverage + 3); break;
case WE_PAINT: {
int rad;
if (WP(w,def_d).close) return;
DrawWindowWidgets(w);
rad = (_patches.modified_catchment) ? CA_DOCK : 4;
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
break;
}
case WE_CLICK:
switch (e->we.click.widget) {
case 3:
case 4:
RaiseWindowWidget(w, _station_show_coverage + 3);
_station_show_coverage = e->we.click.widget - 3;
LowerWindowWidget(w, _station_show_coverage + 3);
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
}
break;
case WE_MOUSELOOP:
if (WP(w,def_d).close) {
DeleteWindow(w);
return;
}
CheckRedrawStationCoverage(w);
break;
case WE_DESTROY:
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
static const Widget _build_dock_station_widgets[] = {
{ 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_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 17, 30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
{ WIDGETS_END},
};
static const WindowDesc _build_dock_station_desc = {
WDP_AUTO, WDP_AUTO, 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(void)
{
AllocateWindowDesc(&_build_dock_station_desc);
}
static void UpdateDocksDirection(void)
{
if (_ship_depot_direction != AXIS_X) {
SetTileSelectSize(1, 2);
} else {
SetTileSelectSize(2, 1);
}
}
static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE: LowerWindowWidget(w, _ship_depot_direction + 3); break;
case WE_PAINT:
DrawWindowWidgets(w);
DrawShipDepotSprite(67, 35, 0);
DrawShipDepotSprite(35, 51, 1);
DrawShipDepotSprite(135, 35, 2);
DrawShipDepotSprite(167, 51, 3);
return;
case WE_CLICK: {
switch (e->we.click.widget) {
case 3:
case 4:
RaiseWindowWidget(w, _ship_depot_direction + 3);
_ship_depot_direction = e->we.click.widget - 3;
LowerWindowWidget(w, _ship_depot_direction + 3);
SndPlayFx(SND_15_BEEP);
UpdateDocksDirection();
SetWindowDirty(w);
break;
}
} break;
case WE_MOUSELOOP:
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, 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},
};
static const WindowDesc _build_docks_depot_desc = {
WDP_AUTO, WDP_AUTO, 204, 86,
WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_docks_depot_widgets,
BuildDocksDepotWndProc
};
static void ShowBuildDocksDepotPicker(void)
{
AllocateWindowDesc(&_build_docks_depot_desc);
UpdateDocksDirection();
}
void InitializeDockGui(void)
{
_ship_depot_direction = AXIS_X;
}

View File

@@ -1,36 +0,0 @@
32bpp and OpenTTD
=================
OpenTTD has 32bpp support. This means: OpenTTD still is 8bpp, but it has the
posibility to override the graphics with 32bpp. This means that it isn't a
replacement of grf or newgrf, but simply an addition. If you want to use 32bpp
graphics of a newgrf, you do need the newgrf itself too (with 8bpp graphics).
The Format
----------
32bpp images are stored in PNG. They should go in:
data/sprites/<grfname>/<SpriteID>.png
For example, a grfname would be 'openttd' (without .grf, lowercase), and the
SpriteID 3, to override the 3rd sprite in openttd.grf with a 32bpp version.
The format of this PNG can be almost anything, but we advise to use RGBA
format. Alpha-channel is fully supported.
As the core of OpenTTD is 8bpp, and because you of course want company colours
in your images, you will need to add a mask for every sprite that needs colour
remapping. The name is simular as above, only you have to put a 'm' behind the
SpriteID. This image should be a 8bpp palette image, where the palette is the
OpenTTD palette. Upon load of the PNG, the mask is loaded too, and overrides
the RGB (not the Alpha) of the original PNG image, and replacing it with a
8bpp color remapped and converted to 32bpp.
An other thing that OpenTTD needs in your png, is 2 tEXt chunks: x_offs and
y_offs. This to define the x- and y-offset, of course. Use the tool we supply
to add this information. Sadly enough most graphical editors trashes those
chunks upon save, so you have to readd it every time you save your image.
Your images should be the same as the grf, in size.

View File

@@ -7,9 +7,8 @@ you have downloaded english.txt, the master language file, for. While this is
not always true, namely when changes in the code have not touched language
files, your safest bet is to assume this 'limitation'.
As a first step you need to compile strgen. This is as easy as typing
'make strgen'. You can download the precompile strgen from:
http://www.openttd.org/download-strgen
'make strgen'. You can also download a precompiled binary from a release,
nightly, etc.
strgen takes as argument a txt file and translates it to a lng file, allowing
it to be used inside OpenTTD. strgen needs the master language file
english.txt to work. Below are some examples of strgen usage.

View File

@@ -0,0 +1,34 @@
This is a guide to compile strgen on gcc
All this is done in the makefile, so it's only interesting for people, who wants to alter something themselves (translators)
HOWTO compile lng files:
First you get strgen compiled (look below/download nightly build/run makefile)
strgen takes the argument of a txt file and translates it to a lng file and places that lng file in the same dir as the txt file.
Example 1:
if you are in the root of your working copy (svn code), you should type
strgen/strgen lang/english.txt
to compile englist.lng. It will be placed in the lang dir
Example 2:
you have strgen but not the source and you want to compile a txt file in the same dir. YOu should type
./strgen english.txt
and you will get english.lng in the same dir
You can change english to whatever language you want
Commands used by strgen
-v --version
strgen will tell what svn revision it is based on
-t
strgen will add <TODO> to the missing strings and use the english strings while compiling
this will need english.txt to be present
-w
strgen will print any missing strings to standard error output(stderr)
this will need english.txt to be present

View File

@@ -13,7 +13,7 @@ Once you have obtained a recent copy of the source, you must build it. Windows b
On UNIX platforms (including OS-X and BeOS), ensure you have a recent GCC (2.9 or above, or 3 and above).You will also need SDL development headers and libraries (libSDL 1.2 or higher). For PNG screenshot support and zlib compressed games, you will need libpng 1.0.12 or higher and zlib 1.2 or higher.
Most UNIX platforms:
First run ./configure, them use make or gmake to compile OpenTTD. You can configure the different compile options via ./configure.
Use make or gmake to compile OpenTTD. You can adjust Makefile.config to compile with other options.
BeOS:
On BeOS, run ./configure and then use jam. There are a variaty of options you can pass to your build tool, these are reported by ./configure.

View File

@@ -50,10 +50,6 @@ To enable music, start OpenTTD with the command line:
If I hear enough responses that both music and sound work together (it might
just be my system), I'll have the defaults changed.
Please note also that the GCC version does not currently support the MCI MIDI
system.
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
------------------------------------------
@@ -64,8 +60,6 @@ directly will result in the console not being displayed. You may
still pass any other parameters ('-D' is already passed) to
dedicated.cmd.
You can find the dedicated.cmd file in the os/os2 directory.
=========================
BUILDING THE OS/2 VERSION
=========================
@@ -80,17 +74,9 @@ may help to set one up (although some of the links from that page are broken):
http://www.mozilla.org/ports/os2/gccsetup.html
Alternatively, Paul Smedley's ready-to-go GCC build environment has been known to
successfully build the game:
http://www.smedley.info/os2ports/index.php?page=build-environment
To build, you should, if your environment is set up well enough, be able to just
type `./configure' (or `sh configure' if you're using the OS/2 shell) and `make'.
You may have to manually specify `--os OS2' on the configure command line, as
configure cannot always detect OS/2 correctly.
A note on Open Watcom
---------------------
@@ -136,4 +122,4 @@ issues, see the Contacting section of readme.txt.
Thanks to Paul Smedley for his help with getting OpenTTD to compile under GCC on OS/2.
- Owen Rudge, 24th June 2007
- Owen Rudge, 8th January 2007

View File

@@ -1,17 +1,15 @@
Compiling OpenTTD using Microsoft Visual C++
January 2, 2007
December 28, 2006
--------------------------------------------
PLEASE READ THE ENTIRE DOCUMENT BEFORE DOING ANY ACTUAL CHANGES!!
SUPPORTED MSVC COMPILERS
------------------------
OpenTTD includes projects for MSVC 2005.NET and MSVC 2008.NET. Both will
OpenTTD includes projects for MSVC 2003.NET and MSVC 2005.NET. Both will
compile out of the box, providing you have the required libraries/headers;
which ones, see below. There is no support for VS6 or MSVC 2002, or
MSVC 2003.NET. You are therefore strongly encouraged to either upgrade to
MSVC 2005 Express (free) or use GCC.
which ones, see below. There is no support for VS6, you are therefore
strongly encouraged to either upgrade to MSVC 2005 Express (free) or use GCC.
MSVC 2002 probably works as well, but it has not been tested.
1) REQUIRED FILES
-----------------
@@ -20,7 +18,7 @@ downloading; mostly because the DirectX SDK and Platform SDK are about
500MB each.
Download the following files:
* openttd-useful.zip (http://binaries.openttd.org/extra/openttd-useful/)
* openttd-useful.zip (http://sf.net/project/showfiles.php?group_id=103924&package_id=114307)
* DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft)
* MS Windows Platform SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en)
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
@@ -29,9 +27,8 @@ Download the following files:
You need an SVN-client to download the source from subversion:
* CLI Subversion (http://subversion.tigris.org/)
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/)
* CLI Subversion (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
2) INCLUDES AND LIBRARIES
-------------------------
@@ -59,7 +56,6 @@ include\ directory and the library files to the Lib\ directory.
It is recommended to use custom directories so you don't overwrite any
default header or library files.
2.2) CUSTOM DIRECTORIES
-----------------------
If you have put the above include and/or library files into custom folders,
@@ -73,10 +69,9 @@ Tools > Options > Projects and Solutions > VC++ Directories > show directories f
NOTE: make sure that the directory for the DirectX SDK is the first one in the
list, above all others, otherwise compilation will most likely fail!!
3) TTD GRAPHICS FILES
---------------------
Copy the following files from Transport Tycoon Deluxe to the bin/data folder
Copy the following files from Transport Tycoon Deluxe to the data folder
* sample.cat
* trg1r.grf
@@ -88,13 +83,12 @@ Copy the following files from Transport Tycoon Deluxe to the bin/data folder
4) COMPILING
------------
Open trunk/openttd_vs[89]0.sln
Open trunk/openttd[_vs80].sln
Set the build mode to 'Release' in
Build > Configuration manager > Active solution configuration > select "Release"
Compile...
If everything works well the binary should be in trunk/objs/Win[32|64]/Release/openttd.exe
If everything works well the binary should be in trunk/Release/openttd.exe
5) EDITING, CHANGING SOURCE CODE
--------------------------------
@@ -103,7 +97,6 @@ Change the startup project to openttd by right-clicking the 'openttd' project
in the Solution Explorer and selecting 'Set as Startup Project'. The 'openttd'
project should now show up bold instead of 'strgen'.
6) PROBLEMS?
------------
If compilation fails, double-check that you are using the latest SVN (!)
@@ -112,4 +105,4 @@ to ask about reasons; or just wait. The problem will most likely solve itself
within a few days as the problem is noticed and fixed.
An up-to-date version of this README can be found on the wiki:
http://wiki.openttd.org/index.php/MicrosoftVisualCExpress
http://wiki.openttd.org/index.php/MicrosoftVisualCExpress

File diff suppressed because it is too large Load Diff

View File

@@ -1,616 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="Author" content="Marcin Grzegorczyk">
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>OpenTTD Landscape externals</title>
</head>
<body>
<h3><a name="Landscape">Landscape</a></h3>
<p>
These are the different house types available on standard game.<br>
<small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
</p>
<table>
<tr>
<th align=left>Type&nbsp;</th>
<th align=left>Size&nbsp;</th>
<th align=left>Climates&nbsp;</th>
<th align=left>Description</th>
</tr>
<tr>
<td nowrap valign=top><tt>00</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>01</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>02</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>small block of flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>03</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>04</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>large office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>05</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>large office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>06</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>town houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
<td>1&times;2</td>
<td>temperate</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>09</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
<td align=left>statue</td>
</tr>
<tr>
<td nowrap valign=top><tt>0A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>fountain</td>
</tr>
<tr>
<td nowrap valign=top><tt>0B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>park (with a pond)</td>
</tr>
<tr>
<td nowrap valign=top><tt>0C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>park (with an alley)</td>
</tr>
<tr>
<td nowrap valign=top><tt>0D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>various types of shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>11</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>modern office building</td>
</tr>
<tr>
<td nowrap valign=top><tt>12</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>warehouse</td>
</tr>
<tr>
<td nowrap valign=top><tt>13</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block (with spiral stairway on the side)</td>
</tr>
<tr>
<td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate</td>
<td align=left>stadium</td>
</tr>
<tr>
<td nowrap valign=top><tt>18</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>old houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>19</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>cottages</td>
</tr>
<tr>
<td nowrap valign=top><tt>1A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>1B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>1C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>1D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>1E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-tropical</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>1F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>theatre</td>
</tr>
<tr>
<td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>stadium (modern style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>24</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>offices (the modern 'vertical tube' style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>25</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>26</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>27</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>cinema</td>
</tr>
<tr>
<td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate</td>
<td align=left>shopping mall</td>
</tr>
<tr>
<td nowrap valign=top><tt>2C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>2D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>2E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>2F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>30</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>31</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>32</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>33</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>34</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>35</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>36</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>37</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>38</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>39</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>3A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>3B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>3C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>3D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>3E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>3F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>40</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>41</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
<td>1&times;2</td>
<td>sub-arctic</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
<td>1&times;2</td>
<td>snow</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>46</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>47</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>48</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>49</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
<td>2&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
<td>2&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (with a tree in a corner)</td>
</tr>
<tr>
<td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>51</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (suburb-type)</td>
</tr>
<tr>
<td nowrap valign=top><tt>52</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>53</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>54</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (with two trees in front)</td>
</tr>
<tr>
<td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
<td>2&times;1</td>
<td>sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>59</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>5A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>5B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>various types of toyland houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>62</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
<td>1&times;2</td>
<td>toyland</td>
<td align=left>houses ('shoe' style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>65</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>66</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>igloo</td>
</tr>
<tr>
<td nowrap valign=top><tt>67</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tepees</td>
</tr>
<tr>
<td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>6A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>6B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>statue</td>
</tr>
<tr>
<td nowrap valign=top><tt>6C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>teapot-house</td>
</tr>
<tr>
<td nowrap valign=top><tt>6D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>piggy-bank</td>
</tr>
</table>
</body>
</html>

View File

@@ -6,7 +6,6 @@
<title>OpenTTD Landscape Internals - #2</title>
<style type="text/css">
span.abuse { font-family: "Courier New", Courier, mono; background-color: rgb(255, 58, 31); }
span.option{ font-family: "Courier New", Courier, mono; background-color: rgb(255,255, 30); }
span.free { font-family: "Courier New", Courier, mono; background-color: rgb(30, 178, 54); }
span.used { font-family: "Courier New", Courier, mono; }
td.bits { white-space: nowrap; text-align: center; font-family: "Courier New", Courier, mono; }
@@ -17,14 +16,13 @@
</head>
<body style="direction: ltr;">
<h3 style="font-weight: bold;">Landscape</h3>
<span style="font-weight: bold;"></span>Six attributes hold the information about a tile.
<span style="font-weight: bold;"></span>Five attributes hold the information about a 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="free">O</span></span> - bit is free</li>
<li><span style="font-weight: bold;"><span class="used">X</span></span> - bit is used</li>
<li><span style="font-weight: bold;"><span class="abuse">&nbsp;</span></span> - bit of attribute is abused for different purposes, i.e. other bits define the actual meaning.</li>
<li><span style="font-weight: bold;"><span class="option">~</span></span> - bit is accessed, but does not really have a meaning (e.g. owner of clear land is always OWNER_NONE)</li>
<li><span style="font-weight: bold;"><span class="abuse">&nbsp;</span></span> - bit of attribute is abused for different purposes</li>
</ul>
<p>
<ul>
@@ -34,110 +32,81 @@ the array so you can quickly see what is used and what is not.
<li><span style="font-weight: bold;">m3</span> - 8 bits in size, is used for general storage</li>
<li><span style="font-weight: bold;">m4</span> - 8 bits in size, is used for general storage</li>
<li><span style="font-weight: bold;">m5</span> - 8 bits in size, is used for general storage</li>
<li><span style="font-weight: bold;">m6</span> - 8 bits in size, special meaning : lower 2 bits only valid in tropic climate, upper 2 bits for bridges</li>
<li><span style="font-weight: bold;">m7</span> - 8 bits in size, is used for general storage</li>
</ul>
<table align=center border="1" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<th colspan=2>class</th>
<th>type_height (8)</th>
<th>m1 (8)</th>
<th>m2 (16)</th>
<th>m3 (8)</th>
<th>m4 (8)</th>
<th>type_height (8)</th>
<th>m5 (8)</th>
<th>m6 (8)</th>
<th>m7 (8)</th>
</tr>
<tr>
<td colspan=2 class="caption">bits</td>
<td class="bits">7654 3210</td>
<td class="bits">7654 3210</td>
<td class="bits">FEDC BA98 7654 3210</td>
<td class="bits">7654 3210</td>
<td class="bits">7654 3210</td>
<td class="bits">7654 3210</td>
<td class="bits">7654 3210</td>
<td class="bits">7654 3210</td>
</tr>
<tr>
<td rowspan="2">0</td>
<td class="caption">ground</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XX<span class="free">OO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td class="caption">farmland</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOO</span>X XXXX</td>
</tr>
<tr>
<td rowspan=4>1</td>
<td rowspan=3>1</td>
<td class="caption">rail</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits"><span class="free">OOOO</span> XXXX <span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO O</span>XXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">rail with signals</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO</span> XXXX XXXX XXXX</td>
<td class="bits">XXXX <span class="option">~~</span>XX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">depot</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">XX<span class="free">O</span>X <span class="free">O</span>XXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO O</span>XXX</td>
</tr>
<tr>
<td class="caption">waypoint</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">XX<span class="free">O</span>X <span class="free">OOO</span>X</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO O</span>XXX</td>
</tr>
<tr>
<td rowspan=3>2</td>
<td class="caption">road</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
@@ -146,207 +115,152 @@ the array so you can quickly see what is used and what is not.
<td class="caption">level crossing</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX <span class="option">~~</span>XX</td>
<td class="bits"><span class="free">O</span>XXX XXXX</td>
<td class="bits">XX<span class="free">O</span>X XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XX<span class="free">OO</span></td>
</tr>
<tr>
<td class="caption">road depot</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">XXX<span class="free">O OOOO</span></td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td>3</td>
<td class="caption">house</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="caption">town</td>
<td class="bits"><span class="abuse">XXXX XXXX</span></td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits">XXX<span class="option">~ ~~</span>XX</td>
<td class="bits">XX<span class="free">OO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXX<span class="abuse">X XXXX</span></td>
<td class="bits"><span class="abuse">XXXX XX</span>XX</td>
<td class="bits">XXXX <span class="abuse">XXXX</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">X<span class="free">O</span>XX XXXX</td>
</tr>
<tr>
<td>4</td>
<td class="caption">trees</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
<td class="bits"><span class="option">~~</span>XX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XX<span class="free">OO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XX<span class="free">OO O</span>XXX</td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td rowspan=6>5</td>
<td class="caption">rail station</td>
<td>5</td>
<td class="caption">station</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits">XXXX <span class="option">~~</span>XX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OO</span>XX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td class="caption">road stop</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO O</span>XXX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
<td class="bits"><span class="free">OO</span>XX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">dock</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">airport</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td>6</td>
<td class="caption">water</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">buoy</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">oilrig</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td rowspan=3>6</td>
<td class="caption">sea, shore</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">X<span class="option">~~</span>X XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">canal, river</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td class="caption">shipdepot</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td>8</td>
<td rowspan=6>8</td>
<td class="caption">industry</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXX<span class="free">O</span> <span class="abuse">
XXXX</span></td>
<td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X XXXX</span></td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OO</span>XX XXXX</td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td rowspan=2>9</td>
<td class="caption">tunnel entrance</td>
<td>bubble/sugar/toffee</td>
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~</span><span class="abuse">XXX</span></td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">X<span class="free">OO</span>X <span class="option">~</span>XXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
</tr>
<tr>
<td>toy factory</td>
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
</tr>
<tr>
<td>gold/copper/coal</td>
<td class="bits"><span class="abuse">XX</span><span class="free">OO OO</span><span class="abuse">XX</span></td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
</tr>
<tr>
<td>oil wells</td>
<td class="bits"><span class="abuse">X</span><span class="free">OOO OO</span><span class="abuse">XX</span></td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
</tr>
<tr>
<td>power station</td>
<td class="bits"><span class="abuse">X</span><span class="free">O</span><span class="abuse">XX XX</span><span class="free">OO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
</tr>
<tr>
<td rowspan=3>9</td>
<td class="caption">tunnel</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">X<span class="free">OOO</span> XXXX</td>
</tr>
<tr>
<td>bridge ramp</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO</span> XXXX <span class="free">OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~</span><span class="abuse">XXX</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span> <span class="free">OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> XXXX</td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">X<span class="free">OO</span>X XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXX<span class="free">O O</span>XXX</td>
</tr>
<tr>
<td rowspan=2>A</td>
<td class="caption">unmovables</td>
<td>bridge middle part</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX XXXX</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>
</tr>
<tr>
<td>A</td>
<td class="caption">various (HQ)</td>
<td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOO</span>X XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
</tr>
<tr>
<td class="caption">company statue</td>
<td class="bits">-inherit-</td>
<td class="bits">-inherit-</td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td>
</tr>
</tbody>
</table>

View File

@@ -1,73 +0,0 @@
;
; Example file for the OpenTTD Base Graphics replacement sets.
; This file consists of basically two different parts:
; * metadata
; * information about the files
;
; Metadata contains information about the name, version and palette
; of the graphics set.
;
; == Getting started ==
; - you can't add comments after values
; - you have to fill the MD5 checksum for each file
; - you may not miss any of the metadata or files items
; - `openttd -h` lists all graphics replacements sets it found to be correct
; - `openttd -d grf=1` shows warnings/errors when parsing an .obg file
; - `openttd -I <name>` starts OpenTTD with the given set (case sensitive)
; - adding `graphicsset = <name>` to the misc section of openttd.cfg makes
; OpenTTD start with that graphics set by default
; - there is a command line tool for all platforms called md5sum that can
; create the MD5 checksum you need.
; - all files specified in this file are search relatively to the path where
; this file is found, i.e. if the graphics files are in a subdir you have
; to add that subdir to the names in this file to! It will NOT search for
; a file named like specified in here.
[metadata]
; the name of the pack, preferably less than 16 characters
name = example
; the short name (4 characters), used to identify this set within NewGRFs
shortname = XMPL
; the version of this graphics set (read as single integer)
version = 0
; a fairly short description of the set
description = foo
; palette used by the set; either DOS or Windows
palette = DOS
; The files section lists the files that replace sprites.
; The file names are case sensitive.
[files]
; GRF file with the base sprites
base = TRG1.GRF
; GRF file with logos, original terrain generator sprites
logos = TRGI.GRF
; GRF file with extra arctic sprites
arctic = TRGC.GRF
; GRF file with extra tropical sprites
tropical = TRGH.GRF
; GRF file with extra toyland sprites
toyland = TRGT.GRF
; NewGRF file using Actions 5, 7, 9 and A to replace sprites
extra = OPENTTDD.GRF
; The md5s section lists the MD5 checksum for the files that replace them.
; Note that the list of files is case sensitive. Each GRF listed in the
; files section must be listed here with it's MD5 checksum, otherwise you
; will get a lot of warnings when starting OpenTTD.
[md5s]
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
TRGC.GRF = ed446637e034104c5559b32c18afe78d
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
OPENTTDD.GRF = f829f62c137d6d7c6e272c481b796dd5
; The origin section provides the possibility to put and extra line into
; the warning that a file is missing/corrupt. This can be used to tell
; them where to find it. It works on the filename specified in the
; files section and if that is not found it will fall back to the default
; as shown below here.
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTDD.GRF = This file was part of your installation.

View File

@@ -1,49 +1,34 @@
.\" Hey, EMACS: -*- nroff -*-
.\" Please adjust this date whenever revising the manpage.
.Dd Feb 05, 2009
.Dd May 29, 2007
.Dt OPENTTD 6
.Sh NAME
.Nm openttd
.Nd An open source clone of the Microprose game "Transport Tycoon Deluxe"
.Sh SYNOPSIS
.Nm
.Op Fl efhx
.Op Fl a Ar ai
.Op Fl b Ar blitter
.Op Fl c Ar config_file
.Op Fl d Ar [level | cat=lvl[, ...]]
.Op Fl D Ar [host][:port]
.Op Fl g Ar [savegame]
.Op Fl Defhi
.Op Fl G Ar seed
.Op Fl i Ar palette
.Op Fl I Ar graphicsset
.Op Fl l Ar host[:port]
.Op Fl m Ar driver
.Op Fl d Ar [level | cat=lvl[, ...]]
.Op Fl g Ar [savegame]
.Op Fl n Ar host[:port][#player]
.Op Fl r Ar widthxheight
.Op Fl t Ar date
.Op Fl m Ar driver
.Op Fl s Ar driver
.Op Fl t Ar year
.Op Fl v Ar driver
.Sh OPTIONS
.Bl -tag -width ".Fl n Ar host[:port][#player]"
.It Fl a Ar ai
Set the AI, see
.Fl h
.It Fl b Ar blitter
Set the blitter, see
.Fl h
.It Fl c Ar config_file
Use 'config_file' instead of 'openttd.cfg'
.It Fl D
Start a dedicated server
.It Fl G Ar seed
Seed the pseudo random number generator
.It Fl d Ar [level]
Set debug verbosity for all categories to
.Ar level
or 1 if omitted
.It Fl d Ar cat=level[, ...]
Set debug verbosity for a specific category
.It Fl D Ar [host][:port]
Start a dedicated server
.It Fl G Ar seed
Seed the pseudo random number generator
.It Fl e
Start in world editor mode
.It Fl f
@@ -54,16 +39,9 @@ Load
.Ar savegame
at start or start a new game if omitted
.It Fl h
Display a summary of all options and available AIs, blitters, drivers and graphic sets
.It Fl i Ar palette
Set the palette, see
.Fl h
.It Fl I Ar graphicsset
Set the graphics set, see
.Fl h
.It Fl l Ar host[:port]
Redirect DEBUG(), See
.Fl D
Display a summary of all options and available drivers
.It Fl i
Force to use the DOS palette (use this if you see a lot of magenta)
.It Fl m Ar driver
Set the music driver, see
.Fl h
@@ -74,13 +52,11 @@ Set the resolution
.It Fl s Ar driver
Set the sound driver, see
.Fl h
.It Fl t Ar year
Set the starting year
.It Fl t Ar date
Set the starting date
.It Fl v Ar driver
Set the video driver, see
.Fl h
.It Fl x
Do not automatically save to config file on exit
.El
.Sh SEE ALSO
http://wiki.openttd.org/, http://www.openttd.org

224
driver.c Normal file
View File

@@ -0,0 +1,224 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
#include "driver.h"
#include "functions.h"
#include "hal.h"
#include "string.h"
#include "music/bemidi.h"
#include "music/dmusic.h"
#include "music/extmidi.h"
#include "music/null_m.h"
#include "music/os2_m.h"
#include "music/win32_m.h"
#include "music/qtmidi.h"
#include "sound/null_s.h"
#include "sound/sdl_s.h"
#include "sound/cocoa_s.h"
#include "sound/win32_s.h"
#include "video/dedicated_v.h"
#include "video/null_v.h"
#include "video/sdl_v.h"
#include "video/cocoa_v.h"
#include "video/win32_v.h"
typedef struct DriverDesc {
const char* name;
const char* longname;
const HalCommonDriver* drv;
} DriverDesc;
typedef struct DriverClass {
const DriverDesc *descs;
const char *name;
const HalCommonDriver** drv;
} DriverClass;
#define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z }
static const DriverDesc _music_driver_descs[] = {
#ifdef __BEOS__
M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver),
#endif
#if defined(__OS2__) && !defined(__INNOTEK_LIBC__)
M("os2", "OS/2 Music Driver", &_os2_music_driver),
#endif
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver),
#endif
#ifdef WIN32
M("win32", "Win32 MIDI Driver", &_win32_music_driver),
#endif
#if defined(__APPLE__) && !defined(DEDICATED)
M("qt", "QuickTime MIDI Driver", &_qtime_music_driver),
#endif
#ifdef UNIX
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
M("extmidi", "External MIDI Driver", &_extmidi_music_driver),
#endif
#endif
M("null", "Null Music Driver", &_null_music_driver),
M(NULL, NULL, NULL)
};
static const DriverDesc _sound_driver_descs[] = {
#ifdef WIN32
M("win32", "Win32 WaveOut Driver", &_win32_sound_driver),
#endif
#ifdef WITH_SDL
M("sdl", "SDL Sound Driver", &_sdl_sound_driver),
#endif
#ifdef WITH_COCOA
M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver),
#endif
M("null", "Null Sound Driver", &_null_sound_driver),
M(NULL, NULL, NULL)
};
static const DriverDesc _video_driver_descs[] = {
#ifdef WIN32
M("win32", "Win32 GDI Video Driver", &_win32_video_driver),
#endif
#ifdef WITH_SDL
M("sdl", "SDL Video Driver", &_sdl_video_driver),
#endif
#ifdef WITH_COCOA
M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver),
#endif
M("null", "Null Video Driver", &_null_video_driver),
#ifdef ENABLE_NETWORK
M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver),
#endif
M(NULL, NULL, NULL)
};
#undef M
#define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z }
static const DriverClass _driver_classes[] = {
M(_video_driver_descs, "video", &_video_driver),
M(_sound_driver_descs, "sound", &_sound_driver),
M(_music_driver_descs, "music", &_music_driver)
};
#undef M
static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name)
{
for (; dd->name != NULL; dd++) {
if (strcmp(dd->name, name) == 0) return dd;
}
return NULL;
}
void LoadDriver(int driver, const char *name)
{
const DriverClass *dc = &_driver_classes[driver];
const DriverDesc *dd;
const char *err;
if (*name == '\0') {
for (dd = dc->descs; dd->name != NULL; dd++) {
err = dd->drv->start(NULL);
if (err == NULL) break;
DEBUG(driver, 1) ("Probing %s driver \"%s\" failed with error: %s",
dc->name, dd->name, err
);
}
if (dd->name == NULL) {
error("Couldn't find any suitable %s driver", dc->name);
}
DEBUG(driver, 1)
("Successfully probed %s driver \"%s\"", dc->name, dd->name);
*dc->drv = dd->drv;
} else {
char* parm;
char buffer[256];
const char* parms[32];
// Extract the driver name and put parameter list in parm
ttd_strlcpy(buffer, name, sizeof(buffer));
parm = strchr(buffer, ':');
parms[0] = NULL;
if (parm != NULL) {
uint np = 0;
// Tokenize the parm.
do {
*parm++ = '\0';
if (np < lengthof(parms) - 1)
parms[np++] = parm;
while (*parm != '\0' && *parm != ',')
parm++;
} while (*parm == ',');
parms[np] = NULL;
}
dd = GetDriverByName(dc->descs, buffer);
if (dd == NULL)
error("No such %s driver: %s\n", dc->name, buffer);
if (*dc->drv != NULL) (*dc->drv)->stop();
*dc->drv = NULL;
err = dd->drv->start(parms);
if (err != NULL) {
error("Unable to load driver %s(%s). The error was: %s\n",
dd->name, dd->longname, err
);
}
*dc->drv = dd->drv;
}
}
static const char* GetDriverParam(const char* const* parm, const char* name)
{
size_t len;
if (parm == NULL) return NULL;
len = strlen(name);
for (; *parm != NULL; parm++) {
const char* p = *parm;
if (strncmp(p, name, len) == 0) {
if (p[len] == '=') return p + len + 1;
if (p[len] == '\0') return p + len;
}
}
return NULL;
}
bool GetDriverParamBool(const char* const* parm, const char* name)
{
return GetDriverParam(parm, name) != NULL;
}
int GetDriverParamInt(const char* const* parm, const char* name, int def)
{
const char* p = GetDriverParam(parm, name);
return p != NULL ? atoi(p) : def;
}
char *GetDriverList(char* p, const char *last)
{
const DriverClass* dc;
for (dc = _driver_classes; dc != endof(_driver_classes); dc++) {
const DriverDesc* dd;
p += snprintf(p, last - p, "List of %s drivers:\n", dc->name);
for (dd = dc->descs; dd->name != NULL; dd++) {
p += snprintf(p, last - p, "%10s: %s\n", dd->name, dd->longname);
}
p = strecpy(p, "\n", last);
}
return p;
}

13
driver.h Normal file
View File

@@ -0,0 +1,13 @@
/* $Id$ */
#ifndef DRIVER_H
#define DRIVER_H
void LoadDriver(int driver, const char *name);
bool GetDriverParamBool(const char* const* parm, const char* name);
int GetDriverParamInt(const char* const* parm, const char* name, int def);
char *GetDriverList(char *p, const char *last);
#endif /* DRIVER_H */

View File

@@ -1,18 +1,16 @@
/* $Id$ */
/** @file dummy_land.cpp Handling of void (or dummy) tiles. */
#include "stdafx.h"
#include "tile_cmd.h"
#include "command_func.h"
#include "viewport_func.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "viewport.h"
#include "command.h"
#include "table/sprites.h"
static void DrawTile_Dummy(TileInfo *ti)
{
DrawGroundSpriteAt(SPR_SHADOW_CELL, PAL_NONE, ti->x, ti->y, ti->z);
DrawGroundSpriteAt(SPR_SHADOW_CELL, ti->x, ti->y, ti->z);
}
@@ -21,12 +19,12 @@ static uint GetSlopeZ_Dummy(TileIndex tile, uint x, uint y)
return 0;
}
static Foundation GetFoundation_Dummy(TileIndex tile, Slope tileh)
static Slope GetSlopeTileh_Dummy(TileIndex tile, Slope tileh)
{
return FOUNDATION_NONE;
return SLOPE_FLAT;
}
static CommandCost ClearTile_Dummy(TileIndex tile, DoCommandFlag flags)
static int32 ClearTile_Dummy(TileIndex tile, byte flags)
{
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
}
@@ -40,7 +38,7 @@ static void GetAcceptedCargo_Dummy(TileIndex tile, AcceptedCargo ac)
static void GetTileDesc_Dummy(TileIndex tile, TileDesc *td)
{
td->str = STR_EMPTY;
td->owner[0] = OWNER_NONE;
td->owner = OWNER_NONE;
}
static void AnimateTile_Dummy(TileIndex tile)
@@ -53,28 +51,22 @@ static void TileLoop_Dummy(TileIndex tile)
/* not used */
}
static bool ClickTile_Dummy(TileIndex tile)
{
/* not used */
return false;
}
static void ChangeTileOwner_Dummy(TileIndex tile, Owner old_owner, Owner new_owner)
static void ClickTile_Dummy(TileIndex tile)
{
/* not used */
}
static TrackStatus GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
static void ChangeTileOwner_Dummy(TileIndex tile, PlayerID old_player, PlayerID new_player)
{
/* not used */
}
static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode)
{
return 0;
}
static CommandCost TerraformTile_Dummy(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
{
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
}
extern const TileTypeProcs _tile_type_dummy_procs = {
const TileTypeProcs _tile_type_dummy_procs = {
DrawTile_Dummy, /* draw_tile_proc */
GetSlopeZ_Dummy, /* get_slope_z_proc */
ClearTile_Dummy, /* clear_tile_proc */
@@ -87,6 +79,5 @@ extern const TileTypeProcs _tile_type_dummy_procs = {
ChangeTileOwner_Dummy, /* change_tile_owner_clear */
NULL, /* get_produced_cargo_proc */
NULL, /* vehicle_enter_tile_proc */
GetFoundation_Dummy, /* get_foundation_proc */
TerraformTile_Dummy, /* terraform_tile_proc */
GetSlopeTileh_Dummy, /* get_slope_tileh_proc */
};

1768
economy.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More