Merge branch 'master' into jgrpp

# Conflicts:
#	Makefile.bundle.in
#	src/os/macosx/string_osx.cpp
#	src/station_cmd.cpp
pull/115/head
Jonathan G Rennison 5 years ago
commit ca3c72438e

@ -0,0 +1,141 @@
# Compiling OpenTTD
## Required/optional libraries
The following libraries are used by OpenTTD for:
- zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads,
heightmaps
- liblzo2: (de)compressing of old (pre 0.3.0) savegames
- liblzma: (de)compressing of savegames (1.1.0 and later)
- libpng: making screenshots and loading heightmaps
- libfreetype: loading generic fonts and rendering them
- libfontconfig: searching for fonts, resolving font names to actual fonts
- libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and
natural sorting of strings (Linux only)
- libSDL2: hardware access (video, sound, mouse) (not required for Windows or macOS)
OpenTTD does not require any of the libraries to be present, but without
liblzma you cannot open most recent savegames and without zlib you cannot
open most older savegames or use the content downloading system.
Without libSDL/liballegro on non-Windows and non-macOS machines you have
no graphical user interface; you would be building a dedicated server.
## Windows:
You need Microsoft Visual Studio 2015 Update 3 or newer.
You can download the free Visual Studio Community Edition from Microsoft at
https://visualstudio.microsoft.com/vs/community/.
OpenTTD needs the Platform SDK, if it isn't installed already. This can be
done during installing Visual Studio, by selecting
`Visual C++ MFC for x86 and x64` (and possibly
`Visual C++ ATL for x86 and x64` depending on your version). If not, you
can get download it as [MS Windows Platform SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk).
Install the SDK by following the instructions as given.
Dependencies for OpenTTD on Windows are handled via
[vcpkg](https://github.com/Microsoft/vcpkg/). First you need to install vcpkg
by following the `Quick Start` instructions of their
[README](https://github.com/Microsoft/vcpkg/blob/master/README.md).
After this, you can install the dependencies OpenTTD needs. We advise to use
the `static` versions, and OpenTTD currently needs the following dependencies:
- liblzma
- libpng
- lzo
- zlib
To install both the x64 (64bit) and x86 (32bit) variants (though only one is necessary), you can use:
```ps
.\vcpkg install liblzma:x64-windows-static libpng:x64-windows-static lzo:x64-windows-static zlib:x64-windows-static
.\vcpkg install liblzma:x86-windows-static libpng:x86-windows-static lzo:x86-windows-static zlib:x86-windows-static
```
Open the relevant project file and it should build automatically.
- VS 2015: projects/openttd_vs140.sln
- VS 2017: projects/openttd_vs141.sln
- VS 2019: projects/openttd_vs142.sln
Set the build mode to `Release` in
`Build > Configuration manager > Active solution configuration`.
You can now compile.
If everything works well the binary should be in `objs\Win[32|64]\Release\openttd.exe`
and in `bin\openttd.exe`
The OpenTTD wiki may provide additional help with [compiling for Windows](https://wiki.openttd.org/Compiling_on_Windows_using_Microsoft_Visual_C%2B%2B_2015).
You can also build OpenTTD with MSYS2/MinGW-w64 or Cygwin/MinGW using the Makefile. The OpenTTD wiki may provide additional help with [MSYS2](https://wiki.openttd.org/Compiling_on_Windows_using_MSYS2)
## Linux, Unix, Solaris:
OpenTTD can be built with GNU '`make`'. On non-GNU systems it is called '`gmake`'.
However, for the first build one has to do a '`./configure`' first.
The OpenTTD wiki may provide additional help with:
- [compiling for Linux and *BSD](https://wiki.openttd.org/Compiling_on_%28GNU/%29Linux_and_*BSD)
- [compiling for Solaris](https://wiki.openttd.org/Compiling_on_Solaris)
## macOS:
Use '`make`' or Xcode (which will then call make for you)
This will give you a binary for your CPU type (PPC/Intel)
However, for the first build one has to do a '`./configure`' first.
To make a universal binary type '`./configure --enable-universal`'
instead of '`./configure`'.
The OpenTTD wiki may provide additional help with [compiling for macOS](https://wiki.openttd.org/Compiling_on_Mac_OS_X).
## Haiku:
Use '`make`', but do a '`./configure`' before the first build.
The OpenTTD wiki may provide additional help with [compiling for Haiku](https://wiki.openttd.org/Compiling_on_Haiku).
## OS/2:
A comprehensive GNU build environment is required to build the OS/2 version.
The OpenTTD wiki may provide additional help with [compiling for OS/2](https://wiki.openttd.org/Compiling_on_OS/2).
## Supported compilers
The following compilers are tested with and known to compile OpenTTD:
- Microsoft Visual C++ (MSVC) 2015, 2017 and 2019.
- GNU Compiler Collection (GCC) 4.8 - 9.
- Clang/LLVM 3.9 - 8
The following compilers are known not to compile OpenTTD:
In general, this is because these old versions do not (fully) support modern
C++11 language features.
- Microsoft Visual C++ (MSVC) 2013 and earlier.
- GNU Compiler Collection (GCC) 4.7 and earlier.
- Clang/LLVM 3.8 and earlier.
If any of these, or any other, compilers can compile OpenTTD, let us know.
Pull requests to support more compilers are welcome.
## Compilation of base sets
To recompile the extra graphics needed to play with the original Transport
Tycoon Deluxe graphics you need GRFCodec (which includes NFORenum) as well.
GRFCodec can be found at https://www.openttd.org/download-grfcodec.
The compilation of these extra graphics does generally not happen, unless
you remove the graphics file using '`make maintainer-clean`'.
Re-compilation of the base sets, thus also use of '`--maintainer-clean`' can
leave the repository in a modified state as different grfcodec versions can
cause binary differences in the resulting grf. Also translations might have
been added for the base sets which are not yet included in the base set
information files. Use the configure option '`--without-grfcodec`' to avoid
modification of the base set files by the build process.

@ -5,21 +5,26 @@ Looking to contribute something to OpenTTD? **Here's how you can help.**
Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved.
Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features.
Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project.
In return, they should reciprocate that respect in addressing your issue or assessing patches and features.
## Using the issue tracker
The [issue tracker](https://github.com/OpenTTD/OpenTTD/issues) is the preferred channel for [bug reports](#bug-reports), but please respect the following restrictions:
* Please **do not** use the issue tracker for help playing or using OpenTTD. Please try [irc](https://wiki.openttd.org/IRC_channel), or the [forums](https://www.tt-forums.net/)
* Please **do not** use the issue tracker for help playing or using OpenTTD.
Please try [irc](https://wiki.openttd.org/IRC_channel), or the [forums](https://www.tt-forums.net/)
* Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others.
* Please **do not** post comments consisting solely of "+1" or ":thumbsup:".
Use [GitHub's "reactions" feature](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) instead. We reserve the right to delete comments which violate this rule.
Use [GitHub's "reactions" feature](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) instead.
We reserve the right to delete comments which violate this rule.
* Please **do not** open issues or pull requests regarding add-on content in NewGRF, GameScripts, AIs, etc.
These are created by third-parties. Please try [irc](https://wiki.openttd.org/IRC_channel) or the [forums](https://www.tt-forums.net/) to discuss these.
* Please **do not** open issues or pull requests regarding add-on content in NewGRF, GameScripts, AIs, etc. These are created by third-parties. Please try [irc](https://wiki.openttd.org/IRC_channel) or the [forums](https://www.tt-forums.net/) to discuss these.
## Bug reports
@ -69,13 +74,15 @@ Example:
> causing the bug, and potential solutions (and your opinions on their
> merits).
## Feature requests
Before opening a feature request, please take a moment to find out whether your idea fits with the scope and aims of the project.
Before opening a feature request, please take a moment to find out whether your idea fits with the [scope and goals](./CONTRIBUTING.md#project-goals) of the project.
It's up to *you* to make a strong case to convince the project's developers of the merits of this feature.
Please provide as much detail and context as possible. This means don't request for a solution, but describe the problem you see and how/why you think it should be fixed.
Please provide as much detail and context as possible.
This means don't request for a solution, but describe the problem you see and how/why you think it should be fixed.
For feature request we have a strict policy.
@ -88,14 +95,18 @@ Many of those ideas etc do have a place on the [forums](https://www.tt-forums.ne
It's usually best discuss in [irc](https://wiki.openttd.org/IRC_channel) before opening a feature request or working on a large feature in a fork.
Discussion in irc can take time, but it can be productive and avoid disappointment :)
## Pull requests
Good pull requests—patches, improvements, new features—are a fantastic help.
They should remain focused in scope and avoid containing unrelated commits.
**Please ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code, porting to a different language), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project.
Pull requests should fit with the [goals of the project](./CONTRIBUTING.md#project-goals).
Please adhere to the [coding guidelines](#code-guidelines) used throughout the project (indentation, accurate comments, etc.) and any other requirements (such as test coverage).
**Please do ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code, porting to a different language), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project.
Every pull request should have a clear scope, with no unrelated commits.
[Code style](https://wiki.openttd.org/Coding_style) must be complied with for pull requests to be accepted; this also includes [commit message format](https://wiki.openttd.org/Coding_style#Commit_message).
Adhering to the following process is the best way to get your work included in the project:
@ -147,33 +158,108 @@ git push
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description against the `master` branch.
**IMPORTANT**: By submitting a patch, you agree to the [License](#license).
**IMPORTANT**: By submitting a pull request or patch, you agree to the [License](#license) and the [Privacy Notice](CONTRIBUTING.md#privacy-notice).
### Privacy Notice
We would like to make you aware that contributing to OpenTTD via git will permanently store the name and email address you provide as well as the actual changes and the time and date you made it inside git's version history.
### Pull request validation
This is inevitable, because it is a main feature of git. If you are concerned about your privacy, we strongly recommend to use "Anonymous <anonymous@openttd.org>" as the git commit author. We might refuse anonymous contributions if malicious intent is suspected.
Continuous integration (CI) tools monitor pull requests, and help us identify build and code quality issues.
Please note that the contributor identity, once given, is used for copyright verification and to provide proof should a malicious commit be made. As such, the [EU GDPR](https://www.eugdpr.org/key-changes.html) "right to be forgotten" does not apply, as this is an overriding legitimate interest.
The results of the CI tests will show on your pull request.
Please also note that your commit is public and as such will potentially be processed by many third-parties. Git's distributed nature makes it impossible to track where exactly your commit, and thus your personal data, will be stored and be processed. If you would not like to accept this risk, please do either commit anonymously or refrain from contributing to the OpenTTD project.
By clicking on Details you can further zoom in; in case of a failure it will show you why it failed.
In case of success it will report how awesome you were.
### Pull request validation
Tip: [commit message format](https://wiki.openttd.org/Coding_style#Commit_message) is a common reason for pull requests to fail validation.
Continuous integration (CI) tools monitor pull requests, and help us identify build and code quality issues.
The results of the CI tests will show on your pull request.
### Are there any development docs?
There is no single source for OpenTTD development docs. It's a complex project with a long history, and multiple APIs.
A good entry point is [Development](https://wiki.openttd.org/Development) on the OpenTTD wiki; this provides links to wiki documentation and other sources.
The GitHub repo also includes some non-comprehensive documentation in [/docs](./docs).
You may also want the guide to [compiling OpenTTD](./COMPILING.md).
## Project goals
### What are the goals of the official branch?
The main goals of the official branch are:
- Stay faithful to the original gameplay from Transport Tycoon Deluxe
- Improve the user interface
- Allow extending the gameplay with add-ons / mods via supported content APIs
- Provide a (relatively) stable core for both players of the official branch, and for authors of add-ons and maintainers of patchpacks
In contrast, extending or altering the gameplay of the base game is not encouraged.
The rationale behind these goals is that people have different opinions about what OpenTTD is and what it should be.
When it comes to gameplay, there are at least these groups of people:
By clicking on Details you can further zoom in; in case of a failure it will show you why it failed. In case of success it will report how awesome you were.
- *Model railway (mostly singleplayer)*: build "realistic" landscapes, roleplay a world, or even replicate historical scenarios
- *Economical challenge (mostly singleplayer)*: run a business with economical challenges
- *Transport challenge (singleplayer or cooperative multiplayer)*: build efficient track layouts with high cargo throughput and tons of vehicles
- *Competitive speed run (competitive multiplayer)*: maximize some goal in some limited amount of time
When it comes to gameplay features there are at least these groups of interests:
- *Control freak:* micromanagement like conditional orders, refitting and loading etc.
- *Casual:* automatisation like cargodist, path based signalling etc.
To please everyone, the official branch tries to stay close to the original gameplay; after all, that is what everyone brought here.
The preferred method to alter and extent the gameplay is via add-ons like NewGRF and GameScripts.
For a long time, the official branch was also open to features which could be enabled/disabled, but the corner-cases that came with some configurations have rendered some parts of the code very complicated.
Today, new features have to work with all the already existing features, which is not only challenging in corner cases, but also requires spending considerable more work than just "making it work in the game mode that I play".
The preferred method to introduce new gameplay features is to extend the content APIs, supporting ever more add-on content / mods.
This moves conflict-solving away from the codebase to content authors / players.
It is more accepted for add-ons not working together than the base game not working with certain setting combinations.
In general the game should allow anything that doesn't violate basic rules, but it should warn players if they take potentially dangerous or "stupid" actions.
For example, players are not prevented from starting vehicles without orders, but will receive a warning about vehicles having too few orders.
This lack of limitation has led to players challenging themselves to create networks where all vehicles have no orders, increasing gameplay possibilities.
### I do not agree with the goals of the official branch, what can I do instead?
Fork! There is a rich history of experimental patches for OpenTTD.
Many of these will never be accepted for core, but are creative and interesting ways to modify OpenTTD.
Sometimes patches are combined into long-running patchpacks, modified OpenTTD versions which can be downloaded by anyone, or modified OpenTTD clients for dedicated multiplayer servers.
One of the reasons to keep core relatively stable is to make life easier for patch authors and patchpack maintainers where possible.
Patchpack discussions and related topics may be found in community sites such as [TT-Forums development section](https://www.tt-forums.net/viewforum.php?f=33).
## Legal stuff
### License
By contributing your code, you agree to license your contribution under the [GPL v2](https://github.com/OpenTTD/OpenTTD/blob/master/COPYING.md).
### Privacy Notice
We would like to make you aware that contributing to OpenTTD via git will permanently store the name and email address you provide as well as the actual changes and the time and date you made it inside git's version history.
## Code guidelines
This is inevitable, because it is a main feature of git.
If you are concerned about your privacy, we strongly recommend to use "Anonymous <anonymous@openttd.org>" as the git commit author. We might refuse anonymous contributions if malicious intent is suspected.
[Code style](https://wiki.openttd.org/Coding_style) must be adhered to for pull requests to be accepted
Please note that the contributor identity, once given, is used for copyright verification and to provide proof should a malicious commit be made.
As such, the [EU GDPR](https://www.eugdpr.org/key-changes.html) "right to be forgotten" does not apply, as this is an overriding legitimate interest.
## License
Please also note that your commit is public and as such will potentially be processed by many third-parties.
Git's distributed nature makes it impossible to track where exactly your commit, and thus your personal data, will be stored and be processed.
If you would not like to accept this risk, please do either commit anonymously or refrain from contributing to the OpenTTD project.
By contributing your code, you agree to license your contribution under the [GPL v2](https://github.com/OpenTTD/OpenTTD/blob/master/COPYING).
### Attribution of this Contributing Guide

@ -1,18 +1,19 @@
This is the license which applies to OpenTTD with the exception of some
3rd party modules. See README.md for details
3rd party modules. See [./README.md](./README.md) for details
GNU General Public License
==========================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
_Version 2, June 1991_
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
### Preamble
The licenses for most software are designed to take away your
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
@ -22,48 +23,47 @@ using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
We protect your rights with two steps: **(1)** copyright the software, and
**(2)** offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
**0.** This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
@ -80,7 +80,7 @@ is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
**1.** You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
@ -91,29 +91,27 @@ along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
**2.** You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
* **a)** You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
* **b)** You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
* **c)** If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
@ -135,26 +133,24 @@ with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
**3.** You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
* **a)** Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
* **b)** Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
* **c)** Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
@ -173,7 +169,7 @@ access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
**4.** You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
@ -181,7 +177,7 @@ However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
**5.** You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
@ -190,7 +186,7 @@ Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
**6.** Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
@ -198,7 +194,7 @@ restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
**7.** If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
@ -230,7 +226,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
**8.** If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
@ -238,7 +234,7 @@ those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
**9.** The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
@ -251,7 +247,7 @@ Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
**10.** If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
@ -259,9 +255,9 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
### NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
@ -271,7 +267,7 @@ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
@ -281,15 +277,15 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
### How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
@ -321,20 +317,20 @@ when it starts in an interactive mode:
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
The hypothetical commands `show w` and `show c` should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
be called something other than `show w` and `show c`; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may

@ -76,12 +76,11 @@ endif
$(Q)cp "$(BIN_DIR)/baseset/"*.obm "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/lang/"*.lng "$(LANG_DIR)/"
$(Q)cp "$(BIN_DIR)/data/"*.grf "$(DATA_DIR)/"
$(Q)cp "$(ROOT_DIR)/README.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/COPYING" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/README.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/COPYING.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.txt" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.md" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/changelog.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/README.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/jgrpp-changelog.md" "$(BUNDLE_DIR)/"
ifdef MAN_DIR
$(Q)mkdir -p "$(BUNDLE_DIR)/man/"
@ -97,7 +96,7 @@ ifdef MENU_DIR
$(Q)sed s/=openttd/=$(BINARY_NAME)/g "$(BUNDLE_DIR)/media/openttd.desktop" > "$(ROOT_DIR)/media/openttd.desktop.install"
endif
ifeq ($(TTD), openttd.exe)
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/COPYING" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"*.md
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"*.md
endif
### Packing the current bundle into several compressed file formats ###
@ -162,7 +161,7 @@ bundle_dmg: bundle
bundle_exe: all
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)unix2dos "$(ROOT_DIR)/docs/"*.txt "$(ROOT_DIR)/COPYING" "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt" "$(ROOT_DIR)/"*.md
$(Q)unix2dos "$(ROOT_DIR)/docs/"*.txt "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt" "$(ROOT_DIR)/"*.md
$(Q)cd $(ROOT_DIR)/os/windows/installer && makensis.exe //DVERSION_INCLUDE=version_$(PLATFORM).txt install.nsi
$(Q)mv $(ROOT_DIR)/os/windows/installer/*$(PLATFORM).exe "$(BUNDLES_DIR)/$(BUNDLE_NAME).exe"
@ -202,7 +201,7 @@ ifndef DO_NOT_INSTALL_CHANGELOG
endif
ifndef DO_NOT_INSTALL_LICENSE
$(Q)install -d "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING" "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING.md" "$(INSTALL_DOC_DIR)"
endif
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)/${BINARY_NAME}.32.xpm"
ifdef ICON_THEME_DIR

@ -303,6 +303,8 @@ Sufficiently up-to-date versions of other compiler toolchains including MSVC and
## Table of contents
- 1.0) [About](#10-about)
- 1.1) [Compiling OpenTTD](#11-compiling-openttd)
- 1.2) [Contributing to OpenTTD](#12-contributing-to-openttd)
- 2.0) [Contacting](#20-contacting)
- 2.1) [Reporting bugs](#21-reporting-bugs)
- 2.2) [Reporting desyncs](#22-reporting-desyncs)
@ -316,15 +318,11 @@ Sufficiently up-to-date versions of other compiler toolchains including MSVC and
- 5.1) [Logging of potentially dangerous actions](#51-logging-of-potentially-dangerous-actions)
- 5.2) [Frame rate and performance metrics](#52-frame-rate-and-performance-metrics)
- 6.0) [Configuration file](#60-configuration-file)
- 7.0) [Compiling](#70-compiling)
- 7.1) [Required/optional libraries](#71-requiredoptional-libraries)
- 7.2) [Supported compilers](#72-supported-compilers)
- 7.3) [Compilation of base sets](#73-compilation-of-base-sets)
- 8.0) [Translating](#80-translating)
- 8.1) [Translation](#81-translation)
- 8.2) [Previewing](#82-previewing)
- 9.0) [Troubleshooting](#90-troubleshooting)
- 10.0) [Licensing](#100-licensing)
- 7.0) [Translating](#70-translating)
- 7.1) [Translation](#71-translation)
- 7.2) [Previewing](#72-previewing)
- 8.0) [Troubleshooting](#80-troubleshooting)
- 9.0) [Licensing](#90-licensing)
- X.X) [Credits](#xx-credits)
## 1.0) About
@ -337,6 +335,14 @@ OpenTTD is licensed under the GNU General Public License version 2.0,
but includes some 3rd party software under different licenses. See the
section "Licensing" below for details.
## 1.1) Compiling OpenTTD
Instructions for compiling OpenTTD can be found in [./COMPILING.md](COMPILING.md)
## 1.2) Contributing to OpenTTD
We welcome contributors to OpenTTD. More information for contributors can be found in [./CONTRIBUTING.md](CONTRIBUTING.md)
## 2.0) Contacting
The easiest way to contact the OpenTTD team is by submitting bug reports or
@ -811,106 +817,7 @@ When you cannot find openttd.cfg you should look in the directories as
described in section 4.2. If you do not have an openttd.cfg OpenTTD will
create one after closing.
## 7.0) Compiling
### Windows:
You need Microsoft Visual Studio 2015 Update 3 or more recent. Open the project file
and it should build automatically. In case you want to build with SDL support
you need to add WITH_SDL to the project settings.
PNG (WITH_PNG), ZLIB (WITH_ZLIB), LZO (WITH_LZO), Freetype (WITH_FREETYPE) and
libLZMA (WITH_LIBLZMA) support is enabled by default. For these to work you need their
development files. To get them just use vcpkg from https://github.com/Microsoft/vcpkg
using x86-windows-static and x64-windows-static triplets.
For more help with VS see docs/Readme_Windows_MSVC.md.
You can also build it using the Makefile with MSYS/MinGW or Cygwin/MinGW.
Please read the Makefile for more information.
### Solaris, FreeBSD, OpenBSD:
Use '`gmake`', but do a '`./configure`' before the first build.
### Linux/Unix:
OpenTTD can be built with GNU '`make`'. On non-GNU systems it is called '`gmake`'.
However, for the first build one has to do a '`./configure`' first.
### macOS:
Use '`make`' or Xcode (which will then call make for you)
This will give you a binary for your CPU type (PPC/Intel)
However, for the first build one has to do a '`./configure`' first.
To make a universal binary type '`./configure --enabled-universal`'
instead of '`./configure`'.
### Haiku:
Use '`make`', but do a '`./configure`' before the first build.
### OS/2:
A comprehensive GNU build environment is required to build the OS/2 version.
See the docs/Readme_OS2.txt file for more information.
### 7.1) Required/optional libraries
The following libraries are used by OpenTTD for:
- libSDL/liballegro: hardware access (video, sound, mouse)
- zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads,
heightmaps
- liblzo2: (de)compressing of old (pre 0.3.0) savegames
- liblzma: (de)compressing of savegames (1.1.0 and later)
- libpng: making screenshots and loading heightmaps
- libfreetype: loading generic fonts and rendering them
- libfontconfig: searching for fonts, resolving font names to actual fonts
- libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and
natural sorting of strings.
OpenTTD does not require any of the libraries to be present, but without
liblzma you cannot open most recent savegames and without zlib you cannot
open most older savegames or use the content downloading system.
Without libSDL/liballegro on non-Windows and non-macOS machines you have
no graphical user interface; you would be building a dedicated server.
### 7.2) Supported compilers
The following compilers are known to compile OpenTTD:
- Microsoft Visual C++ (MSVC) 2015, 2017 and 2019.
- GNU Compiler Collection (GCC) 4.8 - 9.
- Clang/LLVM 3.9 - 8
The following compilers are known not to compile OpenTTD:
In general, this is because these old versions do not (fully) support modern
C++11 language features.
- Microsoft Visual C++ (MSVC) 2013 and earlier.
- GNU Compiler Collection (GCC) 4.7 and earlier.
- Clang/LLVM 3.8 and earlier.
If any of these, or any other, compilers can compile OpenTTD, let us know.
Pull requests to support more compilers are welcome.
### 7.3) Compilation of base sets
To recompile the extra graphics needed to play with the original Transport
Tycoon Deluxe graphics you need GRFCodec (which includes NFORenum) as well.
GRFCodec can be found at https://www.openttd.org/download-grfcodec.
The compilation of these extra graphics does generally not happen, unless
you remove the graphics file using '`make maintainer-clean`'.
Re-compilation of the base sets, thus also use of '`--maintainer-clean`' can
leave the repository in a modified state as different grfcodec versions can
cause binary differences in the resulting grf. Also translations might have
been added for the base sets which are not yet included in the base set
information files. Use the configure option '`--without-grfcodec`' to avoid
modification of the base set files by the build process.
## 8.0) Translating
## 7.0) Translating
See https://www.openttd.org/development for up-to-date information.
@ -925,7 +832,7 @@ Please contact the translations manager (https://www.openttd.org/contact)
before beginning the translation process! This avoids double work, as
someone else may have already started translating to the same language.
### 8.1) Translation
### 7.1) Translation
So, now that you have notified the development team about your intention to
translate (You did, right? Of course you did.) you can pick up english.txt
@ -943,7 +850,7 @@ Note: Do not alter the following parts of the file:
- Lines beginning with ## (such as ##id), other than the first two lines
of the file
### 8.2) Previewing
### 7.2) Previewing
In order to view the translation in the game, you need to compile your language
file with the strgen utility. As this utility is tailored to a specific OpenTTD
@ -963,7 +870,7 @@ should also be.
That is all! You should now be able to select the language in the game options.
## 9.0) Troubleshooting
## 8.0) Troubleshooting
To see all startup options available to you, start OpenTTD with the
'`./openttd -h`' option. This might help you tweak some of the settings.
@ -1008,10 +915,10 @@ or [GRFCrawler](https://grfcrawler.tt-forums.net). Put the NewGRF files in
OpenTTD's newgrf folder (see section 4.2 'OpenTTD directories') and rescan the
list of available NewGRFs. Once you have all missing files, you are set to go.
## 10.0) Licensing
## 9.0) Licensing
OpenTTD is licensed under the GNU General Public License version 2.0. For
the complete license text, see the file 'COPYING'. This license applies
the complete license text, see the file 'COPYING.md'. This license applies
to all files in this distribution, except as noted below.
The squirrel implementation in src/3rdparty/squirrel is licensed under
@ -1044,6 +951,7 @@ terms for Bootstrap documentation.
- Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)
- Christoph Elsenhans (frosch) - General coding (since 0.6)
- Loïc Guilloux (glx) - Windows Expert (since 0.4.5)
- Charles Pigott (LordAro) - General / Correctness police (since 1.9)
- Michael Lutz (michi_cc) - Path based signals (since 0.7)
- Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)
- Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)

@ -119,14 +119,14 @@ jobs:
Tag: 'linux-ubuntu-bionic-i386-gcc'
linux-ubuntu-bionic-amd64-gcc:
Tag: 'linux-ubuntu-bionic-amd64-gcc'
linux-debian-jessie-i386-gcc:
Tag: 'linux-debian-jessie-i386-gcc'
linux-debian-jessie-amd64-gcc:
Tag: 'linux-debian-jessie-amd64-gcc'
linux-debian-stretch-i386-gcc:
Tag: 'linux-debian-stretch-i386-gcc'
linux-debian-stretch-amd64-gcc:
Tag: 'linux-debian-stretch-amd64-gcc'
linux-debian-buster-i386-gcc:
Tag: 'linux-debian-buster-i386-gcc'
linux-debian-buster-amd64-gcc:
Tag: 'linux-debian-buster-amd64-gcc'
steps:
- template: release-fetch-source.yml

@ -1,3 +1,110 @@
1.10.0-beta1 (2019-10-29)
------------------------------------------------------------------------
- Feature: Configurable minimum age for companies before allowing share trading (#7780)
- Feature: Filter on town list window (#7621)
- Feature: Ability to show Newspaper and Ticker messages in parallel (#7612)
- Feature: Show coverage area for stations and towns (#7446)
- Feature: Collapsible vehicle groups (#7417)
- Feature: More flexible docks - can now have multiple per station, ships can use any part of dock (#7380)
- Feature: [NewGRF] Railtype flags to allow/disallow 90 degree curves (#7352)
- Feature/Change: Non-rectangular catchment area for sparse stations (#7235)
- Feature: Improved performance for road vehicle pathfinding (#7261)
- Feature: Option to show local authority boundary of towns (#7025)
- Feature: Experimental method of town cargo generation that scales linearly with population (#6965)
- Feature: [NewGRF] Houses and industries can accept/produce up to 16 different cargo types (#6867, #6872)
- Feature: [NewGRF] RoadTypes (NRT) (#6811)
- Add: [Win32] Select MIDI device by port name (#7666)
- Add: 'getsysdate' console command (#7658)
- Add: Currencies NTD, CNY, HKD (#7596)
- Add: Icons to vehicle construction drop down lists (#7358, #7485)
- Add: Security warning to players that company passwords are not truly secure (#7351)
- Add: [Script] Various API functions for managing vehicle groups (#7225, #7336, #7716)
- Add: SDL2 video driver (#7086)
- Change: Inactive industries do not make sound effects (#7752)
- Change: [Win32] Use native GDI engine for rendering fonts (#7572)
- Change: Scale oil refinery edge distance limit by map size (#7514)
- Change: Do not display a news message about old vehicles when a replacement for it is activated (#7401)
- Change: When filtering purchase list by cargo type, buy button now performs a refit if required (#7301)
- Change: Don't apply forbid 90 deg turn settings to ships, and make penalties for turns configurable (#7289, #7372)
- Change: Make the chance of an aeroplane crashing at an airport with a short runway independent of plane crash setting (#7302)
- Change: Keep town growth rate in sync with house count (#6777)
- Fix #6219: Improve helicopter's ability to takeoff from commuter and international airports (#7710)
- Fix #6407: Show snowy ground sprites for train depots (#7671)
- Fix: Power/running cost sorting algorithm was not correct when power was higher than running cost (#7561)
- Fix: Tweaks to small-map colours to make dark blue company more visible (#7436, #7450)
- Fix: [SDL] Do not offer video smaller than 640x480 (#7442)
- Fix: Incorrect display of industry production around tiles (#7426)
- Fix: Show industry name in Land Area Information window for industries with neutral stations instead of just 'Oil Rig' (#7349)
- Fix: Remove redundant and broken file lookups when loading base sets (#7348)
- Fix: Always report error when ordering a road vehicle to wrong type of road stop (#7316)
- Fix #7043, #7274: Improve performance when creating towns during world creation (#7284)
- Fix #7062: Remove ship max order distance (#7279)
- Fix #7189: Fluidsynth volume gain too high (#7253)
- Fix: Add setting for whether industries with neutral stations (e.g. Oil rigs) accept and supply cargo to/from surrounding stations to fix exploit as old as TTO (#7234)
- Fix: Properly reset dropdown menu windows after changing AI/GS settings (#7092)
- Remove: DOS, MorphOS, AmigaOS & BeOS support (#7326, #7388)
- Remove: Original Path Finder (#7245)
1.9.3 (2019-09-16)
------------------------------------------------------------------------
- Change: Use natural sort when sorting the file list (#7727)
- Fix #7479: Don't close construction windows when changing client name (#7728)
- Fix #7731: Files sorting by modification time on Windows XP (#7731)
- Fix #7644: [OSX] Better solution for colourspace/performance issues (#7741)
1.9.3-RC1 (2019-09-07)
------------------------------------------------------------------------
- Add: Can now click industries to make orders to their neutral station (e.g. oil rig) (#7709)
- Fix #7644: [OSX] Poor framerate on certain systems (#7721)
- Fix #7702: Highscore screen UI scaling (#7714)
- Fix #7704: [OSX] Handle malformed UTF8 strings, leading to crashes in server browser (#7705)
- Fix #7188: [AI] Possible crash when reloading an AI in multiplayer games (#7701, #7725)
- Fix: RemoveAirport function now returns 'Aircraft in the way' error message when occupied (#7690)
- Fix: Spelling in running costs setting help text (#7686)
- Fix #7655: 'Decrease' buttons in cheat window not working properly with UI scaling (#7669)
- Fix: [GS] Could not create elements on Storybook pages with ID > 255 (#7657)
- Fix #7626: Allow building road stops over town-owned one-way roads, instead of crashing (#7627)
1.9.2 (2019-07-07)
------------------------------------------------------------------------
- Change: Set default setting in server browser of "Advertised" to "Yes" (#7568)
- Change: Allow building road stops over self-owned one-way/blocked road (#7547)
- Fix #7463: Promote scroll mode setting to basic category (#7586)
- Fix: Inconsistent GUI scaling (#7539)
- Fix #7491: Send company update admin message when bankruptcy counter changes (#7492)
- Fix #7553: Check bounds when loading strings (#7554)
- Fix: Really increase the maximum number of GameScript texts to 64k (#7555)
- Fix: Crash when attempting to load old save game with GRFs set (#7546)
- Fix #6507: Don't try to load invalid depots from older savegames (#7546)
- Fix: Railtype bits were moved too late, leading to rails under bridges losing their type (#7546)
- Fix: Bounds check access to railtype_map (#7529)
- Fix: Spurious errors when using more than 32 railtypes (#7533)
- Fix #7633: Allow zero-cost track conversion to succeed (#7634)
- Fix #7577: Check if linkgraph station index is valid before dereferencing (#7583)
- Fix #7224: Drag and drop vehicle group creation does not work correctly (#7581)
- Fix #7570: Show Github URL in the crashlog window (#7571)
- Fix: Clicking on scrollbar 'thumb' moved position up instantly (#7549)
- Fix #7255: Prevent crashlog corruption by only printing the 32 most recent news messages (#7542)
- Fix #5685: Check for free wagons in ScriptVehicleList (#7617)
- Fix: Make GSGoal.QuestionClient work correctly at least for clients with ID < 2**16 (#7560)
- Fix #6666: Mismatched parentheses in RTL languages (#7480)
- Fix: [Windows] Various reliability and correctness improvements to MIDI on Windows (#7620)
1.9.1 (2019-04-08)
------------------------------------------------------------------------
- Fix #6564: Enforce types of arguments for station name strings (#7419)
- Fix #7433: Don't use AirportSpec substitute if it's not enabled (#7435)
- Fix #7447, #7466, #7476: Missing NewGRF strings due to Action 4 feature check skipping pseudo-feature 48 (#7449)
- Fix #6222: Advanced sprite layout sometimes showed incorrect railtype ground tile. (#7460)
- Fix #7439: CompanyRemoveReason overwritten by ClientID (#7465)
- Fix: [Windows] Incorrect error handling could lead to cascading error windows (#7482)
- Fix #7478: Don't remove NewGRF objects on company take-over. (#7483)
1.9.0 (2019-04-01)
------------------------------------------------------------------------
- Fix #7411: Use industry production callback (if used) on initial industry cargo generation (#7412)

@ -1,72 +0,0 @@
OpenTTD and strgen
Last updated: 2009-06-30
------------------------------------------------------------------------
Table of contents
-----------------
1.0) strgen usage
* 1.1) Examples
* 1.2) strgen command switches
1.0) strgen usage
---- ------------
This guide is only interesting for people who want to alter something
themselves without access to translator.openttd.org. Please note that
your compiled language file will only be compatible with the OpenTTD version
you have downloaded english.txt, the master language file, for. While this is
not always true, namely when changes in the code have not touched language
files, your safest bet is to assume this 'limitation'.
As a first step you need to compile strgen. This is as easy as typing
'make strgen'. You can download the precompile strgen from:
http://www.openttd.org/download-strgen
strgen takes as argument a txt file and translates it to a lng file, allowing
it to be used inside OpenTTD. strgen needs the master language file
english.txt to work. Below are some examples of strgen usage.
1.1) Examples
---- --------
Example 1:
if you are in the root of your working copy (git repository), you should type
strgen/strgen -s lang lang/english.txt
to compile englist.txt into english.lng. It will be placed in the lang dir
Example 2:
you only have the strgen executable (no working copy) and you want to compile
a txt file in the same directory. You should type
./strgen english.txt
and you will get and english.lng in the same dir
Example 3:
you have strgen somewhere, english.txt in /usr/openttd/lang and you want the
resulting language file to go to /tmp. Use
./strgen -s /usr/openttd/lang -d /tmp english.txt
You can interchange english.txt to whichever language you want to generate a
.lng file for.
1.2) strgen command switches
---- -----------------------
-v | --version
strgen will tell what git revision it was last modified
-t | --todo
strgen will add <TODO> to any untranslated/missing strings and use the english
strings while compiling the language file
-w | --warning
strgen will print any missing strings or wrongly translated (bad format)
to standard error output(stderr)
-h | --help | -?
Print out a summarized help message explaining these switches
-s | --source_dir
strgen will search for the master file english.txt in the directory specified
by this switch instead of the current directory
-d | --dest_dir
strgen will put <language>.lng in the directory specified by this switch; if
no dest_dir is given, output is the same as source_dir

@ -1,139 +0,0 @@
OpenTTD: OS/2 version
=====================
OpenTTD has been ported to work on OS/2 4.x or later (including
eComStation). The game should work as well as it does on Windows
or other platforms: the main issues you may encounter are graphics
card problems, but that is really the fault of SDL.
=========================
USING OPENTTD FOR OS/2
=========================
LIBRARIES REQUIRED FOR END USERS
--------------------------------
SDL.DLL (SDL 1.2.7) and FSLib.dll are required to use this program:
these can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip".
Version 20051222 of SDL or later is required. This can be found at
http://sdl.netlabs.org/.
Please note that earlier SDL releases will probably NOT work with
OpenTTD. If you experience problems with OpenTTD, please check
your SDL and FSLib.dll versions (both must match).
Note that to actually play the game, I have found in my own
experience that a version of the Scitech Display Drivers or its later
incarnation (see www.scitech.com) are necessary for it to work. If
you have trouble with your native drivers, try the Scitech drivers
and see if they help the problem.
KNOWN ISSUES
------------
- If an error occurs during loading, the OS/2 error message window
is not always displayed.
A NOTE ABOUT MUSIC
------------------
OpenTTD includes a music driver which uses the MCI MIDI system. Unfortunately,
due to the lack of proper MIDI hardware myself, I have been unable to test it,
but during testing, I found that when MIDI was enabled, I got no sound
effects. I therefore decided to DISABLE music by default.
To enable music, start OpenTTD with the command line:
openttd -m os2
If I hear enough responses that both music and sound work together (it might
just be my system), I'll have the defaults changed.
Please note also that the GCC version does not currently support the MCI MIDI
system.
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
------------------------------------------
To start a dedicated multiplayer server, you should run the dedicated.cmd
file. This enables OpenTTD to open up a VIO console window to display
its output and gather any necessary input. Running "openttd -D"
directly will result in the console not being displayed. You may
still pass any other parameters ('-D' is already passed) to
dedicated.cmd.
You can find the dedicated.cmd file in the os/os2 directory.
=========================
BUILDING THE OS/2 VERSION
=========================
Compiler
--------
Innotek GCC, an OS/2 port of the popular GCC compiler, was used to build OpenTTD.
See www.innotek.de for more information. You WILL need a reasonably UNIX-like
build environment in order to build OpenTTD successfully - the following link
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
---------------------
Open Watcom C/C++ was previously used to build OpenTTD (version 0.4.x and earlier).
However, due to advanced C++ features used in the YAPF portion of OpenTTD 0.5
in particular, the compiler is no longer able to build the game at the moment.
Hopefully one day Open Watcom will be able to catch up and we will be able to build
the game once again (it's easier than getting an OS/2 UNIX-like environment set up
in my opinion!), but until then, OpenTTD 0.5 and later can only be built with GCC.
Libraries Required
------------------
The following libraries are required. To build zlib and libpng, I
simply added the required files (watch out for sample programs, etc)
to an IDE project file and built a library. Do not use the makefiles
provided, they are not designed for Watcom (apart from SDL):
- zlib
http://www.zlib.org/
- libpng
http://www.libpng.org/
- SDL for OS/2
ftp://ftp.netlabs.org/pub/sdl/sdl-1.2.7-src-20051222.zip used for
0.4.7
- Freetype
http://freetype.sourceforge.net/
Currently, there are no pre-built libraries available for GCC. If you manage to get
OpenTTD working on Watcom though (do let us know if this is the case!), pre-built
versions can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip".
Contact Information
-------------------
If you have any questions regarding OS/2 issues, please contact me
(owen@owenrudge.net) and I'll try to help you out. For general OpenTTD
issues, see the Contacting section of readme.txt.
Thanks to Paul Smedley for his help with getting OpenTTD to compile under GCC on OS/2.
- Owen Rudge, 24th June 2007

@ -1,70 +0,0 @@
# Compiling OpenTTD using Microsoft Visual C++
Last updated: 2018-12-27
## Supported MSVC compilers
OpenTTD includes projects for Visual Studio 2015 Update 3 or more recent.
You can download the free Visual Studio Community Edition from Microsoft at
https://visualstudio.microsoft.com/vs/community/.
## Required files
### Microsoft platform files
OpenTTD needs the Platform SDK, if it isn't installed already. This can be
done during installing Visual Studio, by selecting
`Visual C++ MFC for x86 and x64` (and possibly
`Visual C++ ATL for x86 and x64` depending on your version). If not, you
can get it at this location:
- [MS Windows Platform SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk)
Install the SDK by following the instructions as given.
### OpenTTD dependencies
Dependencies for OpenTTD on Windows are handled via
[vcpkg](https://github.com/Microsoft/vcpkg/). First you need to install vcpkg
by following the `Quick Start` instructions of their
[README](https://github.com/Microsoft/vcpkg/blob/master/README.md).
After this, you can install the dependencies OpenTTD needs. We advise to use
the `static` versions, and OpenTTD currently needs the following dependencies:
- liblzma
- libpng
- lzo
- zlib
To install both the x64 (64bit) and x86 (32bit) variants, you can use:
```ps
.\vcpkg install liblzma:x64-windows-static libpng:x64-windows-static lzo:x64-windows-static zlib:x64-windows-static
.\vcpkg install liblzma:x86-windows-static libpng:x86-windows-static lzo:x86-windows-static zlib:x86-windows-static
```
## TTD Graphics files
See section 4.1 of README.md for the required 3rdparty files and how to install them.
## Compiling
Open the appropriate `sln` (Solution) file for your version of Visual Studio:
- VS 2015: projects/openttd_vs140.sln
- VS 2017: projects/openttd_vs141.sln
- VS 2019: projects/openttd_vs142.sln
Set the build mode to `Release` in
`Build > Configuration manager > Active solution configuration`.
You can now compile.
If everything works well the binary should be in `objs\Win[32|64]\Release\openttd.exe`
and in `bin\openttd.exe`
## Problems
If compilation fails, double-check that you are using the latest github
source. If it still doesn't work, check in on IRC (irc://irc.oftc.net/openttd),
to ask for help.

@ -1,23 +1,23 @@
OpenTTD's admin network
# OpenTTD's admin network
Last updated: 2011-01-20
------------------------------------------------------------------------
Table of contents
-----------------
1.0) Preface
2.0) Joining the network
3.0) Asking for updates
* 3.1) Polling manually
4.0) Sending rcon commands
5.0) Sending chat
* 5.1) Receiving chat
6.0) Disconnecting
7.0) Certain packet information
## Table of contents
- 1.0) [Preface](#10-preface)
- 2.0) [Joining the network](#20-joining-the-network)
- 3.0) [Asking for updates](#30-asking-for-updates)
- 3.1) [Polling manually](#31-polling-manually)
- 4.0) [Sending rcon commands](#40-sending-rcon-commands)
- 5.0) [Sending chat](#50-sending-chat)
- 5.1) [Receiving chat](#51-receiving-chat)
- 6.0) [Disconnecting](#60-disconnecting)
- 7.0) [Certain packet information](#70-certain-packet-information)
1.0) Preface
---- -------
## 1.0) Preface
The admin network provides a dedicated network protocol designed for other
applications to communicate with OpenTTD. Connected applications can execute
console commands remotely (rcon commands) with no further authentication.
@ -28,7 +28,7 @@ Table of contents
This document describes the admin network and its protocol.
Please refer to the mentioned enums in src/network/core/tcp_admin.h
Please refer to the mentioned enums in `src/network/core/tcp_admin.h`
Please also note that further improvements to the admin protocol can mean that
more packet types will be sent by the server. For forward compatibility it is
@ -36,94 +36,106 @@ Table of contents
additional data to packets. This data should be ignored. Data will never be
removed from packets in later versions, except the possibility that complete
packets are dropped in favour of a new packet.
This though will be reflected in the protocol version as announced in the
ADMIN_PACKET_SERVER_PROTOCOL in section 2.0).
`ADMIN_PACKET_SERVER_PROTOCOL` in section 2.0).
A reference implementation in Java for a client connecting to the admin interface
can be found at: http://dev.openttdcoop.org/projects/joan
can be found at: [http://dev.openttdcoop.org/projects/joan](http://dev.openttdcoop.org/projects/joan)
2.0) Joining the network
---- -------------------
## 2.0) Joining the network
Create a TCP connection to the server on port 3977. The application is
expected to authenticate within 10 seconds.
To authenticate send a ADMIN_PACKET_ADMIN_JOIN packet.
To authenticate send a `ADMIN_PACKET_ADMIN_JOIN` packet.
The server will reply with ADMIN_PACKET_SERVER_PROTOCOL followed directly by
ADMIN_PACKET_SERVER_WELCOME.
The server will reply with `ADMIN_PACKET_SERVER_PROTOCOL` followed directly by
`ADMIN_PACKET_SERVER_WELCOME`.
ADMIN_PACKET_SERVER_PROTOCOL contains details about the protocol version.
`ADMIN_PACKET_SERVER_PROTOCOL` contains details about the protocol version.
It is the job of your application to check this number and decide whether
it will remain connected or not.
Furthermore, this packet holds details on every AdminUpdateType and the
supported AdminFrequencyTypes (bitwise representation).
Furthermore, this packet holds details on every `AdminUpdateType` and the
supported `AdminFrequencyTypes` (bitwise representation).
ADMIN_PACKET_SERVER_WELCOME contains details on the server and the map,
`ADMIN_PACKET_SERVER_WELCOME` contains details on the server and the map,
e.g. if the server is dedicated, its NetworkLanguage, size of the Map, etc.
Once you have received ADMIN_PACKET_SERVER_WELCOME you are connected and
Once you have received `ADMIN_PACKET_SERVER_WELCOME` you are connected and
authorized to do your thing.
The server will not provide any game related updates unless you ask for them.
There are four packets the server will none the less send, if applicable:
- ADMIN_PACKET_SERVER_ERROR
- ADMIN_PACKET_SERVER_WELCOME
- ADMIN_PACKET_SERVER_NEWGAME
- ADMIN_PACKET_SERVER_SHUTDOWN
However, ADMIN_PACKET_SERVER_WELCOME only after a ADMIN_PACKET_SERVER_NEWGAME
However, `ADMIN_PACKET_SERVER_WELCOME` only after a `ADMIN_PACKET_SERVER_NEWGAME`
3.0) Asking for updates
---- ------------------
Asking for updates is done with ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY.
## 3.0) Asking for updates
Asking for updates is done with `ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY`.
With this packet you define which update you wish to receive at which
frequency.
Note: not every update type supports every frequency. If in doubt, you can
verify against the data received in ADMIN_PACKET_SERVER_PROTOCOL.
verify against the data received in `ADMIN_PACKET_SERVER_PROTOCOL`.
The server will not confirm your registered update. However, asking for an
invalid AdminUpdateType or a not supported AdminUpdateFrequency you will be
disconnected from the server with NETWORK_ERROR_ILLEGAL_PACKET.
invalid `AdminUpdateType` or a not supported `AdminUpdateFrequency` you will be
disconnected from the server with `NETWORK_ERROR_ILLEGAL_PACKET`.
Additional debug information can be found with a debug level of `net=3`.
Additional debug information can be found with a debug level of net=3.
`ADMIN_UPDATE_DATE` results in the server sending:
ADMIN_UPDATE_DATE results in the server sending:
- ADMIN_PACKET_SERVER_DATE
ADMIN_UPDATE_CLIENT_INFO results in the server sending:
`ADMIN_UPDATE_CLIENT_INFO` results in the server sending:
- ADMIN_PACKET_SERVER_CLIENT_JOIN
- ADMIN_PACKET_SERVER_CLIENT_INFO
- ADMIN_PACKET_SERVER_CLIENT_UPDATE
- ADMIN_PACKET_SERVER_CLIENT_QUIT
- ADMIN_PACKET_SERVER_CLIENT_ERROR
ADMIN_UPDATE_COMPANY_INFO results in the server sending:
`ADMIN_UPDATE_COMPANY_INFO` results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_NEW
- ADMIN_PACKET_SERVER_COMPANY_INFO
- ADMIN_PACKET_SERVER_COMPANY_UPDATE
- ADMIN_PACKET_SERVER_COMPANY_REMOVE
ADMIN_UPDATE_COMPANY_ECONOMY results in the server sending:
`ADMIN_UPDATE_COMPANY_ECONOMY` results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_ECONOMY
ADMIN_UPDATE_COMPANY_STATS results in the server sending:
`ADMIN_UPDATE_COMPANY_STATS` results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_STATS
ADMIN_UPDATE_CHAT results in the server sending:
`ADMIN_UPDATE_CHAT` results in the server sending:
- ADMIN_PACKET_SERVER_CHAT
ADMIN_UPDATE_CONSOLE results in the server sending:
`ADMIN_UPDATE_CONSOLE` results in the server sending:
- ADMIN_PACKET_SERVER_CONSOLE
ADMIN_UPDATE_CMD_LOGGING results in the server sending:
`ADMIN_UPDATE_CMD_LOGGING` results in the server sending:
- ADMIN_PACKET_SERVER_CMD_LOGGING
3.1) Polling manually
---- ----------------
Certain AdminUpdateTypes can also be polled:
## 3.1) Polling manually
Certain `AdminUpdateTypes` can also be polled:
- ADMIN_UPDATE_DATE
- ADMIN_UPDATE_CLIENT_INFO
- ADMIN_UPDATE_COMPANY_INFO
@ -131,88 +143,92 @@ Table of contents
- ADMIN_UPDATE_COMPANY_STATS
- ADMIN_UPDATE_CMD_NAMES
ADMIN_UPDATE_CLIENT_INFO and ADMIN_UPDATE_COMPANY_INFO accept an additional
`ADMIN_UPDATE_CLIENT_INFO` and `ADMIN_UPDATE_COMPANY_INFO` accept an additional
parameter. This parameter is used to specify a certain client or company.
Setting this parameter to UINT32_MAX (0xFFFFFFFF) will tell the server you
Setting this parameter to `UINT32_MAX (0xFFFFFFFF)` will tell the server you
want to receive updates for all clients or companies.
Not supported AdminUpdateType in the poll will result in the server
disconnecting the application with NETWORK_ERROR_ILLEGAL_PACKET.
Not supported `AdminUpdateType` in the poll will result in the server
disconnecting the application with `NETWORK_ERROR_ILLEGAL_PACKET`.
Additional debug information can be found with a debug level of net=3.
Additional debug information can be found with a debug level of `net=3`.
4.0) Sending rcon commands
---- ---------------------
Rcon runs separate from the ADMIN_UPDATE_CONSOLE AdminUpdateType. Requesting
## 4.0) Sending rcon commands
Rcon runs separate from the `ADMIN_UPDATE_CONSOLE` `AdminUpdateType`. Requesting
the execution of a remote console command is done with the packet
ADMIN_PACKET_ADMIN_RCON.
`ADMIN_PACKET_ADMIN_RCON`.
Note: No additional authentication is required for rcon commands.
The server will reply with one or more ADMIN_PACKET_SERVER_RCON packets.
Finally an ADMIN_PACKET_ADMIN_RCON_END packet will be sent. Applications
will not receive the answer twice if they have asked for the AdminUpdateType
ADMIN_UPDATE_CONSOLE, as the result is not printed on the servers console
The server will reply with one or more `ADMIN_PACKET_SERVER_RCON` packets.
Finally an `ADMIN_PACKET_ADMIN_RCON_END` packet will be sent. Applications
will not receive the answer twice if they have asked for the `AdminUpdateType`
`ADMIN_UPDATE_CONSOLE`, as the result is not printed on the servers console
(just like clients rcon commands).
Furthermore, sending a 'say' command (or any similar command) will not
Furthermore, sending a `say` command (or any similar command) will not
be sent back into the admin network.
Chat from the server itself will only be sent to the admin network when it
was not sent from the admin network.
Note that when content is queried or updated via rcon, the processing
happens asynchronously. But the ADMIN_PACKET_ADMIN_RCON_END packet is sent
happens asynchronously. But the `ADMIN_PACKET_ADMIN_RCON_END` packet is sent
already right after the content is requested as there's no immediate output.
Thus other packages and the output of content rcon command may be sent at
an arbitrary later time, mixing into the output of other console activity,
e.g. also of possible subsequent other rcon commands sent.
5.0) Sending chat
---- ------------
Sending a ADMIN_PACKET_ADMIN_CHAT results in chat originating from the server.
## 5.0) Sending chat
Sending a `ADMIN_PACKET_ADMIN_CHAT` results in chat originating from the server.
Currently four types of chat are supported:
- NETWORK_ACTION_CHAT
- NETWORK_ACTION_CHAT_CLIENT
- NETWORK_ACTION_CHAT_COMPANY
- NETWORK_ACTION_SERVER_MESSAGE
NETWORK_ACTION_SERVER_MESSAGE can be sent to a single client or company
using the respective DestType and ID.
This is a message prefixed with the 3 stars, e.g. *** foo has joined the game
`NETWORK_ACTION_SERVER_MESSAGE` can be sent to a single client or company
using the respective `DestType` and ID.
This is a message prefixed with the 3 stars, e.g. `*** foo has joined the game`
5.1) Receiving chat
---- -------------
Register ADMIN_UPDATE_CHAT at ADMIN_FREQUENCY_AUTOMATIC to receive chat.
## 5.1) Receiving chat
Register `ADMIN_UPDATE_CHAT` at `ADMIN_FREQUENCY_AUTOMATIC` to receive chat.
The application will be able to receive all chat the server can see.
The configuration option network.server_admin_chat specifies whether
The configuration option `network.server_admin_chat` specifies whether
private chat for to the server is distributed into the admin network.
6.0) Disconnecting
---- -------------
## 6.0) Disconnecting
It is a kind thing to say good bye before leaving. Do this by sending the
ADMIN_PACKET_ADMIN_QUIT packet.
`ADMIN_PACKET_ADMIN_QUIT` packet.
## 7.0) Certain packet information
7.0) Certain packet information
---- --------------------------
All ADMIN_PACKET_SERVER_* packets have an enum value greater 100.
All `ADMIN_PACKET_SERVER_*` packets have an enum value greater 100.
ADMIN_PACKET_SERVER_WELCOME
Either directly follows ADMIN_PACKET_SERVER_PROTOCOL or is sent
`ADMIN_PACKET_SERVER_WELCOME`
Either directly follows `ADMIN_PACKET_SERVER_PROTOCOL` or is sent
after a new game has been started or a map loaded, i.e. also
after ADMIN_PACKET_SERVER_NEWGAME.
ADMIN_PACKET_SERVER_CLIENT_JOIN and ADMIN_PACKET_SERVER_COMPANY_NEW
`ADMIN_PACKET_SERVER_CLIENT_JOIN` and `ADMIN_PACKET_SERVER_COMPANY_NEW`
These packets directly follow their respective INFO packets. If you receive
a CLIENT_JOIN / COMPANY_NEW packet without having received the INFO packet
it may be a good idea to POLL for the specific ID.
ADMIN_PACKET_SERVER_CMD_NAMES and ADMIN_PACKET_SERVER_CMD_LOGGING
`ADMIN_PACKET_SERVER_CMD_NAMES` and `ADMIN_PACKET_SERVER_CMD_LOGGING`
Data provided with these packets is not stable and will not be
treated as such. Do not rely on IDs or names to be constant
across different versions / revisions of OpenTTD.

@ -0,0 +1,69 @@
# How to compile lang files (OpenTTD and strgen)
Last updated: 2009-06-30
## strgen usage
This guide is only interesting for people who want to alter something
themselves without access to [translator.openttd.org](https://translator.openttd.org/).
Please note that your compiled language file will only be compatible with the OpenTTD version
you have downloaded `english.txt`, the master language file, for. While this is
not always true, namely when changes in the code have not touched language
files, your safest bet is to assume this 'limitation'.
As a first step you need to compile strgen. This is as easy as typing
`'make strgen'`. You can download the precompile strgen from:
[http://www.openttd.org/download-strgen](http://www.openttd.org/download-strgen)
strgen takes as argument a txt file and translates it to a lng file, allowing
it to be used inside OpenTTD. strgen needs the master language file
`english.txt` to work. Below are some examples of strgen usage.
## Examples
### Example 1
If you are in the root of your working copy (git repository), you should type
`./strgen/strgen -s lang lang/english.txt`
to compile `english.txt` into `english.lng`. It will be placed in the lang dir.
### Example 2
You only have the strgen executable (no working copy) and you want to compile
a txt file in the same directory. You should type
`./strgen english.txt`
and you will get and `english.lng` in the same dir.
### Example 3
You have strgen somewhere, `english.txt` in `/usr/openttd/lang` and you want the
resulting language file to go to /tmp. Use
`./strgen -s /usr/openttd/lang -d /tmp english.txt`
You can interchange `english.txt` to whichever language you want to generate a
.lng file for.
## strgen command switches
`-v | --version`
strgen will tell what git revision it was last modified
`-t | --todo`
strgen will add <TODO> to any untranslated/missing strings and use the english
strings while compiling the language file
`-w | --warning`
strgen will print any missing strings or wrongly translated (bad format)
to standard error output(stderr)
`-h | --help | -?`
Print out a summarized help message explaining these switches
`-s | --source_dir`
strgen will search for the master file english.txt in the directory specified
by this switch instead of the current directory
`-d | --dest_dir`
strgen will put <language>.lng in the directory specified by this switch; if
no dest_dir is given, output is the same as source_dir

@ -1,25 +1,24 @@
Some explanations about Desyncs
# Some explanations about Desyncs
Last updated: 2014-02-23
------------------------------------------------------------------------
Table of contents
-----------------
1.0) Desync theory
* 1.1) OpenTTD multiplayer architecture
* 1.2) What is a Desync and how is it detected
* 1.3) Typical causes of Desyncs
2.0) What to do in case of a Desync
* 2.1) Cache debugging
* 2.2) Desync recording
3.0) Evaluating the Desync records
* 3.1) Replaying
* 3.2) Evaluation the replay
* 3.3) Comparing savegames
1.1) OpenTTD multiplayer architecture
---- --------------------------------
## Table of contents
- 1.0) Desync theory
- 1.1) [OpenTTD multiplayer architecture](#11-openttd-multiplayer-architecture)
- 1.2) [What is a Desync and how is it detected](#12-what-is-a-desync-and-how-is-it-detected)
- 1.3) [Typical causes of Desyncs](#13-typical-causes-of-desyncs)
- 2.0) What to do in case of a Desync
- 2.1) [Cache debugging](#21-cache-debugging)
- 2.2) [Desync recording](#22-desync-recording)
- 3.0) Evaluating the Desync records
- 3.1) [Replaying](#31-replaying)
- 3.2) [Evaluation of the replay](#32-evaluation-of-the-replay)
- 3.3) [Comparing savegames](#33-comparing-savegames)
## 1.1) OpenTTD multiplayer architecture
OpenTTD has a huge gamestate, which changes all of the time.
The savegame contains the complete gamestate at a specific point
in time. But this state changes completely each tick: Vehicles move
@ -69,8 +68,8 @@ Table of contents
clients, which execute the command simultaneously in the same
network frame in the same order.
1.2) What is a Desync and how is it detected
---- ---------------------------------------
## 1.2) What is a Desync and how is it detected
In the ideal case all clients have the same gamestate as the server
and run in sync. That is, vehicle movement is the same on all
clients, and commands are executed the same everywhere and
@ -112,8 +111,8 @@ Table of contents
enough to finally affect the checksum. (There was once a desync
which was only noticed by the checksum after 20 game years.)
1.3) Typical causes of Desyncs
---- -------------------------
## 1.3) Typical causes of Desyncs
Desyncs can be caused by the following scenarios:
- The savegame does not describe the complete gamestate.
- Some information which affects the progression of the
@ -138,8 +137,8 @@ Table of contents
using commands.
2.1) Cache debugging
---- ---------------
## 2.1) Cache debugging
Desyncs which are caused by improper cache validation can
often be found by enabling cache validation:
- Start OpenTTD with '-d desync=2'.
@ -151,8 +150,8 @@ Table of contents
Mind that this type of debugging can also be done in singleplayer.
2.2) Desync recording
---- ----------------
## 2.2) Desync recording
If you have a server, which happens to encounter Desyncs often,
you can enable recording of the gamestate alterations. This
will later allow the replay the gamestate and locate the Desync
@ -180,8 +179,8 @@ Table of contents
However, they also take a lot of disk space.
3.1) Replaying
---- ---------
## 3.1) Replaying
To replay a Desync recording, you need these files:
- The savegame from when the server was started, resp.
the automatically created savegame from when the map
@ -201,8 +200,8 @@ Table of contents
This replays the server log and creates new 'commands-out.log'
and 'dmp_cmds_*.sav' in your autosave folder.
3.2) Evaluation the replay
---- ---------------------
## 3.2) Evaluation of the replay
The replaying will also compare the checksums which are part of
the 'commands-out.log' with the replayed gamestate.
If they differ, it will trigger a 'NOT_REACHED'.
@ -242,8 +241,8 @@ Table of contents
dates, and the original log will contain the chat, but otherwise they
should match.
3.2) Comparing savegames
---- -------------------
## 3.3) Comparing savegames
The binary form of the savegames from the original server and from
your replay will always differ:
- The savegame contains paths to used NewGRF files.

@ -1,13 +1,13 @@
Some clarifications about the link graph
----------------------------------------
# Some clarifications about the link graph
InitializeLinkGraphs joins all threads, so if the game is abandoned
`InitializeLinkGraphs` joins all threads, so if the game is abandoned
with some threads still running, they're joined as soon as the next game
(possibly the title game) is started. See also InitializeGame.
(possibly the title game) is started. See also `InitializeGame`.
The MCF (multi-commodity flow) algorithm can be quite CPU-hungry as it's
NP-hard and takes exponential time (though with a very small constant
factor) in the number of nodes.
This is why it is run in a separate thread where possible. However after
some time the thread is joined and if it hasn't finished by then the game
will hang. This problem gets worse if we are running on a platform without

@ -1,28 +1,28 @@
Multiplayer manual for OpenTTD
# Multiplayer manual for OpenTTD
Last updated: 2011-02-16
------------------------------------------------------------------------
Table of contents
-----------------
1.0) Starting a server
2.0) Connecting to a server
* 2.1) Connecting to a server over the console
3.0) Playing internet games
4.0) Tips for servers
* 4.1) Imposing landscaping limits
5.0) Some useful things
6.0) Troubleshooting
## Table of contents
- 1.0) [Starting a server](#10-starting-a-server)
- 2.0) [Connecting to a server](#20-connecting-to-a-server)
- 2.1) [Connecting to a server over the console](#21-connecting-to-a-server-over-the-console)
- 3.0) [Playing internet games](#30-playing-internet-games)
- 4.0) [Tips for servers](#40-tips-for-servers)
- 4.1)[Imposing landscaping limits](#41-imposing-landscaping-limits)
- 5.0) [Some useful things](#50-some-useful-things)
- 6.0) [Troubleshooting](#60-troubleshooting)
1.0) Starting a server
---- -----------------
## 1.0) Starting a server
- Make sure that you have your firewall of the computer as well as possible
routers or modems of the server configured such that:
* port 3979 is free for both UDP and TCP connections in- and outgoing
* port 3978 is free outbound for UDP in order to advertise with the master
- port 3979 is free for both UDP and TCP connections in- and outgoing
- port 3978 is free outbound for UDP in order to advertise with the master
server (if desired). Otherwise you'll have to tell players your IP.
* port 3977 if use of the admin interface is desired (see admin_network.txt)
- port 3977 if use of the admin interface is desired (see admin_network.txt)
- Click "multiplayer" on the startup screen
- Click "start server"
- Type in a game name
@ -33,42 +33,36 @@ Table of contents
- Start playing
2.0) Connecting to a server
---- ----------------------
- Click "multiplayer" on the startup screen
## 2.0) Connecting to a server
- Click "multiplayer" on the startup screen
- If you want to connect to any network game in your LAN click on 'LAN', then
on 'Find Server'
- If you want to see which servers all online on the Internet, click on
'Internet' and 'Find Server'
- If there were more than one server
- select one in the list below the buttons
- click on 'join game'
- select one in the list below the buttons
- click on 'join game'
- If you want to play and you have the ip or hostname of the game server you
want connect to.
- click add server
- type in the ip address or hostname
- if you want to add a port use :<port>
- click add server
- type in the ip address or hostname
- if you want to add a port use :<port>
- Now you can select a company and press: "Join company", to help that company
- Or you can press "Spectate game", to spectate the game
- Or you can press "New company", and start your own company (if there are
- Or you can press "Spectate game", to spectate the game
- Or you can press "New company", and start your own company (if there are
slots free)
- You see a progressbar how far you are with joining the server.
- Happy playing
2.1) Connecting to a server over the console
---- ---------------------------------------
## 2.1) Connecting to a server over the console
- Open the console and type in the following command:
connect <ip/host>:<port>#<company-no>
connect `<ip/host>:<port>#<company-no>`
## 3.0) Playing internet games
3.0) Playing internet games
---- ----------------------
- Servers with a red dot behind it have a different version then you have. You
will not be able to join those servers.
@ -98,8 +92,8 @@ Table of contents
NB: changing frame_freq has more effect on the bandwidth then sync_freq.
4.0) Tips for servers
---- ----------------
## 4.0) Tips for servers
- You can launch a dedicated server by adding -D as parameter.
- In UNIX like systems, you can fork your dedicated server by adding -f as
parameter.
@ -155,8 +149,8 @@ Table of contents
maximum memory usage for packets is:
#max_clients * #max_clients * bytes_per_frame * 10 KiB.
4.1) Imposing landscaping limits
---- ---------------------------
### 4.1) Imposing landscaping limits
- You can impose limits on companies by the following 4 settings:
- terraform_per_64k_frames
- terraform_frame_burst
@ -196,8 +190,8 @@ Table of contents
affected by the above settings.
5.0) Some useful things
---- ------------------
## 5.0) Some useful things
- You can protect your company so nobody else can join uninvited. To do this,
set a password in your Company Screen
@ -209,8 +203,8 @@ Table of contents
- Servers can now kick players, so don't make them use it!
6.0) Troubleshooting
---- ---------------
## 6.0) Troubleshooting
- My advertising server does not show up in list at servers.openttd.org
Run openttd with the '-d net=2' parameter. That will show which incoming
communication is received, whether the replies from the master server or

@ -1,6 +1,6 @@
OpenTTD's known bugs
Last updated: 2019-02-24
Release version: 1.9.0-beta3
Last updated: 2019-10-29
Release version: 1.10.0-beta1
------------------------------------------------------------------------

@ -1,3 +1,32 @@
openttd (1.10.0~beta1-0) unstable; urgency=low
* New upstream release 1.10.0-beta1
-- OpenTTD <info@openttd.org> Tue, 29 Oct 2019 00:00:00 +0000
openttd (1.9.3-0) unstable; urgency=low
* New upstream release 1.9.3
-- OpenTTD <info@openttd.org> Mon, 16 Sep 2019 21:00:00 +0200
openttd (1.9.3~RC1-0) unstable; urgency=low
* New upstream release 1.9.3-RC1
-- OpenTTD <info@openttd.org> Sat, 07 Sep 2019 23:30:00 +0200
openttd (1.9.2-0) unstable; urgency=low
* New upstream release 1.9.2
-- OpenTTD <info@openttd.org> Sun, 07 Jul 2019 23:00:00 +0200
openttd (1.9.1-0) unstable; urgency=low
* New upstream release 1.9.1
-- OpenTTD <info@openttd.org> Mon, 08 Apr 2019 20:00:00 +0100
openttd (1.9.0-0) unstable; urgency=low
* New upstream release 1.9.0

@ -29,7 +29,7 @@ include /usr/share/dpkg/buildflags.mk
# to be explicit about the dependencies, in case we're not running in a
# clean build root.
override_dh_auto_configure:
./configure $(CROSS) --prefix-dir=/usr --install-dir=debian/openttd --without-allegro --with-zlib --with-sdl --with-png --with-freetype --with-fontconfig --with-icu --with-liblzo2 --with-lzma --without-xdg-basedir --without-iconv --disable-strip CFLAGS="$(CFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" CFLAGS_BUILD="$(CFLAGS) $(CPPFLAGS)" CXXFLAGS_BUILD="$(CXXFLAGS) $(CPPFLAGS)" LDFLAGS_BUILD="$(LDFLAGS)"
./configure $(CROSS) --prefix-dir=/usr --install-dir=debian/openttd --without-allegro --with-zlib --with-sdl --with-png --with-freetype --with-fontconfig --with-icu-sort --with-liblzo2 --with-lzma --without-xdg-basedir --without-iconv --disable-strip CFLAGS="$(CFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" CFLAGS_BUILD="$(CFLAGS) $(CPPFLAGS)" CXXFLAGS_BUILD="$(CXXFLAGS) $(CPPFLAGS)" LDFLAGS_BUILD="$(LDFLAGS)"
# Do some extra installation
override_dh_auto_install:

@ -71,7 +71,7 @@
<!-- page 1: introductory page -->
<PAGE INDEX="1" TYPE="README">
<NEXTBUTTON TARGET=2>~Next</NEXTBUTTON>
<README EXTRACTFROMPCK="1">README.TXT</README>
<README EXTRACTFROMPCK="1">README.md</README>
<TEXT>Welcome to the OpenTTD installer. This program will install OpenTTD 1.0 on your system. Before we begin the installation process, please take a moment to read the following document.
Select "Next" to continue, or "Cancel" to abort installation.</TEXT>
@ -80,7 +80,7 @@ Select "Next" to continue, or "Cancel" to abort installation.</TEXT>
<!-- page 2: licence page -->
<PAGE INDEX="2" TYPE="README">
<NEXTBUTTON TARGET=3>~Next</NEXTBUTTON>
<README EXTRACTFROMPCK="1">COPYING</README>
<README EXTRACTFROMPCK="1">COPYING.md</README>
<TEXT>OpenTTD is licenced under the GNU General Public License. The text of the licence is below.
Select "Next" if you agree to this licence.

@ -81,7 +81,7 @@ the original data from the game or install the recommend subackages OpenGFX for
free graphics, OpenSFX for free sounds and OpenMSX for free music.
OpenTTD is licensed under the GNU General Public License version 2.0. For more
information, see the file 'COPYING' included with every release and source
information, see the file 'COPYING.md' included with every release and source
download of the game.
%package gui

@ -63,7 +63,7 @@ Var CDDRIVE
!define MUI_ABORTWARNING
!define MUI_WELCOMEPAGE_TITLE_3LINES
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\..\..\COPYING"
!insertmacro MUI_PAGE_LICENSE "..\..\..\COPYING.md"
!define MUI_COMPONENTSPAGE_SMALLDESC
!insertmacro MUI_PAGE_COMPONENTS
@ -145,8 +145,8 @@ Section "!OpenTTD" Section1
; Copy some documentation files
SetOutPath "$INSTDIR\docs\"
File ${PATH_ROOT}docs\multiplayer.txt
Push "$INSTDIR\docs\multiplayer.txt"
File ${PATH_ROOT}docs\multiplayer.md
Push "$INSTDIR\docs\multiplayer.md"
Call unix2dos
; Copy the rest of the stuff
@ -156,8 +156,8 @@ Section "!OpenTTD" Section1
File ${PATH_ROOT}changelog.txt
Push "$INSTDIR\changelog.txt"
Call unix2dos
File ${PATH_ROOT}COPYING
Push "$INSTDIR\COPYING"
File ${PATH_ROOT}COPYING.md
Push "$INSTDIR\COPYING.md"
Call unix2dos
File ${PATH_ROOT}README.md
Push "$INSTDIR\README.md"
@ -218,7 +218,7 @@ Section "!OpenTTD" Section1
CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" "$INSTDIR\Changelog.txt"
CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Known-bugs.lnk" "$INSTDIR\known-bugs.txt"
CreateDirectory "$SMPROGRAMS\$SHORTCUTS\Docs"
CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Docs\Multiplayer.lnk" "$INSTDIR\docs\multiplayer.txt"
CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Docs\Multiplayer.lnk" "$INSTDIR\docs\multiplayer.md"
CreateDirectory "$SMPROGRAMS\$SHORTCUTS\Scripts"
CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Scripts\Readme.lnk" "$INSTDIR\scripts\README.md"
!insertmacro MUI_STARTMENU_WRITE_END
@ -392,7 +392,7 @@ Section "Uninstall"
Delete "$INSTDIR\README.md"
Delete "$INSTDIR\known-bugs.txt"
Delete "$INSTDIR\openttd.exe"
Delete "$INSTDIR\COPYING"
Delete "$INSTDIR\COPYING.md"
Delete "$INSTDIR\INSTALL.LOG"
Delete "$INSTDIR\crash.log"
Delete "$INSTDIR\crash.dmp"

@ -146,6 +146,7 @@ void AIInstance::RegisterAPI()
SQAIEventSubsidyOffer_Register(this->engine);
SQAIEventSubsidyOfferExpired_Register(this->engine);
SQAIEventTownFounded_Register(this->engine);
SQAIEventVehicleAutoReplaced_Register(this->engine);
SQAIEventVehicleCrashed_Register(this->engine);
SQAIEventVehicleLost_Register(this->engine);
SQAIEventVehicleUnprofitable_Register(this->engine);

@ -2001,8 +2001,8 @@ static uint GetNumTerminals(const AirportFTAClass *apc)
static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc)
{
/* example of more terminalgroups
* {0,HANGAR,NOTHING_block,1}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
* Heading 255 denotes a group. We see 2 groups here:
* {0,HANGAR,NOTHING_block,1}, {0,TERMGROUP,TERM_GROUP1_block,0}, {0,TERMGROUP,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
* Heading TERMGROUP denotes a group. We see 2 groups here:
* 1. group 0 -- TERM_GROUP1_block (check block)
* 2. group 1 -- TERM_GROUP2_ENTER_block (check block)
* First in line is checked first, group 0. If the block (TERM_GROUP1_block) is free, it
@ -2015,7 +2015,7 @@ static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc)
const AirportFTA *temp = apc->layout[v->pos].next;
while (temp != nullptr) {
if (temp->heading == 255) {
if (temp->heading == TERMGROUP) {
if (!(st->airport.flags & temp->block)) {
/* read which group do we want to go to?
* (the first free group) */

@ -60,29 +60,30 @@ enum AirportMovingDataFlags {
/** Movement States on Airports (headings target) */
enum AirportMovementStates {
TO_ALL = 0, ///< Go in this direction for every target.
HANGAR = 1, ///< Heading for hangar.
TERM1 = 2, ///< Heading for terminal 1.
TERM2 = 3, ///< Heading for terminal 2.
TERM3 = 4, ///< Heading for terminal 3.
TERM4 = 5, ///< Heading for terminal 4.
TERM5 = 6, ///< Heading for terminal 5.
TERM6 = 7, ///< Heading for terminal 6.
HELIPAD1 = 8, ///< Heading for helipad 1.
HELIPAD2 = 9, ///< Heading for helipad 2.
TAKEOFF = 10, ///< Airplane wants to leave the airport.
STARTTAKEOFF = 11, ///< Airplane has arrived at a runway for take-off.
ENDTAKEOFF = 12, ///< Airplane has reached end-point of the take-off runway.
HELITAKEOFF = 13, ///< Helicopter wants to leave the airport.
FLYING = 14, ///< %Vehicle is flying in the air.
LANDING = 15, ///< Airplane wants to land.
ENDLANDING = 16, ///< Airplane wants to finish landing.
HELILANDING = 17, ///< Helicopter wants to land.
HELIENDLANDING = 18, ///< Helicopter wants to finish landing.
TERM7 = 19, ///< Heading for terminal 7.
TERM8 = 20, ///< Heading for terminal 8.
HELIPAD3 = 21, ///< Heading for helipad 3.
MAX_HEADINGS = 21, ///< Last valid target to head for.
TO_ALL = 0, ///< Go in this direction for every target.
HANGAR = 1, ///< Heading for hangar.
TERM1 = 2, ///< Heading for terminal 1.
TERM2 = 3, ///< Heading for terminal 2.
TERM3 = 4, ///< Heading for terminal 3.
TERM4 = 5, ///< Heading for terminal 4.
TERM5 = 6, ///< Heading for terminal 5.
TERM6 = 7, ///< Heading for terminal 6.
HELIPAD1 = 8, ///< Heading for helipad 1.
HELIPAD2 = 9, ///< Heading for helipad 2.
TAKEOFF = 10, ///< Airplane wants to leave the airport.
STARTTAKEOFF = 11, ///< Airplane has arrived at a runway for take-off.
ENDTAKEOFF = 12, ///< Airplane has reached end-point of the take-off runway.
HELITAKEOFF = 13, ///< Helicopter wants to leave the airport.
FLYING = 14, ///< %Vehicle is flying in the air.
LANDING = 15, ///< Airplane wants to land.
ENDLANDING = 16, ///< Airplane wants to finish landing.
HELILANDING = 17, ///< Helicopter wants to land.
HELIENDLANDING = 18, ///< Helicopter wants to finish landing.
TERM7 = 19, ///< Heading for terminal 7.
TERM8 = 20, ///< Heading for terminal 8.
HELIPAD3 = 21, ///< Heading for helipad 3.
MAX_HEADINGS = 21, ///< Last valid target to head for.
TERMGROUP = 255, ///< Aircraft is looking for a free terminal in a terminalgroup.
};
/** Movement Blocks on Airports blocks (eg_airport_flags). */

@ -22,6 +22,7 @@
#include "core/random_func.hpp"
#include "vehiclelist.h"
#include "road.h"
#include "ai/ai.hpp"
#include "table/strings.h"
@ -434,6 +435,8 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b
TransferCargo(old_v, new_v, false);
*single_unit = new_v;
AI::NewEvent(old_v->owner, new ScriptEventVehicleAutoReplaced(old_v->index, new_v->index));
}
/* Sell the old vehicle */
@ -603,7 +606,10 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
cost.AddCost(DoCommand(0, w->index, 0, flags | DC_AUTOREPLACE, GetCmdSellVeh(w)));
if ((flags & DC_EXEC) != 0) {
old_vehs[i] = nullptr;
if (i == 0) old_head = nullptr;
if (i == 0) {
AI::NewEvent(old_head->owner, new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index));
old_head = nullptr;
}
}
}
@ -657,6 +663,8 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
if ((flags & DC_EXEC) != 0) {
TransferCargo(old_head, new_head, true);
*chain = new_head;
AI::NewEvent(old_head->owner, new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index));
}
/* Sell the old vehicle */

@ -270,20 +270,34 @@ static bool EnginePowerVsRunningCostSorter(const EngineID &a, const EngineID &b)
{
const Engine *e_a = Engine::Get(a);
const Engine *e_b = Engine::Get(b);
/* Here we are using a few tricks to get the right sort.
* We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
* we will actually calculate cunning cost/power (to make it more than 1).
* Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
* Another thing is that both power and running costs should be doubled for multiheaded engines.
* Since it would be multiplying with 2 in both numerator and denominator, it will even themselves out and we skip checking for multiheaded. */
Money va = (e_a->GetRunningCost()) / max(1U, (uint)e_a->GetPower());
Money vb = (e_b->GetRunningCost()) / max(1U, (uint)e_b->GetPower());
int r = ClampToI32(vb - va);
/* Use EngineID to sort instead since we want consistent sorting */
if (r == 0) return EngineNumberSorter(a, b);
return _engine_sort_direction ? r > 0 : r < 0;
uint p_a = e_a->GetPower();
uint p_b = e_b->GetPower();
Money r_a = e_a->GetRunningCost();
Money r_b = e_b->GetRunningCost();
/* Check if running cost is zero in one or both engines.
* If only one of them is zero then that one has higher value,
* else if both have zero cost then compare powers. */
if (r_a == 0) {
if (r_b == 0) {
/* If it is ambiguous which to return go with their ID */
if (p_a == p_b) return EngineNumberSorter(a, b);
return _engine_sort_direction != (p_a < p_b);
}
return !_engine_sort_direction;
}
if (r_b == 0) return _engine_sort_direction;
/* Using double for more precision when comparing close values.
* This shouldn't have any major effects in performance nor in keeping
* the game in sync between players since it's used in GUI only in client side */
double v_a = (double)p_a / (double)r_a;
double v_b = (double)p_b / (double)r_b;
/* Use EngineID to sort if both have same power/running cost,
* since we want consistent sorting.
* Also if both have no power then sort with reverse of running cost to simulate
* previous sorting behaviour for wagons. */
if (v_a == 0 && v_b == 0) return !EngineRunningCostSorter(a, b);
if (v_a == v_b) return EngineNumberSorter(a, b);
return _engine_sort_direction != (v_a < v_b);
}
/* Train sorting functions */

@ -2275,7 +2275,7 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (c == nullptr || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR;
/* Protect new companies from hostile takeovers */
if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_ERROR_PROTECTED);
if (_cur_year - c->inaugurated_year < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED);
/* Those lines are here for network-protection (clients can be slow) */
if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;

@ -205,12 +205,18 @@ const char *FiosBrowseTo(const FiosItem *item)
*/
static void FiosMakeFilename(char *buf, const char *path, const char *name, const char *ext, const char *last)
{
const char *period;
if (path != nullptr) {
const char *buf_start = buf;
buf = strecpy(buf, path, last);
/* Remove trailing path separator, if present */
if (buf > buf_start && buf[-1] == PATHSEPCHAR) buf--;
}
/* Don't append the extension if it is already there */
period = strrchr(name, '.');
const char *period = strrchr(name, '.');
if (period != nullptr && strcasecmp(period, ext) == 0) ext = "";
seprintf(buf, last, "%s" PATHSEP "%s%s", path, name, ext);
seprintf(buf, last, PATHSEP "%s%s", name, ext);
}
/**

@ -394,7 +394,7 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
/* Get font reference from name. */
UInt8 file_path[PATH_MAX];
OSStatus os_err = -1;
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8);
CFAutoRelease<CFStringRef> name(CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8));
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
if (MacOSVersionIsAtLeast(10, 6, 0)) {
@ -402,28 +402,21 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
* something, no matter the name. As such, we can't use it to check for existence.
* We instead query the list of all font descriptors that match the given name which
* does not do this stupid name fallback. */
CTFontDescriptorRef name_desc = CTFontDescriptorCreateWithNameAndSize(name, 0.0);
CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontNameAttribute, 1, &kCFTypeSetCallBacks);
CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(name_desc, mandatory_attribs);
CFRelease(mandatory_attribs);
CFRelease(name_desc);
CFRelease(name);
CFAutoRelease<CTFontDescriptorRef> name_desc(CTFontDescriptorCreateWithNameAndSize(name.get(), 0.0));
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontNameAttribute, 1, &kCFTypeSetCallBacks));
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(name_desc.get(), mandatory_attribs.get()));
/* Loop over all matches until we can get a path for one of them. */
for (CFIndex i = 0; descs != nullptr && i < CFArrayGetCount(descs) && os_err != noErr; i++) {
CTFontRef font = CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i), 0.0, nullptr);
CFURLRef fontURL = (CFURLRef)CTFontCopyAttribute(font, kCTFontURLAttribute);
if (CFURLGetFileSystemRepresentation(fontURL, true, file_path, lengthof(file_path))) os_err = noErr;
CFRelease(font);
CFRelease(fontURL);
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()) && os_err != noErr; i++) {
CFAutoRelease<CTFontRef> font(CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i), 0.0, nullptr));
CFAutoRelease<CFURLRef> fontURL((CFURLRef)CTFontCopyAttribute(font.get(), kCTFontURLAttribute));
if (CFURLGetFileSystemRepresentation(fontURL.get(), true, file_path, lengthof(file_path))) os_err = noErr;
}
if (descs != nullptr) CFRelease(descs);
} else
#endif
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6)
ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault);
CFRelease(name);
ATSFontRef font = ATSFontFindFromName(name.get(), kATSOptionFlagsDefault);
if (font == kInvalidFont) return err;
/* Get a file system reference for the font. */
@ -480,31 +473,28 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
if (sep != nullptr) *sep = '\0';
}
/* Create a font descriptor matching the wanted language and latin (english) glyphs. */
/* Create a font descriptor matching the wanted language and latin (english) glyphs.
* Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */
CFStringRef lang_codes[2];
lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8);
lang_codes[1] = CFSTR("en");
CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks);
CFDictionaryRef lang_attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontLanguagesAttribute, (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CTFontDescriptorRef lang_desc = CTFontDescriptorCreateWithAttributes(lang_attribs);
CFAutoRelease<CFDictionaryRef> lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontLanguagesAttribute, (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
CFAutoRelease<CTFontDescriptorRef> lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get()));
CFRelease(lang_arr);
CFRelease(lang_attribs);
CFRelease(lang_codes[0]);
/* Get array of all font descriptors for the wanted language. */
CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontLanguagesAttribute, 1, &kCFTypeSetCallBacks);
CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(lang_desc, mandatory_attribs);
CFRelease(mandatory_attribs);
CFRelease(lang_desc);
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontLanguagesAttribute, 1, &kCFTypeSetCallBacks));
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get()));
for (CFIndex i = 0; descs != nullptr && i < CFArrayGetCount(descs); i++) {
CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i);
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) {
CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i);
/* Get font traits. */
CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
CFAutoRelease<CFDictionaryRef> traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute));
CTFontSymbolicTraits symbolic_traits;
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
CFRelease(traits);
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
/* Skip symbol fonts and vertical fonts. */
if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue;
@ -515,9 +505,8 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
/* Get font name. */
char name[128];
CFStringRef font_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute);
CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8);
CFRelease(font_name);
CFAutoRelease<CFStringRef> font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute));
CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8);
/* There are some special fonts starting with an '.' and the last
* resort font that aren't usable. Skip them. */
@ -531,7 +520,6 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
break;
}
}
if (descs != nullptr) CFRelease(descs);
} else
#endif
{

@ -72,11 +72,15 @@ IndustryBuildData _industry_builder; ///< In-game manager of industries.
*/
void ResetIndustries()
{
memset(&_industry_specs, 0, sizeof(_industry_specs));
memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
/* once performed, enable only the current climate industries */
for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
/* Reset the spec to default */
if (i < lengthof(_origin_industry_specs)) {
_industry_specs[i] = _origin_industry_specs[i];
} else {
_industry_specs[i] = IndustrySpec{};
}
/* Enable only the current climate industries */
_industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
}
@ -1129,11 +1133,16 @@ static void ProduceIndustryGoods(Industry *i)
/* play a sound? */
if ((i->counter & 0x3F) == 0) {
uint32 r;
uint num;
if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
SndPlayTileFx(
(SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
i->location.tile);
if (Chance16R(1, 14, r) && indsp->number_of_sounds != 0 && _settings_client.sound.ambient) {
for (size_t j = 0; j < lengthof(i->last_month_production); j++) {
if (i->last_month_production[j] > 0) {
/* Play sound since last month had production */
SndPlayTileFx(
(SoundFx)(indsp->random_sounds[((r >> 16) * indsp->number_of_sounds) >> 16]),
i->location.tile);
break;
}
}
}
}
@ -1418,8 +1427,8 @@ bool IsSlopeRefused(Slope current, Slope refused)
/**
* Are the tiles of the industry free?
* @param tile Position to check.
* @param it Industry tiles table.
* @param itspec_index The index of the itsepc to build/fund
* @param layout Industry tiles table.
* @param layout_index The index of the layout to build/fund
* @param type Type of the industry.
* @param initial_random_bits The random bits the industry is going to have after construction.
* @param founder Industry founder
@ -1427,14 +1436,14 @@ bool IsSlopeRefused(Slope current, Slope refused)
* @param[out] custom_shape_check Perform custom check for the site.
* @return Failed or succeeded command.
*/
static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, uint itspec_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
{
bool refused_slope = false;
bool custom_shape = false;
do {
IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
for (const IndustryTileLayoutTile &it : layout) {
IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
if (!IsValidTile(cur_tile)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
@ -1459,7 +1468,7 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
custom_shape = true;
CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
if (ret.Failed()) return ret;
} else {
Slope tileh = GetTileSlope(cur_tile);
@ -1487,7 +1496,7 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
if (ret.Failed()) return ret;
}
}
} while ((++it)->ti.x != -0x80);
}
if (custom_shape_check != nullptr) *custom_shape_check = custom_shape;
@ -1556,18 +1565,17 @@ static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int i
* This function tries to flatten out the land below an industry, without
* damaging the surroundings too much.
*/
static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileLayout &layout, int type)
{
const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
int max_x = 0;
int max_y = 0;
/* Finds dimensions of largest variant of this industry */
do {
if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
if (it->ti.x > max_x) max_x = it->ti.x;
if (it->ti.y > max_y) max_y = it->ti.y;
} while ((++it)->ti.x != MKEND);
for (const IndustryTileLayoutTile &it : layout) {
if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; // watercheck tiles don't count for footprint size
if (it.ti.x > max_x) max_x = it.ti.x;
if (it.ti.y > max_y) max_y = it.ti.y;
}
/* Remember level height */
uint h = TileHeight(tile);
@ -1721,16 +1729,16 @@ static void PopulateStationsNearby(Industry *ind)
/**
* Put an industry on the map.
* @param i Just allocated poolitem, mostly empty.
* @param tile North tile of the industry.
* @param type Type of the industry.
* @param it Industrylayout to build.
* @param layout Number of the layout.
* @param t Nearest town.
* @param founder Founder of the industry; OWNER_NONE in case of random construction.
* @param i Just allocated poolitem, mostly empty.
* @param tile North tile of the industry.
* @param type Type of the industry.
* @param layout Industrylayout to build.
* @param layout_index Number of the industry layout.
* @param t Nearest town.
* @param founder Founder of the industry; OWNER_NONE in case of random construction.
* @param initial_random_bits Random bits for the industry.
*/
static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileLayout &layout, size_t layout_index, Town *t, Owner founder, uint16 initial_random_bits)
{
const IndustrySpec *indspec = GetIndustrySpec(type);
@ -1775,7 +1783,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
/* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
* 0 = created prior of newindustries
* else, chosen layout + 1 */
i->selected_layout = layout + 1;
i->selected_layout = (byte)(layout_index + 1);
i->prod_level = PRODLEVEL_DEFAULT;
@ -1871,17 +1879,17 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
/* Plant the tiles */
do {
TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
for (const IndustryTileLayoutTile &it : layout) {
TileIndex cur_tile = tile + ToTileIndexDiff(it.ti);
if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
if (it.gfx != GFX_WATERTILE_SPECIALCHECK) {
i->location.Add(cur_tile);
WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
MakeIndustry(cur_tile, i->index, it.gfx, Random(), wc);
if (_generating_world) {
SetIndustryConstructionCounter(cur_tile, 3);
@ -1889,11 +1897,11 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
}
/* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it.gfx);
const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
}
} while ((++it)->ti.x != -0x80);
}
if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
@ -1910,7 +1918,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
* @param type of industry to build
* @param flags of operations to conduct
* @param indspec pointer to industry specifications
* @param itspec_index the index of the itsepc to build/fund
* @param layout_index the index of the itsepc to build/fund
* @param random_var8f random seed (possibly) used by industries
* @param random_initial_bits The random bits the industry is going to have after construction.
* @param founder Founder of the industry
@ -1920,28 +1928,28 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
*
* @post \c *ip contains the newly created industry if all checks are successful and the \a flags request actual creation, else it contains \c nullptr afterwards.
*/
static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, uint itspec_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, size_t layout_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
{
assert(itspec_index < indspec->num_table);
const IndustryTileTable *it = indspec->table[itspec_index];
assert(layout_index < indspec->layouts.size());
const IndustryTileLayout &layout = indspec->layouts[layout_index];
bool custom_shape_check = false;
*ip = nullptr;
std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
CommandCost ret = CheckIfIndustryTilesAreFree(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
_cleared_object_areas = object_areas;
if (ret.Failed()) return ret;
if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
} else {
ret = _check_new_industry_procs[indspec->check_proc](tile);
}
if (ret.Failed()) return ret;
if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
!_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
!_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, layout, type)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
@ -1960,8 +1968,8 @@ static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, Do
if (flags & DC_EXEC) {
*ip = new Industry(tile);
if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, layout, type);
DoCreateNewIndustry(*ip, tile, type, layout, layout_index, t, founder, random_initial_bits);
}
return CommandCost();
@ -1987,7 +1995,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
const IndustrySpec *indspec = GetIndustrySpec(it);
/* Check if the to-be built/founded industry is available for this climate. */
if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR;
/* If the setting for raw-material industries is not on, you cannot build raw-material industries.
* Raw material industries are industries that do not accept cargo (at least for now) */
@ -2003,7 +2011,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
randomizer.SetSeed(p2);
uint16 random_initial_bits = GB(p2, 0, 16);
uint32 random_var8f = randomizer.Next();
int num_layouts = indspec->num_table;
size_t num_layouts = indspec->layouts.size();
CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
@ -2022,9 +2030,9 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
*/
tile = RandomTile();
/* Start with a random layout */
int layout = RandomRange(num_layouts);
size_t layout = RandomRange((uint32)num_layouts);
/* Check now each layout, starting with the random one */
for (int j = 0; j < num_layouts; j++) {
for (size_t j = 0; j < num_layouts; j++) {
layout = (layout + 1) % num_layouts;
ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
if (ret.Succeeded()) break;
@ -2035,11 +2043,11 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
cur_company.Restore();
}
} else {
int layout = GB(p1, 8, 8);
size_t layout = GB(p1, 8, 8);
if (layout >= num_layouts) return CMD_ERROR;
/* Check subsequently each layout, starting with the given layout in p1 */
for (int i = 0; i < num_layouts; i++) {
for (size_t i = 0; i < num_layouts; i++) {
layout = (layout + 1) % num_layouts;
ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
if (ret.Succeeded()) break;
@ -2071,7 +2079,8 @@ static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAv
uint32 seed = Random();
uint32 seed2 = Random();
Industry *i = nullptr;
CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
size_t layout_index = RandomRange((uint32)indspec->layouts.size());
CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
assert(i != nullptr || ret.Failed());
return i;
}
@ -2086,7 +2095,7 @@ static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *forc
{
const IndustrySpec *ind_spc = GetIndustrySpec(it);
uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
if (!ind_spc->enabled || ind_spc->num_table == 0 ||
if (!ind_spc->enabled || ind_spc->layouts.empty() ||
(_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
(chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
*force_at_least_one = false;
@ -2116,7 +2125,7 @@ static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
const IndustrySpec *ind_spc = GetIndustrySpec(it);
byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
if (!ind_spc->enabled || ind_spc->num_table == 0 ||
if (!ind_spc->enabled || ind_spc->layouts.empty() ||
((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
(chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
@ -2955,6 +2964,13 @@ bool IndustrySpec::UsesSmoothEconomy() const
!(HasBit(this->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CHANGE) || HasBit(this->callback_mask, CBM_IND_PROD_CHANGE_BUILD)); // production change callbacks
}
IndustrySpec::~IndustrySpec()
{
if (HasBit(this->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
free(this->random_sounds);
}
}
static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
{
if (AutoslopeEnabled()) {

@ -647,6 +647,7 @@ public:
/* We do not need to protect ourselves against "Random Many Industries" in this mode */
const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
uint32 seed = InteractiveRandom();
uint32 layout_index = InteractiveRandomRange((uint32)indsp->layouts.size());
if (_game_mode == GM_EDITOR) {
/* Show error if no town exists at all */
@ -660,14 +661,14 @@ public:
_generating_world = true;
_ignore_restrictions = true;
DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed,
DoCommandP(tile, (layout_index << 8) | this->selected_type, seed,
CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY), &CcBuildIndustry);
cur_company.Restore();
_ignore_restrictions = false;
_generating_world = false;
} else {
success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
success = DoCommandP(tile, (layout_index << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
}
/* If an industry has been built, just reset the cursor and the system */

@ -13,6 +13,7 @@
#define INDUSTRYTYPE_H
#include <array>
#include <vector>
#include "map_type.h"
#include "slope_type.h"
#include "industry_type.h"
@ -23,7 +24,6 @@
enum IndustryCleanupType {
CLEAN_RANDOMSOUNDS, ///< Free the dynamically allocated sounds table
CLEAN_TILELAYOUT, ///< Free the dynamically allocated tile layout structure
};
/** Available types of industry lifetimes. */
@ -93,17 +93,20 @@ enum IndustryTileSpecialFlags {
};
DECLARE_ENUM_AS_BIT_SET(IndustryTileSpecialFlags)
struct IndustryTileTable {
/** Definition of one tile in an industry tile layout */
struct IndustryTileLayoutTile {
TileIndexDiffC ti;
IndustryGfx gfx;
};
/** A complete tile layout for an industry is a list of tiles */
using IndustryTileLayout = std::vector<IndustryTileLayoutTile>;
/**
* Defines the data structure for constructing industry.
*/
struct IndustrySpec {
const IndustryTileTable * const *table; ///< List of the tiles composing the industry
byte num_table; ///< Number of elements in the table
std::vector<IndustryTileLayout> layouts; ///< List of possible tile layouts for the industry
uint8 cost_multiplier; ///< Base construction cost multiplier.
uint32 removal_cost_multiplier; ///< Base removal cost multiplier.
uint32 prospecting_chance; ///< Chance prospecting succeeds
@ -143,6 +146,8 @@ struct IndustrySpec {
Money GetConstructionCost() const;
Money GetRemovalCost() const;
bool UsesSmoothEconomy() const;
~IndustrySpec();
};
/**

@ -1556,6 +1556,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :Vloeiende econo
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :Wanneer dit is ingeschakeld, verandert de productie van industrieën vaker en in kleinere stappen. Deze instelling heeft meestal geen effect als de industriesoorten worden geleverd door een NewGRF.
STR_CONFIG_SETTING_ALLOW_SHARES :Kopen van aandelen in andere bedrijven toestaan: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Wanneer ingeschakeld is het toegestaan om bedrijfsaandelen te kopen en te verkopen. Aandelen zullen alleen beschikbaar zijn voor bedrijven die een bepaalde leeftijd hebben bereikt
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Minimale leeftijd van bedrijf om aandelen te kunnen verhandelen: {STRING}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Hiermee wordt de minimale leeftijd van een bedrijf ingesteld waarna anderen aandelen in dat bedrijf kunnen gaan kopen en verkopen.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Percentage van routeopbrengst in overdrachtssysteem: {STRING}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Percentage van het inkomen besteed aan de intermediaire delen in feedersystemen waardoor er meer controle over de inkomsten is
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Bij slepen, seinen plaatsen om de: {STRING}

@ -1704,6 +1704,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :Enable smooth e
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :When enabled, industry production changes more often, and in smaller steps. This setting has usually no effect, if industry types are provided by a NewGRF
STR_CONFIG_SETTING_ALLOW_SHARES :Allow buying shares from other companies: {STRING2}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :When enabled, allow buying and selling of company shares. Shares will only be available for companies reaching a certain age
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Minimum company age to trade shares: {STRING2}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Set the minimum age of a company for others to be able to buy and sell shares from them.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Percentage of leg profit to pay in feeder systems: {STRING2}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Percentage of income given to the intermediate legs in feeder systems, giving more control over the income
STR_CONFIG_SETTING_FEEDER_PAYMENT_SRC_STATION :Calculate leg profit relative to source station in feeder systems: {STRING2}

@ -1326,8 +1326,8 @@ STR_CONFIG_SETTING_TERRAIN_TYPE :Maaston tyyppi:
STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Vain TerraGenesis) Maaston mäkisyys
STR_CONFIG_SETTING_INDUSTRY_DENSITY :Teollisuuden määrä: {STRING}
STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Määritä, kuinka paljon teollisuutta tulisi luoda ja millä tasolla teollisuuden tulisi pysytellä pelin aikana
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Suurin sallittu etäisyys kartan reunoilta öljynjalostamoille: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Öljynjalostamoja rakennetaan ainoastaan kartan reunoille eli rannikoille saarikartoilla
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Suurin sallittu etäisyys kartan reunoilta öljyteollisuudelle: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Öljynjalostamojen ja öljylauttojen suurin etäisyys kartan reunasta. Saarikartoilla tämä takaa sen, että ne ovat lähellä rannikkoa. Yli 256 ruudun kartoilla tätä arvoa suurennetaan suhteessa kartan kokoon.
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Lumirajan korkeus: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Määritä, millä korkeudella lumiraja on pohjoisessa maastotyypissä. Lumi vaikuttaa teollisuuslaitosten luontiin sekä kuntien kasvuedellytyksiin
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Maaston epätasaisuus: {STRING}
@ -1556,6 +1556,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :Tasainen talous
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :Mikäli käytössä, teollisuuden tuotanto muuttuu useammin ja vähemmän kerrallaan. Tällä asetuksella ei ole yleensä vaikutusta mikäli teollisuustyypit ovat NewGRF:n tarjoamia
STR_CONFIG_SETTING_ALLOW_SHARES :Salli toisten yhtiöiden osakkeiden ostaminen: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Mikäli käytössä, toisten yhtiöiden osakkeiden ostaminen ja myyminen on mahdollista. Osakkeet ovat saatavilla vain yhtiöille, jotka ovat saavuttaneet tietyn iän
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Yhtiön vähimmäisikä osakekaupoille: {STRING}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Aseta yhtiölle vähimmäisikä, jonka jälkeen muut voivat ostaa ja myydä yhtiön osakkeita.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Syöttöjärjestelmään maksettavan tuoton osuus: {STRING}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Osuus tuotosta, joka annetaan välittäjille syöttöjärjestelmissä
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Opastimien väli vedettäessä: {STRING}
@ -3119,6 +3121,8 @@ STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Nimeä kunta
# Town local authority window
STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN}: viranomaiset
STR_LOCAL_AUTHORITY_ZONE :{BLACK}Alue
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Näytä paikallisviranomaisten hallinnoiman alueen raja
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Kuljetusyhtiön arvioinnit:
STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING}
STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}Toiminnot:

@ -3955,7 +3955,7 @@ STR_ORDER_CONDITIONAL_VALUE_TOOLTIP :{BLACK}La valeu
STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Entrer la valeur à comparer
STR_ORDERS_SKIP_BUTTON :{BLACK}Suivant
STR_ORDERS_SKIP_TOOLTIP :{BLACK}Sauter l'ordre courant et passer au suivant.{}Ctrl-clic pour sauter l'ordre sélectionné.
STR_ORDERS_SKIP_TOOLTIP :{BLACK}Sauter l'ordre courant et passer au suivant.{}Ctrl-clic pour sauter à l'ordre sélectionné.
STR_ORDERS_DELETE_BUTTON :{BLACK}Supprimer
STR_ORDERS_DELETE_TOOLTIP :{BLACK}Supprimer l'ordre sélectionné

@ -253,10 +253,10 @@ STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST :{BLACK}스크
STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}직사각형 모양의 영역에 있는 건물과 땅 등을 부숩니다. CTRL 키를 누른 채로 사용하면 대각선 영역 선택이 가능합니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다
# Show engines button
STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN :{BLACK}숨겨진 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE :{BLACK}숨겨진 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP :{BLACK}숨겨진 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT :{BLACK}숨겨진 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN :{BLACK}숨 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE :{BLACK}숨 차량 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_SHIP :{BLACK}숨긴 선박 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT :{BLACK}숨긴 항공기 보기
STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP :{BLACK}이 버튼을 누르면 숨겨진 열차 차량도 구매 목록에 모두 표시합니다.
STR_SHOW_HIDDEN_ENGINES_VEHICLE_ROAD_VEHICLE_TOOLTIP :{BLACK}이 버튼을 누르면 숨겨진 자동차/전차 차량도 구매 목록에 모두 표시합니다.
@ -611,7 +611,7 @@ STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP :{BLACK}특정
STR_COMPANY_LEAGUE_TABLE_CAPTION :{WHITE}회사 성취도 순위
STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} '{STRING}'
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER :{G=f}기사
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :{G=f}교통 매니저
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :{G=f}교통망 관리자
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :{G=f}수송 조정자
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :{G=f}노선 관리자
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR :{G=m}임원
@ -640,7 +640,7 @@ STR_PERFORMANCE_DETAIL_LOAN :{BLACK}대출:
STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}종합:
############ End of order list
STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP :{BLACK}작년에 이익을 낸 차량의 수를 나타냅니다. 자동차/전차, 열차, 선박, 항공기를 포함합니다.
STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}현재 영업 중인 역사의 수를 나타냅니다. 기차역, 버스 정류장, 공항 등은 같은 역으로 묶여있어도 따로 집계됩니다.
STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}현재 영업 중인 역사의 수를 나타냅니다. 기차역, 버스 정류장, 공항 등은 같은 역으로 묶여있어도 별도로 집계됩니다
STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}가장 낮은 수입을 가진 차량의 이익입니다. (2년 이상된 차량만 계산)
STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}지난 12분기 동안 최소 이익을 달성한 차량이 벌어들인 돈의 양입니다.
STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}지난 12분기 동안 최대 이익을 달성한 차량이 벌어들인 돈의 양입니다.
@ -1704,6 +1704,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :부드러운
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :이 설정을 켜면, 1차 산업시설의 생산량이 소량으로 자주 변하게 됩니다. NewGRF로 추가한 산업시설에는 적용되지 않습니다.
STR_CONFIG_SETTING_ALLOW_SHARES :다른 회사의 지분을 사는 것을 허용: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :이 설정을 켜면, 회사의 지분을 거래할 수 있게 됩니다. 회사의 지분을 거래하려면 해당 회사가 어느 정도 오래되어야 합니다.
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :지분 거래를 허용할 최소 회사 나이: {STRING}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :지분을 사고 팔기 위해 필요한 회사의 최소 나이를 설정합니다.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :환승시 벌어들이는 중간 수익의 비율: {STRING}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :더 많은 수익을 내기 위해, 수송 관계상 중간 구간에게 주어진 수익의 비율을 설정합니다.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SRC_STATION :환승시 출발 역에 대한 중간 수익을 계산: {STRING}

@ -1709,6 +1709,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :Включит
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :При включении производительность предприятий меняется чаще и более плавно. Эта настройка обычно не влияет на предприятия, внесённые в игру модулями NewGRF.
STR_CONFIG_SETTING_ALLOW_SHARES :Разрешить торговлю акциями других компаний: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Разрешает торговлю акциями транспортных компаний. Акции выпускаются компаниями через некоторое время после основания.
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Мин. возраст компании для выпуска акций: {STRING}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Минимальный возраст, которого должна достичь компания для начала выпуска акций, которыми смогут торговать другие игроки.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Процент дохода, начисляемый при частичной перевозке: {STRING}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Процент прибыли, начисляемый транспорту за частичную перевозку груза.
STR_CONFIG_SETTING_SIMULATE_SIGNALS :Симуляция светофоров в туннелях и на мостах каждые: {STRING}

@ -1557,6 +1557,8 @@ STR_CONFIG_SETTING_SMOOTH_ECONOMY :Activar econom
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :Al activarse, habrá cambios de producción en las industrias más frecuentemente y en escala menor. Si se usa un NewGRF con industrias adicionales esta opción generalmente no tiene efecto
STR_CONFIG_SETTING_ALLOW_SHARES :Permitir comprar acciones de otras empresas: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Al activarse, se pueden comprar y vender acciones de otras empresas. Las acciones de una empresa solamente estarán disponibles cuando la empresa cumpla una edad determinada
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Edad mínima de la empresa para intercambiar acciones: {STRING}
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Estabelcer la edad mínima que debe tener una empresa para que otros puedan comprarle y venderle acciones.
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Porcentaje de la utilidad total a pagar por transferencias de carga: {STRING}
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Porcentaje de utilidad cedida a los transportes intermedios en sistemas de transferencia de carga, dando un mayor control sobre la utilidad de cada vehículo
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Al arrastrar, colocar señales cada: {STRING}

@ -189,6 +189,7 @@ STR_COLOUR_ORANGE :ஆரஞ்ச
STR_COLOUR_BROWN :பழுப்பு
STR_COLOUR_GREY :சாம்பல்
STR_COLOUR_WHITE :வெள்ளை
STR_COLOUR_DEFAULT :இயல்பிருப்பு
# Units used in OpenTTD
STR_UNITS_VELOCITY_IMPERIAL :{COMMA}{NBSP}mph
@ -435,7 +436,7 @@ STR_RAIL_MENU_MAGLEV_CONSTRUCTION :மேக்ல
############ range for road construction menu starts
STR_ROAD_MENU_ROAD_CONSTRUCTION :சாலை கட்டுமானம்
STR_ROAD_MENU_TRAM_CONSTRUCTION :ட்ரேம்வே கட்டுமானம்
STR_ROAD_MENU_TRAM_CONSTRUCTION :அமிழ் தண்டூர்திப் பாதை கட்டுமானம்
############ range ends here
############ range for waterways construction menu starts
@ -470,6 +471,7 @@ STR_ABOUT_MENU_SCREENSHOT :திரைப
STR_ABOUT_MENU_ZOOMIN_SCREENSHOT :முழுமையாக பெரிதாக்கிய நிலையில் திரைப்பிடிப்பு செய்
STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT :பெரிதாக்கிய நிலையில் திரைப்பிடிப்பு செய்
STR_ABOUT_MENU_GIANT_SCREENSHOT :முழு வரைபடத்தையும் திரைபிடிப்பு செய்
STR_ABOUT_MENU_SHOW_FRAMERATE :பிரேம் வீதத்தைக் காட்டு
STR_ABOUT_MENU_ABOUT_OPENTTD :'OpenTTD' பற்றி
STR_ABOUT_MENU_SPRITE_ALIGNER :ஸ்ரைட்டு அலைனர்
STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :எல்லைக் கட்டங்களை மாற்றவும்
@ -529,7 +531,7 @@ STR_DAY_NUMBER_31ST :31வது
############ range for days ends
############ range for months starts
STR_MONTH_ABBREV_JAN :னவரி
STR_MONTH_ABBREV_JAN :னவரி
STR_MONTH_ABBREV_FEB :பெப்
STR_MONTH_ABBREV_MAR :மார்ச்
STR_MONTH_ABBREV_APR :ஏப்ரல்
@ -641,6 +643,7 @@ STR_MUSIC_RULER_MARKER :{TINY_FONT}{BLA
STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}--
STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM}
STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------
STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}இசை எதுவும் கிடைக்கவில்லை
STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}"
STR_MUSIC_TRACK :{TINY_FONT}{BLACK}இசைத்தடம்
STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}தலைப்பு
@ -664,6 +667,7 @@ STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTB
STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}இசைத்தடம் வரிசை
STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}பிரோகிராம் - '{STRING}'
STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}அழி
STR_PLAYLIST_CHANGE_SET :{BLACK} மாற்று
STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}தற்போதைய பிரோகிராமிலிருந்து இசைத்தடத்தினை நீக்க சொடுக்கவும் (பயனரால் மாற்றப்பட்ட1 அல்லது 2 மட்டும்)
# Highscore window
@ -888,6 +892,7 @@ STR_GAME_OPTIONS_CURRENCY_LTL :லிதுவ
STR_GAME_OPTIONS_CURRENCY_KRW :தென்கொரிய வொன் (KRW)
STR_GAME_OPTIONS_CURRENCY_ZAR :தென் ஆப்பிரிக்க ரான்ட் (ZAR)
STR_GAME_OPTIONS_CURRENCY_CUSTOM :புதிதாக...
STR_GAME_OPTIONS_CURRENCY_RUB :புதிய ரஷ்ய ரூபிள் (RUB)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}சாலை வாகனங்கள்
@ -946,7 +951,9 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :சராசர
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :இரண்டு மடங்கு
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :நான்கு மடங்கு
STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}எழுத்துரு அளவு
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :இரண்டு மடங்கு
STR_GAME_OPTIONS_BASE_GRF :{BLACK}அடிப்படை அசைவூட்டம்
STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}பயன்படுத்தப்போகும் அடிப்படை அசைவூட்டத்தினை தேர்ந்தெடுக்கவும்
@ -1125,7 +1132,7 @@ STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :சாலை
STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS :இரயில்களின் மலை ஏறுதல் வேகத்தடை: {STRING}
STR_CONFIG_SETTING_PERCENTAGE :{COMMA}%
STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS :சாலை வாகங்களின் மலையேறுதல் வேகத்தடை: {STRING}
STR_CONFIG_SETTING_FORBID_90_DEG :இரயில் மற்றும் கப்பல்களை 90° வளைவுகள் எடுப்பதை அனுமதிக்காதே: {STRING}
STR_CONFIG_SETTING_FORBID_90_DEG :இரயில்கள் 90° வளைவுளை எடுப்பதை அனுமதிக்காதே: {STRING}
STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS :நேரடியாக இணைக்கப்படாத நிலையங்களை இணைக்க அனுமதி: {STRING}
STR_CONFIG_SETTING_INFLATION :விலைவாசி ஏற்றம்: {STRING}
STR_CONFIG_SETTING_INFLATION_HELPTEXT :பண வீக்கத்தினை செயல்படுத்து, இதனால் செலவுகள் வளர்ச்சி வரவுகளின் வளர்ச்சியைவிட அதிகமாகும்
@ -1168,10 +1175,11 @@ STR_CONFIG_SETTING_PLANE_SPEED :விமான
STR_CONFIG_SETTING_PLANE_SPEED_VALUE :1 / {COMMA}
STR_CONFIG_SETTING_PLANE_CRASHES :விமான விபத்துகளின் எண்ணிக்கை: {STRING}
STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :விமான விபத்து நிகழ்வதற்கான வாய்ப்புகளை அமை
STR_CONFIG_SETTING_PLANE_CRASHES_NONE :ஒன்றுமில்லை
STR_CONFIG_SETTING_PLANE_CRASHES_NONE :ஒன்றுமில்லை*
STR_CONFIG_SETTING_PLANE_CRASHES_REDUCED :குறைக்கப்பட்ட
STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :இயல்பான
STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :வழிசெல்லக்கூடிய சாலை நிறுத்தங்களை நகராட்சியின் சாலைகளில் அமைக்க அனுமதி: {STRING}
STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :நகரத்திற்குச் சொந்தமான சாலைகளில் டிரைவ்-த்ரோ சாலை நிறுத்தங்களை உருவாக்க அனுமதிக்கவும்
STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}வாகனங்கள் இருக்கும் பொது இந்த அமைப்பினை மாற்ற இயலாது
STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :கட்டட பராமரிப்பு: {STRING}
@ -1205,7 +1213,7 @@ STR_CONFIG_SETTING_LAND_GENERATOR :நில உ
STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :உண்மையான
STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis
STR_CONFIG_SETTING_INDUSTRY_DENSITY :தொழிற்சாலை அடர்த்தி: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :வரைபட எல்லையிலிருந்து எண்ணெய் சுத்திகரிப்பு நிலையங்கள் இருக்கக்கூடிய தூரம்: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :வரைபட எல்லையிலிருந்து எண்ணெய் தொழிற்சாலைகள் இருக்கக்கூடிய தூரம்: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :எண்ணெய் சுத்திகரிப்பு நிலையங்கள் வரைபடத்தின் எல்லைகளில் மட்டுமே கட்ட இயலும், அதாவது தீவு வரைபடங்களில் கடற்கரைகளில் கட்ட இயலும்
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :பனி-கோடின் உயரம்: {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :நிலப்பகுதியின் சமனில்லாத நிலை (TerraGenesis மட்டும்) : {STRING}
@ -1213,6 +1221,7 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :மிகவு
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :சமமான
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :கரடுமுரடான
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :மிகவும் கரடுமுரடான
STR_CONFIG_SETTING_RIVER_AMOUNT :ஆறுகளின் எண்ணிக்கை: {STRING}
STR_CONFIG_SETTING_TREE_PLACER :மரங்கள் நடும் வகை: {STRING}
STR_CONFIG_SETTING_TREE_PLACER_NONE :ஒன்றுமில்லை
STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :உண்மையான
@ -1321,16 +1330,19 @@ STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}
STR_CONFIG_SETTING_SERVINT_DISABLED :செயலிழக்க செய்யப்பட்டது
STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES :சாலை வாகனங்களின் பழுதுபார்த்தல் இடைவேளி: {STRING}
STR_CONFIG_SETTING_SERVINT_AIRCRAFT :விமாங்களின் பழுதுபார்த்தல் இடைவேளி: {STRING}
STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT :புதிய விமானங்களுக்கான இயல்புநிலை சேவை இடைவெளியை அமைக்கவும், வாகனத்திற்கு வெளிப்படையான சேவை இடைவெளி எதுவும் அமைக்கப்படவில்லை என்றால்
STR_CONFIG_SETTING_SERVINT_SHIPS :கப்பல்களின் பழுதுபார்த்தல் இடைவேளி: {STRING}
STR_CONFIG_SETTING_NOSERVICE :பழுதுகள் இல்லையெனில் பழுதுபார்த்தலினை செயலிழக்கவும்: {STRING}
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :பெட்டி வேக கட்டுப்பாட்டினை செயல்படுத்தவும்: {STRING}
STR_CONFIG_SETTING_DISABLE_ELRAILS :மின்சார இரயில்களை அனுமதிக்காதே: {STRING}
STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN :விளையாடுபவரின் நிலையத்திற்கு முதல் வாகனம் வருகை புரிந்தது: {STRING}
STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN_HELPTEXT :முதல் வாகனம் புதிய வீரர் நிலையத்திற்கு வரும்போது செய்தித்தாளைக் காண்பி
STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OTHER :போட்டியாளரின் நிலையத்திற்கு முதல் வாகனம் வருகை புரிந்தது: {STRING}
STR_CONFIG_SETTING_NEWS_ACCIDENTS_DISASTERS :விபத்துகள் / பேரழிவுகள்: {STRING}
STR_CONFIG_SETTING_NEWS_ACCIDENTS_DISASTERS_HELPTEXT :விபத்துகள் அல்லது பேரழிவுகள் நிகழும்போது செய்தித்தாள் ஒன்றினைக் காட்டு
STR_CONFIG_SETTING_NEWS_COMPANY_INFORMATION :நிறுவனத்தின் விவரம்: {STRING}
STR_CONFIG_SETTING_NEWS_COMPANY_INFORMATION_HELPTEXT :ஒரு புதிய நிறுவனம் தொடங்கும் போது அல்லது நிறுவனங்கள் திவாலாகும் அபாயத்தில் இருக்கும்போது ஒரு செய்தித்தாளைக் காண்பி
STR_CONFIG_SETTING_NEWS_INDUSTRY_OPEN :தொழிற்சாலைகளின் திறப்பு: {STRING}
STR_CONFIG_SETTING_NEWS_INDUSTRY_OPEN_HELPTEXT :தொழிற்சாலைகள் திறக்கப்படும்போது செய்தித்தாளினைக் காட்டு
STR_CONFIG_SETTING_NEWS_INDUSTRY_CLOSE :தொழிற்சாலைகளின் மூடல்: {STRING}
@ -1385,8 +1397,10 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :இந்த
STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :இயலாது
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :அனுமதிக்கப்படுகிறது
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :அனுமதிக்கப்படுகிறது, ஆனால் மாற்றியமைக்கப்பட்ட நகர அமைப்பு
STR_CONFIG_SETTING_TOWN_CARGOGENMODE :நகரத்தின் சரக்கு உற்பத்தி: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :ஆட்டத்தின் போது மரங்களை நடுதல்: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :விளையாட்டின் போது மரங்களின் சீரற்ற தோற்றத்தைக் கட்டுப்படுத்தவும். இது மர வளர்ச்சியை நம்பியுள்ள தொழில்களை பாதிக்கலாம், எடுத்துக்காட்டாக மரம் வெட்டுதல் ஆலைகள்
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE :ஒன்றுமில்லை {RED}(மர மில்லை உடைக்கும்)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST :மழைக் காடுகளில் மட்டும்
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL :எங்கும்
@ -1419,6 +1433,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :தொடக்
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :ஆட்டத்தின் தொடக்கத்தில் மாநகரங்களின் அளவு நகரங்களை ஒப்பிடுகையில்
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :கைமுறை
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :சமச்சீரான
STR_CONFIG_SETTING_DISTRIBUTION_PAX :பயணிகள் பரிமாற்றம் வகை: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_MAIL :அஞ்சல் பரிமாற்றம் வகை: {STRING}
@ -1454,10 +1469,12 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (மீ)
STR_CONFIG_SETTING_GRAPHICS :{ORANGE}அசைவூட்டம்
STR_CONFIG_SETTING_SOUND :{ORANGE}ஒலிகள்
STR_CONFIG_SETTING_INTERFACE :{ORANGE}Interface
STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE} பொதுவான
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}கட்டுமானம்
STR_CONFIG_SETTING_COMPANY :{ORANGE}நிறுவனம்
STR_CONFIG_SETTING_ACCOUNTING :{ORANGE}கணக்கியல்
STR_CONFIG_SETTING_VEHICLES :{ORANGE}வாகனங்கள்
STR_CONFIG_SETTING_VEHICLES_PHYSICS :{ORANGE}இயற்பியல்
STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}வழி மாற்றல்
STR_CONFIG_SETTING_LIMITATIONS :{ORANGE}எல்லைகள்
STR_CONFIG_SETTING_ACCIDENTS :{ORANGE}பேரழிவுகள் / விபத்துகள்
@ -1503,6 +1520,7 @@ STR_INTRO_LOAD_GAME :{BLACK}ஆட
STR_INTRO_PLAY_SCENARIO :{BLACK}சித்திரக்காட்சியில் விளையாடு
STR_INTRO_PLAY_HEIGHTMAP :{BLACK}உயர்படத்தில் விளையாடு
STR_INTRO_SCENARIO_EDITOR :{BLACK}சித்திரக்காட்சி திருத்தி
STR_INTRO_MULTIPLAYER :{BLACK}பல்வீரர்
STR_INTRO_GAME_OPTIONS :{BLACK}ஆட்டத்தின் அமைப்புகள்
STR_INTRO_HIGHSCORE :{BLACK}புள்ளிகள் பட்டியல்
@ -1565,6 +1583,7 @@ STR_CHEAT_CHANGE_DATE_QUERY_CAPT :{WHITE}நட
STR_CHEAT_SETUP_PROD :{LTBLUE}தயாரிப்பு மதிப்புகளை மாற்ற முடியும்: {ORANGE}{STRING}
# Livery window
STR_LIVERY_CAPTION :{WHITE}{COMPANY} - நிற கோட்பாடு
STR_LIVERY_GENERAL_TOOLTIP :{BLACK}பொதுவான நிற கோட்பாடுகளைக் காட்டவும்
STR_LIVERY_TRAIN_TOOLTIP :{BLACK}இரயில் நிற கோட்பாடுகளைக் காட்டவும்
@ -1806,6 +1825,7 @@ STR_NETWORK_CONNECTION_DISCONNECT :{BLACK}இண
STR_NETWORK_NEED_GAME_PASSWORD_CAPTION :{WHITE}சர்வர் காக்கப்பட்டுள்ளது. கடவுச்சொல்லினை இடவும்
STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION :{WHITE}நிற்வனம் காக்கப்பட்டுள்ளது. கடவுச்சொல்லினை இடவும்
STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION :{WHITE}விளையாடுவோர் பட்டியல்
# Network company list added strings
STR_NETWORK_COMPANY_LIST_CLIENT_LIST :விளையாடுவோர் பட்டியல்
@ -1998,6 +2018,7 @@ STR_TRANSPARENCY_CAPTION :{WHITE}ஒள
STR_LINKGRAPH_LEGEND_ALL :{BLACK}அனைத்தும்
STR_LINKGRAPH_LEGEND_NONE :{BLACK}ஒன்றுமில்லை
STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}கட்டப்பட வேண்டிய நிறுவனங்களைத் தேர்ந்தெடு
STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY}
# Linkgraph legend window and linkgraph legend in smallmap
STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}பயன்படுத்தப்படவில்லை
@ -2083,7 +2104,7 @@ STR_BRIDGE_TUBULAR_SILICON :குழாய
# Road construction toolbar
STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION :{WHITE}சாலை கட்டுமானம்
STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION :{WHITE}ட்ரேம்வே கட்டுமானம்
STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION :{WHITE}அமிழ் தண்டூர்திப் பாதை கட்டுமானம்
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION :{BLACK}சாலையினை இடவும். Ctrl அழுத்தினால் சாலையினை நீக்கலாம்/கட்டலாம். Shift அழுத்தினால் கட்டுமான/செலவு மதிப்பீடு காட்டப்படும்
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}ட்ராம்வே தடத்தினைக் கட்டவும். Ctrl அழுத்தினால் தடத்தினை நீக்கலாம்/கட்டலாம். Shift அழுத்தினால் கட்டுமான/செலவு மதிப்பீடு காட்டப்படும்
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}சாலை வாகன பணிமனையினை கட்டவும் (வாகங்களை வாங்க மற்றும் பழுதுபார்க்க). Shift அழுத்தினால் கட்டுமான/செலவு மதிப்பீடு
@ -2270,6 +2291,7 @@ STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME :{BLACK}வி
STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF: {LTBLUE}{STRING}
STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}ஏற்றுக்கொள்ளப்படும் சரக்குகள்: {LTBLUE}
STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING})
STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}அமிழ் தண்டூர்தி வகை: {LTBLUE}{STRING}
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}இரயில் வேகத் தடை: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}சாலை வேகத்தடை: {LTBLUE}{VELOCITY}
@ -2304,14 +2326,14 @@ STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :இரயில
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :இரயில்வே தடம் இணைந்த மற்றும் பாதை சிக்னல்களுடன்
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :இரயில்வே தடம் இணைந்த மற்றும் ஒருவழிப் பாதை சிக்னல்களுடன்
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :இரயில்வே தடம் பாதை மற்றும் ஒருவழிப் பாதை சிக்னல்களுடன்
STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :இரயில்வே இரயில் பணிமனை
STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :இரயில் பணிமனை
STR_LAI_ROAD_DESCRIPTION_ROAD :சாலை
STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS :தெரு விளக்குகளுடன் சாலை
STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD :மரங்கள் நடுவே சாலை
STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT :சாலை வாகன பணிமனை
STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING :சாலை/இரயில் பாதை கடக்கும் இடம்
STR_LAI_ROAD_DESCRIPTION_TRAMWAY :ட்ரேம்வே
STR_LAI_ROAD_DESCRIPTION_TRAMWAY :தண்டூர்திப் பாதை
# Houses come directly from their building names
STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION :{STRING} (கட்டுமானம் நடக்கிறது)
@ -2371,9 +2393,18 @@ STR_ABOUT_VERSION :{BLACK}OpenTTD
STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2019 OpenTTD குழுமம்
# Framerate display window
STR_FRAMERATE_MEMORYUSE :{WHITE}நினைவாற்றல்
STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL} நுண்ணொடி
STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES}
STR_FRAMERATE_BYTES_WARN :{YELLOW}{BYTES}
STR_FRAMERATE_BYTES_BAD :{RED}{BYTES}
############ Leave those lines in this order!!
STR_FRAMERATE_ALLSCRIPTS :{BLACK} GS/AI மொத்தம்:
############ End of leave-in-this-order
############ Leave those lines in this order!!
STR_FRAMETIME_CAPTION_GL_ECONOMY :சரக்கு கையாளுதல்
STR_FRAMETIME_CAPTION_GL_ROADVEHS :சாலை வாகனத்தின் பயண நேரம்
STR_FRAMETIME_CAPTION_GAMESCRIPT :விளையாட்டின் ஸ்கிரிப்ட்
############ End of leave-in-this-order
@ -2392,6 +2423,7 @@ STR_SAVELOAD_SAVE_BUTTON :{BLACK}சே
STR_SAVELOAD_SAVE_TOOLTIP :{BLACK}தற்போதைய ஆட்டத்தினை பதிவு செய், தேர்ந்தெடுக்கப்பட்டப் பெயரில்
STR_SAVELOAD_LOAD_BUTTON :{BLACK}ஏற்று
STR_SAVELOAD_LOAD_TOOLTIP :{BLACK}தேர்ந்தெடுக்கப்பட்ட ஆட்டத்தினை ஏற்று
STR_SAVELOAD_LOAD_HEIGHTMAP_TOOLTIP :{BLACK} தேர்ந்தெடுக்கப்பட்டுள்ள உயர்படத்தினை ஏற்று
STR_SAVELOAD_DETAIL_CAPTION :{BLACK}ஆட்டத்தின் விவரங்கள்
STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}எந்த தகவலும் கிடைக்கவில்லை
STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING}
@ -2418,6 +2450,7 @@ STR_MAPGEN_TERRAIN_TYPE :{BLACK}நி
STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}கடல் மட்டம்:
STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}ஆறுகள்:
STR_MAPGEN_SMOOTHNESS :{BLACK}சமநிலை:
STR_MAPGEN_VARIETY :{BLACK}பலவகை பரவல்:
STR_MAPGEN_GENERATE :{WHITE}உருவாக்கு
# Strings for map borders at game generation
@ -2506,8 +2539,10 @@ STR_NEWGRF_SETTINGS_GRF_ID :{BLACK}GRF ID:
STR_NEWGRF_SETTINGS_VERSION :{BLACK}பதிப்பு: {SILVER}{NUM}
STR_NEWGRF_SETTINGS_MIN_VERSION :{BLACK}குறைந்த். பயன்படுத்தக்கூடிய பதிப்பு: {SILVER}{NUM}
STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE :{BLACK}Palette: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE :{BLACK}தட்டு: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE_LEGACY :மரபுரிமை (W)
STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}குணாதிசயங்கள்: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PARAMETER_NONE :ஒன்றுமில்லை
STR_NEWGRF_SETTINGS_NO_INFO :{BLACK}எந்தத் தகவலும் இல்லை
STR_NEWGRF_SETTINGS_NOT_FOUND :{RED}பொருத்தமான கோப்பு கிடைக்கவில்லை
@ -2515,6 +2550,8 @@ STR_NEWGRF_SETTINGS_DISABLED :{RED}செய
STR_NEWGRF_SETTINGS_INCOMPATIBLE :{RED}இந்த OpenTTD பதிப்புடன் பயன்படுத்த இயலாது
# NewGRF save preset window
STR_SAVE_PRESET_CAPTION :{WHITE}Preset-ஐ பதிவுசெய்
STR_SAVE_PRESET_TITLE :{BLACK}Preset இற்கு ஒரு பெயரினை இடு
# NewGRF parameters window
STR_NEWGRF_PARAMETERS_CAPTION :{WHITE}NewGRF குணாதிசயங்களை மாற்று
@ -2539,6 +2576,8 @@ STR_SPRITE_ALIGNER_CAPTION :{WHITE}ஸ்
STR_SPRITE_ALIGNER_NEXT_BUTTON :{BLACK}அடுத்த ஸ்பிரைட்டு
STR_SPRITE_ALIGNER_GOTO_BUTTON :{BLACK}ஸ்பிரைட்டுயிற்கு செல்லவும்
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}முந்தைய ஸ்பிரைட்டு
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}முன்னிருந்தமாதிரி மாற்று
STR_SPRITE_ALIGNER_OFFSETS_REL :{BLACK}X ஒதுக்கம்: {NUM}, Y ஒதுக்கம்: {NUM} (சார்பு)
STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}ஸ்பிரைட்டினைத் தேர்ந்தெடுக்கவும்
STR_SPRITE_ALIGNER_GOTO_CAPTION :{WHITE}ஸ்பிரைட்டிற்கு செல்லவும்
@ -2621,6 +2660,7 @@ STR_TOWN_POPULATION :{BLACK}உல
STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN}
STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (மாநகரம்)
STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}மக்கள்தொகை: {ORANGE}{COMMA}{BLACK} வீடுகள்: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} சென்ற மாதம்: {ORANGE}{COMMA}{BLACK} அதிகபட்சம்: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}நகரத்தின் வளர்ச்சியிற்கு தேவையான சரக்குகள்:
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} தேவை
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} குளிர்காலத்தில் தேவை
@ -2902,6 +2942,7 @@ STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}தய
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}தொழிற்சாலை உடனடியாக மூடப்படும் என்று அறிவிக்கப்பட்டுள்ளது!
STR_INDUSTRY_VIEW_REQUIRES :{BLACK}வேண்டியவன:
STR_CONFIG_GAME_PRODUCTION :{WHITE}தயாரிப்பினை மாற்றவும் (8 இன் பெருக்கங்கள், 2040 வரை)
STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}தயாரிப்பு அளவினை மாற்றவும் (சதவிகிதம், 800% வரை)
@ -2970,6 +3011,7 @@ STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :புது
STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :புதிய மேக்லெவ் வாகனங்கள்
STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :புது சாலை வாகனங்கள்
STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :புதிய அமிழ் தண்டூர்தி வாகனங்கள்
############ range for vehicle availability starts
STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :புது இரயில் வாகனங்கள்
@ -3008,6 +3050,8 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}வா
STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}கப்பலை வாங்கு
STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}விமானத்தை வாங்கு
STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}கப்பலை வாங்கி மாற்றியமை
STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}விமானத்தை வாங்கி மாற்றியமை
STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}காட்டப்படும் இரயில் வாகனத்தை வாங்கவும். Shift+Click செய்தால் வாங்கும்போது ஆகும் மதிப்பிடப்பட்டச் செலவுகளைக் காட்டு
STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}காட்டப்படும் சாலை வாகனத்தை வாங்கவும். Shift+Click செய்தால் வாங்கும்போது ஆகும் மதிப்பிடப்பட்டச் செலவுகளைக் காட்டும்
@ -3026,7 +3070,9 @@ STR_BUY_VEHICLE_SHIP_RENAME_TOOLTIP :{BLACK}கப
STR_BUY_VEHICLE_AIRCRAFT_RENAME_TOOLTIP :{BLACK}விமான வகையின் பெயரினை மாற்றவும்
STR_BUY_VEHICLE_ROAD_VEHICLE_SHOW_TOGGLE_BUTTON :{BLACK}காட்சி
STR_BUY_VEHICLE_SHIP_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}கப்பல் வகையினை காட்டு/மறை
STR_QUERY_RENAME_TRAIN_TYPE_CAPTION :{WHITE}இரயில் வாகன வகையின் பெயரினை மாற்றவும்
STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}சாலை வாகன வகையின் பெயரினை மாற்றவும்
@ -3114,6 +3160,8 @@ STR_ENGINE_PREVIEW_SHIP :கப்பல
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}செலவு: {CURRENCY_LONG} எடை: {WEIGHT_SHORT}{}வேகம்: {VELOCITY} திறன்: {POWER}{}ஓட்டுவதற்கான செலவு: {CURRENCY_LONG}/வரு{}கொள்ளளவு: {CARGO_LONG}
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}செலவு: {CURRENCY_LONG} எடை: {WEIGHT_SHORT}{}வேகம்: {VELOCITY} திறன்: {POWER} அதி. T.E.: {6:FORCE}{}ஓட்டுவதற்கான செலவு: {4:CURRENCY_LONG}/வரு{}கொள்ளளவு: {5:CARGO_LONG}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}செலவு: {CURRENCY_LONG} அதி. வேகம்: {VELOCITY}{}கொள்ளளவு: {CARGO_LONG}{}ஓட்டும் செலவு: {CURRENCY_LONG}/ஆண்டிற்கு
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}செலவு: {CURRENCY_LONG} அதி. வேகம்: {VELOCITY}{}விமான வகை: {STRING}{}கொள்ளளவு: {CARGO_LONG}{}ஓட்டும் செலவு: {CURRENCY_LONG}/ஆண்டிற்கு
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}செலவு: {CURRENCY_LONG} அதி. வேகம்: {VELOCITY}{}விமான வகை: {STRING} வீச்சு எல்லை: {COMMA} கட்டங்கள்{}கொள்ளளவு: {CARGO_LONG}, {CARGO_LONG}{}ஓட்டும் செலவு: {CURRENCY_LONG}/ஆண்டிற்கு
# Autoreplace window
STR_REPLACE_VEHICLES_WHITE :{WHITE}மாற்று {STRING} - {STRING}
@ -3122,6 +3170,7 @@ STR_REPLACE_VEHICLE_ROAD_VEHICLE :சாலை
STR_REPLACE_VEHICLE_SHIP :கப்பல்
STR_REPLACE_VEHICLE_AIRCRAFT :விமானம்
STR_REPLACE_VEHICLE_VEHICLES_IN_USE :{YELLOW}பயன்பாட்டிலுள்ள வாகனங்கள்
STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}மாற்றியமைக்க பொறி வகையினை தேர்ந்தெடுக்க
@ -3141,6 +3190,7 @@ STR_REPLACE_ELRAIL_VEHICLES :மின்ச
STR_REPLACE_MONORAIL_VEHICLES :மோனோ இரயில் வாகனங்கள்
STR_REPLACE_MAGLEV_VEHICLES :மேக்லெவ் வாகனங்கள்
STR_REPLACE_TRAM_VEHICLES :அமிழ் தண்டூர்தி வாகனங்கள்
STR_REPLACE_REMOVE_WAGON :{BLACK}பெட்டி நீக்கம்: {ORANGE}{STRING}
@ -3453,6 +3503,7 @@ STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :பயணம்
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :அதிகபட்சமாக {2:VELOCITY} உடன் பயணிக்கவும் (கால அட்டவணையிடப்படவில்லை)
STR_TIMETABLE_TRAVEL_FOR :{STRING} காலத்திற்கு பயணி
STR_TIMETABLE_TRAVEL_FOR_SPEED :{STRING} காலத்திற்கு பயணி, அதிகபட்ச வேகம் {VELOCITY}
STR_TIMETABLE_STAY_FOR_ESTIMATED :({STRING} வரை இரு, நேர அட்டவணை இடப்படாதது)
STR_TIMETABLE_STAY_FOR :மற்றும் {STRING} இற்கு நிற்கவும்
STR_TIMETABLE_AND_TRAVEL_FOR :மற்றும் {STRING} இற்கு பயணிக்கவும்
STR_TIMETABLE_DAYS :{COMMA}{NBSP}நாள்{P "" "நாட்கள்"}
@ -3847,6 +3898,7 @@ STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}இங
STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}இங்கிருந்து ட்ராம்வேயினை நீக்க முடியாது...
STR_ERROR_THERE_IS_NO_ROAD :{WHITE}...சாலை இல்லை
STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}...ட்ராம் வழி இல்லை
STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... இணக்கமற்ற தண்டூர்தி
# Waterway construction errors
STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}இங்கே கால்வாய்களை கட்ட இயலாது...
@ -4008,6 +4060,7 @@ STR_BASESOUNDS_DOS_DESCRIPTION :அசல்
STR_BASESOUNDS_WIN_DESCRIPTION :அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு ஒலிகள்.
STR_BASESOUNDS_NONE_DESCRIPTION :ஒலிகள் இல்லாத ஒலி தொகுப்பு.
STR_BASEMUSIC_WIN_DESCRIPTION :அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு இசை.
STR_BASEMUSIC_DOS_DESCRIPTION :அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS பதிப்பு இசை.
STR_BASEMUSIC_NONE_DESCRIPTION :இசை இல்லாத இசைத்தொகுப்பு.
##id 0x2000

@ -451,6 +451,7 @@ static const char * const _credits[] = {
" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)",
" Christoph Elsenhans (frosch) - General coding (since 0.6)",
" Lo\xC3\xAF""c Guilloux (glx) - General / Windows Expert (since 0.4.5)",
" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",

@ -161,13 +161,12 @@ void MusicDriver_Cocoa::PlaySong(const MusicSongInfo &song)
}
const char *os_file = OTTD2FS(filename.c_str());
CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false);
CFAutoRelease<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false));
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (MacOSVersionIsAtLeast(10, 5, 0)) {
if (MusicSequenceFileLoad(_sequence, url, kMusicSequenceFile_AnyType, 0) != noErr) {
if (MusicSequenceFileLoad(_sequence, url.get(), kMusicSequenceFile_AnyType, 0) != noErr) {
DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file");
CFRelease(url);
return;
}
} else
@ -175,19 +174,16 @@ void MusicDriver_Cocoa::PlaySong(const MusicSongInfo &song)
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
FSRef ref_file;
if (!CFURLGetFSRef(url, &ref_file)) {
if (!CFURLGetFSRef(url.get(), &ref_file)) {
DEBUG(driver, 0, "cocoa_m: Failed to make FSRef");
CFRelease(url);
return;
}
if (MusicSequenceLoadSMFWithFlags(_sequence, &ref_file, 0) != noErr) {
DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file old style");
CFRelease(url);
return;
}
#endif
}
CFRelease(url);
/* Construct audio graph */
AUGraph graph = nullptr;

@ -3442,13 +3442,13 @@ static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader *buf)
/**
* Validate the industry layout; e.g. to prevent duplicate tiles.
* @param layout The layout to check.
* @param size The size of the layout.
* @return True if the layout is deemed valid.
*/
static bool ValidateIndustryLayout(const IndustryTileTable *layout, int size)
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
{
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
const size_t size = layout.size();
for (size_t i = 0; i < size - 1; i++) {
for (size_t j = i + 1; j < size; j++) {
if (layout[i].ti.x == layout[j].ti.x &&
layout[i].ti.y == layout[j].ti.y) {
return false;
@ -3458,20 +3458,6 @@ static bool ValidateIndustryLayout(const IndustryTileTable *layout, int size)
return true;
}
/** Clean the tile table of the IndustrySpec if it's needed. */
static void CleanIndustryTileTable(IndustrySpec *ind)
{
if (HasBit(ind->cleanup_flag, CLEAN_TILELAYOUT) && ind->table != nullptr) {
for (int j = 0; j < ind->num_table; j++) {
/* remove the individual layouts */
free(ind->table[j]);
}
/* remove the layouts pointers */
free(ind->table);
ind->table = nullptr;
}
}
/**
* Define properties for industries
* @param indid Local ID of the industry.
@ -3523,10 +3509,10 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
* Only need to do it once. If ever it is called again, it should not
* do anything */
if (*indspec == nullptr) {
*indspec = CallocT<IndustrySpec>(1);
*indspec = new IndustrySpec;
indsp = *indspec;
memcpy(indsp, &_origin_industry_specs[subs_id], sizeof(_industry_specs[subs_id]));
*indsp = _origin_industry_specs[subs_id];
indsp->enabled = true;
indsp->grf_prop.local_id = indid + i;
indsp->grf_prop.subst_id = subs_id;
@ -3552,112 +3538,101 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
}
case 0x0A: { // Set industry layout(s)
byte new_num_layouts = buf->ReadByte(); // Number of layaouts
/* We read the total size in bytes, but we can't rely on the
* newgrf to provide a sane value. First assume the value is
* sane but later on we make sure we enlarge the array if the
* newgrf contains more data. Each tile uses either 3 or 5
* bytes, so to play it safe we assume 3. */
uint32 def_num_tiles = buf->ReadDWord() / 3 + 1;
IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(new_num_layouts); // Table with tiles to compose an industry
IndustryTileTable *itt = CallocT<IndustryTileTable>(def_num_tiles); // Temporary array to read the tile layouts from the GRF
uint size;
const IndustryTileTable *copy_from;
byte new_num_layouts = buf->ReadByte();
uint32 definition_size = buf->ReadDWord();
uint32 bytes_read = 0;
std::vector<IndustryTileLayout> new_layouts;
IndustryTileLayout layout;
for (byte j = 0; j < new_num_layouts; j++) {
layout.clear();
for (uint k = 0;; k++) {
if (bytes_read >= definition_size) {
grfmsg(3, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry %u.", indid);
/* Avoid warning twice */
definition_size = UINT32_MAX;
}
try {
for (byte j = 0; j < new_num_layouts; j++) {
for (uint k = 0;; k++) {
if (k >= def_num_tiles) {
grfmsg(3, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry %u.", indid);
/* Size reported by newgrf was not big enough so enlarge the array. */
def_num_tiles *= 2;
itt = ReallocT<IndustryTileTable>(itt, def_num_tiles);
}
layout.push_back(IndustryTileLayoutTile{});
IndustryTileLayoutTile &it = layout.back();
itt[k].ti.x = buf->ReadByte(); // Offsets from northermost tile
it.ti.x = buf->ReadByte(); // Offsets from northermost tile
++bytes_read;
if (itt[k].ti.x == 0xFE && k == 0) {
/* This means we have to borrow the layout from an old industry */
IndustryType type = buf->ReadByte(); // industry holding required layout
byte laynbr = buf->ReadByte(); // layout number to borrow
if (it.ti.x == 0xFE && k == 0) {
/* This means we have to borrow the layout from an old industry */
IndustryType type = buf->ReadByte();
byte laynbr = buf->ReadByte();
bytes_read += 2;
copy_from = _origin_industry_specs[type].table[laynbr];
for (size = 1;; size++) {
if (copy_from[size - 1].ti.x == -0x80 && copy_from[size - 1].ti.y == 0) break;
}
break;
if (type >= lengthof(_origin_industry_specs)) {
grfmsg(1, "IndustriesChangeInfo: Invalid original industry number for layout import, industry %u", indid);
DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
return CIR_DISABLED;
}
if (laynbr >= _origin_industry_specs[type].layouts.size()) {
grfmsg(1, "IndustriesChangeInfo: Invalid original industry layout index for layout import, industry %u", indid);
DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
return CIR_DISABLED;
}
layout = _origin_industry_specs[type].layouts[laynbr];
break;
}
itt[k].ti.y = buf->ReadByte(); // Or table definition finalisation
it.ti.y = buf->ReadByte(); // Or table definition finalisation
++bytes_read;
if (itt[k].ti.x == 0 && itt[k].ti.y == 0x80) {
/* Not the same terminator. The one we are using is rather
x = -80, y = x . So, adjust it. */
itt[k].ti.x = -0x80;
itt[k].ti.y = 0;
itt[k].gfx = 0;
if (it.ti.x == 0 && it.ti.y == 0x80) {
/* Terminator, remove and finish up */
layout.pop_back();
break;
}
size = k + 1;
copy_from = itt;
break;
}
it.gfx = buf->ReadByte();
++bytes_read;
itt[k].gfx = buf->ReadByte();
if (it.gfx == 0xFE) {
/* Use a new tile from this GRF */
int local_tile_id = buf->ReadWord();
bytes_read += 2;
if (itt[k].gfx == 0xFE) {
/* Use a new tile from this GRF */
int local_tile_id = buf->ReadWord();
/* Read the ID from the _industile_mngr. */
int tempid = _industile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
/* Read the ID from the _industile_mngr. */
int tempid = _industile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
if (tempid == INVALID_INDUSTRYTILE) {
grfmsg(2, "IndustriesChangeInfo: Attempt to use industry tile %u with industry id %u, not yet defined. Ignoring.", local_tile_id, indid);
} else {
/* Declared as been valid, can be used */
itt[k].gfx = tempid;
}
} else if (itt[k].gfx == 0xFF) {
itt[k].ti.x = (int8)GB(itt[k].ti.x, 0, 8);
itt[k].ti.y = (int8)GB(itt[k].ti.y, 0, 8);
/* When there were only 256x256 maps, TileIndex was a uint16 and
* itt[k].ti was just a TileIndexDiff that was added to it.
* As such negative "x" values were shifted into the "y" position.
* x = -1, y = 1 -> x = 255, y = 0
* Since GRF version 8 the position is interpreted as pair of independent int8.
* For GRF version < 8 we need to emulate the old shifting behaviour.
*/
if (_cur.grffile->grf_version < 8 && itt[k].ti.x < 0) itt[k].ti.y += 1;
if (tempid == INVALID_INDUSTRYTILE) {
grfmsg(2, "IndustriesChangeInfo: Attempt to use industry tile %u with industry id %u, not yet defined. Ignoring.", local_tile_id, indid);
} else {
/* Declared as been valid, can be used */
it.gfx = tempid;
}
}
if (!ValidateIndustryLayout(copy_from, size)) {
/* The industry layout was not valid, so skip this one. */
grfmsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id %u. Ignoring", indid);
new_num_layouts--;
j--;
} else {
tile_table[j] = CallocT<IndustryTileTable>(size);
memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size);
} else if (it.gfx == 0xFF) {
it.ti.x = (int8)GB(it.ti.x, 0, 8);
it.ti.y = (int8)GB(it.ti.y, 0, 8);
/* When there were only 256x256 maps, TileIndex was a uint16 and
* it.ti was just a TileIndexDiff that was added to it.
* As such negative "x" values were shifted into the "y" position.
* x = -1, y = 1 -> x = 255, y = 0
* Since GRF version 8 the position is interpreted as pair of independent int8.
* For GRF version < 8 we need to emulate the old shifting behaviour.
*/
if (_cur.grffile->grf_version < 8 && it.ti.x < 0) it.ti.y += 1;
}
}
} catch (...) {
for (int i = 0; i < new_num_layouts; i++) {
free(tile_table[i]);
if (!ValidateIndustryLayout(layout)) {
/* The industry layout was not valid, so skip this one. */
grfmsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id %u. Ignoring", indid);
new_num_layouts--;
j--;
} else {
new_layouts.push_back(layout);
}
free(tile_table);
free(itt);
throw;
}
/* Clean the tile table if it was already set by a previous prop A. */
CleanIndustryTileTable(indsp);
/* Install final layout construction in the industry spec */
indsp->num_table = new_num_layouts;
indsp->table = tile_table;
SetBit(indsp->cleanup_flag, CLEAN_TILELAYOUT);
free(itt);
indsp->layouts = new_layouts;
break;
}
@ -9059,17 +9034,7 @@ static void ResetCustomIndustries()
if (industryspec != nullptr) {
for (uint i = 0; i < NUM_INDUSTRYTYPES_PER_GRF; i++) {
IndustrySpec *ind = industryspec[i];
if (ind == nullptr) continue;
/* We need to remove the sounds array */
if (HasBit(ind->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
free(ind->random_sounds);
}
/* We need to remove the tiles layouts */
CleanIndustryTileTable(ind);
free(ind);
delete ind;
}
free(industryspec);

@ -279,7 +279,7 @@ void IndustryOverrideManager::SetEntitySpec(IndustrySpec *inds)
}
/* Now that we know we can use the given id, copy the spec to its final destination... */
memcpy(&_industry_specs[ind_id], inds, sizeof(*inds));
_industry_specs[ind_id] = *inds;
/* ... and mark it as usable*/
_industry_specs[ind_id].enabled = true;
}

@ -520,7 +520,7 @@ uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, In
* @param creation_type The circumstances the industry is created under.
* @return Succeeded or failed command.
*/
CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint layout, uint32 seed, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, size_t layout, uint32 seed, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
{
const IndustrySpec *indspec = GetIndustrySpec(type);
@ -529,7 +529,7 @@ CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uin
ind.location.tile = tile;
ind.location.w = 0; // important to mark the industry invalid
ind.type = type;
ind.selected_layout = layout;
ind.selected_layout = (byte)layout;
ind.town = ClosestTownFromTile(tile, UINT_MAX);
ind.random = initial_random_bits;
ind.founder = founder;

@ -89,7 +89,7 @@ enum IndustryAvailabilityCallType {
uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile);
uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i, uint32 cur_grfid);
void IndustryProductionCallback(Industry *ind, int reason);
CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint layout, uint32 seed, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type);
CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, size_t layout, uint32 seed, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type);
uint32 GetIndustryProbabilityCallback(IndustryType type, IndustryAvailabilityCallType creation_type, uint32 default_prob);
bool IndustryTemporarilyRefusesCargo(Industry *ind, CargoID cargo_type);

@ -212,13 +212,13 @@ extern bool IsSlopeRefused(Slope current, Slope refused);
* @param its Tile specification.
* @param type Industry type.
* @param gfx Gfx of the tile.
* @param itspec_index Layout.
* @param layout_index Layout.
* @param initial_random_bits Random bits of industry after construction
* @param founder Industry founder
* @param creation_type The circumstances the industry is created under.
* @return Succeeded or failed command.
*/
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, size_t layout_index, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
{
Industry ind;
ind.index = INVALID_INDUSTRY;
@ -228,7 +228,7 @@ CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind
ind.random = initial_random_bits;
ind.founder = founder;
uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, creation_type << 8 | itspec_index, gfx, &ind, ind_tile);
uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, creation_type << 8 | (uint32)layout_index, gfx, &ind, ind_tile);
if (callback_res == CALLBACK_FAILED) {
if (!IsSlopeRefused(GetTileSlope(ind_tile), its->slopes_refused)) return CommandCost();
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);

@ -57,7 +57,7 @@ struct IndustryTileResolverObject : public ResolverObject {
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds);
uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile);
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type);
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, size_t layout_index, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type);
void AnimateNewIndustryTile(TileIndex tile);
bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random = Random());

@ -40,4 +40,17 @@ bool IsMonospaceFont(CFStringRef name);
void MacOSSetThreadName(const char *name);
/** Deleter that calls CFRelease rather than deleting the pointer. */
template <typename T> struct CFDeleter {
void operator()(T *p)
{
if (p) ::CFRelease(p);
}
};
/** Specialisation of std::unique_ptr for CoreFoundation objects. */
template <typename T>
using CFAutoRelease = std::unique_ptr<typename std::remove_pointer<T>::type, CFDeleter<typename std::remove_pointer<T>::type>>;
#endif /* MACOS_H */

@ -23,9 +23,9 @@
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
/** Cached current locale. */
static CFLocaleRef _osx_locale = nullptr;
static CFAutoRelease<CFLocaleRef> _osx_locale;
/** CoreText cache for font information, cleared when OTTD changes fonts. */
static CTFontRef _font_cache[FS_END];
static CFAutoRelease<CTFontRef> _font_cache[FS_END];
/**
@ -37,7 +37,7 @@ private:
ptrdiff_t length;
const FontMap& font_map;
CTTypesetterRef typesetter;
CFAutoRelease<CTTypesetterRef> typesetter;
CFIndex cur_offset = 0; ///< Offset from the start of the current run from where to output.
@ -69,9 +69,9 @@ public:
/** A single line worth of VisualRuns. */
class CoreTextLine : public std::vector<CoreTextVisualRun>, public ParagraphLayouter::Line {
public:
CoreTextLine(CTLineRef line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff)
CoreTextLine(CFAutoRelease<CTLineRef> line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff)
{
CFArrayRef runs = CTLineGetGlyphRuns(line);
CFArrayRef runs = CTLineGetGlyphRuns(line.get());
for (CFIndex i = 0; i < CFArrayGetCount(runs); i++) {
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, i);
@ -82,7 +82,6 @@ public:
this->emplace_back(run, map->second, buff);
}
CFRelease(line);
}
int GetLeading() const override;
@ -97,16 +96,11 @@ public:
}
};
CoreTextParagraphLayout(CTTypesetterRef typesetter, const CoreTextParagraphLayoutFactory::CharType *buffer, ptrdiff_t len, const FontMap &fontMapping) : text_buffer(buffer), length(len), font_map(fontMapping), typesetter(typesetter)
CoreTextParagraphLayout(CFAutoRelease<CTTypesetterRef> typesetter, const CoreTextParagraphLayoutFactory::CharType *buffer, ptrdiff_t len, const FontMap &fontMapping) : text_buffer(buffer), length(len), font_map(fontMapping), typesetter(std::move(typesetter))
{
this->Reflow();
}
~CoreTextParagraphLayout() override
{
CFRelease(this->typesetter);
}
void Reflow() override
{
this->cur_offset = 0;
@ -144,12 +138,11 @@ static CTRunDelegateCallbacks _sprite_font_callback = {
}
/* Make attributed string with embedded font information. */
CFMutableAttributedStringRef str = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringBeginEditing(str);
CFAutoRelease<CFMutableAttributedStringRef> str(CFAttributedStringCreateMutable(kCFAllocatorDefault, 0));
CFAttributedStringBeginEditing(str.get());
CFStringRef base = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull);
CFAttributedStringReplaceString(str, CFRangeMake(0, 0), base);
CFRelease(base);
CFAutoRelease<CFStringRef> base(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull));
CFAttributedStringReplaceString(str.get(), CFRangeMake(0, 0), base.get());
/* Apply font and colour ranges to our string. This is important to make sure
* that we get proper glyph boundaries on style changes. */
@ -157,36 +150,33 @@ static CTRunDelegateCallbacks _sprite_font_callback = {
for (const auto &i : fontMapping) {
if (i.first - last == 0) continue;
if (_font_cache[i.second->fc->GetSize()] == nullptr) {
if (!_font_cache[i.second->fc->GetSize()]) {
/* Cache font information. */
CFStringRef font_name = CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8);
_font_cache[i.second->fc->GetSize()] = CTFontCreateWithName(font_name, i.second->fc->GetFontSize(), nullptr);
CFRelease(font_name);
CFAutoRelease<CFStringRef> font_name(CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8));
_font_cache[i.second->fc->GetSize()].reset(CTFontCreateWithName(font_name.get(), i.second->fc->GetFontSize(), nullptr));
}
CFAttributedStringSetAttribute(str, CFRangeMake(last, i.first - last), kCTFontAttributeName, _font_cache[i.second->fc->GetSize()]);
CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTFontAttributeName, _font_cache[i.second->fc->GetSize()].get());
CGColorRef color = CGColorCreateGenericGray((uint8)i.second->colour / 255.0f, 1.0f); // We don't care about the real colours, just that they are different.
CFAttributedStringSetAttribute(str, CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color);
CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color);
CGColorRelease(color);
/* Install a size callback for our special sprite glyphs. */
for (ssize_t c = last; c < i.first; c++) {
if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END) {
CTRunDelegateRef del = CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24)));
CFAttributedStringSetAttribute(str, CFRangeMake(c, 1), kCTRunDelegateAttributeName, del);
CFRelease(del);
CFAutoRelease<CTRunDelegateRef> del(CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24))));
CFAttributedStringSetAttribute(str.get(), CFRangeMake(c, 1), kCTRunDelegateAttributeName, del.get());
}
}
last = i.first;
}
CFAttributedStringEndEditing(str);
CFAttributedStringEndEditing(str.get());
/* Create and return typesetter for the string. */
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(str);
CFRelease(str);
CFAutoRelease<CTTypesetterRef> typesetter(CTTypesetterCreateWithAttributedString(str.get()));
return typesetter != nullptr ? new CoreTextParagraphLayout(typesetter, buff, length, fontMapping) : nullptr;
return typesetter ? new CoreTextParagraphLayout(std::move(typesetter), buff, length, fontMapping) : nullptr;
}
/* virtual */ std::unique_ptr<const ParagraphLayouter::Line> CoreTextParagraphLayout::NextLine(int max_width)
@ -194,14 +184,14 @@ static CTRunDelegateCallbacks _sprite_font_callback = {
if (this->cur_offset >= this->length) return nullptr;
/* Get line break position, trying word breaking first and breaking somewhere if that doesn't work. */
CFIndex len = CTTypesetterSuggestLineBreak(this->typesetter, this->cur_offset, max_width);
if (len <= 0) len = CTTypesetterSuggestClusterBreak(this->typesetter, this->cur_offset, max_width);
CFIndex len = CTTypesetterSuggestLineBreak(this->typesetter.get(), this->cur_offset, max_width);
if (len <= 0) len = CTTypesetterSuggestClusterBreak(this->typesetter.get(), this->cur_offset, max_width);
/* Create line. */
CTLineRef line = CTTypesetterCreateLine(this->typesetter, CFRangeMake(this->cur_offset, len));
CFAutoRelease<CTLineRef> line(CTTypesetterCreateLine(this->typesetter.get(), CFRangeMake(this->cur_offset, len)));
this->cur_offset += len;
return std::unique_ptr<const Line>(line != nullptr ? new CoreTextLine(line, this->font_map, this->text_buffer) : nullptr);
return std::unique_ptr<const Line>(line ? new CoreTextLine(std::move(line), this->font_map, this->text_buffer) : nullptr);
}
CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff) : font(font)
@ -272,10 +262,7 @@ int CoreTextParagraphLayout::CoreTextLine::GetWidth() const
/** Delete CoreText font reference for a specific font size. */
void MacOSResetScriptCache(FontSize size)
{
if (_font_cache[size] != nullptr) {
CFRelease(_font_cache[size]);
_font_cache[size] = nullptr;
}
_font_cache[size].reset();
}
/** Store current language locale as a CoreFounation locale. */
@ -283,11 +270,8 @@ void MacOSSetCurrentLocaleName(const char *iso_code)
{
if (!MacOSVersionIsAtLeast(10, 5, 0)) return;
if (_osx_locale != nullptr) CFRelease(_osx_locale);
CFStringRef iso = CFStringCreateWithCString(kCFAllocatorDefault, iso_code, kCFStringEncodingUTF8);
_osx_locale = CFLocaleCreate(kCFAllocatorDefault, iso);
CFRelease(iso);
CFAutoRelease<CFStringRef> iso(CFStringCreateWithCString(kCFAllocatorDefault, iso_code, kCFStringEncodingUTF8));
_osx_locale.reset(CFLocaleCreate(kCFAllocatorDefault, iso.get()));
}
/**
@ -306,27 +290,13 @@ int MacOSStringCompare(const char *s1, const char *s2)
CFStringCompareFlags flags = kCFCompareCaseInsensitive | kCFCompareNumerically | kCFCompareLocalized | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
CFStringRef cf1 = CFStringCreateWithCString(kCFAllocatorDefault, s1, kCFStringEncodingUTF8);
if (cf1 == nullptr) return 0;
auto guard1 = scope_guard([&]() {
CFRelease(cf1);
});
CFStringRef cf2 = CFStringCreateWithCString(kCFAllocatorDefault, s2, kCFStringEncodingUTF8);
if (cf2 == nullptr) return 0;
auto guard2 = scope_guard([&]() {
CFRelease(cf2);
});
CFAutoRelease<CFStringRef> cf1(CFStringCreateWithCString(kCFAllocatorDefault, s1, kCFStringEncodingUTF8));
CFAutoRelease<CFStringRef> cf2(CFStringCreateWithCString(kCFAllocatorDefault, s2, kCFStringEncodingUTF8));
/* If any CFString could not be created (e.g., due to UTF8 invalid chars), return OS unsupported functionality */
if (cf1 == nullptr || cf2 == nullptr) {
if (cf1 != nullptr) CFRelease(cf1);
if (cf2 != nullptr) CFRelease(cf2);
return 0;
}
if (cf1 == nullptr || cf2 == nullptr) return 0;
CFComparisonResult res = CFStringCompareWithOptionsAndLocale(cf1, cf2, CFRangeMake(0, CFStringGetLength(cf1)), flags, _osx_locale);
return (int)res + 2;
return (int)CFStringCompareWithOptionsAndLocale(cf1.get(), cf2.get(), CFRangeMake(0, CFStringGetLength(cf1.get())), flags, _osx_locale.get()) + 2;
}
@ -361,30 +331,27 @@ int MacOSStringCompare(const char *s1, const char *s2)
this->str_info.resize(utf16_to_utf8.size());
if (utf16_str.size() > 0) {
CFStringRef str = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &utf16_str[0], utf16_str.size(), kCFAllocatorNull);
CFAutoRelease<CFStringRef> str(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &utf16_str[0], utf16_str.size(), kCFAllocatorNull));
/* Get cluster breaks. */
for (CFIndex i = 0; i < CFStringGetLength(str); ) {
CFRange r = CFStringGetRangeOfComposedCharactersAtIndex(str, i);
for (CFIndex i = 0; i < CFStringGetLength(str.get()); ) {
CFRange r = CFStringGetRangeOfComposedCharactersAtIndex(str.get(), i);
this->str_info[r.location].char_stop = true;
i += r.length;
}
/* Get word breaks. */
CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, str, CFRangeMake(0, CFStringGetLength(str)), kCFStringTokenizerUnitWordBoundary, _osx_locale);
CFAutoRelease<CFStringTokenizerRef> tokenizer(CFStringTokenizerCreate(kCFAllocatorDefault, str.get(), CFRangeMake(0, CFStringGetLength(str.get())), kCFStringTokenizerUnitWordBoundary, _osx_locale.get()));
CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone;
while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) != kCFStringTokenizerTokenNone) {
while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer.get())) != kCFStringTokenizerTokenNone) {
/* Skip tokens that are white-space or punctuation tokens. */
if ((tokenType & kCFStringTokenizerTokenHasNonLettersMask) != kCFStringTokenizerTokenHasNonLettersMask) {
CFRange r = CFStringTokenizerGetCurrentTokenRange(tokenizer);
CFRange r = CFStringTokenizerGetCurrentTokenRange(tokenizer.get());
this->str_info[r.location].word_stop = true;
}
}
CFRelease(tokenizer);
CFRelease(str);
}
/* End-of-string is always a valid stopping point. */

@ -306,6 +306,7 @@ enum SaveLoadVersion : uint16 {
SLV_SCRIPT_MEMLIMIT, ///< 215 PR#7516 Limit on AI/GS memory consumption.
SLV_MULTITILE_DOCKS, ///< 216 PR#7380 Multiple docks per station.
SLV_TRADING_AGE, ///< 217 PR#7780 Configurable company trading age.
SL_MAX_VERSION, ///< Highest possible saveload version

@ -50,6 +50,7 @@ void SQAIEvent_Register(Squirrel *engine)
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_GOAL_QUESTION_ANSWER, "ET_GOAL_QUESTION_ANSWER");
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_EXCLUSIVE_TRANSPORT_RIGHTS, "ET_EXCLUSIVE_TRANSPORT_RIGHTS");
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_ROAD_RECONSTRUCTION, "ET_ROAD_RECONSTRUCTION");
SQAIEvent.DefSQConst(engine, ScriptEvent::ET_VEHICLE_AUTOREPLACED, "ET_VEHICLE_AUTOREPLACED");
SQAIEvent.DefSQMethod(engine, &ScriptEvent::GetEventType, "GetEventType", 1, "x");

