1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-13 17:49:10 +00:00

Compare commits

..

145 Commits

Author SHA1 Message Date
rubidium
d4179a0bec (svn r9860) -Release 0.5.2-RC1. 2007-05-16 21:51:53 +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
794 changed files with 121004 additions and 172554 deletions

11
.gitignore vendored
View File

@@ -1,11 +0,0 @@
Makefile*
bin/*
!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

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" \
@@ -83,7 +84,6 @@ FILE_PATTERNS = *.c \
*.cpp \
*.c++ \
*.h \
*.hpp \
table/*.h
RECURSIVE = YES
EXCLUDE =
@@ -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,274 +0,0 @@
# Auto-generated file -- DO NOT EDIT
# 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!!
CONFIGURE_FILES = !!CONFIGURE_FILES!!
LIPO = !!LIPO!!
BIN_DIR = !!BIN_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_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!!
INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!!
TTD = !!TTD!!
TTDS = $(SRC_DIRS:%=%/$(TTD))
OS = !!OS!!
OSXAPP = !!OSXAPP!!
REVISION = !!REVISION!!
AWK = !!AWK!!
DISTCC = !!DISTCC!!
RES := $(shell if ! [ -f $(CONFIG_CACHE_SOURCE_LIST) ] || [ -n "`cmp $(CONFIG_CACHE_SOURCE_LIST) $(SOURCE_LIST)`" ]; then cp $(SOURCE_LIST) $(CONFIG_CACHE_SOURCE_LIST); fi )
all: 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.cache: $(CONFIG_CACHE_SOURCE_LIST) $(CONFIGURE_FILES)
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. Now compiling..."
@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
$(Q)rm -f $(CONFIG_CACHE_SOURCE_LIST) config.cache config.log
$(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
%.o:
@for dir in $(SRC_DIRS); do \
$(MAKE) -C $$dir $(@:src/%=%); \
done
%.lng:
@for dir in $(LANG_DIRS); do \
$(MAKE) -C $$dir $@; \
done
#
# Creation of bundles
#
# The revision is needed for the bundle name and creating an OSX application bundle.
ifdef REVISION
REV := $(REVISION)
else
# Are we a SVN dir?
ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
# Find if the local source if modified
REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
# Find the revision like: rXXXX-branch
REV := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^URL:.*branches/ { split($$2, a, "/"); BRANCH="-"a[5] } /^Last Changed Rev:/ { REV="r"$$4"$(REV_MODIFIED)" } END { print REV BRANCH }')
endif
endif
# Make sure we have something in REV
ifeq ($(REV),)
REV := norev000
endif
ifndef BUNDLE_NAME
BUNDLE_NAME = OTTD-$(OS)-custom-$(REV)
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 "$(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/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)/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)/docs/"
$(Q)cp "$(ROOT_DIR)/media/openttd.64.png" "$(BUNDLE_DIR)/media/"
$(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/"
$(Q)cp "$(ROOT_DIR)/media/openttd.32.bmp" "$(BUNDLE_DIR)/media/"
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"
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)"
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)/docs"
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)"
$(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)/docs/"* "$(INSTALL_DATA_DIR)/docs"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/"* "$(INSTALL_ICON_DIR)"
$(Q)cp -R "$(BUNDLE_DIR)/scenario" "$(INSTALL_DATA_DIR)"
endif # OSXAPP

View File

@@ -1,89 +0,0 @@
# Auto-generated file -- DO NOT EDIT
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,309 +0,0 @@
# Auto-generated file -- DO NOT EDIT
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!!
BIN_DIR = !!BIN_DIR!!
LANG_DIR = !!LANG_DIR!!
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
LANG_OBJS_DIR= !!LANG_OBJS_DIR!!
SRC_DIR = !!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) $(LANG_OBJS_DIR)/table/strings.h 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)
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
# Make the revision number
ifdef REVISION
REV := $(REVISION)
REV_NR := $(shell echo $(REVISION) | sed "s/[^0-9]//g")
else
# Are we a SVN dir?
ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
# Find if the local source if modified
REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
# Find the revision like: rXXXX-branch
REV := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^URL:.*branch/ { split($$2, a, "/"); BRANCH="-"a[5] } /^Last Changed Rev:/ { REV="r"$$4"$(REV_MODIFIED)" } END { print REV BRANCH }')
REV_NR := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^Last Changed Rev:/ { print $$4 }')
else
# Are we a git dir?
ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1)
# Find the revision like: gXXXXM-branch
REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(shell if cd "$(SRC_DIR)/.." && git diff-index HEAD src | read dummy; then echo M; fi)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//')
REV_NR := $(shell LC_ALL=C cd "$(SRC_DIR)/.." && git log --pretty=format:%s src | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
else
# Are we a hg (Mercurial) dir?
ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1)
# Find the revision like: hXXXXM-branch
REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(shell if hg status $(SRC_DIR) | grep -v '^?' | read dummy; then echo M; fi)$(shell hg branch | sed 's/^/-/;s/^-default$$//')
REV_NR := $(shell LC_ALL=C hg log -k "svn" -l 1 --template "{desc}\n" $(SRC_DIR) | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
endif
endif
endif
endif
# Make sure we have something in REV
ifeq ($(REV),)
REV := norev000
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)" ]; then echo "$(REV)" > $(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, "^$(SRC_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 file is deleted without the deps
# being updated. Now the Makefile continues, the deps are recreated
# and all will be fine.
%.h %.hpp:
@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) $@
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#@@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

View File

@@ -3,18 +3,10 @@
#include "../stdafx.h"
#include "../openttd.h"
#include "../variables.h"
#include "../command_func.h"
#include "../network/network.h"
#include "../core/alloc_func.hpp"
#include "../player_func.h"
#include "../player_base.h"
#include "../command.h"
#include "../network.h"
#include "ai.h"
#include "default/default.h"
#include "trolly/trolly.h"
#include "../signal_func.h"
AIStruct _ai;
AIPlayer _ai_player[MAX_PLAYERS];
/**
* Dequeues commands put in the queue via AI_PutCommandInQueue.
@@ -52,17 +44,17 @@ static void AI_DequeueCommands(PlayerID player)
* 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, uint32 procc, CommandCallback* callback)
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 = MallocT<AICommand>(1);
_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 = MallocT<AICommand>(1);
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
}
@@ -88,10 +80,10 @@ static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uin
/**
* Executes a raw DoCommand for the AI.
*/
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 procc, CommandCallback* callback)
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
{
PlayerID old_lp;
CommandCost res;
int32 res = 0;
const char* tmp_cmdtext;
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
@@ -111,6 +103,11 @@ CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, u
/* 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;
@@ -137,7 +134,7 @@ CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, u
}
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 procc)
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
}
@@ -161,9 +158,6 @@ static void AI_RunTick(PlayerID player)
AiDoGameLoop(p);
_is_old_ai_player = false;
}
/* AI could change some track, so update signals */
UpdateSignalsInBuffer();
}
@@ -171,7 +165,7 @@ static void AI_RunTick(PlayerID player)
* The gameloop for AIs.
* Handles one tick for all the AIs.
*/
void AI_RunGameLoop()
void AI_RunGameLoop(void)
{
/* Don't do anything if ai is disabled */
if (!_ai.enabled) return;
@@ -224,19 +218,12 @@ void AI_PlayerDied(PlayerID player)
{
/* Called if this AI died */
_ai_player[player].active = false;
if (_players_ainew[player].pathfinder == NULL) return;
AyStarMain_Free(_players_ainew[player].pathfinder);
delete _players_ainew[player].pathfinder;
_players_ainew[player].pathfinder = NULL;
}
/**
* Initialize some AI-related stuff.
*/
void AI_Initialize()
void AI_Initialize(void)
{
/* First, make sure all AIs are DEAD! */
AI_Uninitialize();
@@ -250,7 +237,11 @@ void AI_Initialize()
/**
* Deinitializer for AI-related stuff.
*/
void AI_Uninitialize()
void AI_Uninitialize(void)
{
for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) AI_PlayerDied(p);
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
}
}

View File

@@ -1,58 +1,56 @@
/* $Id$ */
#ifndef AI_H
#define AI_H
#include "../network/network.h"
#include "../command_type.h"
#include "../core/random_func.hpp"
#include "../settings_type.h"
#include "../functions.h"
#include "../network.h"
#include "../player.h"
#include "../command.h"
/* How DoCommands look like for an AI */
struct AICommand {
typedef struct AICommand {
uint32 tile;
uint32 p1;
uint32 p2;
uint32 procc;
CommandCallback *callback;
CommandCallback* callback;
char *text;
uint uid;
AICommand *next;
};
struct AICommand *next;
} AICommand;
/* The struct for an AIScript Player */
struct AIPlayer {
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 */
struct AIStruct {
typedef struct AIStruct {
/* General */
bool enabled; ///< Is AI enabled?
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
};
} AIStruct;
extern AIStruct _ai;
extern AIPlayer _ai_player[MAX_PLAYERS];
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 AI_Initialize();
void AI_Uninitialize();
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
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()
static inline bool AI_AllowNewAI(void)
{
/* If disabled, no AI */
if (!_ai.enabled)
@@ -79,8 +77,8 @@ static inline bool AI_AllowNewAI()
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))
#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.
@@ -99,7 +97,7 @@ static inline uint AI_RandomRange(uint max)
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint32 AI_Random()
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.

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

View File

@@ -3,20 +3,18 @@
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../functions.h"
#include "../../map.h"
#include "../../road_map.h"
#include "../../command_func.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 "../../vehicle_func.h"
#include "../../vehicle_base.h"
#include "../../player_base.h"
#include "../../player_func.h"
#include "../ai.h"
#include "../../tunnelbridge.h"
// Build HQ
// Params:
@@ -38,15 +36,15 @@ bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
// 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)
CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
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, ROADTYPES_ROAD << 2 | RoadStop::BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return AI_DoCommand(tile, direction, ROADTYPES_ROAD << 2 | RoadStop::TRUCK, 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);
}
@@ -55,12 +53,12 @@ CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte lengt
// tile_a : starting point
// tile_b : end point
// flag : flag passed to DoCommand
CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
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 = GetTunnelBridgeLength(tile_a, tile_b);
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)) {
@@ -74,10 +72,10 @@ CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, by
if (type2 == 0 && type != 0) type2 = type;
// Now, simply, build the bridge!
if (_players_ainew[p->index].tbt == AI_TRAIN) {
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 | ROADTYPES_ROAD) << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
}
}
@@ -92,45 +90,45 @@ CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, by
// part : Which part we need to build
//
// TODO: skip already builded road-pieces (e.g.: cityroad)
CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
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;
CommandCost cost;
CommandCost res;
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 CommandCost();
return 0;
}
if (PathFinderInfo->rail_or_road) {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost.AddCost(AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL));
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
return CommandCost();
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.AddCost(AiNew_Build_Bridge(p, route[part], route[part - 1], flag));
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part - 1]);
return CommandCost();
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
return 0;
}
return cost;
}
@@ -148,10 +146,10 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(res)) {
// Problem.. let's just abort it all!
_players_ainew[p->index].state = AI_STATE_NOTHING;
return CommandCost();
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
cost.AddCost(res);
cost += res;
// Go to the next tile
part++;
// Check if it is still in range..
@@ -164,33 +162,33 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
} else {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost.AddCost(AI_DoCommand(route[part], 0x200 | ROADTYPES_ROAD, 0, flag, CMD_BUILD_TUNNEL));
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
return CommandCost();
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.AddCost(AiNew_Build_Bridge(p, route[part], route[part + 1], flag));
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part + 1]);
return CommandCost();
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
// EnsureNoVehicleOnGround makes sure we don't build on a tile where a vehicle is. This 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 || EnsureNoVehicleOnGround(route[part]))) {
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicleOnGround(route[part]))) {
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?
@@ -201,14 +199,14 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
// 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_ROAD) && !EnsureNoVehicleOnGround(route[part])) {
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
// Problem.. let's just abort it all!
DEBUG(ai, 0, "[BuidPath] route building failed at tile 0x%X, aborting", route[part]);
_players_ainew[p->index].state = AI_STATE_NOTHING;
return CommandCost();
DEBUG(ai,0)("Darn, the route could not be built.. aborting!");
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
if (CmdSucceeded(res)) cost.AddCost(res);
if (!CmdFailed(res)) cost += res;
}
// Go to the next tile
part++;
@@ -218,7 +216,7 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
part--;
// We want to return the last position, so we go back one
}
if (!EnsureNoVehicleOnGround(route[part]) && flag == DC_EXEC) part--;
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
PathFinderInfo->position = part;
}
@@ -230,35 +228,36 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
// It returns INVALID_ENGINE if not suitable engine is found
EngineID AiNew_PickVehicle(Player *p)
{
if (_players_ainew[p->index].tbt == AI_TRAIN) {
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_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
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 != _players_ainew[p->index].cargo && !CanRefitTo(i, _players_ainew[p->index].cargo)) continue;
/* Skip trams */
if (HasBit(EngInfo(i)->misc_flags, EF_ROAD_TRAM)) continue;
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;
if (!HASBIT(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
/* Rate and compare the engine by speed & capacity */
int rating = rvi->max_speed * rvi->capacity;
rating = rvi->max_speed * rvi->capacity;
if (rating <= best_veh_rating) continue;
// Can we build it?
CommandCost ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (CmdFailed(ret)) continue;
best_veh_rating = rating;
@@ -275,31 +274,31 @@ void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
Player* p = GetPlayer(_current_player);
if (success) {
_players_ainew[p->index].state = AI_STATE_GIVE_ORDERS;
_players_ainew[p->index].veh_id = _new_vehicle_id;
p->ainew.state = AI_STATE_GIVE_ORDERS;
p->ainew.veh_id = _new_vehicle_id;
if (GetVehicle(_players_ainew[p->index].veh_id)->cargo_type != _players_ainew[p->index].cargo) {
if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
/* Cargo type doesn't match, so refit it */
if (CmdFailed(DoCommand(tile, _players_ainew[p->index].veh_id, _players_ainew[p->index].cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
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, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
_players_ainew[p->index].state = AI_STATE_NOTHING;
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 */
_players_ainew[p->index].state = AI_STATE_NOTHING;
p->ainew.state = AI_STATE_NOTHING;
}
}
// Builds the best vehicle possible
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
{
EngineID i = AiNew_PickVehicle(p);
if (i == INVALID_ENGINE) return CMD_ERROR;
if (_players_ainew[p->index].tbt == AI_TRAIN) 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);
@@ -308,19 +307,18 @@ CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
}
}
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
{
CommandCost ret, ret2;
if (_players_ainew[p->index].tbt == AI_TRAIN) {
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(ret2)) return ret;
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;
ret.AddCost(ret2);
return ret;
return ret + ret2;
}
}

View File

@@ -4,18 +4,15 @@
#include "../../openttd.h"
#include "../../bridge_map.h"
#include "../../debug.h"
#include "../../command_func.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 "../../tunnelbridge_map.h"
#include "../ai.h"
#include "../../variables.h"
#include "../../player_base.h"
#include "../../player_func.h"
#include "../../tunnelbridge.h"
#define TEST_STATION_NO_DIR 0xFF
@@ -26,27 +23,30 @@ static bool TestCanBuildStationHere(TileIndex tile, byte dir)
Player *p = GetPlayer(_current_player);
if (dir == TEST_STATION_NO_DIR) {
CommandCost ret;
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, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST);
if (CmdSucceeded(ret)) return true;
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 CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST));
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
}
static bool IsRoad(TileIndex tile)
{
return
// MP_ROAD, but not a road depot?
(IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
(IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD);
// 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)
));
}
@@ -57,7 +57,7 @@ static bool IsRoad(TileIndex tile)
// Check if the current tile is in our end-area
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
{
const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
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;
@@ -82,7 +82,7 @@ static uint AiPathFinder_Hash(uint key1, uint key2)
static void AyStar_AiPathFinder_Free(AyStar *aystar)
{
AyStarMain_Free(aystar);
delete aystar;
free(aystar);
}
@@ -99,7 +99,7 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
uint x;
uint y;
// Create AyStar
AyStar *result = new AyStar();
AyStar *result = malloc(sizeof(AyStar));
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
// Set the function pointers
result->CalculateG = AyStar_AiPathFinder_CalculateG;
@@ -170,7 +170,7 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
// The h-value, simple calculation
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
const Ai_PathFinderInfo* PathFinderInfo = aystar->user_target;
int r, r2;
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
@@ -200,21 +200,22 @@ static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *curre
PathFinderInfo->route[i++] = parent->node.tile;
if (i > lengthof(PathFinderInfo->route)) {
// We ran out of space for the PathFinder
DEBUG(ai, 0, "No more space in pathfinder route[] array");
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
PathFinderInfo->route_length = -1; // -1 indicates out of space
return;
}
parent = parent->parent;
} while (parent != NULL);
PathFinderInfo->route_length = i;
DEBUG(ai, 1, "Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
}
// What tiles are around us.
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
{
CommandCost ret;
uint i;
int ret;
int dir;
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
@@ -222,7 +223,7 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
aystar->num_neighbours = 0;
// Go through all surrounding tiles and check if they are within the limits
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
for (i = 0; i < 4; i++) {
TileIndex ctile = current->path.node.tile; // Current tile
TileIndex atile = ctile + TileOffsByDiagDir(i); // Adjacent tile
@@ -234,7 +235,18 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
// 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 (GetTunnelBridgeDirection(atile) != i) continue;
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;
}
}
@@ -242,7 +254,7 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
(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 ((uint)i != (current->path.node.user_data[0] >> 8)) continue;
if (i != (current->path.node.user_data[0] >> 8)) continue;
}
dir = 0;
@@ -280,9 +292,9 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
dir = 0;
} else {
// It already has road.. check if we miss any bits!
if ((GetAnyRoadBits(ctile, ROADTYPE_ROAD) & dir) != dir) {
if ((_m[ctile].m5 & dir) != dir) {
// We do miss some pieces :(
dir &= ~GetAnyRoadBits(ctile, ROADTYPE_ROAD);
dir &= ~_m[ctile].m5;
} else {
dir = 0;
}
@@ -315,13 +327,13 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
// 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_ROAD)) ||
(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, GetTunnelBridgeLength(tile, new_tile))) break;
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;
@@ -341,11 +353,14 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
// 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 (tileh == InclinedSlope(dir)) {
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 (CmdSucceeded(ret) && IsInclinedSlope(tileh)) {
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;
@@ -355,14 +370,18 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
}
extern Foundation GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c
extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits); // XXX function declaration in .c
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 res = 0;
int r, res = 0;
Slope tileh = GetTileSlope(current->tile, NULL);
Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
@@ -398,16 +417,17 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
// 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) {
Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)));
if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
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)) {
Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
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;
@@ -419,22 +439,31 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
// Are we part of a tunnel?
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
int r;
// Tunnels are very expensive when build on long routes..
// Ironicly, we are using BridgeCode here ;)
r = AI_PATHFINDER_TUNNEL_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
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 * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
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 (!HasBridgeFlatRamp(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
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 (!HasBridgeFlatRamp(tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
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

View File

@@ -3,10 +3,9 @@
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../map_func.h"
#include "../../vehicle_base.h"
#include "../../player_base.h"
#include "../../map.h"
#include "trolly.h"
#include "../../vehicle.h"
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
{
@@ -81,8 +80,8 @@ uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (_players_ainew[p->index].special_vehicles[i].veh_id == v->index) {
return _players_ainew[p->index].special_vehicles[i].flag;
if (p->ainew.special_vehicles[i].veh_id == v->index) {
return p->ainew.special_vehicles[i].flag;
}
}
@@ -97,23 +96,23 @@ bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (_players_ainew[p->index].special_vehicles[i].veh_id == v->index) {
_players_ainew[p->index].special_vehicles[i].flag |= flag;
if (p->ainew.special_vehicles[i].veh_id == v->index) {
p->ainew.special_vehicles[i].flag |= flag;
return true;
}
if (new_id == -1 &&
_players_ainew[p->index].special_vehicles[i].veh_id == 0 &&
_players_ainew[p->index].special_vehicles[i].flag == 0) {
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");
DEBUG(ai, 1)("special_vehicles list is too small :(");
return false;
}
_players_ainew[p->index].special_vehicles[new_id].veh_id = v->index;
_players_ainew[p->index].special_vehicles[new_id].flag = flag;
p->ainew.special_vehicles[new_id].veh_id = v->index;
p->ainew.special_vehicles[new_id].flag = flag;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,9 +4,7 @@
#define AI_TROLLY_H
#include "../../aystar.h"
#include "../../player_type.h"
#include "../../vehicle_type.h"
#include "../../date_type.h"
#include "../../player.h"
/*
* These defines can be altered to change the behavoir of the AI
@@ -241,22 +239,6 @@ typedef void AiNew_StateFunction(Player *p);
// ai_new.c
void AiNewDoGameLoop(Player *p);
struct Ai_PathFinderInfo {
TileIndex start_tile_tl; ///< tl = top-left
TileIndex start_tile_br; ///< br = bottom-right
TileIndex end_tile_tl; ///< tl = top-left
TileIndex end_tile_br; ///< br = bottom-right
DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
DiagDirection end_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
TileIndex route[500];
byte route_extra[500]; ///< Some extra information about the route like bridge/tunnel
int route_length;
int position; ///< Current position in the build-path, needed to build the path
bool rail_or_road; ///< true = rail, false = road
};
// ai_pathfinder.c
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
@@ -270,71 +252,11 @@ uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
// ai_build.c
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
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);
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
/* The amount of memory reserved for the AI-special-vehicles */
#define AI_MAX_SPECIAL_VEHICLES 100
struct Ai_SpecialVehicle {
VehicleID veh_id;
uint32 flag;
};
struct PlayerAiNew {
uint8 state;
uint tick;
uint idle;
int temp; ///< A value used in more than one function, but it just temporary
///< The use is pretty simple: with this we can 'think' about stuff
///< in more than one tick, and more than one AI. A static will not
///< do, because they are not saved. This way, the AI is almost human ;)
int counter; ///< For the same reason as temp, we have counter. It can count how
///< long we are trying something, and just abort if it takes too long
/* Pathfinder stuff */
Ai_PathFinderInfo path_info;
AyStar *pathfinder;
/* Route stuff */
CargoID cargo;
byte tbt; ///< train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK
Money new_cost;
byte action;
int last_id; ///< here is stored the last id of the searched city/industry
Date last_vehiclecheck_date; // Used in CheckVehicle
Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; ///< Some vehicles have some special flags
TileIndex from_tile;
TileIndex to_tile;
DiagDirectionByte from_direction;
DiagDirectionByte to_direction;
bool from_deliver; ///< True if this is the station that GIVES cargo
bool to_deliver;
TileIndex depot_tile;
DiagDirectionByte depot_direction;
byte amount_veh; ///< How many vehicles we are going to build in this route
byte cur_veh; ///< How many vehicles did we bought?
VehicleID veh_id; ///< Used when bought a vehicle
VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy
int from_ic; ///< ic = industry/city. This is the ID of them
byte from_type; ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY
int to_ic;
byte to_type;
};
extern PlayerAiNew _players_ainew[MAX_PLAYERS];
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,16 +1,14 @@
/* $Id$ */
/** @file airport.cpp */
#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
@@ -19,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;
@@ -31,273 +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
);
// 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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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 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_),
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, 2, "[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
@@ -305,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;
@@ -323,11 +304,12 @@ static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
* 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++;
@@ -338,14 +320,16 @@ 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;
@@ -353,7 +337,7 @@ static AirportFTA* AirportBuildAutomata(uint nofelements, const AirportFTAbuildu
// 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;
@@ -363,31 +347,31 @@ static AirportFTA* AirportBuildAutomata(uint nofelements, const AirportFTAbuildu
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 */
@@ -395,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++;
}
@@ -430,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);
}
@@ -466,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 || _patches.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 */

View File

@@ -1,30 +1,25 @@
/* $Id$ */
/** @file airport_gui.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "window_gui.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "station_gui.h"
#include "terraform_gui.h"
#include "command_func.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"
#include "sound_func.h"
#include "window_func.h"
#include "settings_type.h"
#include "viewport_func.h"
#include "gfx_func.h"
#include "player_func.h"
#include "table/sprites.h"
#include "table/strings.h"
static byte _selected_airport_type;
static void ShowBuildAirportPicker();
static void ShowBuildAirportPicker(void);
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
@@ -37,12 +32,12 @@ void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
static void PlaceAirport(TileIndex tile)
{
DoCommandP(tile, _selected_airport_type, _ctrl_pressed, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
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, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
VpStartPlaceSizing(tile, 4);
}
@@ -54,19 +49,24 @@ enum {
static void BuildAirClick_Airport(Window *w)
{
if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, VHM_RECT, PlaceAirport)) ShowBuildAirportPicker();
if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
}
static void BuildAirClick_Demolish(Window *w)
{
HandlePlacePushButton(w, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceAir_DemolishArea);
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)
@@ -85,6 +85,7 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
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;
@@ -94,21 +95,21 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
break;
case WE_PLACE_DRAG:
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
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 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
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:
w->RaiseButtons();
RaiseWindowButtons(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != 0)
WP(w, def_d).close = true;
WP(w,def_d).close = true;
break;
case WE_DESTROY:
@@ -119,53 +120,55 @@ static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
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, 51, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_STICKYBOX, RESIZE_NONE, 7, 52, 63, 0, 13, 0x0, STR_STICKY_BUTTON },
{ 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, 64, 36, 64, 36,
WC_BUILD_TOOLBAR, WC_NONE,
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 ShowBuildAirToolbar(void)
{
if (!IsValidPlayer(_current_player)) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
Window *w = AllocateWindowDescFront(&_air_toolbar_desc, 0);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
AllocateWindowDescFront(&_air_toolbar_desc, 0);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
}
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE:
w->SetWidgetLoweredState(16, !_station_show_coverage);
w->SetWidgetLoweredState(17, _station_show_coverage);
w->LowerWidget(_selected_airport_type + 7);
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;
if (WP(w,def_d).close) return;
avail_airports = GetValidAirports();
w->RaiseWidget(_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;
w->LowerWidget(_selected_airport_type + 7);
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.
@@ -173,41 +176,49 @@ static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
* 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++) w->SetWidgetDisabledState(i + 7, !HasBit(avail_airports, i));
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);
int rad = _patches.modified_catchment ? airport->catchment : (uint)CA_UNMODIFIED;
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'
int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad) + 4;
if (text_end > w->widget[6].bottom) {
SetWindowDirty(w);
ResizeWindowForWidget(w, 6, 0, text_end - w->widget[6].bottom);
SetWindowDirty(w);
}
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:
w->RaiseWidget(_selected_airport_type + 7);
RaiseWindowWidget(w, _selected_airport_type + 7);
_selected_airport_type = e->we.click.widget - 7;
w->LowerWidget(_selected_airport_type + 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);
w->SetWidgetLoweredState(16, !_station_show_coverage);
w->SetWidgetLoweredState(17, _station_show_coverage);
_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;
@@ -215,7 +226,7 @@ static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
} break;
case WE_MOUSELOOP: {
if (WP(w, def_d).close) {
if (WP(w,def_d).close) {
DeleteWindow(w);
return;
}
@@ -224,7 +235,7 @@ static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
} break;
case WE_DESTROY:
if (!WP(w, def_d).close) ResetObjectToPlace();
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
@@ -257,19 +268,19 @@ static const Widget _build_airport_picker_widgets[] = {
};
static const WindowDesc _build_airport_desc = {
WDP_AUTO, WDP_AUTO, 148, 240, 148, 240,
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()
static void ShowBuildAirportPicker(void)
{
AllocateWindowDesc(&_build_airport_desc);
}
void InitializeAirportGui()
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 */
/*
* This file has the core function for AyStar
* AyStar is a fast pathfinding routine and is used for things like
@@ -21,7 +19,6 @@
#include "stdafx.h"
#include "openttd.h"
#include "aystar.h"
#include "core/alloc_func.hpp"
int _aystar_stats_open_size;
int _aystar_stats_closed_size;
@@ -38,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);
}
@@ -69,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,7 +12,6 @@
#define AYSTAR_H
#include "queue.h"
#include "tile_type.h"
//#define AYSTAR_DEBUG
enum {
@@ -28,13 +27,15 @@ enum{
AYSTAR_INVALID_NODE = -1,
};
typedef struct AyStarNode AyStarNode;
struct AyStarNode {
TileIndex tile;
int 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
@@ -44,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:

Binary file not shown.

Binary file not shown.

View File

@@ -1,14 +1,12 @@
/* $Id$ */
/** @file bmp.cpp */
#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;
@@ -330,7 +328,7 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
}
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,13 +1,9 @@
/* $Id$ */
/** @file bmp.h */
#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
@@ -15,22 +11,22 @@ struct BmpInfo {
uint16 bpp; ///< bits per pixel
uint32 compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
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,58 +1,60 @@
/* $Id$ */
/** @file callback_table.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "callback_table.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;
CommandCallback CcAI;
@@ -78,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 */
#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,689 +1,3 @@
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)
- 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 (r9966)
- Fix: Null pointer dereference under MorphOS and AmigaOS (r9861)
0.5.2-RC1 (2007-05-16)
------------------------------------------------------------------------
- Feature: Windows 95/98/ME check in Windows 2000/XP/2003/Vista builds (r9834)
@@ -711,7 +25,6 @@
------------------------------------------------------------------------
(None)
0.5.1-RC3 (2007-04-17)
------------------------------------------------------------------------
- Feature: Add list_patches to console commands; shows all patches and values (r9565)
@@ -794,7 +107,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)
@@ -1438,7 +751,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

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 */

2384
config.lib

File diff suppressed because it is too large Load Diff

437
configure vendored
View File

@@ -1,134 +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" = "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 == "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 == "BEOS" && "'$os'" != "BEOS") { next; }
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
"'$os'" != "CYGWIN" && "'$os'" != "MSVC" ) { 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 == "NO_THREADS" && "'$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"
generate_main
generate_lang
generate_src

View File

@@ -1,25 +1,21 @@
/* $Id$ */
/** @file console.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "window.h"
#include "gui.h"
#include "textbuf_gui.h"
#include "window_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/network.h"
#include "network/network_data.h"
#include "network/network_server.h"
#include "core/alloc_func.hpp"
#include "window_func.h"
#include "string_func.h"
#include "gfx_func.h"
#include "table/strings.h"
#include "network.h"
#include "network_data.h"
#include "network_server.h"
#define ICON_BUFFER 79
#define ICON_HISTORY_SIZE 20
@@ -29,38 +25,25 @@
#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
/* console colors/modes */
byte _icolour_def;
byte _icolour_err;
byte _icolour_warn;
byte _icolour_dbg;
byte _icolour_cmd;
IConsoleModes _iconsole_mode;
/* ** main console ** */
// ** 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;
/* ** main console cmd buffer ** */
// ** main console cmd buffer
static char *_iconsole_history[ICON_HISTORY_SIZE];
static byte _iconsole_historypos;
/* *************** *
* end of header *
* *************** */
/* *************** */
/* end of header */
/* *************** */
static void IConsoleClearCommand()
static void IConsoleClearCommand(void)
{
memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
_iconsole_cmdline.length = 0;
@@ -70,13 +53,13 @@ static void IConsoleClearCommand()
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
}
static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
static inline void IConsoleResetHistoryPos(void) {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
static void IConsoleHistoryAdd(const char *cmd);
static void IConsoleHistoryNavigate(int direction);
/* ** console window ** */
// ** console window ** //
static void IConsoleWndProc(Window *w, WindowEvent *e)
{
static byte iconsole_scroll = ICON_BUFFER;
@@ -102,7 +85,7 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
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, TC_WHITE);
DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, 12);
break;
}
case WE_MOUSELOOP:
@@ -214,14 +197,14 @@ static const Widget _iconsole_window_widgets[] = {
};
static const WindowDesc _iconsole_window_desc = {
0, 0, 2, 2, 2, 2,
WC_CONSOLE, WC_NONE,
0, 0, 2, 2,
WC_CONSOLE, 0,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_iconsole_window_widgets,
IConsoleWndProc,
};
void IConsoleInit()
void IConsoleInit(void)
{
extern const char _openttd_revision[];
_iconsole_output_file = NULL;
@@ -229,7 +212,7 @@ void IConsoleInit()
_icolour_err = 3;
_icolour_warn = 13;
_icolour_dbg = 5;
_icolour_cmd = TC_GOLD;
_icolour_cmd = 2;
_iconsole_historypos = ICON_HISTORY_SIZE - 1;
_iconsole_mode = ICONSOLE_CLOSED;
@@ -240,7 +223,7 @@ void IConsoleInit()
memset(_iconsole_history, 0, sizeof(_iconsole_history));
memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
_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);
@@ -252,7 +235,7 @@ void IConsoleInit()
IConsoleHistoryAdd("");
}
void IConsoleClearBuffer()
void IConsoleClearBuffer(void)
{
uint i;
for (i = 0; i <= ICON_BUFFER; i++) {
@@ -261,7 +244,7 @@ void IConsoleClearBuffer()
}
}
static void IConsoleClear()
static void IConsoleClear(void)
{
free(_iconsole_cmdline.buf);
IConsoleClearBuffer();
@@ -270,13 +253,13 @@ static void IConsoleClear()
static void IConsoleWriteToLogFile(const char *string)
{
if (_iconsole_output_file != NULL) {
/* if there is an console output file ... also print it there */
// 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(_icolour_def, "file output complete");
@@ -288,7 +271,7 @@ bool CloseConsoleLogIfActive()
return false;
}
void IConsoleFree()
void IConsoleFree(void)
{
IConsoleClear();
CloseConsoleLogIfActive();
@@ -311,7 +294,7 @@ void IConsoleResize(Window *w)
MarkWholeScreenDirty();
}
void IConsoleSwitch()
void IConsoleSwitch(void)
{
switch (_iconsole_mode) {
case ICONSOLE_CLOSED: {
@@ -319,20 +302,20 @@ void IConsoleSwitch()
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
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);
CLRBIT(_no_scroll, SCROLL_CON);
break;
}
MarkWholeScreenDirty();
}
void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
void IConsoleOpen() {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
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
@@ -356,7 +339,7 @@ static void IConsoleHistoryNavigate(int direction)
{
int i = _iconsole_historypos + direction;
/* watch out for overflows, just wrap around */
// watch out for overflows, just wrap around
if (i < 0) i = ICON_HISTORY_SIZE - 1;
if (i >= ICON_HISTORY_SIZE) i = 0;
@@ -369,8 +352,8 @@ static void IConsoleHistoryNavigate(int direction)
_iconsole_historypos = i;
IConsoleClearCommand();
/* copy history to 'command prompt / bash' */
assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
// 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);
}
@@ -402,8 +385,7 @@ void IConsolePrint(uint16 color_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;
@@ -426,7 +408,7 @@ void IConsolePrint(uint16 color_code, const char *string)
/**
* 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(uint16 color_code, const char *s, ...)
{
@@ -443,15 +425,13 @@ void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
/**
* 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(_icolour_dbg, "dbg: [%s] %s", dbg, string);
IConsolePrintF(_icolour_dbg, "dbg: %s", string);
}
/**
@@ -477,7 +457,7 @@ void IConsoleError(const char *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
*/
@@ -498,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
*/
@@ -529,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)
@@ -631,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;
@@ -668,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;
@@ -727,18 +706,18 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
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);
@@ -746,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);
@@ -755,7 +734,7 @@ 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) {
@@ -782,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)
{
@@ -806,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;
@@ -883,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;
@@ -1107,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) {

View File

@@ -1,18 +1,14 @@
/* $Id$ */
/** @file console.h */
#ifndef CONSOLE_H
#define CONSOLE_H
#include "window_type.h"
/* maximum length of a typed in command */
// maximum length of a typed in command
#define ICON_CMDLN_SIZE 255
/* maximum length of a totally expanded command */
// maximum length of a totally expanded command
#define ICON_MAX_STREAMSIZE 1024
enum IConsoleVarTypes {
typedef enum IConsoleVarTypes {
ICONSOLE_VAR_BOOLEAN,
ICONSOLE_VAR_BYTE,
ICONSOLE_VAR_UINT16,
@@ -20,31 +16,31 @@ enum IConsoleVarTypes {
ICONSOLE_VAR_INT16,
ICONSOLE_VAR_INT32,
ICONSOLE_VAR_STRING
};
} IConsoleVarTypes;
enum IConsoleModes {
typedef enum IConsoleModes {
ICONSOLE_FULL,
ICONSOLE_OPENED,
ICONSOLE_CLOSED
};
} IConsoleModes;
enum IConsoleHookTypes {
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
@@ -55,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
@@ -72,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,
@@ -95,39 +93,40 @@ 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 */
extern byte _icolour_def;
extern byte _icolour_err;
extern byte _icolour_warn;
extern byte _icolour_dbg;
extern byte _icolour_cmd;
extern IConsoleModes _iconsole_mode;
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 IConsoleInit();
void IConsoleFree();
void IConsoleClearBuffer();
void IConsoleInit(void);
void IConsoleFree(void);
void IConsoleClearBuffer(void);
void IConsoleResize(Window *w);
void IConsoleSwitch();
void IConsoleClose();
void IConsoleOpen();
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 *dbg, const char *string);
void IConsoleDebug(const char *string);
void IConsoleWarning(const char *string);
void IConsoleError(const char *string);
@@ -149,7 +148,7 @@ 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);

View File

@@ -1,42 +1,28 @@
/* $Id$ */
/** @file console_cmds.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "console.h"
#include "debug.h"
#include "engine.h"
#include "landscape.h"
#include "functions.h"
#include "saveload.h"
#include "string.h"
#include "variables.h"
#include "network/network_data.h"
#include "network/network_client.h"
#include "network/network_server.h"
#include "network/network_udp.h"
#include "command_func.h"
#include "settings_func.h"
#include "network_data.h"
#include "network_client.h"
#include "network_server.h"
#include "network_udp.h"
#include "command.h"
#include "settings.h"
#include "fios.h"
#include "fileio.h"
#include "vehicle.h"
#include "station.h"
#include "strings.h"
#include "screenshot.h"
#include "genworld.h"
#include "network/network.h"
#include "strings_func.h"
#include "viewport_func.h"
#include "window_func.h"
#include "functions.h"
#include "map_func.h"
#include "date_func.h"
#include "vehicle_func.h"
#include "string_func.h"
#include "player_func.h"
#include "player_base.h"
#include "settings_type.h"
#ifdef ENABLE_NETWORK
#include "table/strings.h"
#endif /* ENABLE_NETWORK */
#include "date.h"
#include "network.h"
// ** scriptfile handling ** //
static FILE *_script_file;
@@ -44,7 +30,7 @@ static bool _script_running;
// ** console command / variable defines ** //
#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
#define DEF_CONSOLE_HOOK(function) static bool function()
#define DEF_CONSOLE_HOOK(function) static bool function(void)
/* **************************** */
@@ -53,7 +39,7 @@ static bool _script_running;
#ifdef ENABLE_NETWORK
static inline bool NetworkAvailable()
static inline bool NetworkAvailable(void)
{
if (!_network_available) {
IConsoleError("You cannot use this command because there is no network available.");
@@ -144,12 +130,21 @@ DEF_CONSOLE_CMD(ConResetTile)
DEF_CONSOLE_CMD(ConStopAllVehicles)
{
Vehicle* v;
if (argc == 0) {
IConsoleHelp("Stops all vehicles in the game. For debugging only! Use at your own risk... Usage: 'stopall'");
return true;
}
StopAllVehicles();
FOR_ALL_VEHICLES(v) {
/* Code ripped from CmdStartStopTrain. Can't call it, because of
* ownership problems, so we'll duplicate some code, for now */
if (v->type == VEH_Train)
v->u.rail.days_since_order_progr = 0;
v->vehstatus |= VS_STOPPED;
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
}
return true;
}
#endif /* _DEBUG */
@@ -177,7 +172,8 @@ DEF_CONSOLE_CMD(ConScrollToTile)
return false;
}
extern void BuildFileList();
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
extern void BuildFileList(void);
extern void SetFiosType(const byte fiostype);
/* Save the map to a file */
@@ -189,34 +185,22 @@ DEF_CONSOLE_CMD(ConSave)
}
if (argc == 2) {
char *filename = str_fmt("%s.sav", argv[1]);
char buf[200];
snprintf(buf, lengthof(buf), "%s%s%s.sav", _paths.save_dir, PATHSEP, argv[1]);
IConsolePrint(_icolour_def, "Saving map...");
if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
IConsolePrint(_icolour_err, "Saving map failed");
if (SaveOrLoad(buf, SL_SAVE) != SL_OK) {
IConsolePrint(_icolour_err, "SaveMap failed");
} else {
IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", filename);
IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", buf);
}
free(filename);
return true;
}
return false;
}
/* Explicitly save the configuration */
DEF_CONSOLE_CMD(ConSaveConfig)
{
if (argc == 0) {
IConsoleHelp("Saves the current config, typically to 'openttd.cfg'.");
return true;
}
SaveToConfig();
IConsolePrint(_icolour_def, "Saved config.");
return true;
}
static const FiosItem* GetFiosItem(const char* file)
{
int i;
@@ -229,14 +213,14 @@ static const FiosItem* GetFiosItem(const char* file)
if (strcmp(file, _fios_list[i].title) == 0) break;
}
if (i == _fios_num) { // If no name matches, try to parse it as number
if (i == _fios_num) { /* If no name matches, try to parse it as number */
char* endptr;
i = strtol(file, &endptr, 10);
if (file == endptr || *endptr != '\0') i = -1;
}
return IsInsideMM(i, 0, _fios_num) ? &_fios_list[i] : NULL;
return IS_INT_INSIDE(i, 0, _fios_num) ? &_fios_list[i] : NULL;
}
@@ -426,9 +410,9 @@ DEF_CONSOLE_CMD(ConBan)
}
if (ci != NULL) {
IConsolePrint(_icolour_def, "Client banned");
banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
IConsolePrint(_icolour_def, "Client banned");
} else {
IConsolePrint(_icolour_def, "Client not online, banned IP");
}
@@ -500,7 +484,7 @@ DEF_CONSOLE_CMD(ConPauseGame)
return true;
}
if (_pause_game == 0) {
if (_pause == 0) {
DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
IConsolePrint(_icolour_def, "Game paused.");
} else {
@@ -517,7 +501,7 @@ DEF_CONSOLE_CMD(ConUnPauseGame)
return true;
}
if (_pause_game != 0) {
if (_pause != 0) {
DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
IConsolePrint(_icolour_def, "Game unpaused.");
} else {
@@ -537,11 +521,7 @@ DEF_CONSOLE_CMD(ConRcon)
if (argc < 3) return false;
if (_network_server) {
IConsoleCmdExec(argv[2]);
} else {
SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
}
SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
return true;
}
@@ -558,7 +538,7 @@ DEF_CONSOLE_CMD(ConStatus)
"active"
};
NetworkTCPSocketHandler *cs;
const NetworkClientState *cs;
if (argc == 0) {
IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
@@ -570,7 +550,7 @@ DEF_CONSOLE_CMD(ConStatus)
const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
const char* status;
status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
status = (cs->status < lengthof(stat_str) ? stat_str[cs->status] : "unknown");
IConsolePrintF(8, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'",
cs->index, ci->client_name, status, lag,
ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
@@ -600,8 +580,10 @@ DEF_CONSOLE_CMD(ConServerInfo)
DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount)
{
if (_network_game_info.clients_max > MAX_CLIENTS) {
_network_game_info.clients_max = MAX_CLIENTS;
/* XXX - hardcoded, string limiation -- TrueLight
* XXX - also see network.c:NetworkStartup ~1356 */
if (_network_game_info.clients_max > 10) {
_network_game_info.clients_max = 10;
IConsoleError("Maximum clients out of bounds, truncating to limit.");
}
@@ -620,7 +602,7 @@ DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
{
/* XXX see ConHookValidateMaxClientsCount */
/* XXX @see ConHookValidateMaxClientsCount */
if (_network_game_info.spectators_max > 10) {
_network_game_info.spectators_max = 10;
IConsoleError("Maximum spectators out of bounds, truncating to limit.");
@@ -678,7 +660,7 @@ DEF_CONSOLE_CMD(ConKick)
DEF_CONSOLE_CMD(ConResetCompany)
{
const Player *p;
NetworkTCPSocketHandler *cs;
const NetworkClientState *cs;
const NetworkClientInfo *ci;
PlayerID index;
@@ -690,7 +672,7 @@ DEF_CONSOLE_CMD(ConResetCompany)
if (argc != 2) return false;
index = (PlayerID)(atoi(argv[1]) - 1);
index = atoi(argv[1]) - 1;
/* Check valid range */
if (!IsValidPlayer(index)) {
@@ -775,8 +757,13 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
ParseConnectionString(&player, &port, ip);
IConsolePrintF(_icolour_def, "Connecting to %s...", ip);
if (port != NULL) {
rport = atoi(port);
IConsolePrintF(_icolour_def, " port: %s", port);
}
if (player != NULL) {
_network_playas = (PlayerID)atoi(player);
_network_playas = atoi(player);
IConsolePrintF(_icolour_def, " player-no: %d", _network_playas);
/* From a user pov 0 is a new player, internally it's different and all
@@ -786,10 +773,6 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
if (!IsValidPlayer(_network_playas)) return false;
}
}
if (port != NULL) {
rport = atoi(port);
IConsolePrintF(_icolour_def, " port: %s", port);
}
NetworkClientConnectGame(ip, rport);
@@ -814,7 +797,7 @@ DEF_CONSOLE_CMD(ConExec)
if (argc < 2) return false;
_script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
_script_file = fopen(argv[1], "r");
if (_script_file == NULL) {
if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
@@ -838,7 +821,7 @@ DEF_CONSOLE_CMD(ConExec)
IConsoleError("Encountered errror while trying to read from script file");
_script_running = false;
FioFCloseFile(_script_file);
fclose(_script_file);
return true;
}
@@ -856,7 +839,7 @@ DEF_CONSOLE_CMD(ConReturn)
/* **************************** */
/* default console commands */
/* **************************** */
extern bool CloseConsoleLogIfActive();
extern bool CloseConsoleLogIfActive(void);
DEF_CONSOLE_CMD(ConScript)
{
@@ -945,20 +928,6 @@ DEF_CONSOLE_CMD(ConGetSeed)
return true;
}
DEF_CONSOLE_CMD(ConGetDate)
{
if (argc == 0) {
IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
return true;
}
YearMonthDay ymd;
ConvertDateToYMD(_date, &ymd);
IConsolePrintF(_icolour_def, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
return true;
}
DEF_CONSOLE_CMD(ConAlias)
{
IConsoleAlias *alias;
@@ -1084,8 +1053,6 @@ DEF_CONSOLE_CMD(ConExit)
return true;
}
if (_game_mode == GM_NORMAL && _patches.autosave_on_exit) DoExitSave();
_exit_game = true;
return true;
}
@@ -1233,6 +1200,10 @@ DEF_CONSOLE_CMD(ConSay)
return true;
}
#ifdef ENABLE_NETWORK
#include "table/strings.h"
#endif /* ENABLE_NETWORK */
DEF_CONSOLE_CMD(ConPlayers)
{
Player *p;
@@ -1245,19 +1216,20 @@ DEF_CONSOLE_CMD(ConPlayers)
FOR_ALL_PLAYERS(p) {
char buffer[512];
const NetworkPlayerInfo *npi;
if (!p->is_active) continue;
const NetworkPlayerInfo *npi = &_network_player_info[p->index];
npi = &_network_player_info[p->index];
GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer));
IConsolePrintF(8, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %" OTTD_PRINTF64 "d Loan: %" OTTD_PRINTF64 "d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected",
p->index + 1, buffer, npi->company_name, p->inaugurated_year, (int64)p->player_money, (int64)p->current_loan, (int64)CalculateCompanyValue(p),
IConsolePrintF(8, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %d Loan: %d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected",
p->index + 1, buffer, npi->company_name, p->inaugurated_year, p->player_money, p->current_loan, CalculateCompanyValue(p),
/* trains */ npi->num_vehicle[0],
/* lorry + bus */ npi->num_vehicle[1] + npi->num_vehicle[2],
/* planes */ npi->num_vehicle[3],
/* ships */ npi->num_vehicle[4],
/* protected */ StrEmpty(npi->password) ? "un" : "");
/* protected */ npi->password[0] == '\0' ? "un" : "");
}
return true;
@@ -1329,8 +1301,6 @@ DEF_CONSOLE_HOOK(ConHookRconPW)
return true;
}
extern void HashCurrentCompanyPassword();
/* Also use from within player_gui to change the password graphically */
bool NetworkChangeCompanyPassword(byte argc, char *argv[])
{
@@ -1351,11 +1321,8 @@ bool NetworkChangeCompanyPassword(byte argc, char *argv[])
ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
if (!_network_server) {
if (!_network_server)
SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
} else {
HashCurrentCompanyPassword();
}
IConsolePrintF(_icolour_warn, "'company_pw' changed to: %s", _network_player_info[_local_player].password);
@@ -1368,7 +1335,7 @@ DEF_CONSOLE_HOOK(ConProcPlayerName)
if (ci == NULL) return false;
/* Don't change the name if it is the same as the old name */
// Don't change the name if it is the same as the old name
if (strcmp(ci->client_name, _network_player_name) != 0) {
if (!_network_server) {
SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
@@ -1431,11 +1398,7 @@ DEF_CONSOLE_CMD(ConPatch)
if (GetArgumentInteger(&val, argv[2])) {
if (!IConsoleSetPatchSetting(argv[1], val)) {
if (_network_server) {
IConsoleError("This command/variable is not available during network games.");
} else {
IConsoleError("This command/variable is only available to a network server.");
}
IConsoleError("This command/variable is only available to a network server.");
}
}
}
@@ -1482,10 +1445,10 @@ DEF_CONSOLE_CMD(ConListDumpVariables)
/* debug commands and variables */
/* ****************************************** */
static void IConsoleDebugLibRegister()
static void IConsoleDebugLibRegister(void)
{
/* debugging variables and functions */
extern bool _stdlib_con_developer; // XXX extern in .cpp
// debugging variables and functions
extern bool _stdlib_con_developer; /* XXX extern in .c */
IConsoleVarRegister("con_developer", &_stdlib_con_developer, ICONSOLE_VAR_BOOLEAN, "Enable/disable console debugging information (internal)");
IConsoleCmdRegister("resettile", ConResetTile);
@@ -1499,12 +1462,12 @@ static void IConsoleDebugLibRegister()
/* console command and variable registration */
/* ****************************************** */
void IConsoleStdLibRegister()
void IConsoleStdLibRegister(void)
{
/* stdlib */
extern byte _stdlib_developer; // XXX extern in .cpp
// stdlib
extern byte _stdlib_developer; /* XXX extern in .c */
/* default variables and functions */
// default variables and functions
IConsoleCmdRegister("debug_level", ConDebugLevel);
IConsoleCmdRegister("dump_vars", ConListDumpVariables);
IConsoleCmdRegister("echo", ConEcho);
@@ -1521,7 +1484,6 @@ void IConsoleStdLibRegister()
IConsoleCmdRegister("newgame", ConNewGame);
IConsoleCmdRegister("restart", ConRestart);
IConsoleCmdRegister("getseed", ConGetSeed);
IConsoleCmdRegister("getdate", ConGetDate);
IConsoleCmdRegister("quit", ConExit);
IConsoleCmdRegister("resetengines", ConResetEngines);
IConsoleCmdRegister("return", ConReturn);
@@ -1532,7 +1494,6 @@ void IConsoleStdLibRegister()
IConsoleCmdRegister("load", ConLoad);
IConsoleCmdRegister("rm", ConRemove);
IConsoleCmdRegister("save", ConSave);
IConsoleCmdRegister("saveconfig", ConSaveConfig);
IConsoleCmdRegister("ls", ConListFiles);
IConsoleCmdRegister("cd", ConChangeDirectory);
IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
@@ -1657,8 +1618,6 @@ void IConsoleStdLibRegister()
IConsoleVarRegister("min_players", &_network_min_players, ICONSOLE_VAR_BYTE, "Automatically pause the game when the number of active players passes below the given amount");
IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_POST_ACTION, ConHookCheckMinPlayers);
IConsoleVarRegister("reload_cfg", &_network_reload_cfg, ICONSOLE_VAR_BOOLEAN, "reload the entire config file between the end of this game, and starting the next new game - dedicated servers");
IConsoleVarHookAdd("reload_cfg", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
#endif /* ENABLE_NETWORK */

View File

@@ -1,49 +1,46 @@
/* $Id$ */
/** @file currency.cpp **/
#include "stdafx.h"
#include "openttd.h"
#include "currency.h"
#include "news.h"
#include "settings_type.h"
#include "date_func.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, ',', 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
{ 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 */
@@ -125,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;
@@ -148,7 +142,7 @@ 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[_opt.currency].to_euro != CF_NOEURO &&
_currency_specs[_opt.currency].to_euro != CF_ISEURO &&
@@ -161,12 +155,12 @@ void CheckSwitchToEuro()
/**
* 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));
@@ -176,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,13 +1,8 @@
/* $Id$ */
/** @file currency.h */
#ifndef CURRENCY_H
#define CURRENCY_H
#include "date_type.h"
#include "strings_type.h"
enum {
CF_NOEURO = 0,
CF_ISEURO = 1,
@@ -15,7 +10,7 @@ enum {
CUSTOM_CURRENCY_ID = NUM_CURRENCY - 1
};
struct CurrencySpec {
typedef struct {
uint16 rate;
char separator;
Year to_euro;
@@ -32,7 +27,7 @@ struct CurrencySpec {
*/
byte symbol_pos;
StringID name;
};
} CurrencySpec;
extern CurrencySpec _currency_specs[NUM_CURRENCY];
@@ -41,10 +36,10 @@ extern CurrencySpec _currency_specs[NUM_CURRENCY];
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
#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,23 +1,16 @@
/* $Id$ */
/** @file date.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "date.h"
#include "variables.h"
#include "settings_type.h"
#include "network/network.h"
#include "network/network_data.h"
#include "network/network_server.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"
#ifdef DEBUG_DUMP_COMMANDS
#include "saveload.h"
#endif
#include "currency.h"
Year _cur_year;
Month _cur_month;
@@ -165,32 +158,50 @@ Date ConvertYMDToDate(Year year, Month month, Day day)
/** Functions used by the IncreaseDate function */
extern void WaypointsDailyLoop();
extern void ChatMessageDailyLoop();
extern void EnginesDailyLoop();
extern void DisasterDailyLoop();
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 PlayersMonthlyLoop();
extern void EnginesMonthlyLoop();
extern void TownsMonthlyLoop();
extern void IndustryMonthlyLoop();
extern void StationMonthlyLoop();
typedef void OnNewVehicleDayProc(Vehicle *v);
extern void PlayersYearlyLoop();
extern void TrainsYearlyLoop();
extern void RoadVehiclesYearlyLoop();
extern void AircraftYearlyLoop();
extern void ShipsYearlyLoop();
static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = {
OnNewDay_Train,
OnNewDay_RoadVeh,
OnNewDay_Ship,
OnNewDay_Aircraft,
OnNewDay_EffectVehicle,
OnNewDay_DisasterVehicle,
};
extern void ShowEndGameChart();
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
};
/**
@@ -204,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;
@@ -233,7 +240,7 @@ void IncreaseDate()
/* yeah, increase day counter and call various daily loops */
_date++;
ChatMessageDailyLoop();
TextMessageDailyLoop();
DisasterDailyLoop();
WaypointsDailyLoop();
@@ -250,18 +257,11 @@ void IncreaseDate()
/* yes, call various monthly loops */
if (_game_mode != GM_MENU) {
#ifdef DEBUG_DUMP_COMMANDS
char name[MAX_PATH];
snprintf(name, lengthof(name), "dmp_cmds_%d.sav", _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
DebugDumpCommands("ddc:save:%s\n", name);
#endif /* DUMP_COMMANDS */
if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) {
_do_autosave = true;
RedrawAutosave();
}
InvalidateWindowClasses(WC_CHEATS);
PlayersMonthlyLoop();
EnginesMonthlyLoop();
TownsMonthlyLoop();
@@ -297,7 +297,7 @@ void IncreaseDate()
/* 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 */
InitChatMessage();
InitTextMessage();
}
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
@@ -37,20 +35,25 @@
* 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;
struct YearMonthDay {
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 */
#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include "openttd.h"
#include "console.h"
#include "debug.h"
#include "string_func.h"
#include "network/core/core.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,20 +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;
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[] = {
@@ -46,58 +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(freetype)
};
#undef DEBUG_LEVEL
#if !defined(NO_DEBUG_MESSAGES)
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);
#if defined(ENABLE_NETWORK)
if (_debug_socket != INVALID_SOCKET) {
char buf2[lengthof(buf) + 32];
snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
send(_debug_socket, buf2, strlen(buf2), 0);
} else
#endif /* ENABLE_NETWORK */
{
#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);
}
}
#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;
@@ -107,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) {
@@ -143,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));
@@ -160,20 +128,3 @@ const char *GetDebugString()
return dbgstr;
}
#ifdef DEBUG_DUMP_COMMANDS
#include "fileio.h"
void CDECL DebugDumpCommands(const char *s, ...)
{
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
if (f == NULL) return;
va_list va;
va_start(va, s);
vfprintf(f, s, va);
va_end(va);
fflush(f);
}
#endif /* DEBUG_DUMP_COMMANDS */

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,7 +1,5 @@
/* $Id$ */
/** @file dedicated.cpp */
#include "stdafx.h"
#ifdef ENABLE_NETWORK
@@ -14,15 +12,7 @@
#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();
@@ -53,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);
}
}
@@ -63,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},
};

View File

@@ -1,40 +1,66 @@
/* $Id$ */
/** @file depot.h Header files for depots (not hangars) */
#ifndef DEPOT_H
#define DEPOT_H
#include "direction_type.h"
/** @file depot.h Header files for depots (not hangars)
* @see depot.c */
#include "direction.h"
#include "oldpool.h"
#include "road_map.h"
#include "rail_map.h"
#include "water_map.h"
#include "station_map.h"
#include "tile.h"
#include "variables.h"
struct Depot;
DECLARE_OLD_POOL(Depot, Depot, 3, 8000)
struct Depot : PoolItem<Depot, DepotID, &_Depot_pool> {
struct Depot {
TileIndex xy;
TownID town_index;
Depot(TileIndex xy = 0) : xy(xy) {}
~Depot();
inline bool IsValid() const { return this->xy != 0; }
DepotID index;
};
static inline bool IsValidDepotID(DepotID index)
DECLARE_OLD_POOL(Depot, Depot, 3, 8000)
/**
* Check if a depot really exists.
*/
static inline bool IsValidDepot(const Depot *depot)
{
return index < GetDepotPoolSize() && GetDepot(index)->IsValid();
return depot != NULL && depot->xy != 0;
}
void ShowDepotWindow(TileIndex tile, VehicleType type);
static inline bool IsValidDepotID(uint index)
{
return index < GetDepotPoolSize() && IsValidDepot(GetDepot(index));
}
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) if (d->IsValid())
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.
*/
@@ -42,39 +68,24 @@ static inline bool IsTileDepotType(TileIndex tile, TransportType type)
{
switch (type) {
case TRANSPORT_RAIL:
return IsTileType(tile, MP_RAILWAY) && GetRailTileType(tile) == RAIL_TILE_DEPOT;
return IsTileType(tile, MP_RAILWAY) && (_m[tile].m5 & 0xFC) == 0xC0;
case TRANSPORT_ROAD:
return IsRoadDepotTile(tile);
return IsTileType(tile, MP_STREET) && (_m[tile].m5 & 0xF0) == 0x20;
case TRANSPORT_WATER:
return IsTileType(tile, MP_WATER) && GetWaterTileType(tile) == WATER_TILE_DEPOT;
return IsTileType(tile, MP_WATER) && (_m[tile].m5 & ~3) == 0x80;
default:
NOT_REACHED();
assert(0);
return false;
}
}
/**
* Is the given tile a tile with a depot on it?
* @param tile the tile to check
* @return true if and only if there is a depot on the tile.
*/
static inline bool IsDepotTile(TileIndex tile)
{
switch (GetTileType(tile)) {
case MP_ROAD: return IsRoadDepot(tile);
case MP_WATER: return GetWaterTileType(tile) == WATER_TILE_DEPOT;
case MP_RAILWAY: return GetRailTileType(tile) == RAIL_TILE_DEPOT;
case MP_STATION: return IsHangar(tile);
default: 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
* @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
@@ -87,13 +98,14 @@ static inline bool IsDepotTile(TileIndex tile)
* 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(DiagDirection direction, Slope tileh)
static inline bool CanBuildDepotByTileh(uint32 direction, Slope tileh)
{
return ((0x4C >> direction) & tileh) != 0;
}
Depot *GetDepotByTile(TileIndex tile);
void InitializeDepots();
void InitializeDepots(void);
Depot *AllocateDepot(void);
void DeleteDepotHighlightOfVehicle(const Vehicle *v);

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

View File

@@ -1,31 +1,22 @@
/* $Id$ */
/** @file dock_gui.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "tile_map.h"
#include "station.h"
#include "gui.h"
#include "terraform_gui.h"
#include "window_gui.h"
#include "station_gui.h"
#include "command_func.h"
#include "settings_type.h"
#include "water.h"
#include "window_func.h"
#include "vehicle_func.h"
#include "sound_func.h"
#include "viewport_func.h"
#include "gfx_func.h"
#include "player_func.h"
#include "slope_func.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();
static void ShowBuildDocksDepotPicker();
static void ShowBuildDockStationPicker(void);
static void ShowBuildDocksDepotPicker(void);
static Axis _ship_depot_direction;
@@ -45,32 +36,32 @@ void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2)
static void PlaceDocks_Dock(TileIndex tile)
{
DoCommandP(tile, _ctrl_pressed, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
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_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT));
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_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
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, DDSP_DEMOLISH_AREA);
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
}
static void PlaceDocks_BuildCanal(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_CREATE_WATER);
VpStartPlaceSizing(tile, VPM_X_OR_Y);
}
static void PlaceDocks_BuildLock(TileIndex tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_MSG(STR_CANT_BUILD_LOCKS));
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
}
@@ -86,37 +77,38 @@ enum {
static void BuildDocksClick_Canal(Window *w)
{
HandlePlacePushButton(w, DTW_CANAL, SPR_CURSOR_CANAL, VHM_RECT, PlaceDocks_BuildCanal);
HandlePlacePushButton(w, DTW_CANAL, SPR_CURSOR_CANAL, 1, PlaceDocks_BuildCanal);
}
static void BuildDocksClick_Lock(Window *w)
{
HandlePlacePushButton(w, DTW_LOCK, SPR_CURSOR_LOCK, VHM_RECT, PlaceDocks_BuildLock);
HandlePlacePushButton(w, DTW_LOCK, SPR_CURSOR_LOCK, 1, PlaceDocks_BuildLock);
}
static void BuildDocksClick_Demolish(Window *w)
{
HandlePlacePushButton(w, DTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceDocks_DemolishArea);
HandlePlacePushButton(w, DTW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
}
static void BuildDocksClick_Depot(Window *w)
{
if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
}
static void BuildDocksClick_Dock(Window *w)
{
if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker();
if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
}
static void BuildDocksClick_Buoy(Window *w)
{
if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
HandlePlacePushButton(w, DTW_BUOY, SPR_CURSOR_BOUY, VHM_RECT, PlaceDocks_Buoy);
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[] = {
@@ -126,7 +118,8 @@ static OnButtonClick * const _build_docks_button_proc[] = {
BuildDocksClick_Demolish,
BuildDocksClick_Depot,
BuildDocksClick_Dock,
BuildDocksClick_Buoy
BuildDocksClick_Buoy,
BuildDocksClick_Landscaping,
};
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
@@ -134,7 +127,6 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
switch (e->event) {
case WE_PAINT:
DrawWindowWidgets(w);
w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), 7, 8, 9, WIDGET_LIST_END);
break;
case WE_CLICK:
@@ -149,6 +141,7 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
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;
@@ -158,43 +151,42 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
break;
case WE_PLACE_DRAG: {
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
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) {
switch (e->we.place.select_proc) {
case DDSP_DEMOLISH_AREA:
GUIPlaceProcDragXY(e);
break;
case DDSP_CREATE_WATER:
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS));
break;
default: break;
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:
w->RaiseButtons();
RaiseWindowButtons(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != NULL) WP(w, def_d).close = true;
if (w != NULL) WP(w,def_d).close = true;
w = FindWindowById(WC_BUILD_DEPOT, 0);
if (w != NULL) WP(w, def_d).close = true;
if (w != NULL) WP(w,def_d).close = true;
break;
case WE_PLACE_PRESIZE: {
TileIndex tile_from;
TileIndex tile_to;
tile_from = e->we.place.tile;
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, NULL));
tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from);
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;
@@ -206,8 +198,8 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
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, 123, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 124, 135, 0, 13, 0x0, STR_STICKY_BUTTON},
{ 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},
@@ -217,50 +209,43 @@ static const Widget _build_docks_toolb_widgets[] = {
{ 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, 136, 36, 136, 36,
WC_BUILD_TOOLBAR, WC_NONE,
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 ShowBuildDocksToolbar(void)
{
if (!IsValidPlayer(_current_player)) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
Window *w = AllocateWindowDesc(&_build_docks_toolbar_desc);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
AllocateWindowDesc(&_build_docks_toolbar_desc);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
}
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE: w->LowerWidget(_station_show_coverage + 3); break;
case WE_CREATE: LowerWindowWidget(w, _station_show_coverage + 3); break;
case WE_PAINT: {
int rad = (_patches.modified_catchment) ? CA_DOCK : CA_UNMODIFIED;
int rad;
if (WP(w, def_d).close) return;
if (WP(w,def_d).close) return;
DrawWindowWidgets(w);
if (_station_show_coverage) {
SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
} else {
SetTileSelectSize(1, 1);
}
rad = (_patches.modified_catchment) ? CA_DOCK : 4;
int text_end = DrawStationCoverageAreaText(4, 50, SCT_ALL, rad) + 4;
if (text_end > w->widget[2].bottom) {
SetWindowDirty(w);
ResizeWindowForWidget(w, 2, 0, text_end - w->widget[2].bottom);
SetWindowDirty(w);
}
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
break;
}
@@ -268,9 +253,9 @@ static void BuildDockStationWndProc(Window *w, WindowEvent *e)
switch (e->we.click.widget) {
case 3:
case 4:
w->RaiseWidget(_station_show_coverage + 3);
_station_show_coverage = (e->we.click.widget != 3);
w->LowerWidget(_station_show_coverage + 3);
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;
@@ -278,7 +263,7 @@ static void BuildDockStationWndProc(Window *w, WindowEvent *e)
break;
case WE_MOUSELOOP:
if (WP(w, def_d).close) {
if (WP(w,def_d).close) {
DeleteWindow(w);
return;
}
@@ -287,7 +272,7 @@ static void BuildDockStationWndProc(Window *w, WindowEvent *e)
break;
case WE_DESTROY:
if (!WP(w, def_d).close) ResetObjectToPlace();
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
@@ -303,19 +288,19 @@ static const Widget _build_dock_station_widgets[] = {
};
static const WindowDesc _build_dock_station_desc = {
WDP_AUTO, WDP_AUTO, 148, 75, 148, 75,
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()
static void ShowBuildDockStationPicker(void)
{
AllocateWindowDesc(&_build_dock_station_desc);
}
static void UpdateDocksDirection()
static void UpdateDocksDirection(void)
{
if (_ship_depot_direction != AXIS_X) {
SetTileSelectSize(1, 2);
@@ -327,7 +312,7 @@ static void UpdateDocksDirection()
static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE: w->LowerWidget(_ship_depot_direction + 3); break;
case WE_CREATE: LowerWindowWidget(w, _ship_depot_direction + 3); break;
case WE_PAINT:
DrawWindowWidgets(w);
@@ -342,9 +327,9 @@ static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
switch (e->we.click.widget) {
case 3:
case 4:
w->RaiseWidget(_ship_depot_direction + 3);
_ship_depot_direction = (e->we.click.widget == 3 ? AXIS_X : AXIS_Y);
w->LowerWidget(_ship_depot_direction + 3);
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);
@@ -353,11 +338,11 @@ static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
} break;
case WE_MOUSELOOP:
if (WP(w, def_d).close) DeleteWindow(w);
if (WP(w,def_d).close) DeleteWindow(w);
break;
case WE_DESTROY:
if (!WP(w, def_d).close) ResetObjectToPlace();
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
@@ -372,7 +357,7 @@ static const Widget _build_docks_depot_widgets[] = {
};
static const WindowDesc _build_docks_depot_desc = {
WDP_AUTO, WDP_AUTO, 204, 86, 204, 86,
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,
@@ -380,14 +365,14 @@ static const WindowDesc _build_docks_depot_desc = {
};
static void ShowBuildDocksDepotPicker()
static void ShowBuildDocksDepotPicker(void)
{
AllocateWindowDesc(&_build_docks_depot_desc);
UpdateDocksDirection();
}
void InitializeDockGui()
void InitializeDockGui(void)
{
_ship_depot_direction = 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

@@ -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
-----------------
@@ -32,7 +30,6 @@ You need an SVN-client to download the source from subversion:
* CLI Subversion (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
2) INCLUDES AND LIBRARIES
-------------------------
Put the newly downloaded files in the VC lib\ and include\ directories; where
@@ -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 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"><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 OOOO O</span>XXX <span class="free">O</span>XXX</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">OO OO</span>XX</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">OO 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">OO</span> 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"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits">X<span class="free">OOO 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 X<span class="free">O</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></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 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>
</tr>
<tr>
<td>6</td>
<td class="caption">water</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 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">X<span class="free">OOO</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">OOO</span> <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">OOO</span> <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">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">OOOO OOOO</span></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">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>
<td class="bits">XXXX XXXX</td>
</tr>
</tbody>
</table>

View File

@@ -1,37 +1,28 @@
.\" Hey, EMACS: -*- nroff -*-
.\" Please adjust this date whenever revising the manpage.
.Dd Jul 20, 2008
.Dd May 16, 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 Defhix
.Op Fl Defhi
.Op Fl G Ar seed
.Op Fl b Ar blitter
.Op Fl d Ar [level | cat=lvl[, ...]]
.Op Fl c Ar config_file
.Op Fl g Ar [savegame]
.Op Fl l Ar host[:port]
.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 v Ar driver
.Op Fl b Ar blitter
.Sh OPTIONS
.Bl -tag -width ".Fl n Ar host[:port][#player]"
.It Fl D Ar [host][:port]
.It Fl D
Start a dedicated server
.It Fl G Ar seed
Seed the pseudo random number generator
.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 Ar [level]
Set debug verbosity for all categories to
.Ar level
@@ -51,9 +42,6 @@ at start or start a new game if omitted
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 l Ar host[:port]
Redirect DEBUG(), See
.Fl D
.It Fl m Ar driver
Set the music driver, see
.Fl h
@@ -69,8 +57,6 @@ 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,19 +1,16 @@
/* $Id$ */
/** @file dummy_land.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "tile_cmd.h"
#include "command_func.h"
#include "viewport_func.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);
}
@@ -22,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, byte flags)
static int32 ClearTile_Dummy(TileIndex tile, byte flags)
{
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
}
@@ -64,17 +61,12 @@ static void ChangeTileOwner_Dummy(TileIndex tile, PlayerID old_player, PlayerID
/* not used */
}
static TrackStatus GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode)
{
return 0;
}
static CommandCost TerraformTile_Dummy(TileIndex tile, uint32 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

70
economy.h Normal file
View File

@@ -0,0 +1,70 @@
/* $Id$ */
#ifndef ECONOMY_H
#define ECONOMY_H
void ResetPriceBaseMultipliers(void);
void SetPriceBaseMultiplier(uint price, byte factor);
typedef struct {
// Maximum possible loan
int32 max_loan;
int32 max_loan_unround;
// Economy fluctuation status
int fluct;
// Interest
byte interest_rate;
byte infl_amount;
byte infl_amount_pr;
} Economy;
VARDEF Economy _economy;
typedef struct Subsidy {
CargoID cargo_type;
byte age;
/* from and to can either be TownID, StationID or IndustryID */
uint16 from;
uint16 to;
} Subsidy;
enum {
SCORE_VEHICLES = 0,
SCORE_STATIONS = 1,
SCORE_MIN_PROFIT = 2,
SCORE_MIN_INCOME = 3,
SCORE_MAX_INCOME = 4,
SCORE_DELIVERED = 5,
SCORE_CARGO = 6,
SCORE_MONEY = 7,
SCORE_LOAN = 8,
SCORE_TOTAL = 9, // This must always be the last entry
NUM_SCORE = 10, // How many scores are there..
SCORE_MAX = 1000 // The max score that can be in the performance history
// the scores together of score_info is allowed to be more!
};
typedef struct ScoreInfo {
byte id; // Unique ID of the score
int needed; // How much you need to get the perfect score
int score; // How much score it will give
} ScoreInfo;
extern const ScoreInfo _score_info[];
extern int _score_part[MAX_PLAYERS][NUM_SCORE];
int UpdateCompanyRatingAndValue(Player *p, bool update);
VARDEF Subsidy _subsidies[MAX_PLAYERS];
Pair SetupSubsidyDecodeParam(const Subsidy* s, bool mode);
void DeleteSubsidyWithTown(TownID index);
void DeleteSubsidyWithIndustry(IndustryID index);
void DeleteSubsidyWithStation(StationID index);
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
uint MoveGoodsToStation(TileIndex tile, int w, int h, int type, uint amount);
#endif /* ECONOMY_H */

455
elrail.c Normal file
View File

@@ -0,0 +1,455 @@
/* $Id$ */
/** @file elrail.c
* This file deals with displaying wires and pylons for electric railways.
* <h2>Basics</h2>
*
* <h3>Tile Types</h3>
*
* We have two different types of tiles in the drawing code:
* Normal Railway Tiles (NRTs) which can have more than one track on it, and
* Special Railways tiles (SRTs) which have only one track (like crossings, depots
* stations, etc).
*
* <h3>Location Categories</h3>
*
* All tiles are categorized into three location groups (TLG):
* Group 0: Tiles with both an even X coordinate and an even Y coordinate
* Group 1: Tiles with an even X and an odd Y coordinate
* Group 2: Tiles with an odd X and an even Y coordinate
* Group 3: Tiles with both an odd X and Y coordnate.
*
* <h3>Pylon Points</h3>
* <h4>Control Points</h4>
* A Pylon Control Point (PCP) is a position where a wire (or rather two)
* is mounted onto a pylon.
* Each NRT does contain 4 PCPs which are bitmapped to a byte
* variable and are represented by the DiagDirection enum
*
* Each track ends on two PCPs and thus requires one pylon on each end. However,
* there is one exception: Straight-and-level tracks only have one pylon every
* other tile.
*
* Now on each edge there are two PCPs: One from each adjacent tile. Both PCPs
* are merged using an OR operation (i. e. if one tile needs a PCP at the postion
* in question, both tiles get it).
*
* <h4>Position Points</h4>
* A Pylon Position Point (PPP) is a position where a pylon is located on the
* ground. Each PCP owns 8 in (45 degree steps) PPPs that are located around
* it. PPPs are represented using the Direction enum. Each track bit has PPPs
* that are impossible (because the pylon would be situated on the track) and
* some that are preferred (because the pylon would be rectangular to the track).
*
* <img src="../../elrail_tile.png">
* <img src="../../elrail_track.png">
*
*/
#include "stdafx.h"
#include "openttd.h"
#include "station_map.h"
#include "tile.h"
#include "viewport.h"
#include "functions.h" /* We should REALLY get rid of this goddamn file, as it is butt-ugly */
#include "variables.h" /* ... same here */
#include "rail.h"
#include "debug.h"
#include "tunnel_map.h"
#include "road_map.h"
#include "bridge_map.h"
#include "bridge.h"
#include "rail_map.h"
#include "table/sprites.h"
#include "table/elrail_data.h"
#include "vehicle.h"
#include "train.h"
#include "gui.h"
static inline TLG GetTLG(TileIndex t)
{
return (HASBIT(TileX(t), 0) << 1) + HASBIT(TileY(t), 0);
}
/** Finds which Rail Bits are present on a given tile. For bridge tiles,
* returns track bits under the bridge
*/
static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
{
switch (GetTileType(t)) {
case MP_RAILWAY:
if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
switch (GetRailTileType(t)) {
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
return GetTrackBits(t);
case RAIL_TILE_DEPOT_WAYPOINT:
if (GetRailTileSubtype(t) == RAIL_SUBTYPE_WAYPOINT) return GetRailWaypointBits(t);
default:
return 0;
}
break;
case MP_TUNNELBRIDGE:
if (IsTunnel(t)) {
if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
if (override != NULL) *override = 1 << GetTunnelDirection(t);
return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(t)));
} else {
if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
if (IsBridgeMiddle(t)) {
if (IsTransportUnderBridge(t) &&
GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL) {
return GetRailBitsUnderBridge(t);
} else {
return 0;
}
} else {
if (override != NULL && DistanceMax(t, GetOtherBridgeEnd(t)) > 1) *override = 1 << GetBridgeRampDirection(t);
return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(t)));
}
}
case MP_STREET:
if (GetRoadTileType(t) != ROAD_TILE_CROSSING) return 0;
if (GetRailTypeCrossing(t) != RAILTYPE_ELECTRIC) return 0;
return GetCrossingRailBits(t);
case MP_STATION:
if (!IsRailwayStation(t)) return 0;
if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
if (!IsStationTileElectrifiable(t)) return 0;
return TrackToTrackBits(GetRailStationTrack(t));
default:
return 0;
}
}
/** Corrects the tileh for certain tile types. Returns an effective tileh for the track on the tile.
* @param tile The tile to analyse
* @param *tileh the tileh
*/
static void AdjustTileh(TileIndex tile, Slope *tileh)
{
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
if (IsTunnel(tile)) {
*tileh = SLOPE_STEEP; /* XXX - Hack to make tunnel entrances to always have a pylon */
} else {
if (IsBridgeRamp(tile)) {
if (*tileh != SLOPE_FLAT) {
*tileh = SLOPE_FLAT;
} else {
switch (GetBridgeRampDirection(tile)) {
case DIAGDIR_NE: *tileh = SLOPE_NE; break;
case DIAGDIR_SE: *tileh = SLOPE_SE; break;
case DIAGDIR_SW: *tileh = SLOPE_SW; break;
case DIAGDIR_NW: *tileh = SLOPE_NW; break;
default: break;
}
}
}
}
}
}
/** Draws wires and, if required, pylons on a given tile
* @param ti The Tileinfo to draw the tile for
*/
static void DrawCatenaryRailway(const TileInfo *ti)
{
/* Pylons are placed on a tile edge, so we need to take into account
* the track configuration of 2 adjacent tiles. trackconfig[0] stores the
* current tile (home tile) while [1] holds the neighbour */
TrackBits trackconfig[TS_END];
bool isflat[TS_END];
/* Note that ti->tileh has already been adjusted for Foundations */
Slope tileh[TS_END] = { ti->tileh, SLOPE_FLAT };
TLG tlg = GetTLG(ti->tile);
byte PCPstatus = 0;
byte OverridePCP = 0;
byte PPPpreferred[DIAGDIR_END];
byte PPPallowed[DIAGDIR_END];
DiagDirection i;
Track t;
/* Find which rail bits are present, and select the override points.
* We don't draw a pylon:
* 1) INSIDE a tunnel (we wouldn't see it anyway)
* 2) on the "far" end of a bridge head (the one that connects to bridge middle),
* because that one is drawn on the bridge. Exception is for length 0 bridges
* which have no middle tiles */
trackconfig[TS_HOME] = GetRailTrackBitsUniversal(ti->tile, &OverridePCP);
/* If a track bit is present that is not in the main direction, the track is level */
isflat[TS_HOME] = trackconfig[TS_HOME] & (TRACK_BIT_HORZ | TRACK_BIT_VERT);
AdjustTileh(ti->tile, &tileh[TS_HOME]);
for (i = DIAGDIR_NE; i < DIAGDIR_END; i++) {
TileIndex neighbour = ti->tile + TileOffsByDiagDir(i);
uint foundation = 0;
int k;
/* Here's one of the main headaches. GetTileSlope does not correct for possibly
* existing foundataions, so we do have to do that manually later on.*/
tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL);
trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
if (IsTunnelTile(neighbour) && i != GetTunnelDirection(neighbour)) trackconfig[TS_NEIGHBOUR] = 0;
isflat[TS_NEIGHBOUR] = trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT);
PPPpreferred[i] = 0xFF; /* We start with preferring everything (end-of-line in any direction) */
PPPallowed[i] = AllowedPPPonPCP[i];
/* We cycle through all the existing tracks at a PCP and see what
* PPPs we want to have, or may not have at all */
for (k = 0; k < NUM_TRACKS_AT_PCP; k++) {
/* Next to us, we have a bridge head, don't worry about that one, if it shows away from us */
if (TrackSourceTile[i][k] == TS_NEIGHBOUR &&
IsBridgeTile(neighbour) && IsBridgeRamp(neighbour) &&
GetBridgeRampDirection(neighbour) == ReverseDiagDir(i)) {
continue;
}
/* We check whether the track in question (k) is present in the tile
* (TrackSourceTile) */
if (HASBIT(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
/* track found, if track is in the neighbour tile, adjust the number
* of the PCP for preferred/allowed determination*/
DiagDirection PCPpos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
SETBIT(PCPstatus, i); /* This PCP is in use */
PPPpreferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
PPPallowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
}
}
/* Deactivate all PPPs if PCP is not used */
PPPpreferred[i] *= HASBIT(PCPstatus, i);
PPPallowed[i] *= HASBIT(PCPstatus, i);
/* A station is always "flat", so adjust the tileh accordingly */
if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
/* Read the foundataions if they are present, and adjust the tileh */
if (IsTileType(neighbour, MP_RAILWAY) && GetRailType(neighbour) == RAILTYPE_ELECTRIC) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
if (IsBridgeTile(neighbour) && IsBridgeRamp(neighbour)) {
foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
}
if (foundation != 0) {
if (foundation < 15) {
tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
} else {
tileh[TS_NEIGHBOUR] = _inclined_tileh[foundation - 15];
}
}
AdjustTileh(neighbour, &tileh[TS_NEIGHBOUR]);
/* If we have a straight (and level) track, we want a pylon only every 2 tiles
* Delete the PCP if this is the case. */
/* Level means that the slope is the same, or the track is flat */
if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
for (k = 0; k < NUM_IGNORE_GROUPS; k++)
if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) CLRBIT(PCPstatus, i);
}
/* Now decide where we draw our pylons. First try the preferred PPPs, but they may not exist.
* In that case, we try the any of the allowed ones. if they don't exist either, don't draw
* anything. Note that the preferred PPPs still contain the end-of-line markers.
* Remove those (simply by ANDing with allowed, since these markers are never allowed) */
if ((PPPallowed[i] & PPPpreferred[i]) != 0) PPPallowed[i] &= PPPpreferred[i];
if (PPPallowed[i] != 0 && HASBIT(PCPstatus, i) && !HASBIT(OverridePCP, i)) {
for (k = 0; k < DIR_END; k++) {
byte temp = PPPorder[i][GetTLG(ti->tile)][k];
if (HASBIT(PPPallowed[i], temp)) {
uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
/* Don't build the pylon if it would be outside the tile */
if (!HASBIT(OwnedPPPonPCP[i], temp)) {
/* We have a neighour that will draw it, bail out */
if (trackconfig[TS_NEIGHBOUR] != 0) break;
continue; /* No neighbour, go looking for a better position */
}
AddSortableSpriteToDraw(pylons_normal[temp], x, y, 1, 1, 10,
GetSlopeZ(ti->x + x_pcp_offsets[i], ti->y + y_pcp_offsets[i]));
break; /* We already have drawn a pylon, bail out */
}
}
}
}
/* Don't draw a wire under a low bridge */
if (IsBridgeTile(ti->tile) &&
IsBridgeMiddle(ti->tile) &&
!(_display_opt & DO_TRANS_BUILDINGS) &&
GetBridgeHeight(ti->tile) <= TilePixelHeight(ti->tile) + TILE_HEIGHT) {
return;
}
/* Drawing of pylons is finished, now draw the wires */
for (t = 0; t < TRACK_END; t++) {
if (HASBIT(trackconfig[TS_HOME], t)) {
byte PCPconfig;
const SortableSpriteStruct *sss;
int tileh_selector;
if (IsTunnelTile(ti->tile)) {
const SortableSpriteStruct* sss = &CatenarySpriteData_Tunnel[GetTunnelDirection(ti->tile)];
AddSortableSpriteToDraw(
sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
sss->x_size, sss->y_size, sss->z_size,
GetTileZ(ti->tile) + sss->z_offset
);
break;
}
PCPconfig = HASBIT(PCPstatus, PCPpositions[t][0]) +
(HASBIT(PCPstatus, PCPpositions[t][1]) << 1);
tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; /* tileh for the slopes, 0 otherwise */
assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
assert(!IsSteepSlope(tileh[TS_HOME]));
sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + min(sss->x_offset, TILE_SIZE - 1), ti->y + min(sss->y_offset, TILE_SIZE - 1)) + sss->z_offset);
}
}
}
static void DrawCatenaryOnBridge(const TileInfo *ti)
{
TileIndex end = GetSouthernBridgeEnd(ti->tile);
TileIndex start = GetOtherBridgeEnd(end);
uint length = GetBridgeLength(start, end);
uint num = DistanceMax(ti->tile, start);
uint height;
const SortableSpriteStruct *sss;
Axis axis = GetBridgeAxis(ti->tile);
TLG tlg = GetTLG(ti->tile);
CatenarySprite offset = axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH;
if ((length % 2) && num == length) {
/* Draw the "short" wire on the southern end of the bridge
* only needed if the length of the bridge is odd */
sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
} else {
/* Draw "long" wires on all other tiles of the bridge (one pylon every two tiles) */
sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
}
height = GetBridgeHeight(ti->tile);
AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset
);
/* Finished with wires, draw pylons */
/* every other tile needs a pylon on the northern end */
if (num % 2) {
if (axis == AXIS_X) {
AddSortableSpriteToDraw(pylons_bridge[0 + HASBIT(tlg, 0)], ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, height);
} else {
AddSortableSpriteToDraw(pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, height);
}
}
/* need a pylon on the southern end of the bridge */
if (DistanceMax(ti->tile, start) == length) {
if (axis == AXIS_X) {
AddSortableSpriteToDraw(pylons_bridge[0 + HASBIT(tlg, 0)], ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, height);
} else {
AddSortableSpriteToDraw(pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, height);
}
}
}
void DrawCatenary(const TileInfo *ti)
{
if (_patches.disable_elrails) return;
switch (GetTileType(ti->tile)) {
case MP_RAILWAY:
if ( IsRailDepot(ti->tile)) {
const SortableSpriteStruct* sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
AddSortableSpriteToDraw(
sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
sss->x_size, sss->y_size, sss->z_size,
GetTileMaxZ(ti->tile) + sss->z_offset
);
return;
}
break;
case MP_TUNNELBRIDGE:
if (IsBridge(ti->tile) && IsBridgeMiddle(ti->tile) && GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenaryOnBridge(ti);
break;
case MP_STREET: break;
case MP_STATION: break;
default: return;
}
DrawCatenaryRailway(ti);
}
int32 SettingsDisableElrail(int32 p1)
{
EngineID e_id;
Vehicle* v;
Player *p;
bool disable = (p1 != 0);
/* we will now walk through all electric train engines and change their railtypes if it is the wrong one*/
const RailType old_railtype = disable ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL;
const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
/* walk through all train engines */
for (e_id = 0; e_id < NUM_TRAIN_ENGINES; e_id++) {
const RailVehicleInfo *rv_info = RailVehInfo(e_id);
Engine *e = GetEngine(e_id);
/* if it is an electric rail engine and its railtype is the wrong one */
if (rv_info->engclass == 2 && e->railtype == old_railtype) {
/* change it to the proper one */
e->railtype = new_railtype;
}
}
/* when disabling elrails, make sure that all existing trains can run on
* normal rail too */
if (disable) {
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_Train && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
/* this railroad vehicle is now compatible only with elrail,
* so add there also normal rail compatibility */
v->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
v->u.rail.railtype = RAILTYPE_RAIL;
SETBIT(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
}
}
}
/* setup total power for trains */
FOR_ALL_VEHICLES(v) {
/* power is cached only for front engines */
if (v->type == VEH_Train && IsFrontEngine(v)) TrainPowerChanged(v);
}
FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
/* This resets the _last_built_railtype, which will be invalid for electric
* rails. It may have unintended consequences if that function is ever
* extended, though. */
ReinitGuiAfterToggleElrail(disable);
return 0;
}