@ -405,3 +405,19 @@ void SQAIEventRoadReconstruction_Register(Squirrel *engine)
SQAIEventRoadReconstruction.PostRegister(engine);
}
template <> const char *GetClassName<ScriptEventVehicleAutoReplaced, ST_AI>() { return "AIEventVehicleAutoReplaced"; }
void SQAIEventVehicleAutoReplaced_Register(Squirrel *engine)
{
DefSQClass<ScriptEventVehicleAutoReplaced, ST_AI> SQAIEventVehicleAutoReplaced("AIEventVehicleAutoReplaced");
SQAIEventVehicleAutoReplaced.PreRegister(engine, "AIEvent");
SQAIEventVehicleAutoReplaced.DefSQStaticMethod(engine, &ScriptEventVehicleAutoReplaced::Convert, "Convert", 2, ".x");
SQAIEventVehicleAutoReplaced.DefSQMethod(engine, &ScriptEventVehicleAutoReplaced::GetOldVehicleID, "GetOldVehicleID", 1, "x");
SQAIEventVehicleAutoReplaced.DefSQMethod(engine, &ScriptEventVehicleAutoReplaced::GetNewVehicleID, "GetNewVehicleID", 1, "x");
SQAIEventVehicleAutoReplaced.PostRegister(engine);
}

@ -34,6 +34,7 @@
* \li AIEngine::CanRunOnRoad
* \li AIEngine::HasPowerOnRoad
* \li AIRoadTypeList::RoadTypeList
* \li AIEventVehicleAutoReplaced
*
* Other changes:
* \li AITile::DemolishTile works without a selected company

@ -50,6 +50,7 @@ void SQGSEvent_Register(Squirrel *engine)
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_GOAL_QUESTION_ANSWER, "ET_GOAL_QUESTION_ANSWER");
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_EXCLUSIVE_TRANSPORT_RIGHTS, "ET_EXCLUSIVE_TRANSPORT_RIGHTS");
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_ROAD_RECONSTRUCTION, "ET_ROAD_RECONSTRUCTION");
SQGSEvent.DefSQConst(engine, ScriptEvent::ET_VEHICLE_AUTOREPLACED, "ET_VEHICLE_AUTOREPLACED");
SQGSEvent.DefSQMethod(engine, &ScriptEvent::GetEventType, "GetEventType", 1, "x");

@ -55,6 +55,7 @@ public:
ET_GOAL_QUESTION_ANSWER,
ET_EXCLUSIVE_TRANSPORT_RIGHTS,
ET_ROAD_RECONSTRUCTION,
ET_VEHICLE_AUTOREPLACED,
};
/**

@ -1060,4 +1060,44 @@ public:
static ScriptEventRoadReconstruction *Convert(ScriptEventCompanyTown *instance) { return (ScriptEventRoadReconstruction *)instance; }
};
/**
* Event VehicleAutoReplaced, indicating a vehicle has been auto replaced.
* @api ai
*/
class ScriptEventVehicleAutoReplaced : public ScriptEvent {
public:
/**
* @param old_id The vehicle that has been replaced.
* @param new_id The vehicle that has been created in replacement.
*/
ScriptEventVehicleAutoReplaced(VehicleID old_id, VehicleID new_id) :
ScriptEvent(ET_VEHICLE_AUTOREPLACED),
old_id(old_id),
new_id(new_id)
{}
/**
* Convert an ScriptEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static ScriptEventVehicleAutoReplaced *Convert(ScriptEvent *instance) { return (ScriptEventVehicleAutoReplaced *)instance; }
/**
* Get the VehicleID of the vehicle that has been replaced.
* @return The VehicleID of the vehicle that has been replaced. This ID is no longer valid for referencing the vehicle.
*/
VehicleID GetOldVehicleID() { return this->old_id; }
/**
* Get the VehicleID of the vehicle that has been created in replacement.
* @return The VehicleID of the vehicle that has been created in replacement.
*/
VehicleID GetNewVehicleID() { return this->new_id; }
private:
VehicleID old_id; ///< The vehicle that has been replaced.
VehicleID new_id; ///< The vehicle that has been created in replacement.
};
#endif /* SCRIPT_EVENT_TYPES_HPP */