52
endian_check.c Normal file
View File

@@ -0,0 +1,52 @@
/* $Id$ */
#include <stdio.h>
// This pretty simple file checks if the system is LITTLE_ENDIAN or BIG_ENDIAN
// it does that by putting a 1 and a 0 in an array, and read it out as one
// number. If it is 1, it is LITTLE_ENDIAN, if it is 256, it is BIG_ENDIAN
//
// After that it outputs the contents of an include files (endian.h)
// that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes
// care of the real writing to the file.
int main (int argc, char *argv[]) {
unsigned char EndianTest[2] = { 1, 0 };
int force_BE = 0, force_LE = 0, force_PREPROCESSOR = 0;
if (argc > 1 && strcmp(argv[1], "BE") == 0)
force_BE = 1;
if (argc > 1 && strcmp(argv[1], "LE") == 0)
force_LE = 1;
if (argc > 1 && strcmp(argv[1], "PREPROCESSOR") == 0)
force_PREPROCESSOR = 1;
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
if (force_LE == 1) {
printf("#define TTD_LITTLE_ENDIAN\n");
} else {
if (force_BE == 1) {
printf("#define TTD_BIG_ENDIAN\n");
} else {
if (force_PREPROCESSOR == 1) {
// adding support for universal binaries on OSX
// Universal binaries supports both PPC and x86
// If a compiler for OSX gets this setting, it will always pick the correct endian and no test is needed
printf("#ifdef __BIG_ENDIAN__\n");
printf("#define TTD_BIG_ENDIAN\n");
printf("#else\n");
printf("#define TTD_LITTLE_ENDIAN\n");
printf("#endif\n");
} else {
if ( *(short *) EndianTest == 1 )
printf("#define TTD_LITTLE_ENDIAN\n");
else
printf("#define TTD_BIG_ENDIAN\n");
}
}
}
printf("#endif\n");
return 0;
}