@ -123,7 +123,8 @@
EnforcePrecondition(false, ScriptMap::IsValidTile(tile));
uint32 seed = ::InteractiveRandom();
return ScriptObject::DoCommand(tile, (1 << 16) | (::InteractiveRandomRange(::GetIndustrySpec(industry_type)->num_table) << 8) | industry_type, seed, CMD_BUILD_INDUSTRY);
uint32 layout_index = ::InteractiveRandomRange((uint32)::GetIndustrySpec(industry_type)->layouts.size());
return ScriptObject::DoCommand(tile, (1 << 16) | (layout_index << 8) | industry_type, seed, CMD_BUILD_INDUSTRY);
}
/* static */ bool ScriptIndustryType::ProspectIndustry(IndustryType industry_type)

@ -40,7 +40,7 @@ public:
/** The area was already flat */
ERR_AREA_ALREADY_FLAT, // [STR_ERROR_ALREADY_LEVELLED]
/** There is a tunnel underneed */
/** There is a tunnel underneath */
ERR_EXCAVATION_WOULD_DAMAGE, // [STR_ERROR_EXCAVATION_WOULD_DAMAGE]
};
@ -351,7 +351,7 @@ public:
* @pre width > 0.
* @pre height > 0.
* @pre radius >= 0.
* @return Value below 8 means no acceptance; the more the better.
* @return Values below 8 mean no acceptance; the more the better.
*/
static int32 GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int radius);

@ -266,3 +266,12 @@ namespace SQConvert {
template <> inline const ScriptEventRoadReconstruction &GetParam(ForceType<const ScriptEventRoadReconstruction &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventRoadReconstruction *)instance; }
template <> inline int Return<ScriptEventRoadReconstruction *>(HSQUIRRELVM vm, ScriptEventRoadReconstruction *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EventRoadReconstruction", res, nullptr, DefSQDestructorCallback<ScriptEventRoadReconstruction>, true); return 1; }
} // namespace SQConvert
namespace SQConvert {
/* Allow ScriptEventVehicleAutoReplaced to be used as Squirrel parameter */
template <> inline ScriptEventVehicleAutoReplaced *GetParam(ForceType<ScriptEventVehicleAutoReplaced *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptEventVehicleAutoReplaced *)instance; }
template <> inline ScriptEventVehicleAutoReplaced &GetParam(ForceType<ScriptEventVehicleAutoReplaced &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventVehicleAutoReplaced *)instance; }
template <> inline const ScriptEventVehicleAutoReplaced *GetParam(ForceType<const ScriptEventVehicleAutoReplaced *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptEventVehicleAutoReplaced *)instance; }
template <> inline const ScriptEventVehicleAutoReplaced &GetParam(ForceType<const ScriptEventVehicleAutoReplaced &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptEventVehicleAutoReplaced *)instance; }
template <> inline int Return<ScriptEventVehicleAutoReplaced *>(HSQUIRRELVM vm, ScriptEventVehicleAutoReplaced *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EventVehicleAutoReplaced", res, nullptr, DefSQDestructorCallback<ScriptEventVehicleAutoReplaced>, true); return 1; }
} // namespace SQConvert