648
engine.c Normal file
View File

@@ -0,0 +1,648 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
#include "functions.h"
#include "table/strings.h"
#include "engine.h"
#include "gfx.h"
#include "player.h"
#include "command.h"
#include "vehicle.h"
#include "news.h"
#include "saveload.h"
#include "variables.h"
#include "train.h"
#include "newgrf_cargo.h"
#include "date.h"
#include "table/engines.h"
EngineInfo _engine_info[TOTAL_NUM_ENGINES];
RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES];
AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
RoadVehicleInfo _road_vehicle_info[NUM_ROAD_ENGINES];
enum {
ENGINE_AVAILABLE = 1,
ENGINE_INTRODUCING = 2,
ENGINE_PREVIEWING = 4,
};
enum {
YEAR_ENGINE_AGING_STOPS = 2050,
};
void ShowEnginePreviewWindow(EngineID engine);
void DeleteCustomEngineNames(void)
{
uint i;
StringID old;
for (i = 0; i != TOTAL_NUM_ENGINES; i++) {
old = _engine_name_strings[i];
_engine_name_strings[i] = i + STR_8000_KIRBY_PAUL_TANK_STEAM;
DeleteName(old);
}
_vehicle_design_names &= ~1;
}
void LoadCustomEngineNames(void)
{
/* XXX: not done */
DEBUG(misc, 1) ("LoadCustomEngineNames: not done");
}
static void SetupEngineNames(void)
{
StringID *name;
for (name = _engine_name_strings; name != endof(_engine_name_strings); name++)
*name = STR_SV_EMPTY;
DeleteCustomEngineNames();
LoadCustomEngineNames();
}
static void AdjustAvailAircraft(void)
{
byte avail = 0;
if (_cur_year >= 1955) avail |= 2; // big airport
if (_cur_year < 1960 || _patches.always_small_airport) avail |= 1; // small airport
if (_cur_year >= 1963) avail |= 4; // enable heliport
if (avail != _avail_aircraft) {
_avail_aircraft = avail;
InvalidateWindow(WC_BUILD_STATION, 0);
}
}
static void CalcEngineReliability(Engine *e)
{
uint age = e->age;
if (age < e->duration_phase_1) {
uint start = e->reliability_start;
e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start;
} else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _patches.never_expire_vehicles) {
/* We are at the peak of this engines life. It will have max reliability.
* This is also true if the engines never expire. They will not go bad over time */
e->reliability = e->reliability_max;
} else if ((age -= e->duration_phase_2) < e->duration_phase_3) {
uint max = e->reliability_max;
e->reliability = (int)age * (int)(e->reliability_final - max) / e->duration_phase_3 + max;
} else {
/* time's up for this engine.
* We will now completely retire this design */
e->player_avail = 0;
e->reliability = e->reliability_final;
InvalidateWindowClassesData(WC_BUILD_VEHICLE); // Kick this engine out of the lists
}
InvalidateWindowClasses(WC_BUILD_VEHICLE); // Update to show the new reliability
}
void AddTypeToEngines(void)
{
Engine* e = _engines;
do e->type = VEH_Train; while (++e < &_engines[ROAD_ENGINES_INDEX]);
do e->type = VEH_Road; while (++e < &_engines[SHIP_ENGINES_INDEX]);
do e->type = VEH_Ship; while (++e < &_engines[AIRCRAFT_ENGINES_INDEX]);
do e->type = VEH_Aircraft; while (++e < &_engines[TOTAL_NUM_ENGINES]);
do e->type = VEH_Special; while (++e < endof(_engines));
}
void StartupEngines(void)
{
Engine *e;
const EngineInfo *ei;
/* Aging of vehicles stops, so account for that when starting late */
const Date aging_date = min(_date, ConvertYMDToDate(YEAR_ENGINE_AGING_STOPS, 0, 1));
SetupEngineNames();
for (e = _engines, ei = _engine_info; e != endof(_engines); e++, ei++) {
uint32 r;
e->age = 0;
e->railtype = ei->railtype;
e->flags = 0;
e->player_avail = 0;
// The magic value of 729 days below comes from the NewGRF spec. If the
// base intro date is before 1922 then the random number of days is not
// added.
r = Random();
e->intro_date = ei->base_intro <= ConvertYMDToDate(1922, 0, 1) ? ei->base_intro : (Date)GB(r, 0, 9) + ei->base_intro;
if (e->intro_date <= _date) {
e->age = (aging_date - e->intro_date) >> 5;
e->player_avail = (byte)-1;
e->flags |= ENGINE_AVAILABLE;
}
e->reliability_start = GB(r, 16, 14) + 0x7AE0;
r = Random();
e->reliability_max = GB(r, 0, 14) + 0xBFFF;
e->reliability_final = GB(r, 16, 14) + 0x3FFF;
r = Random();
e->duration_phase_1 = GB(r, 0, 5) + 7;
e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96;
e->duration_phase_3 = GB(r, 9, 7) + 120;
e->reliability_spd_dec = (ei->unk2&0x7F) << 2;
/* my invented flag for something that is a wagon */
if (ei->unk2 & 0x80) {
e->age = 0xFFFF;
} else {
CalcEngineReliability(e);
}
e->lifelength = ei->lifelength + _patches.extend_vehicle_life;
// prevent certain engines from ever appearing.
if (!HASBIT(ei->climates, _opt.landscape)) {
e->flags |= ENGINE_AVAILABLE;
e->player_avail = 0;
}
/* This sets up type for the engine
* It is needed if you want to ask the engine what type it is
* It should hopefully be the same as when you ask a vehicle what it is
* but using this, you can ask what type an engine number is
* even if it is not a vehicle (yet)*/
}
AdjustAvailAircraft();
}
static void AcceptEnginePreview(Engine *e, PlayerID player)
{
Player *p = GetPlayer(player);
assert(e->railtype < RAILTYPE_END);
SETBIT(e->player_avail, player);
SETBIT(p->avail_railtypes, e->railtype);
e->preview_player = 0xFF;
if (player == _local_player) {
InvalidateWindowClassesData(WC_BUILD_VEHICLE);
InvalidateWindowClasses(WC_REPLACE_VEHICLE);
}
}
static PlayerID GetBestPlayer(PlayerID pp)
{
const Player *p;
int32 best_hist;
PlayerID best_player;
uint mask = 0;
do {
best_hist = -1;
best_player = PLAYER_SPECTATOR;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->block_preview == 0 && !HASBIT(mask, p->index) &&
p->old_economy[0].performance_history > best_hist) {
best_hist = p->old_economy[0].performance_history;
best_player = p->index;
}
}
if (best_player == PLAYER_SPECTATOR) return PLAYER_SPECTATOR;
SETBIT(mask, best_player);
} while (--pp != 0);
return best_player;
}
void EnginesDailyLoop(void)
{
EngineID i;
if (_cur_year >= YEAR_ENGINE_AGING_STOPS) return;
for (i = 0; i != lengthof(_engines); i++) {
Engine *e = &_engines[i];
if (e->flags & ENGINE_INTRODUCING) {
if (e->flags & ENGINE_PREVIEWING) {
if (e->preview_player != 0xFF && !--e->preview_wait) {
e->flags &= ~ENGINE_PREVIEWING;
DeleteWindowById(WC_ENGINE_PREVIEW, i);
e->preview_player++;
}
} else if (e->preview_player != 0xFF) {
PlayerID best_player = GetBestPlayer(e->preview_player);
if (best_player == PLAYER_SPECTATOR) {
e->preview_player = 0xFF;
continue;
}
if (!IsHumanPlayer(best_player)) {
/* XXX - TTDBUG: TTD has a bug here ???? */
AcceptEnginePreview(e, best_player);
} else {
e->flags |= ENGINE_PREVIEWING;
e->preview_wait = 20;
if (IsInteractivePlayer(best_player)) ShowEnginePreviewWindow(i);
}
}
}
}
}
/** Accept an engine prototype. XXX - it is possible that the top-player
* changes while you are waiting to accept the offer? Then it becomes invalid
* @param tile unused
* @param p1 engine-prototype offered
* @param p2 unused
*/
int32 CmdWantEnginePreview(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
Engine *e;
if (!IsEngineIndex(p1)) return CMD_ERROR;
e = GetEngine(p1);
if (GetBestPlayer(e->preview_player) != _current_player) return CMD_ERROR;
if (flags & DC_EXEC) AcceptEnginePreview(e, _current_player);
return 0;
}
// Determine if an engine type is a wagon (and not a loco)
static bool IsWagon(EngineID index)
{
return index < NUM_TRAIN_ENGINES && RailVehInfo(index)->flags & RVI_WAGON;
}
static void NewVehicleAvailable(Engine *e)
{
Vehicle *v;
Player *p;
EngineID index = e - _engines;
// In case the player didn't build the vehicle during the intro period,
// prevent that player from getting future intro periods for a while.
if (e->flags & ENGINE_INTRODUCING) {
FOR_ALL_PLAYERS(p) {
uint block_preview = p->block_preview;
if (!HASBIT(e->player_avail, p->index)) continue;
/* We assume the user did NOT build it.. prove me wrong ;) */
p->block_preview = 20;
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship ||
(v->type == VEH_Aircraft && v->subtype <= 2)) {
if (v->owner == p->index && v->engine_type == index) {
/* The user did prove me wrong, so restore old value */
p->block_preview = block_preview;
break;
}
}
}
}
}
e->flags = (e->flags & ~ENGINE_INTRODUCING) | ENGINE_AVAILABLE;
InvalidateWindowClassesData(WC_BUILD_VEHICLE);
InvalidateWindowClasses(WC_REPLACE_VEHICLE);
// Now available for all players
e->player_avail = (byte)-1;
// Do not introduce new rail wagons
if (IsWagon(index)) return;
// make maglev / monorail available
FOR_ALL_PLAYERS(p) {
if (p->is_active) {
assert(e->railtype < RAILTYPE_END);
SETBIT(p->avail_railtypes, e->railtype);
}
}
AddNewsItem(index, NEWS_FLAGS(NM_CALLBACK, 0, NT_NEW_VEHICLES, DNC_VEHICLEAVAIL), 0, 0);
}
void EnginesMonthlyLoop(void)
{
Engine *e;
if (_cur_year < YEAR_ENGINE_AGING_STOPS) {
for (e = _engines; e != endof(_engines); e++) {
// Age the vehicle
if (e->flags & ENGINE_AVAILABLE && e->age != 0xFFFF) {
e->age++;
CalcEngineReliability(e);
}
if (!(e->flags & ENGINE_AVAILABLE) && _date >= (e->intro_date + 365)) {
// Introduce it to all players
NewVehicleAvailable(e);
} else if (!(e->flags & (ENGINE_AVAILABLE|ENGINE_INTRODUCING)) && _date >= e->intro_date) {
// Introduction date has passed.. show introducing dialog to one player.
e->flags |= ENGINE_INTRODUCING;
// Do not introduce new rail wagons
if (!IsWagon(e - _engines))
e->preview_player = 1; // Give to the player with the highest rating.
}
}
}
AdjustAvailAircraft();
}
/** Rename an engine.
* @param tile unused
* @param p1 engine ID to rename
* @param p2 unused
*/
int32 CmdRenameEngine(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
StringID str;
if (!IsEngineIndex(p1) || _cmd_text[0] == '\0') return CMD_ERROR;
str = AllocateNameUnique(_cmd_text, 0);
if (str == 0) return CMD_ERROR;
if (flags & DC_EXEC) {
StringID old_str = _engine_name_strings[p1];
_engine_name_strings[p1] = str;
DeleteName(old_str);
_vehicle_design_names |= 3;
MarkWholeScreenDirty();
} else {
DeleteName(str);
}
return 0;
}
/*
* returns true if an engine is valid, of the specified type, and buildable by
* the given player, false otherwise
*
* engine = index of the engine to check
* type = the type the engine should be of (VEH_xxx)
* player = index of the player
*/
bool IsEngineBuildable(EngineID engine, byte type, PlayerID player)
{
const Engine *e;
// check if it's an engine that is in the engine array
if (!IsEngineIndex(engine)) return false;
e = GetEngine(engine);
// check if it's an engine of specified type
if (e->type != type) return false;
// check if it's available
if (!HASBIT(e->player_avail, player)) return false;
if (type == VEH_Train) {
/* Check if the rail type is available to this player */
const Player *p = GetPlayer(player);
if (!HASBIT(p->avail_railtypes, EngInfo(engine)->railtype)) return false;
}
return true;
}
/************************************************************************
* Engine Replacement stuff
************************************************************************/
static void EngineRenewPoolNewBlock(uint start_item);
DEFINE_OLD_POOL(EngineRenew, EngineRenew, EngineRenewPoolNewBlock, NULL)
static void EngineRenewPoolNewBlock(uint start_item)
{
EngineRenew *er;
/* 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 (er = GetEngineRenew(start_item); er != NULL; er = (er->index + 1U < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1U) : NULL) {
er->index = start_item++;
er->from = INVALID_ENGINE;
}
}
static EngineRenew *AllocateEngineRenew(void)
{
EngineRenew *er;
/* 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 (er = GetEngineRenew(0); er != NULL; er = (er->index + 1U < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1U) : NULL) {
if (IsValidEngineRenew(er)) continue;
er->to = INVALID_ENGINE;
er->next = NULL;
return er;
}
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_EngineRenew_pool)) return AllocateEngineRenew();
return NULL;
}
/**
* Retrieves the EngineRenew that specifies the replacement of the given
* engine type from the given renewlist */
static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine)
{
EngineRenew *er = (EngineRenew *)erl;
while (er) {
if (er->from == engine) return er;
er = er->next;
}
return NULL;
}
void RemoveAllEngineReplacement(EngineRenewList *erl)
{
EngineRenew *er = (EngineRenew *)(*erl);
EngineRenew *next;
while (er) {
next = er->next;
DeleteEngineRenew(er);
er = next;
}
*erl = NULL; // Empty list
}
EngineID EngineReplacement(EngineRenewList erl, EngineID engine)
{
const EngineRenew *er = GetEngineReplacement(erl, engine);
return er == NULL ? INVALID_ENGINE : er->to;
}
int32 AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, uint32 flags)
{
EngineRenew *er;
/* Check if the old vehicle is already in the list */
er = GetEngineReplacement(*erl, old_engine);
if (er != NULL) {
if (flags & DC_EXEC) er->to = new_engine;
return 0;
}
er = AllocateEngineRenew();
if (er == NULL) return CMD_ERROR;
if (flags & DC_EXEC) {
er->from = old_engine;
er->to = new_engine;
/* Insert before the first element */
er->next = (EngineRenew *)(*erl);
*erl = (EngineRenewList)er;
}
return 0;
}
int32 RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, uint32 flags)
{
EngineRenew *er = (EngineRenew *)(*erl);
EngineRenew *prev = NULL;
while (er)
{
if (er->from == engine) {
if (flags & DC_EXEC) {
if (prev == NULL) { // First element
/* The second becomes the new first element */
*erl = (EngineRenewList)er->next;
} else {
/* Cut this element out */
prev->next = er->next;
}
DeleteEngineRenew(er);
}
return 0;
}
prev = er;
er = er->next;
}
return CMD_ERROR;
}
static const SaveLoad _engine_renew_desc[] = {
SLE_VAR(EngineRenew, from, SLE_UINT16),
SLE_VAR(EngineRenew, to, SLE_UINT16),
SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS),
SLE_END()
};
static void Save_ERNW(void)
{
EngineRenew *er;
FOR_ALL_ENGINE_RENEWS(er) {
SlSetArrayIndex(er->index);
SlObject(er, _engine_renew_desc);
}
}
static void Load_ERNW(void)
{
int index;
while ((index = SlIterateArray()) != -1) {
EngineRenew *er;
if (!AddBlockIfNeeded(&_EngineRenew_pool, index))
error("EngineRenews: failed loading savegame: too many EngineRenews");
er = GetEngineRenew(index);
SlObject(er, _engine_renew_desc);
}
}
static const SaveLoad _engine_desc[] = {
SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLE_CONDVAR(Engine, intro_date, SLE_INT32, 31, SL_MAX_VERSION),
SLE_CONDVAR(Engine, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLE_CONDVAR(Engine, age, SLE_INT32, 31, SL_MAX_VERSION),
SLE_VAR(Engine, reliability, SLE_UINT16),
SLE_VAR(Engine, reliability_spd_dec, SLE_UINT16),
SLE_VAR(Engine, reliability_start, SLE_UINT16),
SLE_VAR(Engine, reliability_max, SLE_UINT16),
SLE_VAR(Engine, reliability_final, SLE_UINT16),
SLE_VAR(Engine, duration_phase_1, SLE_UINT16),
SLE_VAR(Engine, duration_phase_2, SLE_UINT16),
SLE_VAR(Engine, duration_phase_3, SLE_UINT16),
SLE_VAR(Engine, lifelength, SLE_UINT8),
SLE_VAR(Engine, flags, SLE_UINT8),
SLE_VAR(Engine, preview_player, SLE_UINT8),
SLE_VAR(Engine, preview_wait, SLE_UINT8),
SLE_VAR(Engine, railtype, SLE_UINT8),
SLE_VAR(Engine, player_avail, SLE_UINT8),
// reserve extra space in savegame here. (currently 16 bytes)
SLE_CONDNULL(16, 2, SL_MAX_VERSION),
SLE_END()
};
static void Save_ENGN(void)
{
uint i;
for (i = 0; i != lengthof(_engines); i++) {
SlSetArrayIndex(i);
SlObject(&_engines[i], _engine_desc);
}
}
static void Load_ENGN(void)
{
int index;
while ((index = SlIterateArray()) != -1) {
SlObject(GetEngine(index), _engine_desc);
}
}
static void LoadSave_ENGS(void)
{
SlArray(_engine_name_strings, lengthof(_engine_name_strings), SLE_STRINGID);
}
const ChunkHandler _engine_chunk_handlers[] = {
{ 'ENGN', Save_ENGN, Load_ENGN, CH_ARRAY },
{ 'ENGS', LoadSave_ENGS, LoadSave_ENGS, CH_RIFF },
{ 'ERNW', Save_ERNW, Load_ERNW, CH_ARRAY | CH_LAST},
};
void InitializeEngines(void)
{
/* Clean the engine renew pool and create 1 block in it */
CleanPool(&_EngineRenew_pool);
AddBlockToPool(&_EngineRenew_pool);
}

View File

@@ -1,122 +1,92 @@
/* $Id$ */
/** @file engine.h */
#ifndef ENGINE_H
#define ENGINE_H
#include "rail_type.h"
#include "cargo_type.h"
#include "vehicle_type.h"
#include "gfx_type.h"
#include "date_type.h"
#include "sound_type.h"
#include "player_type.h"
#include "strings_type.h"
/** @file engine.h */
enum RailVehicleTypes {
RAILVEH_SINGLEHEAD, ///< indicates a "standalone" locomotive
RAILVEH_MULTIHEAD, ///< indicates a combination of two locomotives
RAILVEH_WAGON, ///< simple wagon, not motorized
};
#include "oldpool.h"
enum EngineClass {
EC_STEAM,
EC_DIESEL,
EC_ELECTRIC,
EC_MONORAIL,
EC_MAGLEV,
};
struct RailVehicleInfo {
typedef struct RailVehicleInfo {
byte image_index;
RailVehicleTypes railveh_type;
byte flags; /* 1=multihead engine, 2=wagon */
byte base_cost;
RailTypeByte railtype;
uint16 max_speed;
uint16 power;
uint16 weight;
byte running_cost;
byte running_cost_base;
byte running_cost_class;
EngineClass engclass; ///< Class of engine for this vehicle
byte engclass; // 0: steam, 1: diesel, 2: electric
byte capacity;
CargoID cargo_type;
byte ai_rank;
byte ai_passenger_only; ///< Bit value to tell AI that this engine is for passenger use only
uint16 pow_wag_power;
byte pow_wag_weight;
byte visual_effect; // NOTE: this is not 100% implemented yet, at the moment it is only used as a 'fallback' value
// for when the 'powered wagon' callback fails. But it should really also determine what
// kind of visual effect to generate for a vehicle (default, steam, diesel, electric).
// Same goes for the callback result, which atm is only used to check if a wagon is powered.
byte shorten_factor; ///< length on main map for this type is 8 - shorten_factor
byte tractive_effort; ///< Tractive effort coefficient
byte user_def_data; ///< Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles
};
byte shorten_factor; // length on main map for this type is 8 - shorten_factor
byte user_def_data; ///! Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles
} RailVehicleInfo;
struct ShipVehicleInfo {
typedef struct ShipVehicleInfo {
byte image_index;
byte base_cost;
uint16 max_speed;
CargoID cargo_type;
uint16 capacity;
byte running_cost;
SoundFxByte sfx;
bool refittable;
};
byte sfx;
byte refittable;
} ShipVehicleInfo;
/* AircraftVehicleInfo subtypes, bitmask type.
* If bit 0 is 0 then it is a helicopter, otherwise it is a plane
* in which case bit 1 tells us whether it's a big(fast) plane or not */
// Aircraft subtypes
enum {
AIR_HELI = 0,
AIR_CTOL = 1, ///< Conventional Take Off and Landing, i.e. planes
AIR_CTOL = 1, // Conventional Take Off and Landing, i.e. planes
AIR_FAST = 2
};
struct AircraftVehicleInfo {
typedef struct AircraftVehicleInfo {
byte image_index;
byte base_cost;
byte running_cost;
byte subtype;
SoundFxByte sfx;
byte sfx;
byte acceleration;
uint16 max_speed;
byte max_speed;
byte mail_capacity;
uint16 passenger_capacity;
};
} AircraftVehicleInfo;
struct RoadVehicleInfo {
typedef struct RoadVehicleInfo {
byte image_index;
byte base_cost;
byte running_cost;
byte running_cost_class;
SoundFxByte sfx;
byte sfx;
byte max_speed;
byte capacity;
CargoID cargo_type;
};
} RoadVehicleInfo;
/** Information about a vehicle
* @see table/engines.h
*/
struct EngineInfo {
typedef struct EngineInfo {
Date base_intro;
byte unk2; ///< Carriages have the highest bit set in this one
Year lifelength;
Year base_life;
byte unk2; ///< flag for carriage(bit 7) and decay speed(bits0..6)
byte load_amount;
byte climates;
byte railtype:4;
byte climates:4;
uint32 refit_mask;
byte refit_cost;
byte misc_flags;
byte callbackmask;
int8 retire_early; ///< Number of years early to retire vehicle
StringID string_id; ///< Default name of engine
};
} EngineInfo;
struct Engine {
char *name; ///< Custom name of engine
typedef struct Engine {
Date intro_date;
Date age;
uint16 reliability;
@@ -125,52 +95,49 @@ struct Engine {
uint16 duration_phase_1, duration_phase_2, duration_phase_3;
byte lifelength;
byte flags;
uint8 preview_player_rank;
byte preview_player;
byte preview_wait;
byte railtype;
byte player_avail;
VehicleType type; ///< type, ie VEH_ROAD, VEH_TRAIN, etc.
};
byte type; // type, ie VEH_Road, VEH_Train, etc. Same as in vehicle.h
} Engine;
/**
* EngineInfo.misc_flags is a bitmask, with the following values
*/
enum {
EF_RAIL_TILTS = 0, ///< Rail vehicle tilts in curves
EF_ROAD_TRAM = 0, ///< Road vehicle is a tram/light rail vehicle
EF_RAIL_TILTS = 0, ///< Rail vehicle tilts in curves (unsupported)
EF_ROAD_TRAM = 0, ///< Road vehicle is a tram/light rail vehicle (unsup)
EF_USES_2CC = 1, ///< Vehicle uses two company colours
EF_RAIL_IS_MU = 2, ///< Rail vehicle is a multiple-unit (DMU/EMU)
};
/**
* Engine.flags is a bitmask, with the following values.
*/
enum {
ENGINE_AVAILABLE = 1, ///< This vehicle is available to everyone.
ENGINE_EXCLUSIVE_PREVIEW = 2, ///< This vehicle is in the exclusive preview stage, either being used or being offered to a player.
ENGINE_OFFER_WINDOW_OPEN = 4, ///< The exclusive offer window is currently open for a player.
RVI_MULTIHEAD = 1,
RVI_WAGON = 2,
};
enum {
NUM_VEHICLE_TYPES = 6
};
static const EngineID INVALID_ENGINE = 0xFFFF;
enum {
INVALID_ENGINE = 0xFFFF,
};
void AddTypeToEngines(void);
void StartupEngines(void);
void SetupEngines();
void StartupEngines();
void DrawTrainEngine(int x, int y, EngineID engine, uint32 image_ormod);
void DrawRoadVehEngine(int x, int y, EngineID engine, uint32 image_ormod);
void DrawShipEngine(int x, int y, EngineID engine, uint32 image_ormod);
void DrawAircraftEngine(int x, int y, EngineID engine, uint32 image_ormod);
void LoadCustomEngineNames(void);
void DeleteCustomEngineNames(void);
void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal);
void DrawRoadVehEngine(int x, int y, EngineID engine, SpriteID pal);
void DrawShipEngine(int x, int y, EngineID engine, SpriteID pal);
void DrawAircraftEngine(int x, int y, EngineID engine, SpriteID pal);
void LoadCustomEngineNames();
void DeleteCustomEngineNames();
bool IsEngineBuildable(EngineID engine, VehicleType type, PlayerID player);
CargoID GetEngineCargoType(EngineID engine);
bool IsEngineBuildable(EngineID engine, byte type, PlayerID player);
enum {
NUM_NORMAL_RAIL_ENGINES = 54,
@@ -185,29 +152,8 @@ enum {
SHIP_ENGINES_INDEX = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES,
ROAD_ENGINES_INDEX = NUM_TRAIN_ENGINES,
};
static inline EngineID GetFirstEngineOfType(VehicleType type)
{
const EngineID start[] = {0, ROAD_ENGINES_INDEX, SHIP_ENGINES_INDEX, AIRCRAFT_ENGINES_INDEX};
return start[type];
}
static inline EngineID GetLastEngineOfType(VehicleType type)
{
const EngineID end[] = {
NUM_TRAIN_ENGINES,
ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES,
SHIP_ENGINES_INDEX + NUM_SHIP_ENGINES,
AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES};
return end[type];
}
extern Engine _engines[TOTAL_NUM_ENGINES];
VARDEF Engine _engines[TOTAL_NUM_ENGINES];
#define FOR_ALL_ENGINES(e) for (e = _engines; e != endof(_engines); e++)
#define FOR_ALL_ENGINEIDS_OF_TYPE(e, type) for (e = GetFirstEngineOfType(type); e != GetLastEngineOfType(type); e++)
static inline Engine* GetEngine(EngineID i)
{
@@ -215,17 +161,20 @@ static inline Engine* GetEngine(EngineID i)
return &_engines[i];
}
VARDEF StringID _engine_name_strings[TOTAL_NUM_ENGINES];
static inline bool IsEngineIndex(uint index)
{
return index < TOTAL_NUM_ENGINES;
}
/* Access Vehicle Data */
extern const EngineInfo _orig_engine_info[TOTAL_NUM_ENGINES];
extern const RailVehicleInfo _orig_rail_vehicle_info[NUM_TRAIN_ENGINES];
extern const ShipVehicleInfo _orig_ship_vehicle_info[NUM_SHIP_ENGINES];
extern const AircraftVehicleInfo _orig_aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
extern const RoadVehicleInfo _orig_road_vehicle_info[NUM_ROAD_ENGINES];
//#include "table/engines.h"
extern const EngineInfo orig_engine_info[TOTAL_NUM_ENGINES];
extern const RailVehicleInfo orig_rail_vehicle_info[NUM_TRAIN_ENGINES];
extern const ShipVehicleInfo orig_ship_vehicle_info[NUM_SHIP_ENGINES];
extern const AircraftVehicleInfo orig_aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
extern const RoadVehicleInfo orig_road_vehicle_info[NUM_ROAD_ENGINES];
extern EngineInfo _engine_info[TOTAL_NUM_ENGINES];
extern RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
@@ -263,6 +212,88 @@ static inline const RoadVehicleInfo* RoadVehInfo(EngineID e)
return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
}
/************************************************************************
* Engine Replacement stuff
************************************************************************/
/**
* Struct to store engine replacements. DO NOT USE outside of engine.c. Is
* placed here so the only exception to this rule, the saveload code, can use
* it.
*/
struct EngineRenew {
EngineRenewID index;
EngineID from;
EngineID to;
struct EngineRenew *next;
};
typedef struct EngineRenew EngineRenew;
/**
* Memory pool for engine renew elements. DO NOT USE outside of engine.c. Is
* placed here so the only exception to this rule, the saveload code, can use
* it.
*/
DECLARE_OLD_POOL(EngineRenew, EngineRenew, 3, 8000)
/**
* Check if a EngineRenew really exists.
*/
static inline bool IsValidEngineRenew(const EngineRenew *er)
{
return er->from != INVALID_ENGINE;
}
static inline void DeleteEngineRenew(EngineRenew *er)
{
er->from = INVALID_ENGINE;
}
#define FOR_ALL_ENGINE_RENEWS_FROM(er, start) for (er = GetEngineRenew(start); er != NULL; er = (er->index + 1U < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1U) : NULL) if (er->from != INVALID_ENGINE) if (IsValidEngineRenew(er))
#define FOR_ALL_ENGINE_RENEWS(er) FOR_ALL_ENGINE_RENEWS_FROM(er, 0)
/**
* A list to group EngineRenew directives together (such as per-player).
*/
typedef EngineRenew* EngineRenewList;
/**
* Remove all engine replacement settings for the player.
* @param er The renewlist for a given player.
* @return The new renewlist for the player.
*/
void RemoveAllEngineReplacement(EngineRenewList* erl);
/**
* Retrieve the engine replacement in a given renewlist for an original engine type.
* @param erl The renewlist to search in.
* @param engine Engine type to be replaced.
* @return The engine type to replace with, or INVALID_ENGINE if no
* replacement is in the list.
*/
EngineID EngineReplacement(EngineRenewList erl, EngineID engine);
/**
* Add an engine replacement to the given renewlist.
* @param erl The renewlist to add to.
* @param old_engine The original engine type.
* @param new_engine The replacement engine type.
* @param flags The calling command flags.
* @return 0 on success, CMD_ERROR on failure.
*/
int32 AddEngineReplacement(EngineRenewList* erl, EngineID old_engine, EngineID new_engine, uint32 flags);
/**
* Remove an engine replacement from a given renewlist.
* @param erl The renewlist from which to remove the replacement
* @param engine The original engine type.
* @param flags The calling command flags.
* @return 0 on success, CMD_ERROR on failure.
*/
int32 RemoveEngineReplacement(EngineRenewList* erl, EngineID engine, uint32 flags);
/* Engine list manipulators - current implementation is only C wrapper of CBlobT<EngineID> class (helpers.cpp) */
void EngList_Create(EngineList *el); ///< Creates engine list
void EngList_Destroy(EngineList *el); ///< Deallocate and destroy engine list

View File

@@ -1,32 +1,31 @@
/* $Id$ */
/** @file engine_gui.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "table/sprites.h"
#include "functions.h"
#include "window.h"
#include "gui.h"
#include "window_gui.h"
#include "gfx_func.h"
#include "viewport.h"
#include "gfx.h"
#include "engine.h"
#include "command_func.h"
#include "economy_func.h"
#include "command.h"
#include "news.h"
#include "variables.h"
#include "newgrf_engine.h"
#include "strings_func.h"
#include "vehicle.h"
#include "table/strings.h"
#include "table/sprites.h"
static StringID GetEngineCategoryName(EngineID engine)
{
switch (GetEngine(engine)->type) {
default: NOT_REACHED();
case VEH_ROAD: return STR_8103_ROAD_VEHICLE;
case VEH_AIRCRAFT: return STR_8104_AIRCRAFT;
case VEH_SHIP: return STR_8105_SHIP;
case VEH_TRAIN:
switch (RailVehInfo(engine)->railtype) {
case VEH_Road: return STR_8103_ROAD_VEHICLE;
case VEH_Aircraft: return STR_8104_AIRCRAFT;
case VEH_Ship: return STR_8105_SHIP;
case VEH_Train:
switch (GetEngine(engine)->railtype) {
default: NOT_REACHED();
case RAILTYPE_RAIL: return STR_8102_RAILROAD_LOCOMOTIVE;
case RAILTYPE_ELECTRIC: return STR_8102_RAILROAD_LOCOMOTIVE;
@@ -45,13 +44,13 @@ static const Widget _engine_preview_widgets[] = {
{ WIDGETS_END},
};
typedef void DrawEngineProc(int x, int y, EngineID engine, SpriteID pal);
typedef void DrawEngineProc(int x, int y, EngineID engine, uint32 image_ormod);
typedef void DrawEngineInfoProc(EngineID, int x, int y, int maxw);
struct DrawEngineInfo {
typedef struct DrawEngineInfo {
DrawEngineProc *engine_proc;
DrawEngineInfoProc *info_proc;
};
} DrawEngineInfo;
static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw);
static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw);
@@ -78,10 +77,9 @@ static void EnginePreviewWndProc(Window *w, WindowEvent *e)
SetDParam(0, GetEngineCategoryName(engine));
DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
SetDParam(0, engine);
DrawStringCentered(w->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK);
DrawStringCentered(w->width >> 1, 80, GetCustomEngineName(engine), 0x10);
dei = &_draw_engine_list[GetEngine(engine)->type];
dei = &_draw_engine_list[GetEngine(engine)->type - VEH_Train];
width = w->width;
dei->engine_proc(width >> 1, 100, engine, 0);
@@ -103,8 +101,8 @@ static void EnginePreviewWndProc(Window *w, WindowEvent *e)
}
static const WindowDesc _engine_preview_desc = {
WDP_CENTER, WDP_CENTER, 300, 192, 300, 192,
WC_ENGINE_PREVIEW, WC_NONE,
WDP_CENTER, WDP_CENTER, 300, 192,
WC_ENGINE_PREVIEW,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_engine_preview_widgets,
EnginePreviewWndProc
@@ -119,14 +117,14 @@ void ShowEnginePreviewWindow(EngineID engine)
static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw)
{
const RailVehicleInfo *rvi = RailVehInfo(engine);
int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD) ? 1 : 0;
uint multihead = (rvi->flags & RVI_MULTIHEAD) ? 1 : 0;
SetDParam(0, (_price.build_railvehicle >> 3) * rvi->base_cost >> 5);
SetDParam(2, rvi->max_speed * 10 / 16);
SetDParam(2, rvi->max_speed);
SetDParam(3, rvi->power << multihead);
SetDParam(1, rvi->weight << multihead);
SetDParam(4, rvi->running_cost * GetPriceByIndex(rvi->running_cost_class) >> 8 << multihead);
SetDParam(4, rvi->running_cost_base * _price.running_rail[rvi->running_cost_class] >> 8 << multihead);
if (rvi->capacity != 0) {
SetDParam(5, rvi->cargo_type);
@@ -141,7 +139,7 @@ static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw)
{
const AircraftVehicleInfo *avi = AircraftVehInfo(engine);
SetDParam(0, (_price.aircraft_base >> 3) * avi->base_cost >> 5);
SetDParam(1, avi->max_speed * 10 / 16);
SetDParam(1, avi->max_speed * 128 / 10);
SetDParam(2, avi->passenger_capacity);
SetDParam(3, avi->mail_capacity);
SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
@@ -154,8 +152,8 @@ static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw)
const RoadVehicleInfo *rvi = RoadVehInfo(engine);
SetDParam(0, (_price.roadveh_base >> 3) * rvi->base_cost >> 5);
SetDParam(1, rvi->max_speed * 10 / 32);
SetDParam(2, rvi->running_cost * GetPriceByIndex(rvi->running_cost_class) >> 8);
SetDParam(1, rvi->max_speed / 2);
SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
SetDParam(3, rvi->cargo_type);
SetDParam(4, rvi->capacity);
@@ -166,38 +164,37 @@ static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw)
{
const ShipVehicleInfo *svi = ShipVehInfo(engine);
SetDParam(0, svi->base_cost * (_price.ship_base >> 3) >> 5);
SetDParam(1, svi->max_speed * 10 / 32);
SetDParam(1, svi->max_speed / 2);
SetDParam(2, svi->cargo_type);
SetDParam(3, svi->capacity);
SetDParam(4, svi->running_cost * _price.ship_running >> 8);
DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw);
}
StringID GetNewsStringNewVehicleAvail(const NewsItem *ni)
{
{
EngineID engine = ni->string_id;
SetDParam(0, GetEngineCategoryName(engine));
SetDParam(1, engine);
SetDParam(1, GetCustomEngineName(engine));
return STR_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE;
}
void DrawNewsNewVehicleAvail(Window *w)
{
DrawNewsBorder(w);
EngineID engine = WP(w, news_d).ni->string_id;
const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type];
const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type - VEH_Train];
DrawNewsBorder(w);
SetDParam(0, GetEngineCategoryName(engine));
DrawStringMultiCenter(w->width >> 1, 20, STR_NEW_VEHICLE_NOW_AVAILABLE, w->width - 2);
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
SetDParam(0, engine);
SetDParam(0, GetCustomEngineName(engine));
DrawStringMultiCenter(w->width >> 1, 57, STR_NEW_VEHICLE_TYPE, w->width - 2);
dei->engine_proc(w->width >> 1, 88, engine, 0);
GfxFillRect(25, 56, w->width - 56, 112, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE));
GfxFillRect(25, 56, w->width - 56, 112, 0x323 | USE_COLORTABLE);
dei->info_proc(engine, w->width >> 1, 129, w->width - 52);
}

151
fileio.c Normal file
View File

@@ -0,0 +1,151 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "fileio.h"
#include "functions.h"
#include "string.h"
#include "macros.h"
#include "variables.h"
/*************************************************/
/* FILE IO ROUTINES ******************************/
/*************************************************/
#define FIO_BUFFER_SIZE 512
typedef struct {
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
uint32 pos; ///< current (system) position in file
FILE *cur_fh; ///< current file handle
FILE *handles[64]; ///< array of file handles we can have open
byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
} Fio;
static Fio _fio;
// Get current position in file
uint32 FioGetPos(void)
{
return _fio.pos + (_fio.buffer - _fio.buffer_start) - FIO_BUFFER_SIZE;
}
void FioSeekTo(uint32 pos, int mode)
{
if (mode == SEEK_CUR) pos += FioGetPos();
_fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE;
_fio.pos = pos;
fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
}
// Seek to a file and a position
void FioSeekToFile(uint32 pos)
{
FILE *f = _fio.handles[pos >> 24];
assert(f != NULL);
_fio.cur_fh = f;
FioSeekTo(GB(pos, 0, 24), SEEK_SET);
}
byte FioReadByte(void)
{
if (_fio.buffer == _fio.buffer_end) {
_fio.pos += FIO_BUFFER_SIZE;
fread(_fio.buffer = _fio.buffer_start, 1, FIO_BUFFER_SIZE, _fio.cur_fh);
}
return *_fio.buffer++;
}
void FioSkipBytes(int n)
{
for (;;) {
int m = min(_fio.buffer_end - _fio.buffer, n);
_fio.buffer += m;
n -= m;
if (n == 0) break;
FioReadByte();
n--;
}
}
uint16 FioReadWord(void)
{
byte b = FioReadByte();
return (FioReadByte() << 8) | b;
}
uint32 FioReadDword(void)
{
uint b = FioReadWord();
return (FioReadWord() << 16) | b;
}
void FioReadBlock(void *ptr, uint size)
{
FioSeekTo(FioGetPos(), SEEK_SET);
_fio.pos += size;
fread(ptr, 1, size, _fio.cur_fh);
}
static inline void FioCloseFile(int slot)
{
if (_fio.handles[slot] != NULL) {
fclose(_fio.handles[slot]);
_fio.handles[slot] = NULL;
}
}
void FioCloseAll(void)
{
int i;
for (i = 0; i != lengthof(_fio.handles); i++)
FioCloseFile(i);
}
bool FioCheckFileExists(const char *filename)
{
FILE *f = FioFOpenFile(filename);
if (f == NULL) return false;
fclose(f);
return true;
}
FILE *FioFOpenFile(const char *filename)
{
FILE *f;
char buf[MAX_PATH];
snprintf(buf, lengthof(buf), "%s%s", _paths.data_dir, filename);
f = fopen(buf, "rb");
#if !defined(WIN32)
if (f == NULL) {
strtolower(buf + strlen(_paths.data_dir) - 1);
f = fopen(buf, "rb");
#if defined SECOND_DATA_DIR
// tries in the 2nd data directory
if (f == NULL) {
snprintf(buf, lengthof(buf), "%s%s", _paths.second_data_dir, filename);
strtolower(buf + strlen(_paths.second_data_dir) - 1);
f = fopen(buf, "rb");
}
#endif
}
#endif
return f;
}
void FioOpenFile(int slot, const char *filename)
{
FILE *f = FioFOpenFile(filename);
if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
FioCloseFile(slot); // if file was opened before, close it
_fio.handles[slot] = f;
FioSeekToFile(slot << 24);
}

19
fileio.h Normal file
View File

@@ -0,0 +1,19 @@
/* $Id$ */
#ifndef FILEIO_H
#define FILEIO_H
void FioSeekTo(uint32 pos, int mode);
void FioSeekToFile(uint32 pos);
uint32 FioGetPos(void);
byte FioReadByte(void);
uint16 FioReadWord(void);
uint32 FioReadDword(void);
void FioCloseAll(void);
FILE *FioFOpenFile(const char *filename);
void FioOpenFile(int slot, const char *filename);
void FioReadBlock(void *ptr, uint size);
void FioSkipBytes(int n);
bool FioCheckFileExists(const char *filename);
#endif /* FILEIO_H */

View File

@@ -1,45 +1,40 @@
/* $Id$ */
/** @file fios.cpp
/** @file fios.c
* This file contains functions for building file lists for the save/load dialogs.
*/
#include "stdafx.h"
#include "openttd.h"
#include "hal.h"
#include "string.h"
#include "variables.h"
#include "heightmap.h"
#include "fios.h"
#include "fileio.h"
#include "core/alloc_func.hpp"
#include "functions.h"
#include "string_func.h"
#include "heightmap.h"
#include "table/strings.h"
#include "fios.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
# include <tchar.h>
# include <io.h>
# define access _taccess
# define unlink _tunlink
#else
# include <unistd.h>
#endif /* WIN32 */
#include "table/strings.h"
/* Variables to display file lists */
int _fios_num;
static char *_fios_path;
static FiosItem *_fios_items;
SmallFiosItem _file_to_saveload;
static int _fios_count, _fios_alloc;
/* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */
extern bool FiosIsRoot(const char *path);
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
extern bool FiosIsHiddenFile(const struct dirent *ent);
extern void FiosGetDrives();
extern void FiosGetDrives(void);
extern bool FiosGetDiskFreeSpace(const char *path, uint32 *tot);
/* get the name of an oldstyle savegame */
@@ -49,11 +44,11 @@ extern void GetOldSaveGameName(char *title, const char *path, const char *file);
* Allocate a new FiosItem.
* @return A pointer to the newly allocated FiosItem.
*/
FiosItem *FiosAlloc()
FiosItem *FiosAlloc(void)
{
if (_fios_count == _fios_alloc) {
_fios_alloc += 256;
_fios_items = ReallocT(_fios_items, _fios_alloc);
_fios_items = realloc(_fios_items, _fios_alloc * sizeof(FiosItem));
}
return &_fios_items[_fios_count++];
}
@@ -61,7 +56,7 @@ FiosItem *FiosAlloc()
/**
* Compare two FiosItem's. Used with qsort when sorting the file list.
* @param a A pointer to the first FiosItem to compare.
* @param b A pointer to the second FiosItem to compare.
* @param a A pointer to the second FiosItem to compare.
* @return -1, 0 or 1, depending on how the two items should be sorted.
*/
int CDECL compare_FiosItems(const void *a, const void *b)
@@ -83,7 +78,7 @@ int CDECL compare_FiosItems(const void *a, const void *b)
/**
* Free the list of savegames
*/
void FiosFreeSavegameList()
void FiosFreeSavegameList(void)
{
free(_fios_items);
_fios_items = NULL;
@@ -112,20 +107,16 @@ char *FiosBrowseTo(const FiosItem *item)
char *path = _fios_path;
switch (item->type) {
#if defined(WINCE)
case FIOS_TYPE_DRIVE: sprintf(path, PATHSEP ""); break;
#elif defined(WIN32) || defined(__OS2__)
#if defined(WIN32) || defined(__OS2__)
case FIOS_TYPE_DRIVE: sprintf(path, "%c:" PATHSEP, item->title[0]); break;
#endif
case FIOS_TYPE_PARENT:
/* Check for possible NULL ptr (not required for UNIXes, but AmigaOS-alikes) */
s = strrchr(path, PATHSEPCHAR);
if (s != NULL && s != path) {
s[0] = '\0'; // Remove last path separator character, so we can go up one level.
if ((s = strrchr(path, PATHSEPCHAR)) != NULL) {
s[1] = '\0'; // go up a directory
if (!FiosIsRoot(path)) s[0] = '\0';
}
s = strrchr(path, PATHSEPCHAR);
if (s != NULL) s[1] = '\0'; // go up a directory
#if defined(__MORPHOS__) || defined(__AMIGAOS__)
/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
else if ((s = strrchr(path, ':')) != NULL) s[1] = '\0';
@@ -133,12 +124,14 @@ char *FiosBrowseTo(const FiosItem *item)
break;
case FIOS_TYPE_DIR:
if (!FiosIsRoot(path)) strcat(path, PATHSEP);
strcat(path, item->name);
strcat(path, PATHSEP);
break;
case FIOS_TYPE_DIRECT:
sprintf(path, "%s", item->name);
sprintf(path, "%s" PATHSEP, item->name);
s = strrchr(path, PATHSEPCHAR);
if (s != NULL && s[1] == '\0') s[0] = '\0'; // strip trailing slash
break;
case FIOS_TYPE_FILE:
@@ -149,7 +142,15 @@ char *FiosBrowseTo(const FiosItem *item)
case FIOS_TYPE_BMP:
{
static char str_buffr[512];
snprintf(str_buffr, lengthof(str_buffr), "%s%s", path, item->name);
#if defined(__MORPHOS__) || defined(__AMIGAOS__)
/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
if (FiosIsRoot(path)) {
snprintf(str_buffr, lengthof(str_buffr), "%s:%s", path, item->name);
} else // XXX - only next line!
#endif
snprintf(str_buffr, lengthof(str_buffr), "%s" PATHSEP "%s", path, item->name);
return str_buffr;
}
}
@@ -166,21 +167,8 @@ void FiosMakeSavegameName(char *buf, const char *name, size_t size)
/* Don't append the extension if it is already there */
period = strrchr(name, '.');
if (period != NULL && strcasecmp(period, extension) == 0) extension = "";
#if defined(__MORPHOS__) || defined(__AMIGAOS__)
if (_fios_path != NULL) {
unsigned char sepchar = _fios_path[(strlen(_fios_path) - 1)];
if (sepchar != ':' && sepchar != '/') {
snprintf(buf, size, "%s" PATHSEP "%s%s", _fios_path, name, extension);
} else {
snprintf(buf, size, "%s%s%s", _fios_path, name, extension);
}
} else {
snprintf(buf, size, "%s%s", name, extension);
}
#else
snprintf(buf, size, "%s" PATHSEP "%s%s", _fios_path, name, extension);
#endif
}
#if defined(WIN32)
@@ -197,22 +185,15 @@ bool FiosDelete(const char *name)
bool FileExists(const char *filename)
{
#if defined(WINCE)
/* There is always one platform that doesn't support basic commands... */
HANDLE hand = CreateFile(OTTD2FS(filename), 0, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hand == INVALID_HANDLE_VALUE) return 1;
CloseHandle(hand);
return 0;
#else
return access(OTTD2FS(filename), 0) == 0;
#endif
return access(filename, 0) == 0;
}
typedef byte fios_getlist_callback_proc(int mode, const char *filename, const char *ext, char *title);
/** Create a list of the files in a directory, according to some arbitrary rule.
* @param num Will be filled with the amount of items.
* @param mode The mode we are in. Some modes don't allow 'parent'.
* @param callback_proc The function that is called where you need to do the filtering.
* @param callback The function that is called where you need to do the filtering.
* @return Return the list of files. */
static FiosItem *FiosGetFileList(int mode, fios_getlist_callback_proc *callback_proc)
{
@@ -269,6 +250,7 @@ static FiosItem *FiosGetFileList(int mode, fios_getlist_callback_proc *callback_
while ((dirent = readdir(dir)) != NULL) {
char fios_title[64];
char *t;
byte type;
ttd_strlcpy(d_name, FS2OTTD(dirent->d_name), sizeof(d_name));
if (!FiosIsValidFile(_fios_path, dirent, &sb) || !(sb.st_mode & S_IFREG) || FiosIsHiddenFile(dirent)) continue;
@@ -277,7 +259,7 @@ static FiosItem *FiosGetFileList(int mode, fios_getlist_callback_proc *callback_
if ((t = strrchr(d_name, '.')) == NULL) continue;
fios_title[0] = '\0'; // reset the title;
byte type = callback_proc(mode, d_name, t, fios_title);
type = callback_proc(mode, d_name, t, fios_title);
if (type != FIOS_TYPE_INVALID) {
fios = FiosAlloc();
fios->mtime = sb.st_mtime;
@@ -344,8 +326,8 @@ FiosItem *FiosGetSavegameList(int mode)
static char *_fios_save_path = NULL;
if (_fios_save_path == NULL) {
_fios_save_path = MallocT<char>(MAX_PATH);
FioGetDirectory(_fios_save_path, MAX_PATH, SAVE_DIR);
_fios_save_path = malloc(MAX_PATH);
ttd_strlcpy(_fios_save_path, _paths.save_dir, MAX_PATH);
}
_fios_path = _fios_save_path;
@@ -391,10 +373,9 @@ FiosItem *FiosGetScenarioList(int mode)
{
static char *_fios_scn_path = NULL;
/* Copy the default path on first run or on 'New Game' */
if (_fios_scn_path == NULL) {
_fios_scn_path = MallocT<char>(MAX_PATH);
FioGetDirectory(_fios_scn_path, MAX_PATH, SCENARIO_DIR);
_fios_scn_path = malloc(MAX_PATH);
ttd_strlcpy(_fios_scn_path, _paths.scenario_dir, MAX_PATH);
}
_fios_path = _fios_scn_path;
@@ -418,14 +399,14 @@ static byte FiosGetHeightmapListCallback(int mode, const char *file, const char
return FIOS_TYPE_INVALID;
}
/* Get a list of Heightmaps */
// Get a list of Heightmaps
FiosItem *FiosGetHeightmapList(int mode)
{
static char *_fios_hmap_path = NULL;
if (_fios_hmap_path == NULL) {
_fios_hmap_path = MallocT<char>(MAX_PATH);
FioGetDirectory(_fios_hmap_path, MAX_PATH, HEIGHTMAP_DIR);
_fios_hmap_path = malloc(MAX_PATH);
strcpy(_fios_hmap_path, _paths.heightmap_dir);
}
_fios_path = _fios_hmap_path;

101
fios.h Normal file
View File

@@ -0,0 +1,101 @@
/* $Id$ */
#ifndef FIOS_H
#define FIOS_H
/* Deals with finding savegames */
typedef struct {
byte type;
uint64 mtime;
char title[64];
char name[256 - 12 - 64];
} FiosItem;
enum {
FIOS_TYPE_DRIVE = 0,
FIOS_TYPE_PARENT = 1,
FIOS_TYPE_DIR = 2,
FIOS_TYPE_FILE = 3,
FIOS_TYPE_OLDFILE = 4,
FIOS_TYPE_SCENARIO = 5,
FIOS_TYPE_OLD_SCENARIO = 6,
FIOS_TYPE_DIRECT = 7,
FIOS_TYPE_PNG = 8,
FIOS_TYPE_BMP = 9,
FIOS_TYPE_INVALID = 255,
};
/* Variables to display file lists */
extern FiosItem *_fios_list; // defined in misc_gui.c
extern int _fios_num; // defined in fios.c, read_only version of _fios_count
extern int _saveload_mode; // defined in misc_gui.c
// Get a list of savegames
FiosItem *FiosGetSavegameList(int mode);
// Get a list of scenarios
FiosItem *FiosGetScenarioList(int mode);
// Get a list of Heightmaps
FiosItem *FiosGetHeightmapList(int mode);
// Free the list of savegames
void FiosFreeSavegameList(void);
// Browse to. Returns a filename w/path if we reached a file.
char *FiosBrowseTo(const FiosItem *item);
// Return path, free space and stringID
StringID FiosGetDescText(const char **path, uint32 *total_free);
// Delete a name
bool FiosDelete(const char *name);
// Make a filename from a name
void FiosMakeSavegameName(char *buf, const char *name, size_t size);
// Allocate a new FiosItem
FiosItem *FiosAlloc(void);
int CDECL compare_FiosItems(const void *a, const void *b);
/* Implementation of opendir/readdir/closedir for Windows */
#if defined(WIN32)
#include <windows.h>
typedef struct DIR DIR;
typedef struct dirent { // XXX - only d_name implemented
TCHAR *d_name; /* name of found file */
/* little hack which will point to parent DIR struct which will
* save us a call to GetFileAttributes if we want information
* about the file (for example in function fio_bla */
DIR *dir;
} dirent;
struct DIR {
HANDLE hFind;
/* the dirent returned by readdir.
* note: having only one global instance is not possible because
* multiple independent opendir/readdir sequences must be supported. */
dirent ent;
WIN32_FIND_DATA fd;
/* since opendir calls FindFirstFile, we need a means of telling the
* first call to readdir that we already have a file.
* that's the case iff this is true */
bool at_first_entry;
};
DIR *opendir(const TCHAR *path);
struct dirent *readdir(DIR *d);
int closedir(DIR *d);
#else
/* Use system-supplied opendir/readdir/closedir functions */
# include <sys/types.h>
# include <dirent.h>
#endif /* defined(WIN32) */
/**
* A wrapper around opendir() which will convert the string from
* OPENTTD encoding to that of the filesystem. For all purposes this
* function behaves the same as the original opendir function
* @param path string to open directory of
* @return DIR pointer
*/
static inline DIR *ttd_opendir(const char *path)
{
return opendir(OTTD2FS(path));
}
#endif /* FIOS_H */

View File

@@ -1,22 +1,19 @@
/* $Id$ */
/** @file fontcache.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "functions.h"
#include "macros.h"
#include "debug.h"
#include "spritecache.h"
#include "fontcache.h"
#include "spriteloader/spriteloader.hpp"
#include "blitter/factory.hpp"
#include "gfx_func.h"
#include "core/alloc_func.hpp"
#include "core/math_func.hpp"
#include "table/sprites.h"
#include "table/control_codes.h"
#include "spritecache.h"
#include "gfx.h"
#include "string.h"
#include "fontcache.h"
#ifdef WITH_FREETYPE
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
@@ -72,7 +69,7 @@ static FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey);
if (ret != ERROR_SUCCESS) {
DEBUG(freetype, 0, "Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
DEBUG(freetype, 0) ("Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
return err;
}
@@ -80,7 +77,7 @@ static FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
* normal char to match the data returned by RegEnumValue,
* otherwise just use parameter */
#if defined(UNICODE)
font_namep = MallocT<TCHAR>(MAX_PATH);
font_namep = malloc(MAX_PATH * sizeof(TCHAR));
MB_TO_WIDE_BUFFER(font_name, font_namep, MAX_PATH * sizeof(TCHAR));
#else
font_namep = (char*)font_name; // only cast because in unicode pointer is not const
@@ -114,7 +111,7 @@ static FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
}
if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) {
DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory");
DEBUG(freetype, 0) ("SHGetFolderPath cannot return fonts directory");
goto folder_error;
}
@@ -237,14 +234,14 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t
{
FT_Error error;
if (StrEmpty(font_name)) return;
if (strlen(font_name) == 0) return;
error = FT_New_Face(_library, font_name, 0, face);
if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, face);
if (error == FT_Err_Ok) {
DEBUG(freetype, 2, "Requested '%s', using '%s %s'", font_name, (*face)->family_name, (*face)->style_name);
DEBUG(freetype, 2) ("[FreeType] Requested '%s', using '%s %s'", font_name, (*face)->family_name, (*face)->style_name);
/* Attempt to select the unicode character map */
error = FT_Select_Charmap(*face, ft_encoding_unicode);
@@ -278,10 +275,10 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t
}
void InitFreeType()
void InitFreeType(void)
{
if (StrEmpty(_freetype.small_font) && StrEmpty(_freetype.medium_font) && StrEmpty(_freetype.large_font)) {
DEBUG(freetype, 1, "No font faces specified, using sprite fonts instead");
if (strlen(_freetype.small_font) == 0 && strlen(_freetype.medium_font) == 0 && strlen(_freetype.large_font) == 0) {
DEBUG(freetype, 1) ("[FreeType] No font faces specified, using sprite fonts instead");
return;
}
@@ -290,7 +287,7 @@ void InitFreeType()
return;
}
DEBUG(freetype, 2, "Initialized");
DEBUG(freetype, 2) ("[FreeType] Initialized");
/* Load each font */
LoadFreeTypeFont(_freetype.small_font, &_face_small, "small");
@@ -315,10 +312,10 @@ static FT_Face GetFontFace(FontSize size)
}
struct GlyphEntry {
typedef struct GlyphEntry {
Sprite *sprite;
byte width;
};
} GlyphEntry;
/* The glyph cache. This is structured to reduce memory consumption.
@@ -347,40 +344,20 @@ static GlyphEntry *GetGlyphPtr(FontSize size, WChar key)
static void SetGlyphPtr(FontSize size, WChar key, const GlyphEntry *glyph)
{
if (_glyph_ptr[size] == NULL) {
DEBUG(freetype, 3, "Allocating root glyph cache for size %u", size);
_glyph_ptr[size] = CallocT<GlyphEntry*>(256);
DEBUG(freetype, 3) ("[FreeType] Allocating root glyph cache for size %u", size);
_glyph_ptr[size] = calloc(256, sizeof(**_glyph_ptr));
}
if (_glyph_ptr[size][GB(key, 8, 8)] == NULL) {
DEBUG(freetype, 3, "Allocating glyph cache for range 0x%02X00, size %u", GB(key, 8, 8), size);
_glyph_ptr[size][GB(key, 8, 8)] = CallocT<GlyphEntry>(256);
DEBUG(freetype, 3) ("[FreeType] Allocating glyph cache for range 0x%02X00, size %u", GB(key, 8, 8), size);
_glyph_ptr[size][GB(key, 8, 8)] = calloc(256, sizeof(***_glyph_ptr));
}
DEBUG(freetype, 4, "Set glyph for unicode character 0x%04X, size %u", key, size);
DEBUG(freetype, 4) ("[FreeType] Set glyph for unicode character 0x%04X, size %u", key, size);
_glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].sprite = glyph->sprite;
_glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].width = glyph->width;
}
void *AllocateFont(size_t size)
{
return MallocT<byte>(size);
}
/* Check if a glyph should be rendered with antialiasing */
static bool GetFontAAState(FontSize size)
{
/* AA is only supported for 32 bpp */
if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 32) return false;
switch (size) {
default: NOT_REACHED();
case FS_NORMAL: return _freetype.medium_aa;
case FS_SMALL: return _freetype.small_aa;
case FS_LARGE: return _freetype.large_aa;
}
}
const Sprite *GetGlyph(FontSize size, WChar key)
{
@@ -388,7 +365,7 @@ const Sprite *GetGlyph(FontSize size, WChar key)
FT_GlyphSlot slot;
GlyphEntry new_glyph;
GlyphEntry *glyph;
SpriteLoader::Sprite sprite;
Sprite *sprite;
int width;
int height;
int x;
@@ -410,31 +387,29 @@ const Sprite *GetGlyph(FontSize size, WChar key)
slot = face->glyph;
bool aa = GetFontAAState(size);
FT_Load_Char(face, key, FT_LOAD_DEFAULT);
FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
/* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */
width = max(1, slot->bitmap.width + (size == FS_NORMAL));
height = max(1, slot->bitmap.rows + (size == FS_NORMAL));
/* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
sprite.data = CallocT<SpriteLoader::CommonPixel>(width * height);
sprite.width = width;
sprite.height = height;
sprite.x_offs = slot->bitmap_left;
sprite = calloc(width * height + 8, 1);
sprite->info = 1;
sprite->width = width;
sprite->height = height;
sprite->x_offs = slot->bitmap_left;
// XXX 2 should be determined somehow... it's right for the normal face
y_adj = (size == FS_NORMAL) ? 2 : 0;
sprite.y_offs = GetCharacterHeight(size) - slot->bitmap_top - y_adj;
sprite->y_offs = GetCharacterHeight(size) - slot->bitmap_top - y_adj;
/* Draw shadow for medium size */
if (size == FS_NORMAL) {
for (y = 0; y < slot->bitmap.rows; y++) {
for (x = 0; x < slot->bitmap.width; x++) {
if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR;
sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
if (HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
sprite->data[1 + x + (1 + y) * sprite->width] = SHADOW_COLOUR;
}
}
}
@@ -442,20 +417,18 @@ const Sprite *GetGlyph(FontSize size, WChar key)
for (y = 0; y < slot->bitmap.rows; y++) {
for (x = 0; x < slot->bitmap.width; x++) {
if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
sprite.data[x + y * sprite.width].m = FACE_COLOUR;
sprite.data[x + y * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
if (HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
sprite->data[x + y * sprite->width] = FACE_COLOUR;
}
}
}
new_glyph.sprite = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, AllocateFont);
free(sprite.data);
new_glyph.sprite = sprite;
new_glyph.width = (slot->advance.x >> 6) + (size != FS_NORMAL);
SetGlyphPtr(size, key, &new_glyph);
return new_glyph.sprite;
return sprite;
}
@@ -510,46 +483,40 @@ SpriteID GetUnicodeGlyph(FontSize size, uint32 key)
void SetUnicodeGlyph(FontSize size, uint32 key, SpriteID sprite)
{
if (_unicode_glyph_map[size] == NULL) _unicode_glyph_map[size] = CallocT<SpriteID*>(256);
if (_unicode_glyph_map[size][GB(key, 8, 8)] == NULL) _unicode_glyph_map[size][GB(key, 8, 8)] = CallocT<SpriteID>(256);
if (_unicode_glyph_map[size] == NULL) _unicode_glyph_map[size] = calloc(256, sizeof(*_unicode_glyph_map[size]));
if (_unicode_glyph_map[size][GB(key, 8, 8)] == NULL) _unicode_glyph_map[size][GB(key, 8, 8)] = calloc(256, sizeof(**_unicode_glyph_map[size]));
_unicode_glyph_map[size][GB(key, 8, 8)][GB(key, 0, 8)] = sprite;
}
void InitializeUnicodeGlyphMap()
void InitializeUnicodeGlyphMap(void)
{
for (FontSize size = FS_NORMAL; size != FS_END; size++) {
FontSize size;
SpriteID base;
SpriteID sprite;
uint i;
for (size = FS_NORMAL; size != FS_END; size++) {
/* Clear out existing glyph map if it exists */
if (_unicode_glyph_map[size] != NULL) {
for (uint i = 0; i < 256; i++) {
for (i = 0; i < 256; i++) {
if (_unicode_glyph_map[size][i] != NULL) free(_unicode_glyph_map[size][i]);
}
free(_unicode_glyph_map[size]);
_unicode_glyph_map[size] = NULL;
}
SpriteID base = GetFontBase(size);
for (uint i = ASCII_LETTERSTART; i < 256; i++) {
SpriteID sprite = base + i - ASCII_LETTERSTART;
base = GetFontBase(size);
for (i = ASCII_LETTERSTART; i < 256; i++) {
sprite = base + i - ASCII_LETTERSTART;
if (!SpriteExists(sprite)) continue;
SetUnicodeGlyph(size, i, sprite);
SetUnicodeGlyph(size, i + SCC_SPRITE_START, sprite);
}
for (uint i = 0; i < lengthof(_default_unicode_map); i++) {
byte key = _default_unicode_map[i].key;
if (key == CLRA || key == CLRL) {
/* Clear the glyph. This happens if the glyph at this code point
* is non-standard and should be accessed by an SCC_xxx enum
* entry only. */
if (key == CLRA || size == FS_LARGE) {
SetUnicodeGlyph(size, _default_unicode_map[i].code, 0);
}
} else {
SpriteID sprite = base + key - ASCII_LETTERSTART;
SetUnicodeGlyph(size, _default_unicode_map[i].code, sprite);
}
for (i = 0; i < lengthof(_default_unicode_map); i++) {
sprite = base + _default_unicode_map[i].key - ASCII_LETTERSTART;
SetUnicodeGlyph(size, _default_unicode_map[i].code, sprite);
}
}
}

View File

@@ -3,8 +3,6 @@
#ifndef FONTCACHE_H
#define FONTCACHE_H
#include "gfx_type.h"
/** Get the SpriteID mapped to the given font size and key */
SpriteID GetUnicodeGlyph(FontSize size, uint32 key);
@@ -12,32 +10,29 @@ SpriteID GetUnicodeGlyph(FontSize size, uint32 key);
void SetUnicodeGlyph(FontSize size, uint32 key, SpriteID sprite);
/** Initialize the glyph map */
void InitializeUnicodeGlyphMap();
void InitializeUnicodeGlyphMap(void);
#ifdef WITH_FREETYPE
struct FreeTypeSettings {
typedef struct FreeTypeSettings {
char small_font[260];
char medium_font[260];
char large_font[260];
uint small_size;
uint medium_size;
uint large_size;
bool small_aa;
bool medium_aa;
bool large_aa;
};
} FreeTypeSettings;
extern FreeTypeSettings _freetype;
void InitFreeType();
void InitFreeType(void);
const struct Sprite *GetGlyph(FontSize size, uint32 key);
uint GetGlyphWidth(FontSize size, uint32 key);
#else
/* Stub for initializiation */
static inline void InitFreeType() {}
static inline void InitFreeType(void) {}
/** Get the Sprite for a glyph */
static inline const Sprite *GetGlyph(FontSize size, uint32 key)

227
functions.h Normal file
View File

@@ -0,0 +1,227 @@
/* $Id$ */
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
void DoClearSquare(TileIndex tile);
void RunTileLoop(void);
uint GetPartialZ(int x, int y, Slope corners);
uint GetSlopeZ(int x, int y);
uint32 GetTileTrackStatus(TileIndex tile, TransportType mode);
void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac);
void ChangeTileOwner(TileIndex tile, byte old_player, byte new_player);
void AnimateTile(TileIndex tile);
void ClickTile(TileIndex tile);
void GetTileDesc(TileIndex tile, TileDesc *td);
void UpdateTownMaxPass(Town *t);
bool IsValidTile(TileIndex tile);
static inline Point RemapCoords(int x, int y, int z)
{
#if !defined(NEW_ROTATION)
Point pt;
pt.x = (y - x) * 2;
pt.y = y + x - z;
#else
Point pt;
pt.x = (x + y) * 2;
pt.y = x - y - z;
#endif
return pt;
}
static inline Point RemapCoords2(int x, int y)
{
return RemapCoords(x, y, GetSlopeZ(x, y));
}
/* clear_land.c */
void DrawHillyLandTile(const TileInfo *ti);
void DrawClearLandTile(const TileInfo *ti, byte set);
void DrawClearLandFence(const TileInfo *ti);
void TileLoopClearHelper(TileIndex tile);
/* water_land.c */
void DrawShipDepotSprite(int x, int y, int image);
void TileLoop_Water(TileIndex tile);
/* players.c */
bool CheckPlayerHasMoney(int32 cost);
void SubtractMoneyFromPlayer(int32 cost);
void SubtractMoneyFromPlayerFract(PlayerID player, int32 cost);
bool CheckOwnership(Owner owner);
bool CheckTileOwnership(TileIndex tile);
StringID GetPlayerNameString(PlayerID player, uint index);
/* standard */
void ShowInfo(const char *str);
void CDECL ShowInfoF(const char *str, ...);
void NORETURN CDECL error(const char *str, ...);
/* openttd.c */
/**************
* Warning: DO NOT enable this unless you understand what it does
*
* If enabled, in a network game all randoms will be dumped to the
* stdout if the first client joins (or if you are a client). This
* is to help finding desync problems.
*
* Warning: DO NOT enable this unless you understand what it does
**************/
//#define RANDOM_DEBUG
// Enable this to produce higher quality random numbers.
// Doesn't work with network yet.
//#define MERSENNE_TWISTER
// Mersenne twister functions
void SeedMT(uint32 seed);
uint32 RandomMT(void);
#ifdef MERSENNE_TWISTER
static inline uint32 Random(void) { return RandomMT(); }
uint RandomRange(uint max);
#else
#ifdef RANDOM_DEBUG
#define Random() DoRandom(__LINE__, __FILE__)
uint32 DoRandom(int line, const char *file);
#define RandomRange(max) DoRandomRange(max, __LINE__, __FILE__)
uint DoRandomRange(uint max, int line, const char *file);
#else
uint32 Random(void);
uint RandomRange(uint max);
#endif
#endif // MERSENNE_TWISTER
static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
uint InteractiveRandomRange(uint max);
/* facedraw.c */
void DrawPlayerFace(uint32 face, int color, int x, int y);
/* texteff.c */
void MoveAllTextEffects(void);
void AddTextEffect(StringID msg, int x, int y, uint16 duration);
void InitTextEffects(void);
void DrawTextEffects(DrawPixelInfo *dpi);
void InitTextMessage(void);
void DrawTextMessage(void);
void CDECL AddTextMessage(uint16 color, uint8 duration, const char *message, ...);
void UndrawTextMessage(void);
bool AddAnimatedTile(TileIndex tile);
void DeleteAnimatedTile(TileIndex tile);
void AnimateAnimatedTiles(void);
void InitializeAnimatedTiles(void);
/* tunnelbridge_cmd.c */
bool CheckBridge_Stuff(byte bridge_type, uint bridge_len);
uint32 GetBridgeLength(TileIndex begin, TileIndex end);
int CalcBridgeLenCostFactor(int x);
/* misc_cmd.c */
void PlaceTreesRandomly(void);
void InitializeLandscapeVariables(bool only_constants);
/* misc.c */
bool IsCustomName(StringID id);
void DeleteName(StringID id);
char *GetName(char *buff, StringID id, const char* last);
// AllocateNameUnique also tests if the name used is not used anywere else
// and if it is used, it returns an error.
#define AllocateNameUnique(name, skip) RealAllocateName(name, skip, true)
#define AllocateName(name, skip) RealAllocateName(name, skip, false)
StringID RealAllocateName(const char *name, byte skip, bool check_double);
void ConvertNameArray(void);
/* misc functions */
void MarkTileDirty(int x, int y);
void MarkTileDirtyByTile(TileIndex tile);
void InvalidateWindow(WindowClass cls, WindowNumber number);
void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index);
void InvalidateWindowClasses(WindowClass cls);
void InvalidateWindowClassesData(WindowClass cls);
void DeleteWindowById(WindowClass cls, WindowNumber number);
void DeleteWindowByClass(WindowClass cls);
void SetObjectToPlaceWnd(CursorID icon, byte mode, Window *w);
void SetObjectToPlace(CursorID icon, byte mode, WindowClass window_class, WindowNumber window_num);
void ResetObjectToPlace(void);
bool ScrollWindowTo(int x, int y, Window * w);
bool ScrollMainWindowToTile(TileIndex tile);
bool ScrollMainWindowTo(int x, int y);
void DrawSprite(uint32 img, int x, int y);
bool EnsureNoVehicle(TileIndex tile);
bool EnsureNoVehicleOnGround(TileIndex tile);
void MarkAllViewportsDirty(int left, int top, int right, int bottom);
void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost);
void ShowFeederIncomeAnimation(int x, int y, int z, int32 cost);
void DrawFoundation(TileInfo *ti, uint f);
bool CheckIfAuthorityAllows(TileIndex tile);
Town *ClosestTownFromTile(TileIndex tile, uint threshold);
void ChangeTownRating(Town *t, int add, int max);
uint GetTownRadiusGroup(const Town* t, TileIndex tile);
int FindFirstBit(uint32 x);
void ShowHighscoreTable(int difficulty, int8 rank);
TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng);
void AfterLoadTown(void);
void UpdatePatches(void);
void AskExitGame(void);
void AskExitToGameMenu(void);
void RedrawAutosave(void);
StringID RemapOldStringID(StringID s);
void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str);
enum {
SLD_LOAD_GAME,
SLD_LOAD_SCENARIO,
SLD_SAVE_GAME,
SLD_SAVE_SCENARIO,
SLD_LOAD_HEIGHTMAP,
SLD_NEW_GAME,
};
void ShowSaveLoadDialog(int mode);
// callback from drivers that is called if the game size changes dynamically
void GameSizeChanged(void);
bool FileExists(const char *filename);
bool ReadLanguagePack(int index);
void InitializeLanguagePacks(void);
const char *GetCurrentLocale(const char *param);
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
void LoadFromConfig(void);
void SaveToConfig(void);
void CheckConfig(void);
int ttd_main(int argc, char* argv[]);
void HandleExitGameRequest(void);
void DeterminePaths(void);
void CSleep(int milliseconds);
#endif /* FUNCTIONS_H */

View File

@@ -1,45 +1,37 @@
/* $Id$ */
/** @file genworld.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "landscape.h"
#include "player_func.h"
#include "functions.h"
#include "player.h"
#include "table/sprites.h"
#include "variables.h"
#include "thread.h"
#include "command_func.h"
#include "genworld.h"
#include "gfx.h"
#include "gfxinit.h"
#include "window_func.h"
#include "network/network.h"
#include "gui.h"
#include "network.h"
#include "debug.h"
#include "settings_func.h"
#include "settings.h"
#include "heightmap.h"
#include "viewport_func.h"
#include "gfx_func.h"
#include "map_func.h"
#include "date_func.h"
#include "core/random_func.hpp"
#include "engine.h"
#include "settings_type.h"
#include "newgrf_storage.h"
#include "water.h"
#include "date.h"
#include "table/sprites.h"
void GenerateLandscape(byte mode);
void GenerateClearTile(void);
void GenerateIndustries(void);
void GenerateUnmovables(void);
bool GenerateTowns(void);
void GenerateTrees(void);
void GenerateClearTile();
void GenerateIndustries();
void GenerateUnmovables();
bool GenerateTowns();
void GenerateTrees();
void StartupEconomy();
void StartupPlayers();
void StartupDisasters();
void StartupEconomy(void);
void StartupPlayers(void);
void StartupDisasters(void);
void InitializeGame(int mode, uint size_x, uint size_y);
void ConvertGroundTilesIntoWaterTiles(void);
/* Please only use this variable in genworld.h and genworld.c and
* nowhere else. For speed improvements we need it to be global, but
* in no way the meaning of it is to use it anywhere else besides
@@ -64,7 +56,7 @@ void SetGeneratingWorldPaintStatus(bool status)
* writing in a thread, it can cause damaged data (reading and writing the
* same tile at the same time).
*/
bool IsGeneratingWorldReadyForPaint()
bool IsGeneratingWorldReadyForPaint(void)
{
/* If we are in quit_thread mode, ignore this and always return false. This
* forces the screen to not be drawn, and the GUI not to wait for a draw. */
@@ -76,7 +68,7 @@ bool IsGeneratingWorldReadyForPaint()
/**
* Tells if the world generation is done in a thread or not.
*/
bool IsGenerateWorldThreaded()
bool IsGenerateWorldThreaded(void)
{
return _gw.threaded && !_gw.quit_thread;
}
@@ -87,18 +79,18 @@ bool IsGenerateWorldThreaded()
static void *_GenerateWorld(void *arg)
{
_generating_world = true;
if (_network_dedicated) DEBUG(net, 0, "Generating map, please wait...");
if (_network_dedicated) DEBUG(net, 0)("Generating map, please wait...");
/* Set the Random() seed to generation_seed so we produce the same map with the same seed */
if (_patches.generation_seed == GENERATE_NEW_SEED) _patches.generation_seed = _patches_newgame.generation_seed = InteractiveRandom();
_random.SetSeed(_patches.generation_seed);
_random_seeds[0][0] = _random_seeds[0][1] = _patches.generation_seed;
SetGeneratingWorldProgress(GWP_MAP_INIT, 2);
SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
IncreaseGeneratingWorldProgress(GWP_MAP_INIT);
/* Must start economy early because of the costs. */
// Must start economy early because of the costs.
StartupEconomy();
/* Don't generate landscape items when in the scenario editor. */
// Don't generate landscape items when in the scenario editor.
if (_gw.mode == GW_EMPTY) {
SetGeneratingWorldProgress(GWP_UNMOVABLE, 1);
@@ -111,7 +103,7 @@ static void *_GenerateWorld(void *arg)
GenerateLandscape(_gw.mode);
GenerateClearTile();
/* only generate towns, tree and industries in newgame mode. */
// only generate towns, tree and industries in newgame mode.
if (_game_mode != GM_EDITOR) {
GenerateTowns();
GenerateIndustries();
@@ -120,9 +112,7 @@ static void *_GenerateWorld(void *arg)
}
}
ClearStorageChanges(true);
/* These are probably pointless when inside the scenario editor. */
// These are probably pointless when inside the scenario editor.
SetGeneratingWorldProgress(GWP_GAME_INIT, 3);
StartupPlayers();
IncreaseGeneratingWorldProgress(GWP_GAME_INIT);
@@ -131,7 +121,7 @@ static void *_GenerateWorld(void *arg)
StartupDisasters();
_generating_world = false;
/* No need to run the tile loop in the scenario editor. */
// No need to run the tile loop in the scenario editor.
if (_gw.mode != GW_EMPTY) {
uint i;
@@ -150,7 +140,7 @@ static void *_GenerateWorld(void *arg)
if (_gw.proc != NULL) _gw.proc();
IncreaseGeneratingWorldProgress(GWP_GAME_START);
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
/* Show all vital windows again, because we have hidden them */
if (_gw.threaded && _game_mode != GM_MENU) ShowVitalWindows();
_gw.active = false;
@@ -161,9 +151,7 @@ static void *_GenerateWorld(void *arg)
DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
MarkWholeScreenDirty();
if (_network_dedicated) DEBUG(net, 0, "Map generated, starting game");
if (_patches.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
if (_network_dedicated) DEBUG(net, 0)("Map generated, starting game");
return NULL;
}
@@ -190,11 +178,11 @@ void GenerateWorldSetAbortCallback(gw_abort_proc *proc)
* This will wait for the thread to finish up his work. It will not continue
* till the work is done.
*/
void WaitTillGeneratedWorld()
void WaitTillGeneratedWorld(void)
{
if (_gw.thread == NULL) return;
_gw.quit_thread = true;
OTTDJoinThread((OTTDThread*)_gw.thread);
OTTDJoinThread(_gw.thread);
_gw.thread = NULL;
_gw.threaded = false;
}
@@ -202,7 +190,7 @@ void WaitTillGeneratedWorld()
/**
* Initializes the abortion process
*/
void AbortGeneratingWorld()
void AbortGeneratingWorld(void)
{
_gw.abort = true;
}
@@ -210,7 +198,7 @@ void AbortGeneratingWorld()
/**
* Is the generation being aborted?
*/
bool IsGeneratingWorldAborted()
bool IsGeneratingWorldAborted(void)
{
return _gw.abort;
}
@@ -218,14 +206,14 @@ bool IsGeneratingWorldAborted()
/**
* Really handle the abortion, i.e. clean up some of the mess
*/
void HandleGeneratingWorldAbortion()
void HandleGeneratingWorldAbortion(void)
{
/* Clean up - in SE create an empty map, otherwise, go to intro menu */
_switch_mode = (_game_mode == GM_EDITOR) ? SM_EDITOR : SM_MENU;
if (_gw.abortp != NULL) _gw.abortp();
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
/* Show all vital windows again, because we have hidden them */
if (_gw.threaded && _game_mode != GM_MENU) ShowVitalWindows();
_gw.active = false;
@@ -242,7 +230,7 @@ void HandleGeneratingWorldAbortion()
/**
* Generate a world.
* @param mode The mode of world generation (see GenerateWorldModes).
* @param mode The mode of world generation (@see GenerateWorldModes).
* @param size_x The X-size of the map.
* @param size_y The Y-size of the map.
*/
@@ -283,7 +271,7 @@ void GenerateWorld(int mode, uint size_x, uint size_y)
if (_network_dedicated ||
(_gw.thread = OTTDCreateThread(&_GenerateWorld, NULL)) == NULL) {
DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
DEBUG(misc, 1) ("[Sl] Cannot create savegame thread, reverting to single-threaded mode...");
_gw.threaded = false;
_GenerateWorld(NULL);
return;
@@ -299,6 +287,6 @@ void GenerateWorld(int mode, uint size_x, uint size_y)
/* Centre the view on the map */
if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) {
ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2), true);
ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2));
}
}

94
genworld.h Normal file
View File

@@ -0,0 +1,94 @@
/* $Id$ */
#ifndef GENWORLD_H
#define GENWORLD_H
/* If OTTDThread isn't defined, define it to a void, but make sure to undefine
* it after this include. This makes including genworld.h easier, as you
* don't need to include thread.h before it, while it stays possible to
* include it after it, and still work.
*/
#ifndef OTTDThread
#define TEMPORARY_OTTDTHREAD_DEFINITION
#define OTTDThread void
#endif
/*
* Order of these enums has to be the same as in lang/english.txt
* Otherwise you will get inconsistent behaviour.
*/
enum {
LG_ORIGINAL = 0, //! The original landscape generator
LG_TERRAGENESIS = 1, //! TerraGenesis Perlin landscape generator
GENERATE_NEW_SEED = (uint)-1, //! Create a new random seed
};
typedef void gw_done_proc(void);
typedef void gw_abort_proc(void);
typedef struct gw_info {
bool active; //! Is generating world active
bool abort; //! Whether to abort the thread ASAP
bool wait_for_draw; //! Are we waiting on a draw event
bool quit_thread; //! Do we want to quit the active thread
bool threaded; //! Whether we run _GenerateWorld threaded
int mode; //! What mode are we making a world in
byte lp; //! The local_player before generating
uint size_x; //! X-size of the map
uint size_y; //! Y-size of the map
gw_done_proc *proc; //! Proc that is called when done (can be NULL)
gw_abort_proc *abortp; //! Proc that is called when aborting (can be NULL)
OTTDThread *thread; //! The thread we are in (can be NULL)
} gw_info;
#ifdef TEMPORARY_OTTDTHREAD_DEFINITION
#undef OTTDThread
#undef TEMPORARY_OTTDTHREAD_DEFINITION
#endif
typedef enum gwp_classes {
GWP_MAP_INIT, /* Initialize/allocate the map, start economy */
GWP_LANDSCAPE, /* Create the landscape */
GWP_ROUGH_ROCKY, /* Make rough and rocky areas */
GWP_TOWN, /* Generate towns */
GWP_INDUSTRY, /* Generate industries */
GWP_UNMOVABLE, /* Generate unmovables (radio tower, light houses) */
GWP_TREE, /* Generate trees */
GWP_GAME_INIT, /* Initialize the game */
GWP_RUNTILELOOP, /* Runs the tile loop 1280 times to make snow etc */
GWP_GAME_START, /* Really prepare to start the game */
GWP_CLASS_COUNT
} gwp_class;
/**
* Check if we are currently in the process of generating a world.
*/
static inline bool IsGeneratingWorld(void)
{
extern gw_info _gw;
return _gw.active;
}
/* genworld.c */
void SetGeneratingWorldPaintStatus(bool status);
bool IsGeneratingWorldReadyForPaint(void);
bool IsGenerateWorldThreaded(void);
void GenerateWorldSetCallback(gw_done_proc *proc);
void GenerateWorldSetAbortCallback(gw_abort_proc *proc);
void WaitTillGeneratedWorld(void);
void GenerateWorld(int mode, uint size_x, uint size_y);
void AbortGeneratingWorld(void);
bool IsGeneratingWorldAborted(void);
void HandleGeneratingWorldAbortion(void);
/* genworld_gui.c */
void SetGeneratingWorldProgress(gwp_class class, uint total);
void IncreaseGeneratingWorldProgress(gwp_class class);
void PrepareGenerateWorldProgress(void);
void ShowGenerateWorldProgress(void);
void StartNewGameWithoutGUI(uint seed);
void ShowCreateScenario(void);
#endif /* GENWORLD_H */

893
genworld_gui.c Normal file
View File

@@ -0,0 +1,893 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "heightmap.h"
#include "functions.h"
#include "table/strings.h"
#include "table/sprites.h"
#include "window.h"
#include "gui.h"
#include "gfx.h"
#include "strings.h"
#include "gfxinit.h"
#include "player.h"
#include "command.h"
#include "sound.h"
#include "variables.h"
#include "string.h"
#include "settings.h"
#include "debug.h"
#include "genworld.h"
#include "network.h"
#include "thread.h"
#include "date.h"
#include "newgrf_config.h"
enum {
START_DATE_QUERY,
SNOW_LINE_QUERY,
FLAT_WORLD_HEIGHT_QUERY,
LEN_RND_SEED = 11,
SEED_EDIT = 15,
};
/**
* In what 'mode' the GenerateLandscapeWindowProc is.
*/
typedef enum glwp_modes {
GLWP_GENERATE,
GLWP_HEIGHTMAP,
GLWP_SCENARIO,
GLWP_END
} glwp_modes;
static uint _heightmap_x = 0;
static uint _heightmap_y = 0;
static StringID _heightmap_str = STR_NULL;
static bool _goto_editor = false;
extern void SwitchMode(int new_mode);
static inline void SetNewLandscapeType(byte landscape)
{
_opt_newgame.landscape = landscape;
InvalidateWindowClasses(WC_SELECT_GAME);
InvalidateWindowClasses(WC_GENERATE_LANDSCAPE);
}
// no longer static to allow calling from outside module
const Widget _generate_landscape_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 13, 11, 337, 0, 13, STR_WORLD_GENERATION_CAPTION, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 13, 0, 337, 14, 267, 0x0, STR_NULL},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 10, 86, 24, 78, SPR_SELECT_TEMPERATE, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 90, 166, 24, 78, SPR_SELECT_SUB_ARCTIC, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246, 24, 78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326, 24, 78, SPR_SELECT_TOYLAND, STR_0311_SELECT_TOYLAND_LANDSCAPE},
{ WWT_PANEL, RESIZE_NONE, 12, 114, 149, 90, 101, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161, 90, 101, STR_0225, STR_NULL}, // Mapsize X
{ WWT_PANEL, RESIZE_NONE, 12, 180, 215, 90, 101, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227, 90, 101, STR_0225, STR_NULL}, // Mapsize Y
{ WWT_PANEL, RESIZE_NONE, 12, 114, 163, 112, 123, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 112, 123, STR_0225, STR_NULL}, // Number of towns
{ WWT_PANEL, RESIZE_NONE, 12, 114, 163, 130, 141, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 130, 141, STR_0225, STR_NULL}, // Number of industries
{ WWT_PANEL, RESIZE_NONE, 15, 114, 207, 152, 163, 0x0, STR_RANDOM_SEED_HELP}, // Edit box for seed
{ WWT_TEXTBTN, RESIZE_NONE, 12, 216, 326, 152, 163, STR_RANDOM, STR_RANDOM_HELP},
{ WWT_TEXTBTN, RESIZE_NONE, 6, 243, 326, 228, 257, STR_GENERATE, STR_NULL}, // Generate button
{ WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 112, 123, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE},
{ WWT_PANEL, RESIZE_NONE, 12, 228, 314, 112, 123, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 112, 123, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE},
{ WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 130, 141, SPR_ARROW_DOWN, STR_SNOW_LINE_DOWN},
{ WWT_PANEL, RESIZE_NONE, 12, 294, 314, 130, 141, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 130, 141, SPR_ARROW_UP, STR_SNOW_LINE_UP},
{ WWT_PANEL, RESIZE_NONE, 12, 114, 219, 192, 203, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 192, 203, STR_0225, STR_NULL}, // Tree placer
{ WWT_PANEL, RESIZE_NONE, 12, 114, 219, 174, 185, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 174, 185, STR_0225, STR_NULL}, // Landscape generator
{ WWT_PANEL, RESIZE_NONE, 12, 114, 219, 210, 221, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 210, 221, STR_0225, STR_NULL}, // Terrain type
{ WWT_PANEL, RESIZE_NONE, 12, 113, 219, 228, 239, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 228, 239, STR_0225, STR_NULL}, // Water quantity
{ WWT_PANEL, RESIZE_NONE, 12, 113, 219, 246, 257, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 246, 257, STR_0225, STR_NULL}, // Map smoothness
{ WIDGETS_END},
};
const Widget _heightmap_load_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 13, 11, 337, 0, 13, STR_WORLD_GENERATION_CAPTION, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 13, 0, 337, 14, 235, 0x0, STR_NULL},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 10, 86, 24, 78, SPR_SELECT_TEMPERATE, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 90, 166, 24, 78, SPR_SELECT_SUB_ARCTIC, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246, 24, 78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326, 24, 78, SPR_SELECT_TOYLAND, STR_0311_SELECT_TOYLAND_LANDSCAPE},
{ WWT_PANEL, RESIZE_NONE, 12, 114, 149, 112, 123, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161, 112, 123, STR_0225, STR_NULL}, // Mapsize X
{ WWT_PANEL, RESIZE_NONE, 12, 180, 215, 112, 123, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227, 112, 123, STR_0225, STR_NULL}, // Mapsize Y
{ WWT_PANEL, RESIZE_NONE, 12, 114, 163, 134, 145, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 134, 145, STR_0225, STR_NULL}, // Number of towns
{ WWT_PANEL, RESIZE_NONE, 12, 114, 163, 152, 163, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 152, 163, STR_0225, STR_NULL}, // Number of industries
{ WWT_PANEL, RESIZE_NONE, 15, 114, 194, 174, 185, 0x0, STR_RANDOM_SEED_HELP}, // Edit box for seed
{ WWT_TEXTBTN, RESIZE_NONE, 12, 203, 285, 174, 185, STR_RANDOM, STR_RANDOM_HELP},
{ WWT_TEXTBTN, RESIZE_NONE, 6, 243, 326, 196, 225, STR_GENERATE, STR_NULL}, // Generate button
{ WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 134, 145, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE},
{ WWT_PANEL, RESIZE_NONE, 12, 228, 314, 134, 145, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 134, 145, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE},
{ WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 152, 163, SPR_ARROW_DOWN, STR_SNOW_LINE_DOWN},
{ WWT_PANEL, RESIZE_NONE, 12, 294, 314, 152, 163, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 152, 163, SPR_ARROW_UP, STR_SNOW_LINE_UP},
{ WWT_PANEL, RESIZE_NONE, 12, 114, 219, 196, 207, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 196, 207, STR_0225, STR_NULL}, // Tree placer
{ WWT_PANEL, RESIZE_NONE, 12, 114, 219, 214, 225, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 220, 231, 214, 225, STR_0225, STR_NULL}, // Heightmap rotation
{ WIDGETS_END},
};
static void StartGeneratingLandscape(glwp_modes mode)
{
/* If we want to go to the editor, and aren't yet, we need to delay
* it as long as possible, else it gives nasty side-effects (aborting
* results in ending up in the SE, which you don't want. Therefor we
* use this switch to do it at the very end.
*/
if (_goto_editor) _game_mode = GM_EDITOR;
DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
DeleteWindowByClass(WC_INDUSTRY_VIEW);
DeleteWindowByClass(WC_TOWN_VIEW);
DeleteWindowByClass(WC_LAND_INFO);
/* Copy all XXX_newgame to XXX */
UpdatePatches();
_opt_ptr = &_opt;
*_opt_ptr = _opt_newgame;
ResetGRFConfig(true);
SndPlayFx(SND_15_BEEP);
switch (mode) {
case GLWP_GENERATE: _switch_mode = (_game_mode == GM_EDITOR) ? SM_GENRANDLAND : SM_NEWGAME; break;
case GLWP_HEIGHTMAP: _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_HEIGHTMAP : SM_START_HEIGHTMAP; break;
case GLWP_SCENARIO: _switch_mode = SM_EDITOR; break;
default: NOT_REACHED(); return;
}
}
static void HeightmapScaledTooMuchCallback(bool ok_clicked)
{
if (ok_clicked) {
Window *w;
glwp_modes mode = 0;
for (mode = 0; mode < GLWP_END; mode++) {
w = FindWindowById(WC_GENERATE_LANDSCAPE, mode);
if (w != NULL) StartGeneratingLandscape(mode);
}
}
}
void GenerateLandscapeWndProc(Window *w, WindowEvent *e)
{
static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
static const StringID elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
static const StringID sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
static const StringID smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
static const StringID tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
static const StringID rotation[] = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
static const StringID landscape[] = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
static const StringID num_towns[] = {STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
static const StringID num_inds[] = {STR_26816_NONE, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
/* Data used for the generate seed edit box */
static querystr_d _genseed_query;
static char _genseed_buffer[LEN_RND_SEED];
uint mode = w->window_number;
uint y;
switch (e->event) {
case WE_CREATE:
LowerWindowWidget(w, _opt_newgame.landscape + 3);
snprintf(_genseed_buffer, sizeof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
InitializeTextBuffer(&_genseed_query.text, _genseed_buffer, lengthof(_genseed_buffer), 120);
_genseed_query.caption = STR_NULL;
_genseed_query.afilter = CS_NUMERAL;
break;
case WE_PAINT:
/* You can't select smoothness if not terragenesis */
if (mode == GLWP_GENERATE) {
SetWindowWidgetDisabledState(w, 32, _patches_newgame.land_generator == 0);
SetWindowWidgetDisabledState(w, 33, _patches_newgame.land_generator == 0);
}
/* Disable snowline if not hilly */
SetWindowWidgetDisabledState(w, 22, _opt_newgame.landscape != LT_HILLY);
/* Disable town and industry in SE */
SetWindowWidgetDisabledState(w, 11, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 12, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 13, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 14, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 24, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 25, _game_mode == GM_EDITOR);
SetWindowWidgetDisabledState(w, 18, _patches_newgame.starting_year <= MIN_YEAR);
SetWindowWidgetDisabledState(w, 20, _patches_newgame.starting_year >= MAX_YEAR);
SetWindowWidgetDisabledState(w, 21, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_HILLY);
SetWindowWidgetDisabledState(w, 23, _patches_newgame.snow_line_height >= 13 || _opt_newgame.landscape != LT_HILLY);
SetWindowWidgetLoweredState(w, 3, _opt_newgame.landscape == LT_NORMAL);
SetWindowWidgetLoweredState(w, 4, _opt_newgame.landscape == LT_HILLY);
SetWindowWidgetLoweredState(w, 5, _opt_newgame.landscape == LT_DESERT);
SetWindowWidgetLoweredState(w, 6, _opt_newgame.landscape == LT_CANDY);
DrawWindowWidgets(w);
y = (mode == GLWP_HEIGHTMAP) ? 22 : 0;
DrawString( 12, 91 + y, STR_MAPSIZE, 0);
DrawString(119, 91 + y, mapsizes[_patches_newgame.map_x - 6], 0x10);
DrawString(168, 91 + y, STR_BY, 0);
DrawString(182, 91 + y, mapsizes[_patches_newgame.map_y - 6], 0x10);
DrawString( 12, 113 + y, STR_NUMBER_OF_TOWNS, 0);
DrawString( 12, 131 + y, STR_NUMBER_OF_INDUSTRIES, 0);
if (_game_mode == GM_EDITOR) {
DrawString(118, 113 + y, STR_6836_OFF, 0x10);
DrawString(118, 131 + y, STR_6836_OFF, 0x10);
} else {
DrawString(118, 113 + y, num_towns[_opt_newgame.diff.number_towns], 0x10);
DrawString(118, 131 + y, num_inds[_opt_newgame.diff.number_industries], 0x10);
}
DrawString( 12, 153 + y, STR_RANDOM_SEED, 0);
DrawEditBox(w, &_genseed_query, SEED_EDIT);
DrawString(182, 113 + y, STR_DATE, 0);
SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
DrawStringCentered(271, 113 + y, STR_GENERATE_DATE, 0);
DrawString(182, 131 + y, STR_SNOW_LINE_HEIGHT, 0);
SetDParam(0, _patches_newgame.snow_line_height);
DrawStringCentered(303, 131 + y, STR_SNOW_LINE_HEIGHT_NUM, 0x10);
if (mode == GLWP_GENERATE) {
DrawString( 12, 175, STR_LAND_GENERATOR, 0);
DrawString(118, 175, landscape[_patches_newgame.land_generator], 0x10);
DrawString( 12, 193, STR_TREE_PLACER, 0);
DrawString(118, 193, tree_placer[_patches_newgame.tree_placer], 0x10);
DrawString( 12, 211, STR_TERRAIN_TYPE, 0);
DrawString(118, 211, elevations[_opt_newgame.diff.terrain_type], 0x10);
DrawString( 12, 229, STR_QUANTITY_OF_SEA_LAKES, 0);
DrawString(118, 229, sea_lakes[_opt_newgame.diff.quantity_sea_lakes], 0x10);
DrawString( 12, 247, STR_SMOOTHNESS, 0);
DrawString(118, 247, smoothness[_patches_newgame.tgen_smoothness], 0x10);
} else {
char buffer[512];
if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
SetDParam(0, _heightmap_y);
SetDParam(1, _heightmap_x);
} else {
SetDParam(0, _heightmap_x);
SetDParam(1, _heightmap_y);
}
GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, 0x10);
DrawString( 12, 91, STR_HEIGHTMAP_NAME, 0x10);
SetDParam(0, _heightmap_str);
DrawStringTruncated(114, 91, STR_ORANGE, 0x10, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
DrawString( 12, 197, STR_TREE_PLACER, 0);
DrawString(118, 197, tree_placer[_patches_newgame.tree_placer], 0x10);
DrawString( 12, 215, STR_HEIGHTMAP_ROTATION, 0);
DrawString(118, 215, rotation[_patches_newgame.heightmap_rotation], 0x10);
}
break;
case WE_CLICK:
switch (e->we.click.widget) {
case 0: DeleteWindow(w); break;
case 3: case 4: case 5: case 6:
RaiseWindowWidget(w, _opt_newgame.landscape + 3);
SetNewLandscapeType(e->we.click.widget - 3);
break;
case 7: case 8: // Mapsize X
ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
break;
case 9: case 10: // Mapsize Y
ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, 10, 0, 0);
break;
case 11: case 12: // Number of towns
ShowDropDownMenu(w, num_towns, _opt_newgame.diff.number_towns, 12, 0, 0);
break;
case 13: case 14: // Number of industries
ShowDropDownMenu(w, num_inds, _opt_newgame.diff.number_industries, 14, 0, 0);
break;
case 16: // Random seed
_patches_newgame.generation_seed = InteractiveRandom();
snprintf(_genseed_buffer, lengthof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
UpdateTextBufferSize(&_genseed_query.text);
SetWindowDirty(w);
break;
case 17: // Generate
if (mode == GLWP_HEIGHTMAP && (
_heightmap_x * 2 < (1U << _patches_newgame.map_x) || _heightmap_x / 2 > (1U << _patches_newgame.map_x) ||
_heightmap_y * 2 < (1U << _patches_newgame.map_y) || _heightmap_y / 2 > (1U << _patches_newgame.map_y))) {
ShowQuery(STR_HEIGHTMAP_SCALE_WARNING_CAPTION, STR_HEIGHTMAP_SCALE_WARNING_MESSAGE, HeightmapScaledTooMuchCallback, WC_GENERATE_LANDSCAPE, mode);
} else {
StartGeneratingLandscape(mode);
}
break;
case 18: case 20: // Year buttons
/* Don't allow too fast scrolling */
if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
HandleButtonClick(w, e->we.click.widget);
SetWindowDirty(w);
_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->we.click.widget - 19, MIN_YEAR, MAX_YEAR);
}
_left_button_clicked = false;
break;
case 19: // Year text
WP(w, def_d).data_3 = START_DATE_QUERY;
SetDParam(0, _patches_newgame.starting_year);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
break;
case 21: case 23: // Snow line buttons
/* Don't allow too fast scrolling */
if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
HandleButtonClick(w, e->we.click.widget);
SetWindowDirty(w);
_patches_newgame.snow_line_height = clamp(_patches_newgame.snow_line_height + e->we.click.widget - 22, 2, 13);
}
_left_button_clicked = false;
break;
case 22: // Snow line text
WP(w, def_d).data_3 = SNOW_LINE_QUERY;
SetDParam(0, _patches_newgame.snow_line_height);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, WC_GENERATE_LANDSCAPE, mode, CS_NUMERAL);
break;
case 24: case 25: // Tree placer
ShowDropDownMenu(w, tree_placer, _patches_newgame.tree_placer, 25, 0, 0);
break;
case 26: case 27: // Landscape generator OR Heightmap rotation
if (mode == GLWP_HEIGHTMAP) {
ShowDropDownMenu(w, rotation, _patches_newgame.heightmap_rotation, 27, 0, 0);
} else {
ShowDropDownMenu(w, landscape, _patches_newgame.land_generator, 27, 0, 0);
}
break;
case 28: case 29: // Terrain type
ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, 29, 0, 0);
break;
case 30: case 31: // Water quantity
ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, 31, 0, 0);
break;
case 32: case 33: // Map smoothness
ShowDropDownMenu(w, smoothness, _patches_newgame.tgen_smoothness, 33, 0, 0);
break;
}
break;
case WE_MOUSELOOP:
HandleEditBox(w, &_genseed_query, SEED_EDIT);
break;
case WE_KEYPRESS:
HandleEditBoxKey(w, &_genseed_query, SEED_EDIT, e);
/* the seed is unsigned, therefore atoi cannot be used.
* As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
* (use random seed) it should not be possible to be
* entered into the input field; the generate seed
* button can be used instead. */
_patches_newgame.generation_seed = minu(strtoul(_genseed_buffer, NULL, sizeof(_genseed_buffer) - 1), MAX_UVALUE(uint32) - 1);
break;
case WE_DROPDOWN_SELECT:
switch (e->we.dropdown.button) {
case 8: _patches_newgame.map_x = e->we.dropdown.index + 6; break;
case 10: _patches_newgame.map_y = e->we.dropdown.index + 6; break;
case 12:
_opt_newgame.diff.number_towns = e->we.dropdown.index;
if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
break;
case 14:
_opt_newgame.diff.number_industries = e->we.dropdown.index;
if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
break;
case 25:
_patches_newgame.tree_placer = e->we.dropdown.index;
break;
case 27:
if (mode == GLWP_HEIGHTMAP) {
_patches_newgame.heightmap_rotation = e->we.dropdown.index;
} else {
_patches_newgame.land_generator = e->we.dropdown.index;
}
break;
case 29:
_opt_newgame.diff.terrain_type = e->we.dropdown.index;
if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
break;
case 31:
_opt_newgame.diff.quantity_sea_lakes = e->we.dropdown.index;
if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
break;
case 33:
_patches_newgame.tgen_smoothness = e->we.dropdown.index;
break;
}
SetWindowDirty(w);
break;
case WE_ON_EDIT_TEXT: {
if (e->we.edittext.str != NULL) {
int32 value = atoi(e->we.edittext.str);
switch (WP(w, def_d).data_3) {
case START_DATE_QUERY:
InvalidateWidget(w, 19);
_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
break;
case SNOW_LINE_QUERY:
InvalidateWidget(w, 22);
_patches_newgame.snow_line_height = clamp(value, 2, 13);
break;
}
SetWindowDirty(w);
}
break;
}
}
}
const WindowDesc _generate_landscape_desc = {
WDP_CENTER, WDP_CENTER, 338, 268,
WC_GENERATE_LANDSCAPE, 0,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_generate_landscape_widgets,
GenerateLandscapeWndProc,
};
const WindowDesc _heightmap_load_desc = {
WDP_CENTER, WDP_CENTER, 338, 236,
WC_GENERATE_LANDSCAPE, 0,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_heightmap_load_widgets,
GenerateLandscapeWndProc,
};
static void _ShowGenerateLandscape(glwp_modes mode)
{
Window *w;
/* Don't kill WC_GENERATE_LANDSCAPE:GLWP_SCENARIO, because it resets
* _goto_editor, which we maybe need later on. */
DeleteWindowById(WC_GENERATE_LANDSCAPE, GLWP_GENERATE);
DeleteWindowById(WC_GENERATE_LANDSCAPE, GLWP_HEIGHTMAP);
/* Always give a new seed if not editor */
if (_game_mode != GM_EDITOR) _patches_newgame.generation_seed = InteractiveRandom();
if (mode == GLWP_HEIGHTMAP) {
if (_heightmap_str != STR_NULL) DeleteName(_heightmap_str);
_heightmap_x = 0;
_heightmap_y = 0;
_heightmap_str = AllocateName(_file_to_saveload.title, 0);
/* If the function returns negative, it means there was a problem loading the heightmap */
if (!GetHeightmapDimensions(_file_to_saveload.name, &_heightmap_x, &_heightmap_y))
return;
}
w = AllocateWindowDescFront((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
if (w != NULL) {
InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
}
}
void ShowGenerateLandscape(void)
{
_ShowGenerateLandscape(GLWP_GENERATE);
}
void ShowHeightmapLoad(void)
{
_ShowGenerateLandscape(GLWP_HEIGHTMAP);
}
void StartNewGameWithoutGUI(uint seed)
{
/* GenerateWorld takes care of the possible GENERATE_NEW_SEED value in 'seed' */
_patches_newgame.generation_seed = seed;
StartGeneratingLandscape(GLWP_GENERATE);
}
void CreateScenarioWndProc(Window *w, WindowEvent *e)
{
static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
switch (e->event) {
case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + 3); break;
case WE_PAINT:
SetWindowWidgetDisabledState(w, 14, _patches_newgame.starting_year <= MIN_YEAR);
SetWindowWidgetDisabledState(w, 16, _patches_newgame.starting_year >= MAX_YEAR);
SetWindowWidgetDisabledState(w, 17, _patches_newgame.se_flat_world_height <= 0);
SetWindowWidgetDisabledState(w, 19, _patches_newgame.se_flat_world_height >= 15);
SetWindowWidgetLoweredState(w, 3, _opt_newgame.landscape == LT_NORMAL);
SetWindowWidgetLoweredState(w, 4, _opt_newgame.landscape == LT_HILLY);
SetWindowWidgetLoweredState(w, 5, _opt_newgame.landscape == LT_DESERT);
SetWindowWidgetLoweredState(w, 6, _opt_newgame.landscape == LT_CANDY);
DrawWindowWidgets(w);
DrawString( 12, 96, STR_MAPSIZE, 0);
DrawString(167, 96, mapsizes[_patches_newgame.map_x - 6], 0x10);
DrawString(216, 96, STR_BY, 0);
DrawString(230, 96, mapsizes[_patches_newgame.map_y - 6], 0x10);
DrawString(162, 118, STR_DATE, 0);
SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
DrawStringCentered(271, 118, STR_GENERATE_DATE, 0);
DrawString(162, 136, STR_FLAT_WORLD_HEIGHT, 0);
SetDParam(0, _patches_newgame.se_flat_world_height);
DrawStringCentered(303, 136, STR_FLAT_WORLD_HEIGHT_NUM, 0x10);
break;
case WE_CLICK:
switch (e->we.click.widget) {
case 0: DeleteWindow(w); break;
case 3: case 4: case 5: case 6:
RaiseWindowWidget(w, _opt_newgame.landscape + 3);
SetNewLandscapeType(e->we.click.widget - 3);
break;
case 7: case 8: // Mapsize X
ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
break;
case 9: case 10: // Mapsize Y
ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, 10, 0, 0);
break;
case 11: // Empty world / flat world
StartGeneratingLandscape(GLWP_SCENARIO);
break;
case 12: // Generate
_goto_editor = true;
ShowGenerateLandscape();
break;
case 13: // Heightmap
_goto_editor = true;
ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP);
break;
case 14: case 16: // Year buttons
/* Don't allow too fast scrolling */
if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
HandleButtonClick(w, e->we.click.widget);
SetWindowDirty(w);
_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->we.click.widget - 15, MIN_YEAR, MAX_YEAR);
}
_left_button_clicked = false;
break;
case 15: // Year text
WP(w, def_d).data_3 = START_DATE_QUERY;
SetDParam(0, _patches_newgame.starting_year);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
break;
case 17: case 19: // Height level buttons
/* Don't allow too fast scrolling */
if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
HandleButtonClick(w, e->we.click.widget);
SetWindowDirty(w);
_patches_newgame.se_flat_world_height = clamp(_patches_newgame.se_flat_world_height + e->we.click.widget - 18, 0, 15);
}
_left_button_clicked = false;
break;
case 18: // Height level text
WP(w, def_d).data_3 = FLAT_WORLD_HEIGHT_QUERY;
SetDParam(0, _patches_newgame.se_flat_world_height);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, WC_GENERATE_LANDSCAPE, GLWP_SCENARIO, CS_NUMERAL);
break;
}
break;
case WE_DROPDOWN_SELECT:
switch (e->we.dropdown.button) {
case 8: _patches_newgame.map_x = e->we.dropdown.index + 6; break;
case 10: _patches_newgame.map_y = e->we.dropdown.index + 6; break;
}
SetWindowDirty(w);
break;
case WE_DESTROY:
_goto_editor = false;
break;
case WE_ON_EDIT_TEXT: {
if (e->we.edittext.str != NULL) {
int32 value = atoi(e->we.edittext.str);
switch (WP(w, def_d).data_3) {
case START_DATE_QUERY:
InvalidateWidget(w, 15);
_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
break;
case FLAT_WORLD_HEIGHT_QUERY:
InvalidateWidget(w, 18);
_patches_newgame.se_flat_world_height = clamp(value, 0, 15);
break;
}
SetWindowDirty(w);
}
break;
}
}
}
const Widget _create_scenario_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 13, 11, 337, 0, 13, STR_SE_CAPTION, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 13, 0, 337, 14, 179, 0x0, STR_NULL},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 10, 86, 24, 78, SPR_SELECT_TEMPERATE, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 90, 166, 24, 78, SPR_SELECT_SUB_ARCTIC, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246, 24, 78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
{ WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326, 24, 78, SPR_SELECT_TOYLAND, STR_0311_SELECT_TOYLAND_LANDSCAPE},
{ WWT_PANEL, RESIZE_NONE, 12, 162, 197, 95, 106, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 198, 209, 95, 106, STR_0225, STR_NULL}, // Mapsize X
{ WWT_PANEL, RESIZE_NONE, 12, 228, 263, 95, 106, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 264, 275, 95, 106, STR_0225, STR_NULL}, // Mapsize Y
{ WWT_TEXTBTN, RESIZE_NONE, 6, 12, 145, 117, 128, STR_SE_FLAT_WORLD, STR_SE_FLAT_WORLD_TIP}, // Empty (sea-level) map
{ WWT_TEXTBTN, RESIZE_NONE, 6, 12, 145, 135, 146, STR_SE_RANDOM_LAND, STR_022A_GENERATE_RANDOM_LAND}, // Generate
{ WWT_TEXTBTN, RESIZE_NONE, 6, 12, 145, 153, 164, STR_LOAD_GAME_HEIGHTMAP, STR_LOAD_SCEN_HEIGHTMAP}, // Heightmap
{ WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 117, 128, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE},
{ WWT_PANEL, RESIZE_NONE, 12, 228, 314, 117, 128, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 117, 128, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE},
{ WWT_IMGBTN, RESIZE_NONE, 12, 282, 293, 135, 146, SPR_ARROW_DOWN, STR_FLAT_WORLD_HEIGHT_DOWN},
{ WWT_PANEL, RESIZE_NONE, 12, 294, 314, 135, 146, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 12, 315, 326, 135, 146, SPR_ARROW_UP, STR_FLAT_WORLD_HEIGHT_UP},
{ WIDGETS_END},
};
const WindowDesc _create_scenario_desc = {
WDP_CENTER, WDP_CENTER, 338, 180,
WC_GENERATE_LANDSCAPE, 0,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_create_scenario_widgets,
CreateScenarioWndProc,
};
void ShowCreateScenario(void)
{
DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
AllocateWindowDescFront(&_create_scenario_desc, GLWP_SCENARIO);
}
static const Widget _show_terrain_progress_widgets[] = {
{ WWT_CAPTION, RESIZE_NONE, 14, 0, 180, 0, 13, STR_GENERATION_WORLD, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 14, 0, 180, 14, 96, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 15, 20, 161, 74, 85, STR_GENERATION_ABORT, STR_NULL}, // Abort button
{ WIDGETS_END},
};
typedef struct tp_info {
uint percent;
StringID class;
uint current;
uint total;
int timer;
} tp_info;
static tp_info _tp;
static void AbortGeneratingWorldCallback(bool ok_clicked)
{
if (ok_clicked) AbortGeneratingWorld();
else if (IsGeneratingWorld() && !IsGeneratingWorldAborted()) SetMouseCursor(SPR_CURSOR_ZZZ);
}
static void ShowTerrainProgressProc(Window* w, WindowEvent* e)
{
switch (e->event) {
case WE_CLICK:
switch (e->we.click.widget) {
case 2:
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE);
ShowQuery(STR_GENERATION_ABORT_CAPTION, STR_GENERATION_ABORT_MESSAGE, AbortGeneratingWorldCallback, WC_GENERATE_PROGRESS_WINDOW, 0);
break;
}
break;
case WE_PAINT:
DrawWindowWidgets(w);
/* Draw the % complete with a bar and a text */
DrawFrameRect(19, 20, (w->width - 18), 37, 14, FR_BORDERONLY);
DrawFrameRect(20, 21, (int)((w->width - 40) * _tp.percent / 100) + 20, 36, 10, 0);
SetDParam(0, _tp.percent);
DrawStringCentered(90, 25, STR_PROGRESS, 0);
/* Tell which class we are generating */
DrawStringCentered(90, 46, _tp.class, 0);
/* And say where we are in that class */
SetDParam(0, _tp.current);
SetDParam(1, _tp.total);
DrawStringCentered(90, 58, STR_GENERATION_PROGRESS, 0);
SetWindowDirty(w);
break;
}
}
static const WindowDesc _show_terrain_progress_desc = {
WDP_CENTER, WDP_CENTER, 181, 97,
WC_GENERATE_PROGRESS_WINDOW, 0,
WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_show_terrain_progress_widgets,
ShowTerrainProgressProc
};
/**
* Initializes the progress counters to the starting point.
*/
void PrepareGenerateWorldProgress(void)
{
_tp.class = STR_WORLD_GENERATION;
_tp.current = 0;
_tp.total = 0;
_tp.percent = 0;
_tp.timer = 0; // Forces to paint the progress window immediatelly
}
/**
* Show the window where a user can follow the process of the map generation.
*/
void ShowGenerateWorldProgress(void)
{
AllocateWindowDescFront(&_show_terrain_progress_desc, 0);
}
static void _SetGeneratingWorldProgress(gwp_class class, uint progress, uint total)
{
static const int percent_table[GWP_CLASS_COUNT + 1] = {0, 5, 15, 20, 40, 60, 65, 80, 85, 99, 100 };
static const StringID class_table[GWP_CLASS_COUNT] = {
STR_WORLD_GENERATION,
STR_022E_LANDSCAPE_GENERATION,
STR_CLEARING_TILES,
STR_022F_TOWN_GENERATION,
STR_0230_INDUSTRY_GENERATION,
STR_UNMOVABLE_GENERATION,
STR_TREE_GENERATION,
STR_SETTINGUP_GAME,
STR_PREPARING_TILELOOP,
STR_PREPARING_GAME
};
assert(class < GWP_CLASS_COUNT);
/* Do not run this function if we aren't in a thread */
if (!IsGenerateWorldThreaded() && !_network_dedicated) return;
if (IsGeneratingWorldAborted()) HandleGeneratingWorldAbortion();
if (total == 0) {
assert(_tp.class == class_table[class]);
_tp.current += progress;
} else {
_tp.class = class_table[class];
_tp.current = progress;
_tp.total = total;
_tp.percent = percent_table[class];
}
/* Don't update the screen too often. So update it once in every 200ms.
* However, the _tick_counter increases by 8 every 30ms, so compensate
* for that. */
if (!_network_dedicated && _tp.timer != 0 && _timer_counter - _tp.timer < (200 * 8 / 30)) return;
/* Percentage is about the number of completed tasks, so 'current - 1' */
_tp.percent = percent_table[class] + (percent_table[class + 1] - percent_table[class]) * (_tp.current == 0 ? 0 : _tp.current - 1) / _tp.total;
_tp.timer = _timer_counter;
if (_network_dedicated) {
static uint last_percent = 0;
/* Never display 0% */
if (_tp.percent == 0) return;
/* Reset if percent is lower then the last recorded */
if (_tp.percent < last_percent) last_percent = 0;
/* Display every 5%, but 6% is also very valid.. just not smaller steps then 5% */
if (_tp.percent % 5 != 0 && _tp.percent <= last_percent + 5) return;
/* Never show steps smaller then 2%, even if it is a mod 5% */
if (_tp.percent <= last_percent + 2) return;
DEBUG(net, 1)("Percent complete: %d", _tp.percent);
last_percent = _tp.percent;
/* Don't continue as dedicated never has a thread running */
return;
}
InvalidateWindow(WC_GENERATE_PROGRESS_WINDOW, 0);
MarkWholeScreenDirty();
SetGeneratingWorldPaintStatus(true);
/* We wait here till the paint is done, so we don't read and write
* on the same tile at the same moment. Nasty hack, but that happens
* if you implement threading afterwards */
while (IsGeneratingWorldReadyForPaint()) { CSleep(10); }
}
/**
* Set the total of a stage of the world generation.
* @param class the current class we are in.
* @param total Set the total expected items for this class.
*
* Warning: this function isn't clever. Don't go from class 4 to 3. Go upwards, always.
* Also, progress works if total is zero, total works if progress is zero.
*/
void SetGeneratingWorldProgress(gwp_class class, uint total)
{
if (total == 0) return;
_SetGeneratingWorldProgress(class, 0, total);
}
/**
* Increases the current stage of the world generation with one.
* @param class the current class we are in.
*
* Warning: this function isn't clever. Don't go from class 4 to 3. Go upwards, always.
* Also, progress works if total is zero, total works if progress is zero.
*/
void IncreaseGeneratingWorldProgress(gwp_class class)
{
/* In fact the param 'class' isn't needed.. but for some security reasons, we want it around */
_SetGeneratingWorldProgress(class, 1, 0);
}