@ -1977,6 +1977,7 @@ static SettingsContainer &GetSettingsTree()
ai->Add(new SettingEntry("economy.give_money"));
ai->Add(new SettingEntry("economy.allow_shares"));
ai->Add(new SettingEntry("economy.min_years_for_shares"));
}
main->Init();

@ -552,6 +552,7 @@ struct EconomySettings {
bool bribe; ///< enable bribing the local authority
bool smooth_economy; ///< smooth economy
bool allow_shares; ///< allow the buying/selling of shares
uint8 min_years_for_shares; ///< minimum age of a company for it to trade shares
uint8 feeder_payment_share; ///< percentage of leg payment to virtually pay in feeder systems
bool feeder_payment_src_station; ///< calculate leg payment relative to the source station, not the leg source
byte dist_local_authority; ///< distance for town local authority, default 20

@ -2804,10 +2804,8 @@ void RemoveDockingTile(TileIndex t)
if (IsTileType(tile, MP_STATION)) {
UpdateStationDockingTiles(Station::GetByTile(tile));
} else if (IsTileType(tile, MP_INDUSTRY)) {
Station *st = Industry::GetByTile(tile)->neutral_station;
if (st != nullptr) {
UpdateStationDockingTiles(Industry::GetByTile(tile)->neutral_station);
}
Station *neutral = Industry::GetByTile(tile)->neutral_station;
if (neutral != nullptr) UpdateStationDockingTiles(neutral);
}
}
}