2034
gfx.c Normal file

File diff suppressed because it is too large Load Diff

163
gfx.h Normal file
View File

@@ -0,0 +1,163 @@
/* $Id$ */
#ifndef GFX_H
#define GFX_H
typedef byte Pixel;
struct DrawPixelInfo {
Pixel *dst_ptr;
int left, top, width, height;
int pitch;
uint16 zoom;
};
typedef struct CursorVars {
Point pos, size, offs, delta; ///< position, size, offset from top-left, and movement
Point draw_pos, draw_size; ///< position and size bounding-box for drawing
CursorID sprite; ///< current image of cursor
int wheel; ///< mouse wheel movement
const CursorID *animate_list, *animate_cur; ///< in case of animated cursor, list of frames
uint animate_timeout; ///< current frame in list of animated cursor
bool visible; ///< cursor is visible
bool dirty; ///< the rect occupied by the mouse is dirty (redraw)
bool fix_at; ///< mouse is moving, but cursor is not (used for scrolling)
bool in_window; ///< mouse inside this window, determines drawing logic
} CursorVars;
typedef enum FontSizes {
FS_NORMAL,
FS_SMALL,
FS_LARGE,
FS_END,
} FontSize;
void RedrawScreenRect(int left, int top, int right, int bottom);
void GfxScroll(int left, int top, int width, int height, int xo, int yo);
// XXX doesn't really belong here, but the only
// consumers always use it in conjunction with DoDrawString()
#define UPARROW "\xEE\x8A\x80"
#define DOWNARROW "\xEE\x8A\xAA"
int DrawStringCentered(int x, int y, StringID str, uint16 color);
int DrawStringCenteredTruncated(int xl, int xr, int y, StringID str, uint16 color);
int DoDrawStringCentered(int x, int y, const char *str, uint16 color);
int DrawString(int x, int y, StringID str, uint16 color);
int DrawStringTruncated(int x, int y, StringID str, uint16 color, uint maxw);
int DoDrawString(const char *string, int x, int y, uint16 color);
int DoDrawStringTruncated(const char *str, int x, int y, uint16 color, uint maxw);
void DrawStringCenterUnderline(int x, int y, StringID str, uint16 color);
void DrawStringCenterUnderlineTruncated(int xl, int xr, int y, StringID str, uint16 color);
int DrawStringRightAligned(int x, int y, StringID str, uint16 color);
void DrawStringRightAlignedTruncated(int x, int y, StringID str, uint16 color, uint maxw);
void DrawStringRightAlignedUnderline(int x, int y, StringID str, uint16 color);
void GfxFillRect(int left, int top, int right, int bottom, int color);
void GfxDrawLine(int left, int top, int right, int bottom, int color);
BoundingRect GetStringBoundingBox(const char *str);
uint32 FormatStringLinebreaks(char *str, int maxw);
void LoadStringWidthTable(void);
void DrawStringMultiCenter(int x, int y, StringID str, int maxw);
uint DrawStringMultiLine(int x, int y, StringID str, int maxw);
void DrawDirtyBlocks(void);
void SetDirtyBlocks(int left, int top, int right, int bottom);
void MarkWholeScreenDirty(void);
void GfxInitPalettes(void);
bool FillDrawPixelInfo(DrawPixelInfo* n, int left, int top, int width, int height);
/* window.c */
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom);
void SetMouseCursor(uint cursor);
void SetAnimatedMouseCursor(const CursorID *table);
void CursorTick(void);
void DrawMouseCursor(void);
void ScreenSizeChanged(void);
void UndrawMouseCursor(void);
bool ChangeResInGame(int w, int h);
void SortResolutions(int count);
void ToggleFullScreen(bool fs);
/* gfx.c */
#define ASCII_LETTERSTART 32
extern FontSize _cur_fontsize;
byte GetCharacterWidth(FontSize size, uint32 key);
static inline byte GetCharacterHeight(FontSize size)
{
switch (size) {
default: NOT_REACHED();
case FS_NORMAL: return 10;
case FS_SMALL: return 6;
case FS_LARGE: return 18;
}
}
VARDEF DrawPixelInfo _screen;
VARDEF DrawPixelInfo *_cur_dpi;
VARDEF CursorVars _cursor;
enum {
COLOUR_DARK_BLUE,
COLOUR_PALE_GREEN,
COLOUR_PINK,
COLOUR_YELLOW,
COLOUR_RED,
COLOUR_LIGHT_BLUE,
COLOUR_GREEN,
COLOUR_DARK_GREEN,
COLOUR_BLUE,
COLOUR_CREAM,
COLOUR_MAUVE,
COLOUR_PURPLE,
COLOUR_ORANGE,
COLOUR_BROWN,
COLOUR_GREY,
COLOUR_WHITE
};
/**
* All 16 colour gradients
* 8 colours per gradient from darkest (0) to lightest (7)
*/
VARDEF byte _colour_gradient[16][8];
VARDEF int _pal_first_dirty;
VARDEF int _pal_last_dirty;
VARDEF bool _use_dos_palette;
typedef struct Colour {
byte r;
byte g;
byte b;
} Colour;
extern Colour _cur_palette[256];
typedef enum StringColorFlags {
IS_PALETTE_COLOR = 0x100, // color value is already a real palette color index, not an index of a StringColor
} StringColorFlags;
#ifdef _DEBUG
extern bool _dbg_screen_rect;
#endif
#endif /* GFX_H */

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