@ -71,10 +71,10 @@ static const AirportMovingData _airport_moving_data_country[22] = {
};
/** Commuter Airfield (small) 5x4. */
static const AirportMovingData _airport_moving_data_commuter[37] = {
static const AirportMovingData _airport_moving_data_commuter[38] = {
AMD( 69, 3, AMED_EXACTPOS, DIR_SE), // 00 In Hangar
AMD( 72, 22, 0, DIR_N ), // 01 Taxi to right outside depot
AMD( 8, 22, AMED_EXACTPOS, DIR_SW), // 01 Taxi to right outside depot
AMD( 8, 22, AMED_EXACTPOS, DIR_SW), // 02 Taxi to right outside depot
AMD( 24, 36, AMED_EXACTPOS, DIR_SE), // 03 Terminal 1
AMD( 40, 36, AMED_EXACTPOS, DIR_SE), // 04 Terminal 2
AMD( 56, 36, AMED_EXACTPOS, DIR_SE), // 05 Terminal 3
@ -108,8 +108,9 @@ static const AirportMovingData _airport_moving_data_commuter[37] = {
AMD( 48, 8, AMED_HELI_RAISE, DIR_N ), // 32 Takeoff Helipad2
AMD( 64, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, DIR_N ), // 33 Go to position for Hangarentrance in air
AMD( 64, 22, AMED_HELI_LOWER, DIR_N ), // 34 Land in front of hangar
AMD( 40, 8, AMED_EXACTPOS, DIR_N ), // pre-helitakeoff helipad 1
AMD( 56, 8, AMED_EXACTPOS, DIR_N ), // pre-helitakeoff helipad 2
AMD( 40, 8, AMED_EXACTPOS, DIR_N ), // 35 pre-helitakeoff helipad 1
AMD( 56, 8, AMED_EXACTPOS, DIR_N ), // 36 pre-helitakeoff helipad 2
AMD( 64, 25, AMED_HELI_RAISE, DIR_N ), // 37 Take off in front of hangar
};
/** City Airport (large) 6x6. */
@ -179,11 +180,11 @@ static const AirportMovingData _airport_moving_data_metropolitan[28] = {
};
/** International Airport (international) - 2 runways, 6 terminals, dedicated helipad. */
static const AirportMovingData _airport_moving_data_international[51] = {
static const AirportMovingData _airport_moving_data_international[53] = {
AMD( 7, 55, AMED_EXACTPOS, DIR_SE), // 00 In Hangar 1
AMD( 100, 21, AMED_EXACTPOS, DIR_SE), // 01 In Hangar 2
AMD( 7, 70, 0, DIR_N ), // 02 Taxi to right outside depot
AMD( 100, 36, 0, DIR_N ), // 03 Taxi to right outside depot
AMD( 7, 70, 0, DIR_N ), // 02 Taxi to right outside depot (Hangar 1)
AMD( 100, 36, 0, DIR_N ), // 03 Taxi to right outside depot (Hangar 2)
AMD( 38, 70, AMED_EXACTPOS, DIR_SW), // 04 Terminal 1
AMD( 38, 54, AMED_EXACTPOS, DIR_SW), // 05 Terminal 2
AMD( 38, 38, AMED_EXACTPOS, DIR_SW), // 06 Terminal 3
@ -232,6 +233,8 @@ static const AirportMovingData _airport_moving_data_international[51] = {
AMD( 104, 55, AMED_HELI_RAISE, DIR_N ), // 48 Takeoff Helipad2
AMD( 104, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, DIR_N ), // 49 Go to position for Hangarentrance in air
AMD( 104, 32, AMED_HELI_LOWER, DIR_N ), // 50 Land in HANGAR2_AREA to go to hangar
AMD( 7, 70, AMED_HELI_RAISE, DIR_N ), // 51 Takeoff from HANGAR1_AREA
AMD( 100, 36, AMED_HELI_RAISE, DIR_N ), // 52 Takeoff from HANGAR2_AREA
};
/** Intercontinental Airport - 4 runways, 8 terminals, 2 dedicated helipads. */
@ -408,11 +411,11 @@ static const AirportMovingData _airport_moving_data_oilrig[9] = {
/////**********Movement Machine on Airports*********************///////
static const byte _airport_entries_dummy[] = {0, 1, 2, 3};
static const AirportFTAbuildup _airport_fta_dummy[] = {
{ 0, 0, 0, 3},
{ 1, 0, 0, 0},
{ 2, 0, 0, 1},
{ 3, 0, 0, 2},
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
{ 0, TO_ALL, 0, 3},
{ 1, TO_ALL, 0, 0},
{ 2, TO_ALL, 0, 1},
{ 3, TO_ALL, 0, 2},
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
/* First element of terminals array tells us how many depots there are (to know size of array)
@ -422,11 +425,11 @@ static const byte _airport_terminal_country[] = {1, 2};
static const byte _airport_entries_country[] = {16, 15, 18, 17};
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 },
{ 1, TERMGROUP, AIRPORT_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM1, TERM1_block, 2 }, { 1, TERM2, 0, 4 }, { 1, HELITAKEOFF, 0, 19 }, { 1, TO_ALL, 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 },
{ 4, TERMGROUP, AIRPORT_BUSY_block, 0 }, { 4, TERM2, 0, 5 }, { 4, HANGAR, 0, 1 }, { 4, TAKEOFF, 0, 6 }, { 4, HELITAKEOFF, 0, 1 },
{ 5, TERMGROUP, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TO_ALL, 0, 4 },
{ 6, 0, AIRPORT_BUSY_block, 7 },
/* takeoff */
{ 7, TAKEOFF, AIRPORT_BUSY_block, 8 },
@ -435,82 +438,83 @@ static const AirportFTAbuildup _airport_fta_country[] = {
/* 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 },
{ 12, TO_ALL, AIRPORT_BUSY_block, 13 },
{ 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, TO_ALL, 0, 14 },
{ 14, TO_ALL, 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 },
{ 15, TO_ALL, NOTHING_block, 16 },
{ 16, TO_ALL, NOTHING_block, 17 },
{ 17, TO_ALL, NOTHING_block, 18 },
{ 18, TO_ALL, 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
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
static const HangarTileTable _airport_depots_commuter[] = { {{4, 0}, DIR_SE, 0} };
static const byte _airport_terminal_commuter[] = { 1, 3 };
static const byte _airport_entries_commuter[] = {22, 21, 24, 23};
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 },
{ 0, HANGAR, NOTHING_block, 1 }, { 0, HELITAKEOFF, TAXIWAY_BUSY_block, 1 }, { 0, TO_ALL, 0, 1 },
{ 1, TERMGROUP, 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, 37 }, { 1, TO_ALL, 0, 0 },
{ 2, TERMGROUP, 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, TO_ALL, 0, 2 },
{ 3, TERM1, TERM1_block, 8 }, { 3, HANGAR, 0, 8 }, { 3, TAKEOFF, 0, 8 }, { 3, TO_ALL, 0, 3 },
{ 4, TERM2, TERM2_block, 9 }, { 4, HANGAR, 0, 9 }, { 4, TAKEOFF, 0, 9 }, { 4, TO_ALL, 0, 4 },
{ 5, TERM3, TERM3_block, 10 }, { 5, HANGAR, 0, 10 }, { 5, TAKEOFF, 0, 10 }, { 5, TO_ALL, 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 },
{ 8, TERMGROUP, TAXIWAY_BUSY_block, 8 }, { 8, TAKEOFF, TAXIWAY_BUSY_block, 9 }, { 8, HANGAR, TAXIWAY_BUSY_block, 9 }, { 8, TERM1, TERM1_block, 3 }, { 8, TO_ALL, TAXIWAY_BUSY_block, 9 },
{ 9, TERMGROUP, 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, TO_ALL, TAXIWAY_BUSY_block, 10 },
{ 10, TERMGROUP, TAXIWAY_BUSY_block, 10 }, { 10, TERM3, TERM3_block, 5 }, { 10, HELIPAD1, 0, 9 }, { 10, HELIPAD2, HELIPAD2_block, 7 }, { 10, HELITAKEOFF, 0, 1 }, { 10, TAKEOFF, TAXIWAY_BUSY_block, 1 }, { 10, HANGAR, TAXIWAY_BUSY_block, 1 }, { 10, TO_ALL, TAXIWAY_BUSY_block, 9 },
{ 11, TO_ALL, OUT_WAY_block, 12 },
/* takeoff */
{ 12, TAKEOFF, RUNWAY_IN_OUT_block, 13 },
{ 13, 0, RUNWAY_IN_OUT_block, 14 },
{ 13, TO_ALL, 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 },
{ 18, TO_ALL, RUNWAY_IN_OUT_block, 19 },
{ 19, TO_ALL, 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 },
{ 21, TO_ALL, NOTHING_block, 22 },
{ 22, TO_ALL, NOTHING_block, 23 },
{ 23, TO_ALL, NOTHING_block, 24 },
{ 24, TO_ALL, 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 },
{ 27, TO_ALL, NOTHING_block, 29 }, // helipad1 approach
{ 28, TO_ALL, NOTHING_block, 30 },
/* landing */
{ 29, 255, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
{ 30, 255, NOTHING_block, 0 }, { 30, HELIPAD2, HELIPAD2_block, 7 },
{ 29, TERMGROUP, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
{ 30, TERMGROUP, 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
{ 33, TO_ALL, TAXIWAY_BUSY_block, 34 }, // need to go to hangar when waiting in air
{ 34, TO_ALL, TAXIWAY_BUSY_block, 1 },
{ 35, TO_ALL, HELIPAD1_block, 31 },
{ 36, TO_ALL, HELIPAD2_block, 32 },
{ 37, HELITAKEOFF, NOTHING_block, 0 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
static const HangarTileTable _airport_depots_city[] = { {{5, 0}, DIR_SE, 0} };
static const byte _airport_terminal_city[] = { 1, 3 };
static const byte _airport_entries_city[] = {26, 29, 27, 28};
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, 6 }, { 3, 0, 0, 6 },
{ 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, TERM2_block, 3 }, { 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 },
{ 0, HANGAR, NOTHING_block, 1 }, { 0, TAKEOFF, OUT_WAY_block, 1 }, { 0, TO_ALL, 0, 1 },
{ 1, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, TO_ALL, 0, 7 }, // for all else, go to 7
{ 2, TERM1, TERM1_block, 7 }, { 2, TAKEOFF, OUT_WAY_block, 7 }, { 2, TO_ALL, 0, 7 },
{ 3, TERM2, TERM2_block, 5 }, { 3, TAKEOFF, OUT_WAY_block, 6 }, { 3, TO_ALL, 0, 6 },
{ 4, TERM3, TERM3_block, 5 }, { 4, TAKEOFF, OUT_WAY_block, 5 }, { 4, TO_ALL, 0, 5 },
{ 5, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, TO_ALL, 0, 6 },
{ 6, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, TERM2_block, 3 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, TO_ALL, 0, 7 },
{ 7, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, OUT_WAY_block, 8 }, { 7, HELITAKEOFF, 0, 22 }, { 7, HANGAR, 0, 1 }, { 7, TO_ALL, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_IN_OUT_block, 10 },
/* takeoff */
@ -520,24 +524,24 @@ static const AirportFTAbuildup _airport_fta_city[] = {
/* 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, 17 },
{ 16, 0, RUNWAY_IN_OUT_block, 17 }, // not used, left for compatibility
{ 15, TO_ALL, RUNWAY_IN_OUT_block, 17 },
{ 16, TO_ALL, RUNWAY_IN_OUT_block, 17 }, // not used, left for compatibility
{ 17, ENDLANDING, IN_WAY_block, 7 },
/* In Air */
{ 18, 0, NOTHING_block, 25 },
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 13 },
{ 18, TO_ALL, NOTHING_block, 25 },
{ 19, TO_ALL, NOTHING_block, 20 },
{ 20, TO_ALL, NOTHING_block, 21 },
{ 21, TO_ALL, NOTHING_block, 13 },
/* helicopter */
{ 22, HELITAKEOFF, NOTHING_block, 0 },
{ 23, HELILANDING, IN_WAY_block, 24 },
{ 24, HELIENDLANDING, IN_WAY_block, 17 },
{ 25, 0, NOTHING_block, 20},
{ 26, 0, NOTHING_block, 19},
{ 27, 0, NOTHING_block, 28},
{ 28, 0, NOTHING_block, 19},
{ 29, 0, NOTHING_block, 26},
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
{ 25, TO_ALL, NOTHING_block, 20},
{ 26, TO_ALL, NOTHING_block, 19},
{ 27, TO_ALL, NOTHING_block, 28},
{ 28, TO_ALL, NOTHING_block, 19},
{ 29, TO_ALL, NOTHING_block, 26},
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
static const HangarTileTable _airport_depots_metropolitan[] = { {{5, 0}, DIR_SE, 0} };
@ -545,13 +549,13 @@ static const byte _airport_terminal_metropolitan[] = { 1, 3 };
static const byte _airport_entries_metropolitan[] = {20, 19, 22, 21};
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
{ 1, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, TO_ALL, 0, 7 }, // for all else, go to 7
{ 2, TERM1, TERM1_block, 7 },
{ 3, TERM2, TERM2_block, 6 },
{ 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, TERM2_block, 3 }, { 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 },
{ 5, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, TO_ALL, 0, 6 },
{ 6, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, TERM2_block, 3 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, TO_ALL, 0, 7 },
{ 7, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, 0, 8 }, { 7, HELITAKEOFF, 0, 23 }, { 7, HANGAR, 0, 1 }, { 7, TO_ALL, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_OUT_block, 10 },
/* takeoff */
@ -561,86 +565,88 @@ static const AirportFTAbuildup _airport_fta_metropolitan[] = {
/* 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 },
{ 15, TO_ALL, RUNWAY_IN_block, 16 },
{ 16, TERMGROUP, RUNWAY_IN_block, 0 }, { 16, ENDLANDING, IN_WAY_block, 17 },
{ 17, TERMGROUP, RUNWAY_OUT_block, 0 }, { 17, ENDLANDING, IN_WAY_block, 18 },
{ 18, ENDLANDING, IN_WAY_block, 27 },
/* In Air */
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 22 },
{ 22, 0, NOTHING_block, 13 },
{ 19, TO_ALL, NOTHING_block, 20 },
{ 20, TO_ALL, NOTHING_block, 21 },
{ 21, TO_ALL, NOTHING_block, 22 },
{ 22, TO_ALL, NOTHING_block, 13 },
/* helicopter */
{ 23, 0, NOTHING_block, 24 },
{ 23, TO_ALL, NOTHING_block, 24 },
{ 24, HELITAKEOFF, NOTHING_block, 0 },
{ 25, HELILANDING, IN_WAY_block, 26 },
{ 26, HELIENDLANDING, IN_WAY_block, 18 },
{ 27, 255, TAXIWAY_BUSY_block, 27 }, { 27, TERM1, TERM1_block, 2 }, { 27, 0, 0, 7 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
{ 27, TERMGROUP, TAXIWAY_BUSY_block, 27 }, { 27, TERM1, TERM1_block, 2 }, { 27, TO_ALL, 0, 7 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
static const HangarTileTable _airport_depots_international[] = { {{0, 3}, DIR_SE, 0}, {{6, 1}, DIR_SE, 1} };
static const byte _airport_terminal_international[] = { 2, 3, 3 };
static const byte _airport_entries_international[] = { 38, 37, 40, 39 };
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 },
{ 0, HANGAR, NOTHING_block, 2 }, { 0, TERMGROUP, TERM_GROUP1_block, 0 }, { 0, TERMGROUP, TERM_GROUP2_ENTER1_block, 1 }, { 0, HELITAKEOFF, AIRPORT_ENTRANCE_block, 2 }, { 0, TO_ALL, 0, 2 },
{ 1, HANGAR, NOTHING_block, 3 }, { 1, TERMGROUP, HANGAR2_AREA_block, 1 }, { 1, HELITAKEOFF, HANGAR2_AREA_block, 3 }, { 1, TO_ALL, 0, 3 },
{ 2, TERMGROUP, 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, 51 }, { 2, TO_ALL, 0, 23 },
{ 3, TERMGROUP, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 52 }, { 3, TO_ALL, 0, 18 },
{ 4, TERM1, TERM1_block, 23 }, { 4, HANGAR, AIRPORT_ENTRANCE_block, 23 }, { 4, TO_ALL, 0, 23 },
{ 5, TERM2, TERM2_block, 24 }, { 5, HANGAR, AIRPORT_ENTRANCE_block, 24 }, { 5, TO_ALL, 0, 24 },
{ 6, TERM3, TERM3_block, 25 }, { 6, HANGAR, AIRPORT_ENTRANCE_block, 25 }, { 6, TO_ALL, 0, 25 },
{ 7, TERM4, TERM4_block, 16 }, { 7, HANGAR, HANGAR2_AREA_block, 16 }, { 7, TO_ALL, 0, 16 },
{ 8, TERM5, TERM5_block, 17 }, { 8, HANGAR, HANGAR2_AREA_block, 17 }, { 8, TO_ALL, 0, 17 },
{ 9, TERM6, TERM6_block, 18 }, { 9, HANGAR, HANGAR2_AREA_block, 18 }, { 9, TO_ALL, 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 },
{ 12, TO_ALL, TERM_GROUP2_ENTER1_block, 13 },
{ 13, TO_ALL, TERM_GROUP2_ENTER1_block, 14 },
{ 14, TO_ALL, TERM_GROUP2_ENTER2_block, 15 },
{ 15, TO_ALL, TERM_GROUP2_ENTER2_block, 16 },
{ 16, TERMGROUP, TERM_GROUP2_block, 0 }, { 16, TERM4, TERM4_block, 7 }, { 16, HELIPAD1, HELIPAD1_block, 10 }, { 16, HELITAKEOFF, HELIPAD1_block, 10 }, { 16, TO_ALL, 0, 17 },
{ 17, TERMGROUP, 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, TO_ALL, 0, 18 },
{ 18, TERMGROUP, TERM_GROUP2_block, 0 }, { 18, TERM6, TERM6_block, 9 }, { 18, TAKEOFF, 0, 19 }, { 18, HANGAR, HANGAR2_AREA_block, 3 }, { 18, TO_ALL, 0, 17 },
{ 19, TO_ALL, TERM_GROUP2_EXIT1_block, 20 },
{ 20, TO_ALL, TERM_GROUP2_EXIT1_block, 21 },
{ 21, TO_ALL, TERM_GROUP2_EXIT2_block, 22 },
{ 22, TO_ALL, TERM_GROUP2_EXIT2_block, 26 },
{ 23, TERMGROUP, TERM_GROUP1_block, 0 }, { 23, TERM1, TERM1_block, 4 }, { 23, HANGAR, AIRPORT_ENTRANCE_block, 2 }, { 23, TO_ALL, 0, 24 },
{ 24, TERMGROUP, TERM_GROUP1_block, 0 }, { 24, TERM2, TERM2_block, 5 }, { 24, TERM1, 0, 23 }, { 24, HANGAR, 0, 23 }, { 24, TO_ALL, 0, 25 },
{ 25, TERMGROUP, TERM_GROUP1_block, 0 }, { 25, TERM3, TERM3_block, 6 }, { 25, TAKEOFF, 0, 26 }, { 25, TO_ALL, 0, 24 },
{ 26, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 26, TAKEOFF, 0, 27 }, { 26, TO_ALL, 0, 25 },
{ 27, TO_ALL, OUT_WAY_block, 28 },
/* takeoff */
{ 28, TAKEOFF, OUT_WAY_block, 29 },
{ 29, 0, RUNWAY_OUT_block, 30 },
{ 29, TO_ALL, 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 },
{ 34, TO_ALL, RUNWAY_IN_block, 35 },
{ 35, TO_ALL, RUNWAY_IN_block, 36 },
{ 36, ENDLANDING, IN_WAY_block, 36 }, { 36, TERMGROUP, TERM_GROUP1_block, 0 }, { 36, TERMGROUP, TERM_GROUP2_ENTER1_block, 1 }, { 36, TERM4, 0, 12 }, { 36, TERM5, 0, 12 }, { 36, TERM6, 0, 12 }, { 36, TO_ALL, 0, 2 },
/* In Air */
{ 37, 0, NOTHING_block, 38 },
{ 38, 0, NOTHING_block, 39 },
{ 39, 0, NOTHING_block, 40 },
{ 40, 0, NOTHING_block, 32 },
{ 37, TO_ALL, NOTHING_block, 38 },
{ 38, TO_ALL, NOTHING_block, 39 },
{ 39, TO_ALL, NOTHING_block, 40 },
{ 40, TO_ALL, 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 },
{ 43, TO_ALL, NOTHING_block, 45 },
{ 44, TO_ALL, NOTHING_block, 46 },
/* landing */
{ 45, 255, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
{ 46, 255, NOTHING_block, 0 }, { 46, HELIPAD2, HELIPAD2_block, 11 },
{ 45, TERMGROUP, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
{ 46, TERMGROUP, 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
{ 49, TO_ALL, HANGAR2_AREA_block, 50 }, // need to go to hangar when waiting in air
{ 50, TO_ALL, HANGAR2_AREA_block, 3 },
{ 51, HELITAKEOFF, NOTHING_block, 0 },
{ 52, HELITAKEOFF, NOTHING_block, 0 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
/* intercontinental */
@ -648,92 +654,92 @@ static const HangarTileTable _airport_depots_intercontinental[] = { {{0, 5}, DIR
static const byte _airport_terminal_intercontinental[] = { 2, 4, 4 };
static const byte _airport_entries_intercontinental[] = { 44, 43, 46, 45 };
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, TAKEOFF, 0, 59}, { 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 },
{ 0, HANGAR, NOTHING_block, 2 }, { 0, TERMGROUP, HANGAR1_AREA_block | TERM_GROUP1_block, 0 }, { 0, TERMGROUP, HANGAR1_AREA_block | TERM_GROUP1_block, 1 }, { 0, TAKEOFF, HANGAR1_AREA_block | TERM_GROUP1_block, 2 }, { 0, TO_ALL, 0, 2 },
{ 1, HANGAR, NOTHING_block, 3 }, { 1, TERMGROUP, HANGAR2_AREA_block, 1 }, { 1, TERMGROUP, HANGAR2_AREA_block, 0 }, { 1, TO_ALL, 0, 3 },
{ 2, TERMGROUP, HANGAR1_AREA_block, 0 }, { 2, TERMGROUP, TERM_GROUP1_block, 0 }, { 2, TERMGROUP, 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, TO_ALL, 0, 27 },
{ 3, TERMGROUP, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 75 }, {3, TAKEOFF, 0, 59}, { 3, TO_ALL, 0, 20 },
{ 4, TERM1, TERM1_block, 26 }, { 4, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 26 }, { 4, TO_ALL, 0, 26 },
{ 5, TERM2, TERM2_block, 27 }, { 5, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 27 }, { 5, TO_ALL, 0, 27 },
{ 6, TERM3, TERM3_block, 28 }, { 6, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 28 }, { 6, TO_ALL, 0, 28 },
{ 7, TERM4, TERM4_block, 29 }, { 7, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 7, TO_ALL, 0, 29 },
{ 8, TERM5, TERM5_block, 18 }, { 8, HANGAR, HANGAR2_AREA_block, 18 }, { 8, TO_ALL, 0, 18 },
{ 9, TERM6, TERM6_block, 19 }, { 9, HANGAR, HANGAR2_AREA_block, 19 }, { 9, TO_ALL, 0, 19 },
{ 10, TERM7, TERM7_block, 20 }, { 10, HANGAR, HANGAR2_AREA_block, 20 }, { 10, TO_ALL, 0, 20 },
{ 11, TERM8, TERM8_block, 21 }, { 11, HANGAR, HANGAR2_AREA_block, 21 }, { 11, TO_ALL, 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 },
{ 14, TO_ALL, TERM_GROUP2_ENTER1_block, 15 },
{ 15, TO_ALL, TERM_GROUP2_ENTER1_block, 16 },
{ 16, TO_ALL, TERM_GROUP2_ENTER2_block, 17 },
{ 17, TO_ALL, TERM_GROUP2_ENTER2_block, 18 },
{ 18, TERMGROUP, TERM_GROUP2_block, 0 }, { 18, TERM5, TERM5_block, 8 }, { 18, TAKEOFF, 0, 19 }, { 18, HELITAKEOFF, HELIPAD1_block, 19 }, { 18, TO_ALL, TERM_GROUP2_EXIT1_block, 19 },
{ 19, TERMGROUP, TERM_GROUP2_block, 0 }, { 19, TERM6, TERM6_block, 9 }, { 19, TERM5, 0, 18 }, { 19, TAKEOFF, 0, 57 }, { 19, HELITAKEOFF, HELIPAD1_block, 20 }, { 19, TO_ALL, TERM_GROUP2_EXIT1_block, 20 }, // add exit to runway out 2
{ 20, TERMGROUP, 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, TO_ALL, TERM_GROUP2_EXIT1_block, 21 },
{ 21, TERMGROUP, 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, TO_ALL, TERM_GROUP2_EXIT1_block, 22 },
{ 22, TERMGROUP, 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, TO_ALL, 0, 23 },
{ 23, TO_ALL, TERM_GROUP2_EXIT1_block, 70 },
{ 24, TO_ALL, TERM_GROUP2_EXIT2_block, 25 },
{ 25, TERMGROUP, TERM_GROUP2_EXIT2_block, 0 }, { 25, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 25, TO_ALL, 0, 29 },
{ 26, TERMGROUP, 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, TO_ALL, 0, 27 },
{ 27, TERMGROUP, 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, TO_ALL, 0, 28 },
{ 28, TERMGROUP, 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, TO_ALL, 0, 29 },
{ 29, TERMGROUP, TERM_GROUP1_block, 0 }, { 29, TERM4, TERM4_block, 7 }, { 29, HANGAR, HANGAR1_AREA_block, 27 }, { 29, TAKEOFF, 0, 30 }, { 29, TO_ALL, 0, 28 },
{ 30, TO_ALL, OUT_WAY_block2, 31 },
{ 31, TO_ALL, OUT_WAY_block, 32 },
/* takeoff */
{ 32, TAKEOFF, RUNWAY_OUT_block, 33 },
{ 33, 0, RUNWAY_OUT_block, 34 },
{ 33, TO_ALL, RUNWAY_OUT_block, 34 },
{ 34, STARTTAKEOFF, NOTHING_block, 35 },
{ 35, ENDTAKEOFF, NOTHING_block, 0 },
/* landing */
{ 36, 0, 0, 0 },
{ 36, TO_ALL, 0, 0 },
{ 37, LANDING, RUNWAY_IN_block, 38 },
{ 38, 0, RUNWAY_IN_block, 39 },
{ 39, 0, RUNWAY_IN_block, 40 },
{ 38, TO_ALL, RUNWAY_IN_block, 39 },
{ 39, TO_ALL, 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 },
{ 41, TO_ALL, IN_WAY_block, 42 },
{ 42, TERMGROUP, IN_WAY_block, 0 }, { 42, TERMGROUP, TERM_GROUP1_block, 0 }, { 42, TERMGROUP, TERM_GROUP1_block, 1 }, { 42, HANGAR, 0, 2 }, { 42, TO_ALL, 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 },
{ 43, TO_ALL, 0, 44 },
{ 44, FLYING, 0, 45 }, { 44, HELILANDING, 0, 47 }, { 44, LANDING, 0, 69 }, { 44, TO_ALL, 0, 45 },
{ 45, TO_ALL, 0, 46 },
{ 46, FLYING, 0, 43 }, { 46, LANDING, 0, 76 }, { 46, TO_ALL, 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 },
{ 49, TO_ALL, NOTHING_block, 51 },
{ 50, TO_ALL, 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 },
{ 51, TERMGROUP, NOTHING_block, 0 }, { 51, HELIPAD1, HELIPAD1_block, 12 }, { 51, HANGAR, 0, 55 }, { 51, TO_ALL, 0, 12 },
{ 52, TERMGROUP, NOTHING_block, 0 }, { 52, HELIPAD2, HELIPAD2_block, 13 }, { 52, HANGAR, 0, 55 }, { 52, TO_ALL, 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 },
{ 55, TO_ALL, HANGAR2_AREA_block, 56 }, // need to go to hangar when waiting in air
{ 56, TO_ALL, 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 },
{ 57, TERMGROUP, OUT_WAY2_block, 0 }, { 57, TAKEOFF, 0, 58 }, { 57, TO_ALL, 0, 58 },
{ 58, TO_ALL, OUT_WAY2_block, 59 },
{ 59, TAKEOFF, RUNWAY_OUT2_block, 60 }, // takeoff
{ 60, 0, RUNWAY_OUT2_block, 61 },
{ 60, TO_ALL, 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 },
{ 64, TO_ALL, RUNWAY_IN2_block, 65 },
{ 65, TO_ALL, RUNWAY_IN2_block, 66 },
{ 66, ENDLANDING, RUNWAY_IN2_block, 0 }, { 66, TERMGROUP, 0, 1 }, { 66, TERMGROUP, 0, 0 }, { 66, TO_ALL, 0, 67 },
{ 67, TO_ALL, IN_WAY2_block, 68 },
{ 68, TERMGROUP, IN_WAY2_block, 0 }, { 68, TERMGROUP, TERM_GROUP2_block, 1 }, { 68, TERMGROUP, TERM_GROUP1_block, 0 }, { 68, HANGAR, HANGAR2_AREA_block, 22 }, { 68, TO_ALL, 0, 22 },
{ 69, TERMGROUP, RUNWAY_IN2_block, 0 }, { 69, TO_ALL, RUNWAY_IN2_block, 63 },
{ 70, TERMGROUP, TERM_GROUP2_EXIT1_block, 0 }, { 70, HELIPAD1, HELIPAD1_block, 12 }, { 70, HELITAKEOFF, HELIPAD1_block, 12 }, { 70, TO_ALL, 0, 71 },
{ 71, TERMGROUP, TERM_GROUP2_EXIT1_block, 0 }, { 71, HELIPAD2, HELIPAD2_block, 13 }, { 71, HELITAKEOFF, HELIPAD1_block, 12 }, { 71, TO_ALL, 0, 24 },
{ 72, TO_ALL, HELIPAD1_block, 53 },
{ 73, TO_ALL, 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
{ 76, TERMGROUP, RUNWAY_IN_block, 0 }, { 76, TO_ALL, RUNWAY_IN_block, 37 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
@ -742,15 +748,15 @@ static const byte _airport_entries_heliport[] = { 7, 7, 7, 7 };
static const AirportFTAbuildup _airport_fta_heliport[] = {
{ 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 },
{ 2, TERMGROUP, 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 },
{ 5, TO_ALL, NOTHING_block, 6 },
{ 6, TO_ALL, NOTHING_block, 7 },
{ 7, TO_ALL, NOTHING_block, 8 },
{ 8, FLYING, NOTHING_block, 5 }, { 8, HELILANDING, HELIPAD1_block, 2 }, // landing
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
#define _airport_entries_oilrig _airport_entries_heliport
#define _airport_fta_oilrig _airport_fta_heliport
@ -760,7 +766,7 @@ static const HangarTileTable _airport_depots_helidepot[] = { {{1, 0}, DIR_SE, 0}
static const byte _airport_entries_helidepot[] = { 4, 4, 4, 4 };
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 },
{ 1, TERMGROUP, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELIPAD1, HELIPAD1_block, 14 }, { 1, HELITAKEOFF, 0, 15 }, { 1, TO_ALL, 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 },
@ -769,63 +775,63 @@ static const AirportFTAbuildup _airport_fta_helidepot[] = {
{ 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 },
{ 8, HELIENDLANDING, PRE_HELIPAD_block, 8 }, { 8, HELIPAD1, 0, 9 }, { 8, HANGAR, 0, 12 }, { 8, TO_ALL, 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 },
{ 10, TERMGROUP, NOTHING_block, 10 }, { 10, HELIPAD1, HELIPAD1_block, 14 }, { 10, HANGAR, 0, 1 }, { 10, TO_ALL, 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 },
{ 12, TO_ALL, HANGAR2_AREA_block, 13 }, // need to go to hangar when waiting in air
{ 13, TO_ALL, 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
{ 17, TO_ALL, NOTHING_block, 11 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
/* helistation */
static const HangarTileTable _airport_depots_helistation[] = { {{0, 0}, DIR_SE, 0} };
static const byte _airport_entries_helistation[] = { 25, 25, 25, 25 };
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 },
{ 0, HANGAR, NOTHING_block, 8 }, { 0, HELIPAD1, 0, 1 }, { 0, HELIPAD2, 0, 1 }, { 0, HELIPAD3, 0, 1 }, { 0, HELITAKEOFF, 0, 1 }, { 0, TO_ALL, 0, 0 },
{ 1, TERMGROUP, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELITAKEOFF, 0, 3 }, { 1, TO_ALL, 0, 4 },
/* landing */
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, 0, 0, 28 },
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, TO_ALL, 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 },
{ 4, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 4, HANGAR, HANGAR2_AREA_block, 1 }, { 4, HELITAKEOFF, 0, 1 }, { 4, TO_ALL, 0, 5 },
{ 5, TERMGROUP, TAXIWAY_BUSY_block, 0 }, { 5, HELIPAD1, HELIPAD1_block, 6 }, { 5, HELIPAD2, HELIPAD2_block, 7 }, { 5, HELIPAD3, HELIPAD3_block, 8 }, { 5, TO_ALL, 0, 4 },
{ 6, HELIPAD1, HELIPAD1_block, 5 }, { 6, HANGAR, HANGAR2_AREA_block, 5 }, { 6, HELITAKEOFF, 0, 9 }, { 6, TO_ALL, 0, 6 },
{ 7, HELIPAD2, HELIPAD2_block, 5 }, { 7, HANGAR, HANGAR2_AREA_block, 5 }, { 7, HELITAKEOFF, 0, 10 }, { 7, TO_ALL, 0, 7 },
{ 8, HELIPAD3, HELIPAD3_block, 5 }, { 8, HANGAR, HANGAR2_AREA_block, 5 }, { 8, HELITAKEOFF, 0, 11 }, { 8, TO_ALL, 0, 8 },
{ 9, 0, HELIPAD1_block, 12 },
{ 10, 0, HELIPAD2_block, 13 },
{ 11, 0, HELIPAD3_block, 14 },
{ 10, TO_ALL, HELIPAD2_block, 13 },
{ 11, TO_ALL, 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 },
{ 17, TO_ALL, NOTHING_block, 20 },
{ 18, TO_ALL, NOTHING_block, 21 },
{ 19, TO_ALL, 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
{ 20, TERMGROUP, NOTHING_block, 0 }, { 20, HELIPAD1, HELIPAD1_block, 6 }, { 20, HANGAR, 0, 23 }, { 20, TO_ALL, 0, 6 },
{ 21, TERMGROUP, NOTHING_block, 0 }, { 21, HELIPAD2, HELIPAD2_block, 7 }, { 21, HANGAR, 0, 23 }, { 21, TO_ALL, 0, 7 },
{ 22, TERMGROUP, NOTHING_block, 0 }, { 22, HELIPAD3, HELIPAD3_block, 8 }, { 22, HANGAR, 0, 23 }, { 22, TO_ALL, 0, 8 },
{ 23, TO_ALL, HANGAR2_AREA_block, 24 }, // need to go to helihangar when waiting in air
{ 24, TO_ALL, HANGAR2_AREA_block, 1 },
{ 25, TO_ALL, NOTHING_block, 26 },
{ 26, TO_ALL, NOTHING_block, 27 },
{ 27, TO_ALL, NOTHING_block, 2 },
{ 28, TO_ALL, NOTHING_block, 29 },
{ 29, TO_ALL, NOTHING_block, 30 },
{ 30, TO_ALL, NOTHING_block, 31 },
{ 31, TO_ALL, NOTHING_block, 32 },
{ 32, TO_ALL, NOTHING_block, 25 },
{ MAX_ELEMENTS, TO_ALL, 0, 0 } // end marker. DO NOT REMOVE
};
#endif /* AIRPORT_MOVEMENT_H */

@ -22,22 +22,16 @@
*/
#define MK(x, y, m) {{x, y}, m}
/**
* Terminator of industry tiles layout definition
*/
#define MKEND {{-0x80, 0}, 0}
static const IndustryTileTable _tile_table_coal_mine_0[] = {
static const IndustryTileLayout _tile_table_coal_mine_0 {
MK(1, 1, 0),
MK(1, 2, 2),
MK(0, 0, 5),
MK(1, 0, 6),
MK(2, 0, 3),
MK(2, 2, 3),
MKEND
};
static const IndustryTileTable _tile_table_coal_mine_1[] = {
static const IndustryTileLayout _tile_table_coal_mine_1 {
MK(1, 1, 0),
MK(1, 2, 2),
MK(2, 0, 0),
@ -47,20 +41,18 @@ static const IndustryTileTable _tile_table_coal_mine_1[] = {
MK(0, 1, 4),
MK(0, 2, 4),
MK(2, 2, 4),
MKEND
};
static const IndustryTileTable _tile_table_coal_mine_2[] = {
static const IndustryTileLayout _tile_table_coal_mine_2 {
MK(0, 0, 0),
MK(0, 1, 2),
MK(0, 2, 5),
MK(1, 0, 3),
MK(1, 1, 3),
MK(1, 2, 6),
MKEND
};
static const IndustryTileTable _tile_table_coal_mine_3[] = {
static const IndustryTileLayout _tile_table_coal_mine_3 {
MK(0, 1, 0),
MK(0, 2, 2),
MK(0, 3, 4),
@ -71,17 +63,16 @@ static const IndustryTileTable _tile_table_coal_mine_3[] = {
MK(2, 0, 6),
MK(2, 1, 4),
MK(2, 2, 3),
MKEND
};
static const IndustryTileTable * const _tile_table_coal_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_coal_mine {
_tile_table_coal_mine_0,
_tile_table_coal_mine_1,
_tile_table_coal_mine_2,
_tile_table_coal_mine_3,
};
static const IndustryTileTable _tile_table_power_station_0[] = {
static const IndustryTileLayout _tile_table_power_station_0 {
MK(0, 0, 7),
MK(0, 1, 9),
MK(1, 0, 7),
@ -90,10 +81,9 @@ static const IndustryTileTable _tile_table_power_station_0[] = {
MK(2, 1, 8),
MK(3, 0, 10),
MK(3, 1, 10),
MKEND
};
static const IndustryTileTable _tile_table_power_station_1[] = {
static const IndustryTileLayout _tile_table_power_station_1 {
MK(0, 1, 7),
MK(0, 2, 7),
MK(1, 0, 8),
@ -102,26 +92,24 @@ static const IndustryTileTable _tile_table_power_station_1[] = {
MK(2, 0, 9),
MK(2, 1, 10),
MK(2, 2, 9),
MKEND
};
static const IndustryTileTable _tile_table_power_station_2[] = {
static const IndustryTileLayout _tile_table_power_station_2 {
MK(0, 0, 7),
MK(0, 1, 7),
MK(1, 0, 9),
MK(1, 1, 8),
MK(2, 0, 10),
MK(2, 1, 9),
MKEND
};
static const IndustryTileTable * const _tile_table_power_station[] = {
static const std::vector<IndustryTileLayout> _tile_table_power_station {
_tile_table_power_station_0,
_tile_table_power_station_1,
_tile_table_power_station_2,
};
static const IndustryTileTable _tile_table_sawmill_0[] = {
static const IndustryTileLayout _tile_table_sawmill_0 {
MK(1, 0, 14),
MK(1, 1, 12),
MK(1, 2, 11),
@ -130,10 +118,9 @@ static const IndustryTileTable _tile_table_sawmill_0[] = {
MK(0, 0, 15),
MK(0, 1, 15),
MK(0, 2, 12),
MKEND
};
static const IndustryTileTable _tile_table_sawmill_1[] = {
static const IndustryTileLayout _tile_table_sawmill_1 {
MK(0, 0, 15),
MK(0, 1, 11),
MK(0, 2, 14),
@ -142,15 +129,14 @@ static const IndustryTileTable _tile_table_sawmill_1[] = {
MK(1, 2, 12),
MK(2, 0, 11),
MK(2, 1, 13),
MKEND
};
static const IndustryTileTable * const _tile_table_sawmill[] = {
static const std::vector<IndustryTileLayout> _tile_table_sawmill {
_tile_table_sawmill_0,
_tile_table_sawmill_1,
};
static const IndustryTileTable _tile_table_forest_0[] = {
static const IndustryTileLayout _tile_table_forest_0 {
MK(0, 0, 16),
MK(0, 1, 16),
MK(0, 2, 16),
@ -169,10 +155,9 @@ static const IndustryTileTable _tile_table_forest_0[] = {
MK(3, 3, 16),
MK(1, 4, 16),
MK(2, 4, 16),
MKEND
};
static const IndustryTileTable _tile_table_forest_1[] = {
static const IndustryTileLayout _tile_table_forest_1 {
MK(0, 0, 16),
MK(1, 0, 16),
MK(2, 0, 16),
@ -196,15 +181,14 @@ static const IndustryTileTable _tile_table_forest_1[] = {
MK(1, 4, 16),
MK(2, 4, 16),
MK(3, 4, 16),
MKEND
};
static const IndustryTileTable * const _tile_table_forest[] = {
static const std::vector<IndustryTileLayout> _tile_table_forest {
_tile_table_forest_0,
_tile_table_forest_1,
};
static const IndustryTileTable _tile_table_oil_refinery_0[] = {
static const IndustryTileLayout _tile_table_oil_refinery_0 {
MK(0, 0, 20),
MK(0, 1, 21),
MK(0, 2, 22),
@ -220,10 +204,9 @@ static const IndustryTileTable _tile_table_oil_refinery_0[] = {
MK(3, 3, 18),
MK(2, 0, 23),
MK(3, 1, 23),
MKEND
};
static const IndustryTileTable _tile_table_oil_refinery_1[] = {
static const IndustryTileLayout _tile_table_oil_refinery_1 {
MK(0, 0, 18),
MK(0, 1, 18),
MK(0, 2, 21),
@ -239,15 +222,14 @@ static const IndustryTileTable _tile_table_oil_refinery_1[] = {
MK(2, 3, 22),
MK(1, 4, 23),
MK(2, 4, 23),
MKEND
};
static const IndustryTileTable * const _tile_table_oil_refinery[] = {
static const std::vector<IndustryTileLayout> _tile_table_oil_refinery {
_tile_table_oil_refinery_0,
_tile_table_oil_refinery_1,
};
static const IndustryTileTable _tile_table_oil_rig_0[] = {
static const IndustryTileLayout _tile_table_oil_rig_0 {
MK(0, 0, 24),
MK(0, 1, 24),
MK(0, 2, 25),
@ -306,14 +288,13 @@ static const IndustryTileTable _tile_table_oil_rig_0[] = {
MK(2, 3, 255),
MK(2, 2, 255),
MK(2, 1, 255),
MKEND
};
static const IndustryTileTable * const _tile_table_oil_rig[] = {
static const std::vector<IndustryTileLayout> _tile_table_oil_rig {
_tile_table_oil_rig_0,
};
static const IndustryTileTable _tile_table_factory_0[] = {
static const IndustryTileLayout _tile_table_factory_0 {
MK(0, 0, 39),
MK(0, 1, 40),
MK(1, 0, 41),
@ -326,10 +307,9 @@ static const IndustryTileTable _tile_table_factory_0[] = {
MK(2, 2, 40),
MK(3, 1, 41),
MK(3, 2, 42),
MKEND
};
static const IndustryTileTable _tile_table_factory_1[] = {
static const IndustryTileLayout _tile_table_factory_1 {
MK(0, 0, 39),
MK(0, 1, 40),
MK(1, 0, 41),
@ -342,15 +322,14 @@ static const IndustryTileTable _tile_table_factory_1[] = {
MK(1, 3, 40),
MK(2, 2, 41),
MK(2, 3, 42),
MKEND
};
static const IndustryTileTable * const _tile_table_factory[] = {
static const std::vector<IndustryTileLayout> _tile_table_factory {
_tile_table_factory_0,
_tile_table_factory_1,
};
static const IndustryTileTable _tile_table_printing_works_0[] = {
static const IndustryTileLayout _tile_table_printing_works_0 {
MK(0, 0, 43),
MK(0, 1, 44),
MK(1, 0, 45),
@ -363,10 +342,9 @@ static const IndustryTileTable _tile_table_printing_works_0[] = {
MK(2, 2, 44),
MK(3, 1, 45),
MK(3, 2, 46),
MKEND
};
static const IndustryTileTable _tile_table_printing_works_1[] = {
static const IndustryTileLayout _tile_table_printing_works_1 {
MK(0, 0, 43),
MK(0, 1, 44),
MK(1, 0, 45),
@ -379,15 +357,14 @@ static const IndustryTileTable _tile_table_printing_works_1[] = {
MK(1, 3, 44),
MK(2, 2, 45),
MK(2, 3, 46),
MKEND
};
static const IndustryTileTable * const _tile_table_printing_works[] = {
static const std::vector<IndustryTileLayout> _tile_table_printing_works {
_tile_table_printing_works_0,
_tile_table_printing_works_1,
};
static const IndustryTileTable _tile_table_steel_mill_0[] = {
static const IndustryTileLayout _tile_table_steel_mill_0 {
MK(2, 1, 52),
MK(2, 2, 53),
MK(3, 1, 54),
@ -400,10 +377,9 @@ static const IndustryTileTable _tile_table_steel_mill_0[] = {
MK(1, 2, 57),
MK(2, 0, 56),
MK(3, 0, 57),
MKEND
};
static const IndustryTileTable _tile_table_steel_mill_1[] = {
static const IndustryTileLayout _tile_table_steel_mill_1 {
MK(0, 0, 52),
MK(0, 1, 53),
MK(1, 0, 54),
@ -418,15 +394,14 @@ static const IndustryTileTable _tile_table_steel_mill_1[] = {
MK(3, 2, 57),
MK(1, 3, 56),
MK(2, 3, 57),
MKEND
};
static const IndustryTileTable * const _tile_table_steel_mill[] = {
static const std::vector<IndustryTileLayout> _tile_table_steel_mill {
_tile_table_steel_mill_0,
_tile_table_steel_mill_1,
};
static const IndustryTileTable _tile_table_farm_0[] = {
static const IndustryTileLayout _tile_table_farm_0 {
MK(1, 0, 33),
MK(1, 1, 34),
MK(1, 2, 36),
@ -436,10 +411,9 @@ static const IndustryTileTable _tile_table_farm_0[] = {
MK(2, 0, 35),
MK(2, 1, 38),
MK(2, 2, 38),
MKEND
};
static const IndustryTileTable _tile_table_farm_1[] = {
static const IndustryTileLayout _tile_table_farm_1 {
MK(1, 1, 33),
MK(1, 2, 34),
MK(0, 0, 35),
@ -452,10 +426,9 @@ static const IndustryTileTable _tile_table_farm_1[] = {
MK(2, 1, 37),
MK(2, 2, 38),
MK(2, 3, 38),
MKEND
};
static const IndustryTileTable _tile_table_farm_2[] = {
static const IndustryTileLayout _tile_table_farm_2 {
MK(2, 0, 33),
MK(2, 1, 34),
MK(0, 0, 36),
@ -468,16 +441,15 @@ static const IndustryTileTable _tile_table_farm_2[] = {
MK(1, 3, 37),
MK(2, 2, 37),
MK(2, 3, 35),
MKEND
};
static const IndustryTileTable * const _tile_table_farm[] = {
static const std::vector<IndustryTileLayout> _tile_table_farm {
_tile_table_farm_0,
_tile_table_farm_1,
_tile_table_farm_2,
};
static const IndustryTileTable _tile_table_copper_mine_0[] = {
static const IndustryTileLayout _tile_table_copper_mine_0 {
MK(0, 0, 47),
MK(0, 1, 49),
MK(0, 2, 51),
@ -486,10 +458,9 @@ static const IndustryTileTable _tile_table_copper_mine_0[] = {
MK(1, 2, 50),
MK(2, 0, 51),
MK(2, 1, 51),
MKEND
};
static const IndustryTileTable _tile_table_copper_mine_1[] = {
static const IndustryTileLayout _tile_table_copper_mine_1 {
MK(0, 0, 50),
MK(0, 1, 47),
MK(0, 2, 49),
@ -499,48 +470,44 @@ static const IndustryTileTable _tile_table_copper_mine_1[] = {
MK(2, 0, 51),
MK(2, 1, 47),
MK(2, 2, 49),
MKEND
};
static const IndustryTileTable * const _tile_table_copper_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_copper_mine {
_tile_table_copper_mine_0,
_tile_table_copper_mine_1,
};
static const IndustryTileTable _tile_table_oil_well_0[] = {
static const IndustryTileLayout _tile_table_oil_well_0 {
MK(0, 0, 29),
MK(1, 0, 29),
MK(2, 0, 29),
MK(0, 1, 29),
MK(0, 2, 29),
MKEND
};
static const IndustryTileTable _tile_table_oil_well_1[] = {
static const IndustryTileLayout _tile_table_oil_well_1 {
MK(0, 0, 29),
MK(1, 0, 29),
MK(1, 1, 29),
MK(2, 2, 29),
MK(2, 3, 29),
MKEND
};
static const IndustryTileTable * const _tile_table_oil_well[] = {
static const std::vector<IndustryTileLayout> _tile_table_oil_well {
_tile_table_oil_well_0,
_tile_table_oil_well_1,
};
static const IndustryTileTable _tile_table_bank_0[] = {
static const IndustryTileLayout _tile_table_bank_0 {
MK(0, 0, 58),
MK(1, 0, 59),
MKEND
};
static const IndustryTileTable * const _tile_table_bank[] = {
static const std::vector<IndustryTileLayout> _tile_table_bank {
_tile_table_bank_0,
};
static const IndustryTileTable _tile_table_food_process_0[] = {
static const IndustryTileLayout _tile_table_food_process_0 {
MK(0, 0, 60),
MK(1, 0, 60),
MK(2, 0, 60),
@ -553,10 +520,9 @@ static const IndustryTileTable _tile_table_food_process_0[] = {
MK(0, 3, 62),
MK(1, 3, 62),
MK(2, 3, 63),
MKEND
};
static const IndustryTileTable _tile_table_food_process_1[] = {
static const IndustryTileLayout _tile_table_food_process_1 {
MK(0, 0, 61),
MK(1, 0, 60),
MK(2, 0, 61),
@ -571,15 +537,14 @@ static const IndustryTileTable _tile_table_food_process_1[] = {
MK(3, 2, 60),
MK(0, 3, 62),
MK(1, 3, 62),
MKEND
};
static const IndustryTileTable * const _tile_table_food_process[] = {
static const std::vector<IndustryTileLayout> _tile_table_food_process {
_tile_table_food_process_0,
_tile_table_food_process_1,
};
static const IndustryTileTable _tile_table_paper_mill_0[] = {
static const IndustryTileLayout _tile_table_paper_mill_0 {
MK(0, 0, 64),
MK(1, 0, 65),
MK(2, 0, 66),
@ -592,14 +557,13 @@ static const IndustryTileTable _tile_table_paper_mill_0[] = {
MK(1, 2, 71),
MK(2, 2, 71),
MK(3, 2, 70),
MKEND
};
static const IndustryTileTable * const _tile_table_paper_mill[] = {
static const std::vector<IndustryTileLayout> _tile_table_paper_mill {
_tile_table_paper_mill_0,
};
static const IndustryTileTable _tile_table_gold_mine_0[] = {
static const IndustryTileLayout _tile_table_gold_mine_0 {
MK(0, 0, 72),
MK(0, 1, 73),
MK(0, 2, 74),
@ -616,24 +580,22 @@ static const IndustryTileTable _tile_table_gold_mine_0[] = {
MK(3, 1, 85),
MK(3, 2, 86),
MK(3, 3, 87),
MKEND
};
static const IndustryTileTable * const _tile_table_gold_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_gold_mine {
_tile_table_gold_mine_0,
};
static const IndustryTileTable _tile_table_bank2_0[] = {
static const IndustryTileLayout _tile_table_bank2_0 {
MK(0, 0, 89),
MK(1, 0, 90),
MKEND
};
static const IndustryTileTable * const _tile_table_bank2[] = {
static const std::vector<IndustryTileLayout> _tile_table_bank2 {
_tile_table_bank2_0,
};
static const IndustryTileTable _tile_table_diamond_mine_0[] = {
static const IndustryTileLayout _tile_table_diamond_mine_0 {
MK(0, 0, 91),
MK(0, 1, 92),
MK(0, 2, 93),
@ -643,14 +605,13 @@ static const IndustryTileTable _tile_table_diamond_mine_0[] = {
MK(2, 0, 97),
MK(2, 1, 98),
MK(2, 2, 99),
MKEND
};
static const IndustryTileTable * const _tile_table_diamond_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_diamond_mine {
_tile_table_diamond_mine_0,
};
static const IndustryTileTable _tile_table_iron_mine_0[] = {
static const IndustryTileLayout _tile_table_iron_mine_0 {
MK(0, 0, 100),
MK(0, 1, 101),
MK(0, 2, 102),
@ -667,14 +628,13 @@ static const IndustryTileTable _tile_table_iron_mine_0[] = {
MK(3, 1, 113),
MK(3, 2, 114),
MK(3, 3, 115),
MKEND
};
static const IndustryTileTable * const _tile_table_iron_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_iron_mine {
_tile_table_iron_mine_0,
};
static const IndustryTileTable _tile_table_fruit_plantation_0[] = {
static const IndustryTileLayout _tile_table_fruit_plantation_0 {
MK(0, 0, 116),
MK(0, 1, 116),
MK(0, 2, 116),
@ -695,14 +655,13 @@ static const IndustryTileTable _tile_table_fruit_plantation_0[] = {
MK(4, 1, 116),
MK(4, 2, 116),
MK(4, 3, 116),
MKEND
};
static const IndustryTileTable * const _tile_table_fruit_plantation[] = {
static const std::vector<IndustryTileLayout> _tile_table_fruit_plantation {
_tile_table_fruit_plantation_0,
};
static const IndustryTileTable _tile_table_rubber_plantation_0[] = {
static const IndustryTileLayout _tile_table_rubber_plantation_0 {
MK(0, 0, 117),
MK(0, 1, 117),
MK(0, 2, 117),
@ -723,35 +682,32 @@ static const IndustryTileTable _tile_table_rubber_plantation_0[] = {
MK(4, 1, 117),
MK(4, 2, 117),
MK(4, 3, 117),
MKEND
};
static const IndustryTileTable * const _tile_table_rubber_plantation[] = {
static const std::vector<IndustryTileLayout> _tile_table_rubber_plantation {
_tile_table_rubber_plantation_0,
};
static const IndustryTileTable _tile_table_water_supply_0[] = {
static const IndustryTileLayout _tile_table_water_supply_0 {
MK(0, 0, 118),
MK(0, 1, 119),
MK(1, 0, 118),
MK(1, 1, 119),
MKEND
};
static const IndustryTileTable * const _tile_table_water_supply[] = {
static const std::vector<IndustryTileLayout> _tile_table_water_supply {
_tile_table_water_supply_0,
};
static const IndustryTileTable _tile_table_water_tower_0[] = {
static const IndustryTileLayout _tile_table_water_tower_0 {
MK(0, 0, 120),
MKEND
};
static const IndustryTileTable * const _tile_table_water_tower[] = {
static const std::vector<IndustryTileLayout> _tile_table_water_tower {
_tile_table_water_tower_0,
};
static const IndustryTileTable _tile_table_factory2_0[] = {
static const IndustryTileLayout _tile_table_factory2_0 {
MK(0, 0, 121),
MK(0, 1, 122),
MK(1, 0, 123),
@ -760,10 +716,9 @@ static const IndustryTileTable _tile_table_factory2_0[] = {
MK(0, 3, 122),
MK(1, 2, 123),
MK(1, 3, 124),
MKEND
};
static const IndustryTileTable _tile_table_factory2_1[] = {
static const IndustryTileLayout _tile_table_factory2_1 {
MK(0, 0, 121),
MK(0, 1, 122),
MK(1, 0, 123),
@ -772,15 +727,14 @@ static const IndustryTileTable _tile_table_factory2_1[] = {
MK(2, 1, 122),
MK(3, 0, 123),
MK(3, 1, 124),
MKEND
};
static const IndustryTileTable * const _tile_table_factory2[] = {
static const std::vector<IndustryTileLayout> _tile_table_factory2 {
_tile_table_factory2_0,
_tile_table_factory2_1,
};
static const IndustryTileTable _tile_table_farm2_0[] = {
static const IndustryTileLayout _tile_table_farm2_0 {
MK(1, 0, 33),
MK(1, 1, 34),
MK(1, 2, 36),
@ -790,10 +744,9 @@ static const IndustryTileTable _tile_table_farm2_0[] = {
MK(2, 0, 35),
MK(2, 1, 38),
MK(2, 2, 38),
MKEND
};
static const IndustryTileTable _tile_table_farm2_1[] = {
static const IndustryTileLayout _tile_table_farm2_1 {
MK(1, 1, 33),
MK(1, 2, 34),
MK(0, 0, 35),
@ -806,10 +759,9 @@ static const IndustryTileTable _tile_table_farm2_1[] = {
MK(2, 1, 37),
MK(2, 2, 38),
MK(2, 3, 38),
MKEND
};
static const IndustryTileTable _tile_table_farm2_2[] = {
static const IndustryTileLayout _tile_table_farm2_2 {
MK(2, 0, 33),
MK(2, 1, 34),
MK(0, 0, 36),
@ -822,28 +774,26 @@ static const IndustryTileTable _tile_table_farm2_2[] = {
MK(1, 3, 37),
MK(2, 2, 37),
MK(2, 3, 35),
MKEND
};
static const IndustryTileTable * const _tile_table_farm2[] = {
static const std::vector<IndustryTileLayout> _tile_table_farm2 {
_tile_table_farm2_0,
_tile_table_farm2_1,
_tile_table_farm2_2,
};
static const IndustryTileTable _tile_table_lumber_mill_0[] = {
static const IndustryTileLayout _tile_table_lumber_mill_0 {
MK(0, 0, 125),
MK(0, 1, 126),
MK(1, 0, 127),
MK(1, 1, 128),
MKEND
};
static const IndustryTileTable * const _tile_table_lumber_mill[] = {
static const std::vector<IndustryTileLayout> _tile_table_lumber_mill {
_tile_table_lumber_mill_0,
};
static const IndustryTileTable _tile_table_cotton_candy_0[] = {
static const IndustryTileLayout _tile_table_cotton_candy_0 {
MK(0, 0, 129),
MK(0, 1, 129),
MK(0, 2, 129),
@ -862,10 +812,9 @@ static const IndustryTileTable _tile_table_cotton_candy_0[] = {
MK(3, 3, 129),
MK(1, 4, 129),
MK(2, 4, 129),
MKEND
};
static const IndustryTileTable _tile_table_cotton_candy_1[] = {
static const IndustryTileLayout _tile_table_cotton_candy_1 {
MK(0, 0, 129),
MK(1, 0, 129),
MK(2, 0, 129),
@ -889,15 +838,14 @@ static const IndustryTileTable _tile_table_cotton_candy_1[] = {
MK(1, 4, 129),
MK(2, 4, 129),
MK(3, 4, 129),
MKEND
};
static const IndustryTileTable * const _tile_table_cotton_candy[] = {
static const std::vector<IndustryTileLayout> _tile_table_cotton_candy {
_tile_table_cotton_candy_0,
_tile_table_cotton_candy_1,
};
static const IndustryTileTable _tile_table_candy_factory_0[] = {
static const IndustryTileLayout _tile_table_candy_factory_0 {
MK(0, 0, 131),
MK(0, 1, 132),
MK(1, 0, 133),
@ -910,10 +858,9 @@ static const IndustryTileTable _tile_table_candy_factory_0[] = {
MK(2, 2, 132),
MK(3, 1, 133),
MK(3, 2, 134),
MKEND
};
static const IndustryTileTable _tile_table_candy_factory_1[] = {
static const IndustryTileLayout _tile_table_candy_factory_1 {
MK(0, 0, 131),
MK(0, 1, 132),
MK(1, 0, 133),
@ -926,15 +873,14 @@ static const IndustryTileTable _tile_table_candy_factory_1[] = {
MK(1, 3, 132),
MK(2, 2, 133),
MK(2, 3, 134),
MKEND
};
static const IndustryTileTable * const _tile_table_candy_factory[] = {
static const std::vector<IndustryTileLayout> _tile_table_candy_factory {
_tile_table_candy_factory_0,
_tile_table_candy_factory_1,
};
static const IndustryTileTable _tile_table_battery_farm_0[] = {
static const IndustryTileLayout _tile_table_battery_farm_0 {
MK(0, 0, 135),
MK(0, 1, 135),
MK(0, 2, 135),
@ -955,14 +901,13 @@ static const IndustryTileTable _tile_table_battery_farm_0[] = {
MK(4, 1, 135),
MK(4, 2, 135),
MK(4, 3, 135),
MKEND
};
static const IndustryTileTable * const _tile_table_battery_farm[] = {
static const std::vector<IndustryTileLayout> _tile_table_battery_farm {
_tile_table_battery_farm_0,
};
static const IndustryTileTable _tile_table_cola_wells_0[] = {
static const IndustryTileLayout _tile_table_cola_wells_0 {
MK(0, 0, 137),
MK(0, 1, 137),
MK(0, 2, 137),
@ -971,10 +916,9 @@ static const IndustryTileTable _tile_table_cola_wells_0[] = {
MK(1, 2, 137),
MK(2, 1, 137),
MK(2, 2, 137),
MKEND
};
static const IndustryTileTable _tile_table_cola_wells_1[] = {
static const IndustryTileLayout _tile_table_cola_wells_1 {
MK(0, 1, 137),
MK(0, 2, 137),
MK(0, 3, 137),
@ -982,27 +926,25 @@ static const IndustryTileTable _tile_table_cola_wells_1[] = {
MK(1, 1, 137),
MK(1, 2, 137),
MK(2, 1, 137),
MKEND
};
static const IndustryTileTable * const _tile_table_cola_wells[] = {
static const std::vector<IndustryTileLayout> _tile_table_cola_wells {
_tile_table_cola_wells_0,
_tile_table_cola_wells_1,
};
static const IndustryTileTable _tile_table_toy_shop_0[] = {
static const IndustryTileLayout _tile_table_toy_shop_0 {
MK(0, 0, 138),
MK(0, 1, 139),
MK(1, 0, 140),
MK(1, 1, 141),
MKEND
};
static const IndustryTileTable * const _tile_table_toy_shop[] = {
static const std::vector<IndustryTileLayout> _tile_table_toy_shop {
_tile_table_toy_shop_0,
};
static const IndustryTileTable _tile_table_toy_factory_0[] = {
static const IndustryTileLayout _tile_table_toy_factory_0 {
MK(0, 0, 147),
MK(0, 1, 142),
MK(1, 0, 147),
@ -1011,45 +953,41 @@ static const IndustryTileTable _tile_table_toy_factory_0[] = {
MK(2, 1, 144),
MK(3, 0, 146),
MK(3, 1, 145),
MKEND
};
static const IndustryTileTable * const _tile_table_toy_factory[] = {
static const std::vector<IndustryTileLayout> _tile_table_toy_factory {
_tile_table_toy_factory_0,
};
static const IndustryTileTable _tile_table_plastic_fountain_0[] = {
static const IndustryTileLayout _tile_table_plastic_fountain_0 {
MK(0, 0, 148),
MK(0, 1, 151),
MK(0, 2, 154),
MKEND
};
static const IndustryTileTable _tile_table_plastic_fountain_1[] = {
static const IndustryTileLayout _tile_table_plastic_fountain_1 {
MK(0, 0, 148),
MK(1, 0, 151),
MK(2, 0, 154),
MKEND
};
static const IndustryTileTable * const _tile_table_plastic_fountain[] = {
static const std::vector<IndustryTileLayout> _tile_table_plastic_fountain {
_tile_table_plastic_fountain_0,
_tile_table_plastic_fountain_1,
};
static const IndustryTileTable _tile_table_fizzy_drink_0[] = {
static const IndustryTileLayout _tile_table_fizzy_drink_0 {
MK(0, 0, 156),
MK(0, 1, 157),
MK(1, 0, 158),
MK(1, 1, 159),
MKEND
};
static const IndustryTileTable * const _tile_table_fizzy_drink[] = {
static const std::vector<IndustryTileLayout> _tile_table_fizzy_drink {
_tile_table_fizzy_drink_0,
};
static const IndustryTileTable _tile_table_bubble_generator_0[] = {
static const IndustryTileLayout _tile_table_bubble_generator_0 {
MK(0, 0, 163),
MK(0, 1, 160),
MK(1, 0, 163),
@ -1062,25 +1000,23 @@ static const IndustryTileTable _tile_table_bubble_generator_0[] = {
MK(1, 3, 161),
MK(2, 2, 163),
MK(2, 3, 162),
MKEND
};
static const IndustryTileTable * const _tile_table_bubble_generator[] = {
static const std::vector<IndustryTileLayout> _tile_table_bubble_generator {
_tile_table_bubble_generator_0,
};
static const IndustryTileTable _tile_table_toffee_quarry_0[] = {
static const IndustryTileLayout _tile_table_toffee_quarry_0 {
MK(0, 0, 164),
MK(1, 0, 165),
MK(2, 0, 166),
MKEND
};
static const IndustryTileTable * const _tile_table_toffee_quarry[] = {
static const std::vector<IndustryTileLayout> _tile_table_toffee_quarry {
_tile_table_toffee_quarry_0,
};
static const IndustryTileTable _tile_table_sugar_mine_0[] = {
static const IndustryTileLayout _tile_table_sugar_mine_0 {
MK(0, 0, 167),
MK(0, 1, 168),
MK(1, 0, 169),
@ -1089,15 +1025,13 @@ static const IndustryTileTable _tile_table_sugar_mine_0[] = {
MK(2, 1, 172),
MK(3, 0, 173),
MK(3, 1, 174),
MKEND
};
static const IndustryTileTable * const _tile_table_sugar_mine[] = {
static const std::vector<IndustryTileLayout> _tile_table_sugar_mine {
_tile_table_sugar_mine_0,
};
#undef MK
#undef MKEND
/** Array with saw sound, for sawmill */
static const uint8 _sawmill_sounds[] = { SND_28_SAWMILL };
@ -1195,7 +1129,7 @@ enum IndustryTypes {
#define MI(tbl, sndc, snd, d, pc, ai1, ai2, ai3, ai4, ag1, ag2, ag3, ag4, col, \
c1, c2, c3, proc, p1, r1, p2, r2, m, a1, im1, a2, im2, a3, im3, pr, clim, bev, in, intx, s1, s2, s3) \
{tbl, lengthof(tbl), d, 0, pc, {c1, c2, c3}, proc, \
{tbl, d, 0, pc, {c1, c2, c3}, proc, \
{p1, p2, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
{r1, r2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, m, \
{a1, a2, a3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \

@ -1929,6 +1929,20 @@ str = STR_CONFIG_SETTING_ALLOW_SHARES
strhelp = STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT
proc = InvalidateCompanyWindow
[SDT_VAR]
base = GameSettings
var = economy.min_years_for_shares
type = SLE_UINT8
from = SLV_TRADING_AGE
def = 6
min = 0
max = 255
interval = 1
str = STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES
strhelp = STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT
strval = STR_JUST_INT
cat = SC_EXPERT
[SDT_VAR]
base = GameSettings
var = economy.feeder_payment_share

@ -258,11 +258,10 @@ static void QZ_GetDisplayModeInfo(CFArrayRef modes, CFIndex i, int &bpp, uint16
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
/* Extract bit depth from mode string. */
CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 32;
if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 16;
if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 8;
CFRelease(pixEnc);
CFAutoRelease<CFStringRef> pixEnc(CGDisplayModeCopyPixelEncoding(mode));
if (CFStringCompare(pixEnc.get(), CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 32;
if (CFStringCompare(pixEnc.get(), CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 16;
if (CFStringCompare(pixEnc.get(), CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 8;
#else
/* CGDisplayModeCopyPixelEncoding is deprecated on OSX 10.11+, but there are no 8 bpp modes anyway... */
bpp = 32;
@ -687,15 +686,13 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel
void cocoaSetApplicationBundleDir()
{
char tmp[MAXPATHLEN];
CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
if (CFURLGetFileSystemRepresentation(url, true, (unsigned char*)tmp, MAXPATHLEN)) {
CFAutoRelease<CFURLRef> url(CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()));
if (CFURLGetFileSystemRepresentation(url.get(), true, (unsigned char*)tmp, MAXPATHLEN)) {
AppendPathSeparator(tmp, lastof(tmp));
_searchpaths[SP_APPLICATION_BUNDLE_DIR] = stredup(tmp);
} else {
_searchpaths[SP_APPLICATION_BUNDLE_DIR] = nullptr;
}
CFRelease(url);
}
/**

@ -517,7 +517,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
_sdl_realscreen = newscreen;
if (bpp == 8) {
newscreen = SDL_CreateRGBSurfaceWithFormat(0, w, h, 8, SDL_PIXELFORMAT_INDEX8);
newscreen = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0);
if (newscreen == nullptr) {
DEBUG(driver, 0, "SDL2: Couldn't allocate shadow surface: %s", SDL_GetError());

Loading…
Cancel
Save