mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-13 01:29:10 +00:00
Compare commits
55 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
80c73b93ed | ||
|
8a74170da0 | ||
|
a0bf18c3c9 | ||
|
31b226dc9f | ||
|
b320aa40fa | ||
|
37835e9158 | ||
|
749a4f8c7d | ||
e72232dc4c | |||
|
45a4c69842 | ||
|
a2c882af6f | ||
|
bb7c37b515 | ||
|
ec54b3ac24 | ||
|
a9032183df | ||
|
90feff4982 | ||
|
e434485dd8 | ||
|
dcc4ccf4e9 | ||
|
ef7e4abf7f | ||
|
5d0ed8fab8 | ||
|
ed7df6e2bf | ||
|
7cf9e0d8ca | ||
|
85141929a8 | ||
|
f4d5c1b01b | ||
|
31d6286cb4 | ||
|
ca0a0cdbfd | ||
|
04572ed7fe | ||
|
ebfef9683e | ||
|
c05d3dd558 | ||
|
6e029fe97d | ||
|
26ed195319 | ||
|
7170357a10 | ||
|
e4bbd3b41c | ||
|
5ed5e6beed | ||
|
5de94db9df | ||
|
6b664a3ba0 | ||
|
beee5698f9 | ||
|
a86ec733a0 | ||
|
37c1135d6b | ||
|
923dee9bec | ||
|
1856976d8e | ||
|
818a5a596f | ||
|
2be4b388ec | ||
|
300aba48cc | ||
|
f470a87dea | ||
|
4b938510a5 | ||
|
7ddae93da8 | ||
|
f75365fcf4 | ||
|
e89a98d296 | ||
|
8157969b2b | ||
|
b3ccef7045 | ||
|
af0fb58264 | ||
|
5f2e2ef32a | ||
|
8353c1260a | ||
|
8de919ce50 | ||
|
f9cacc9f5c | ||
|
af3ac4954a |
@@ -1,15 +0,0 @@
|
||||
notifications:
|
||||
global:
|
||||
irc:
|
||||
- openttd
|
||||
- openttd.notice
|
||||
|
||||
push:
|
||||
only:
|
||||
- master
|
||||
only-by:
|
||||
- DorpsGek
|
||||
commit-comment:
|
||||
pull-request:
|
||||
issue:
|
||||
tag-created:
|
@@ -1,9 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{c,cpp,h,hpp}]
|
||||
indent_style = tab
|
||||
charset = utf-8
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
||||
custom: https://www.openttd.org/donate.html
|
7
.github/ISSUE_TEMPLATE.md
vendored
7
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,7 +0,0 @@
|
||||
## Version of OpenTTD
|
||||
|
||||
## Expected result
|
||||
|
||||
## Actual result
|
||||
|
||||
## Steps to reproduce
|
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,48 +0,0 @@
|
||||
## Motivation / Problem
|
||||
|
||||
<!--
|
||||
Describe here shortly
|
||||
* For bug fixes:
|
||||
* What problem does this solve?
|
||||
* If there is already an issue, link the issue, otherwise describe the problem here.
|
||||
* For features or gameplay changes:
|
||||
* What was the motivation to develop this feature?
|
||||
* Does this address any problem with the gameplay or interface?
|
||||
* Which group of players do you think would enjoy this feature?
|
||||
-->
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
<!--
|
||||
Describe here shortly
|
||||
* For bug fixes:
|
||||
* How is the problem solved?
|
||||
* For features or gameplay changes:
|
||||
* What does this feature do?
|
||||
* How does it improve/solve the situation described under 'motivation'.
|
||||
-->
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
<!--
|
||||
Describe here
|
||||
* Is the problem solved in all scenarios?
|
||||
* Is this feature complete? Are there things that could be added in the future?
|
||||
* Are there things that are intentionally left out?
|
||||
* Do you know of a bug or corner case that does not work?
|
||||
-->
|
||||
|
||||
|
||||
## Checklist for review
|
||||
|
||||
Some things are not automated, and forgotten often. This list is a reminder for the reviewers.
|
||||
* The bug fix is important enough to be backported? (label: 'backport requested')
|
||||
* This PR affects the save game format? (label 'savegame upgrade')
|
||||
* This PR affects the GS/AI API? (label 'needs review: Script API')
|
||||
* ai_changelog.hpp, gs_changelog.hpp need updating.
|
||||
* The compatibility wrappers (compat_*.nut) need updating.
|
||||
* This PR affects the NewGRF API? (label 'needs review: NewGRF')
|
||||
* newgrf_debug_data.h may need updating.
|
||||
* [PR must be added to API tracker](https://wiki.openttd.org/en/Development/NewGRF/Specification%20Status)
|
16
.github/changelog.sh
vendored
16
.github/changelog.sh
vendored
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
tag=$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null | sed 's@\^0$@@')
|
||||
|
||||
# If we are a tag, show the part of the changelog till (but excluding) the last stable
|
||||
if [ -n "$tag" ]; then
|
||||
grep='^[0-9]\+\.[0-9]\+\.[0-9]\+[^-]'
|
||||
next=$(cat changelog.txt | grep '^[0-9]' | awk 'BEGIN { show="false" } // { if (show=="true") print $0; if ($1=="'$tag'") show="true"} ' | grep "$grep" | head -n1 | sed 's/ .*//')
|
||||
cat changelog.txt | awk 'BEGIN { show="false" } /^[0-9]+.[0-9]+.[0-9]+/ { if ($1=="'$next'") show="false"; if ($1=="'$tag'") show="true";} // { if (show=="true") print $0 }'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# In all other cases, show the git log of the last 7 days
|
||||
revdate=$(git log -1 --pretty=format:"%ci")
|
||||
last_week=$(date -d "$revdate -7days" +"%Y-%m-%d %H:%M")
|
||||
git log --after="${last_week}" --pretty=fuller
|
34
.github/stale.yml
vendored
34
.github/stale.yml
vendored
@@ -1,34 +0,0 @@
|
||||
daysUntilClose: 7
|
||||
staleLabel: stale
|
||||
closeComment: false
|
||||
exemptMilestones: true
|
||||
exemptAssignees: true
|
||||
|
||||
issues:
|
||||
daysUntilStale: 60
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- "good first issue"
|
||||
- regression
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had any activity in the last two months.
|
||||
|
||||
If you believe the issue is still relevant, please test on the latest nightly and report back.
|
||||
|
||||
It will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
pulls:
|
||||
daysUntilStale: 30
|
||||
exemptLabels:
|
||||
- pinned
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had any activity in the last month.
|
||||
|
||||
Please feel free to give a status update now, ping for review, or re-open when it's ready.
|
||||
|
||||
It will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
317
.github/workflows/ci-build.yml
vendored
317
.github/workflows/ci-build.yml
vendored
@@ -1,317 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
|
||||
jobs:
|
||||
emscripten:
|
||||
name: Emscripten
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
# If you change this version, change the number in the cache step too.
|
||||
image: emscripten/emsdk:2.0.10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /emsdk/upstream/emscripten/cache
|
||||
key: 2.0.10-${{ runner.os }}
|
||||
|
||||
- name: Build (host tools)
|
||||
run: |
|
||||
mkdir build-host
|
||||
cd build-host
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake .. -DOPTION_TOOLS_ONLY=ON
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
cmake --build . -j $(nproc) --target tools
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
emcmake cmake .. -DHOST_BINARY_DIR=../build-host
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
cmake --build . -j $(nproc)
|
||||
echo "::endgroup::"
|
||||
|
||||
linux:
|
||||
name: Linux
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- compiler: clang
|
||||
cxxcompiler: clang++
|
||||
libsdl: libsdl2-dev
|
||||
- compiler: gcc
|
||||
cxxcompiler: g++
|
||||
libsdl: libsdl2-dev
|
||||
- compiler: gcc
|
||||
cxxcompiler: g++
|
||||
libsdl: libsdl1.2-dev
|
||||
- compiler: gcc
|
||||
cxxcompiler: g++
|
||||
extra-cmake-parameters: -DOPTION_DEDICATED=ON
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
CXX: ${{ matrix.cxxcompiler }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo "::group::Update apt"
|
||||
sudo apt-get update
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Install dependencies"
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
liballegro4-dev \
|
||||
libfontconfig-dev \
|
||||
libicu-dev \
|
||||
liblzma-dev \
|
||||
liblzo2-dev \
|
||||
${{ matrix.libsdl }} \
|
||||
zlib1g-dev \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
|
||||
- name: Get OpenGFX
|
||||
run: |
|
||||
mkdir -p ~/.local/share/openttd/baseset
|
||||
cd ~/.local/share/openttd/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake .. ${{ matrix.extra-cmake-parameters }}
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
cmake --build . -j $(nproc)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd build
|
||||
ctest -j $(nproc)
|
||||
|
||||
macos:
|
||||
name: Mac OS
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
full_arch: x86_64
|
||||
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.9
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
run: |
|
||||
echo "::set-output name=image::$ImageOS-$ImageVersion"
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /usr/local/share/vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
restore-keys: |
|
||||
${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}
|
||||
|
||||
- name: Prepare vcpkg
|
||||
run: |
|
||||
vcpkg install --triplet=${{ matrix.arch }}-osx \
|
||||
liblzma \
|
||||
libpng \
|
||||
lzo \
|
||||
zlib \
|
||||
# EOF
|
||||
|
||||
- name: Install OpenGFX
|
||||
run: |
|
||||
mkdir -p ~/Documents/OpenTTD/baseset
|
||||
cd ~/Documents//OpenTTD/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.full_arch }} \
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-osx \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(sysctl -n hw.logicalcpu) cores"
|
||||
cmake --build . -j $(sysctl -n hw.logicalcpu)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd build
|
||||
ctest -j $(sysctl -n hw.logicalcpu)
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, windows-2016]
|
||||
arch: [x86, x64]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
shell: powershell
|
||||
run: |
|
||||
# Work around caching failure with GNU tar
|
||||
New-Item -Type Junction -Path vcpkg -Target c:\vcpkg
|
||||
|
||||
Write-Output "::set-output name=image::$env:ImageOS-$env:ImageVersion"
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
restore-keys: |
|
||||
${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}
|
||||
|
||||
- name: Prepare vcpkg
|
||||
shell: bash
|
||||
run: |
|
||||
vcpkg install --triplet=${{ matrix.arch }}-windows-static \
|
||||
liblzma \
|
||||
libpng \
|
||||
lzo \
|
||||
zlib \
|
||||
# EOF
|
||||
|
||||
- name: Install OpenGFX
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
cd "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
|
||||
- name: Install MSVC problem matcher
|
||||
uses: ammaraskar/msvc-problem-matcher@master
|
||||
|
||||
- name: Configure developer command prompt for ${{ matrix.arch }}
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake .. \
|
||||
-GNinja \
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
|
||||
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build .
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
ctest
|
51
.github/workflows/commit-checker.yml
vendored
51
.github/workflows/commit-checker.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Commit checker
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
commit-checker:
|
||||
name: Commit checker
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 4
|
||||
|
||||
- name: Get pull-request commits
|
||||
run: |
|
||||
set -x
|
||||
# actions/checkout did a merge checkout of the pull-request. As such, the first
|
||||
# commit is the merge commit. This means that on HEAD^ is the base branch, and
|
||||
# on HEAD^2 are the commits from the pull-request. We now check if those trees
|
||||
# have a common parent. If not, we fetch a few more commits till we do. In result,
|
||||
# the log between HEAD^ and HEAD^2 will be the commits in the pull-request.
|
||||
DEPTH=4
|
||||
while [ -z "$(git merge-base HEAD^ HEAD^2)" ]; do
|
||||
# Prevent infinite recursion
|
||||
if [ ${DEPTH} -gt 256 ]; then
|
||||
echo "No common parent between '${GITHUB_HEAD_REF}' and '${GITHUB_BASE_REF}'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --deepen=${DEPTH} origin HEAD
|
||||
DEPTH=$(( ${DEPTH} * 4 ))
|
||||
done
|
||||
|
||||
# Just to show which commits we are going to evaluate.
|
||||
git log --oneline HEAD^..HEAD^2
|
||||
|
||||
- name: Checkout commit-checker
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: OpenTTD/OpenTTD-git-hooks
|
||||
path: git-hooks
|
||||
ref: master
|
||||
|
||||
- name: Check commits
|
||||
run: |
|
||||
set -x
|
||||
HOOKS_DIR=./git-hooks/hooks GIT_DIR=.git ./git-hooks/hooks/check-commits.sh HEAD^..HEAD^2
|
||||
echo "Commit checks passed"
|
133
.github/workflows/preview_build.yml
vendored
133
.github/workflows/preview_build.yml
vendored
@@ -1,133 +0,0 @@
|
||||
name: Preview build
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types:
|
||||
- Preview*
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
name: Build preview
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
# If you change this version, change the number in the cache step too.
|
||||
image: emscripten/emsdk:2.0.10
|
||||
# uid=1001(runner) gid=121(docker)
|
||||
options: -u 1001:121
|
||||
|
||||
steps:
|
||||
- name: Update deployment status to in progress
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||
mediaType: |
|
||||
previews:
|
||||
- ant-man
|
||||
- flash
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||
state: in_progress
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.sha }}
|
||||
|
||||
- name: Name branch
|
||||
run: |
|
||||
name=$(echo "${{ github.event.client_payload.folder }}")
|
||||
git checkout -b ${name}
|
||||
|
||||
- name: Setup cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /emsdk/upstream/emscripten/cache
|
||||
key: 2.0.10-${{ runner.os }}
|
||||
|
||||
- name: Build (host tools)
|
||||
run: |
|
||||
mkdir build-host
|
||||
cd build-host
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake .. -DOPTION_TOOLS_ONLY=ON
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
make -j$(nproc) tools
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
emcmake cmake .. \
|
||||
-DHOST_BINARY_DIR=../build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
emmake make -j$(nproc)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Publish preview
|
||||
run: |
|
||||
# setuptools is missing in this Docker image, which breaks installing
|
||||
# awscli. So we need to do this in two steps to recover sanity.
|
||||
pip3 install setuptools
|
||||
pip3 install awscli
|
||||
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.data s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.html s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.js s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
~/.local/bin/aws s3 cp --only-show-errors build/openttd.wasm s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||
|
||||
# Invalidate the cache of the CloudFront distribution
|
||||
~/.local/bin/aws cloudfront create-invalidation --distribution-id ${{ secrets.PREVIEW_CF_DISTRIBUTION_ID }} --paths "/${{ github.event.client_payload.folder }}/*"
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- name: Update deployment status to success
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||
mediaType: |
|
||||
previews:
|
||||
- ant-man
|
||||
- flash
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||
state: success
|
||||
environment_url: https://preview.openttd.org/${{ github.event.client_payload.folder }}/
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: failure()
|
||||
name: Update deployment status to failure
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||
mediaType: |
|
||||
previews:
|
||||
- ant-man
|
||||
- flash
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||
state: failure
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
66
.github/workflows/preview_label.yml
vendored
66
.github/workflows/preview_label.yml
vendored
@@ -1,66 +0,0 @@
|
||||
name: Preview label
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
env:
|
||||
TEAM_CORE_DEVELOPER: core-developers
|
||||
|
||||
jobs:
|
||||
check_preview_label:
|
||||
name: Check for preview label
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'preview'
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Check if label was added by core developer
|
||||
id: core_developer
|
||||
continue-on-error: true
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: GET /orgs/OpenTTD/teams/${{ env.TEAM_CORE_DEVELOPER }}/memberships/${{ github.event.sender.login }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: steps.core_developer.outcome == 'failure'
|
||||
name: Remove preview label if not core developer
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/preview
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
issue_number: ${{ github.event.number }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: steps.core_developer.outcome == 'success'
|
||||
name: Create deployment
|
||||
id: deployment
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/deployments
|
||||
mediaType: |
|
||||
previews:
|
||||
- ant-man
|
||||
- flash
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
task: deploy:preview
|
||||
auto_merge: false
|
||||
required_contexts: "[]"
|
||||
environment: preview-pr-${{ github.event.number }}
|
||||
description: "Preview for Pull Request #${{ github.event.number }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: steps.core_developer.outcome == 'success'
|
||||
name: Trigger 'preview build'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
event-type: "Preview build #${{ github.event.number }}"
|
||||
client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}'
|
66
.github/workflows/preview_push.yml
vendored
66
.github/workflows/preview_push.yml
vendored
@@ -1,66 +0,0 @@
|
||||
name: Preview push
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
check_new_preview:
|
||||
name: Check preview needs update
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Check if earlier preview exists
|
||||
id: earlier_preview
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: GET /repos/{owner}/{repo}/deployments
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
environment: preview-pr-${{ github.event.number }}
|
||||
per_page: 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]'
|
||||
name: Check for preview label
|
||||
id: preview_label
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: GET /repos/{owner}/{repo}/issues/{issue_number}/labels
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
issue_number: ${{ github.event.number }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview')
|
||||
name: Create deployment
|
||||
id: deployment
|
||||
uses: octokit/request-action@v2.x
|
||||
with:
|
||||
route: POST /repos/{owner}/{repo}/deployments
|
||||
mediaType: |
|
||||
previews:
|
||||
- ant-man
|
||||
- flash
|
||||
owner: ${{ github.event.repository.owner.login }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
task: deploy:preview
|
||||
auto_merge: false
|
||||
required_contexts: "[]"
|
||||
environment: preview-pr-${{ github.event.number }}
|
||||
description: "Preview for Pull Request #${{ github.event.number }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
|
||||
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview')
|
||||
name: Trigger 'preview build'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||
event-type: "Preview build #${{ github.event.number }}"
|
||||
client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}'
|
952
.github/workflows/release.yml
vendored
952
.github/workflows/release.yml
vendored
@@ -1,952 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'Ref to build (for Pull Requests, use refs/pull/NNN/head)'
|
||||
required: true
|
||||
repository_dispatch:
|
||||
# client_payload should be the same as the inputs for workflow_dispatch.
|
||||
types:
|
||||
- Build*
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
source:
|
||||
name: Source
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
outputs:
|
||||
version: ${{ steps.metadata.outputs.version }}
|
||||
is_tag: ${{ steps.metadata.outputs.is_tag }}
|
||||
trigger_type: ${{ steps.metadata.outputs.trigger_type }}
|
||||
folder: ${{ steps.metadata.outputs.folder }}
|
||||
|
||||
steps:
|
||||
- name: Checkout (Release)
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout (Manual)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout (Trigger)
|
||||
if: github.event_name == 'repository_dispatch'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check valid branch name
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
REF="${{ github.event.inputs.ref }}"
|
||||
elif [ "${{ github.event_name }}" = "repository_dispatch" ]; then
|
||||
REF="${{ github.event.client_payload.ref }}"
|
||||
else
|
||||
REF="${{ github.ref }}"
|
||||
fi
|
||||
|
||||
# Check if we are a tag.
|
||||
if [ -n "$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || false)" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if the checkout caused the branch to be named.
|
||||
if [ "$(git rev-parse --abbrev-ref HEAD)" != "HEAD" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if this was a pull request.
|
||||
if [ -n "$(echo ${REF} | grep '^refs/pull/[0-9]*')" ]; then
|
||||
PULL=$(echo ${REF} | cut -d/ -f3)
|
||||
git checkout -b pr${PULL}
|
||||
fi
|
||||
|
||||
# Are we still in a detached state? Error out.
|
||||
if [ "$(git rev-parse --abbrev-ref HEAD)" == "HEAD" ]; then
|
||||
echo "The 'ref' given resulted in a checkout of a detached HEAD."
|
||||
echo "We cannot detect the version for these checkout accurate."
|
||||
echo ""
|
||||
echo "If you want to build a Pull Request, make sure you use 'refs/pull/NNN/head'."
|
||||
echo ""
|
||||
echo "Cancelling build, as without a version we cannot store the artifacts."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Generate metadata
|
||||
id: metadata
|
||||
run: |
|
||||
echo "::group::Prepare metadata files"
|
||||
cmake -DGENERATE_OTTDREV=1 -P cmake/scripts/FindVersion.cmake
|
||||
./.github/changelog.sh > .changelog
|
||||
TZ='UTC' date +"%Y-%m-%d %H:%M UTC" > .release_date
|
||||
cat .ottdrev | cut -f 1 -d$'\t' > .version
|
||||
|
||||
if [ $(cat .ottdrev | cut -f 5 -d$'\t') = '1' ]; then
|
||||
# Assume that all tags are always releases. Why else make a tag?
|
||||
IS_TAG="true"
|
||||
|
||||
FOLDER="${{ env.FOLDER_RELEASES }}"
|
||||
TRIGGER_TYPE="new-tag"
|
||||
else
|
||||
IS_TAG="false"
|
||||
|
||||
BRANCH=$(git symbolic-ref -q HEAD | sed 's@.*/@@')
|
||||
if [ -z "${BRANCH}" ]; then
|
||||
echo "Internal error: branch name is empty."
|
||||
echo "An earlier step should have prevented this from happening."
|
||||
echo "Cancelling build, as without a branch name we cannot store the artifacts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${BRANCH}" = "${{ env.NIGHTLIES_BRANCH }}" ]; then
|
||||
# The "master" branch is special, and we call a nightly.
|
||||
FOLDER="${{ env.FOLDER_NIGHTLIES }}/$(date +%Y)"
|
||||
TRIGGER_TYPE="new-master"
|
||||
else
|
||||
# All other branches, which can be builds of Pull Requests, are
|
||||
# put in their own folder.
|
||||
FOLDER="${{ env.FOLDER_BRANCHES }}/${BRANCH}"
|
||||
TRIGGER_TYPE="new-branch"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p build/bundles
|
||||
cp .changelog build/bundles/changelog.txt
|
||||
cp .release_date build/bundles/released.txt
|
||||
cp README.md build/bundles/README.md
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "Release Date: $(cat .release_date)"
|
||||
echo "Revision: $(cat .ottdrev)"
|
||||
echo "Version: $(cat .version)"
|
||||
echo "Is tag: ${IS_TAG}"
|
||||
echo "Folder on CDN: ${FOLDER}"
|
||||
echo "Workflow trigger: ${TRIGGER_TYPE}"
|
||||
|
||||
echo "::set-output name=version::$(cat .version)"
|
||||
echo "::set-output name=is_tag::${IS_TAG}"
|
||||
echo "::set-output name=folder::${FOLDER}"
|
||||
echo "::set-output name=trigger_type::${TRIGGER_TYPE}"
|
||||
env:
|
||||
NIGHTLIES_BRANCH: master
|
||||
FOLDER_RELEASES: openttd-releases
|
||||
FOLDER_NIGHTLIES: openttd-nightlies
|
||||
FOLDER_BRANCHES: openttd-branches
|
||||
|
||||
- name: Remove VCS information
|
||||
run: |
|
||||
rm -rf .git
|
||||
|
||||
- name: Create bundles
|
||||
run: |
|
||||
FOLDER_NAME=openttd-${{ steps.metadata.outputs.version }}
|
||||
|
||||
# Rename the folder to openttd-NNN
|
||||
mkdir ${FOLDER_NAME}
|
||||
find . -maxdepth 1 -not -name . -not -name build -not -name ${FOLDER_NAME} -exec mv {} ${FOLDER_NAME}/ \;
|
||||
|
||||
echo "::group::Create tarball (xz) bundle"
|
||||
tar --xz -cvf build/bundles/${FOLDER_NAME}-source.tar.xz ${FOLDER_NAME}
|
||||
echo "::endgroup::"
|
||||
|
||||
# This tarball is only to be used within this workflow.
|
||||
echo "::group::Create tarball (gz) bundle"
|
||||
tar --gzip -cvf source.tar.gz ${FOLDER_NAME}
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Create zip bundle"
|
||||
zip -9 -r build/bundles/${FOLDER_NAME}-source.zip ${FOLDER_NAME}
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-source
|
||||
path: build/bundles/*
|
||||
retention-days: 5
|
||||
|
||||
- name: Store source (for other jobs)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
path: source.tar.gz
|
||||
retention-days: 1
|
||||
|
||||
docs:
|
||||
name: Docs
|
||||
needs: source
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo "::group::Update apt"
|
||||
sudo apt-get update
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Install dependencies"
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
doxygen \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p ${GITHUB_WORKSPACE}/build
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DOPTION_DOCS_ONLY=ON \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build . --target docs
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Create bundles
|
||||
run: |
|
||||
BASENAME=openttd-${{ needs.source.outputs.version }}
|
||||
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
|
||||
mv docs/source ${BASENAME}-docs
|
||||
mv docs/ai-api ${BASENAME}-docs-ai
|
||||
mv docs/gs-api ${BASENAME}-docs-gs
|
||||
|
||||
mkdir -p bundles
|
||||
|
||||
echo "::group::Create docs bundle"
|
||||
tar --xz -cf bundles/${BASENAME}-docs.tar.xz ${BASENAME}-docs
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Create AI API docs bundle"
|
||||
tar --xz -cf bundles/${BASENAME}-docs-ai.tar.xz ${BASENAME}-docs-ai
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Create GameScript API docs bundle"
|
||||
tar --xz -cf bundles/${BASENAME}-docs-gs.tar.xz ${BASENAME}-docs-gs
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-docs
|
||||
path: build/bundles/*.tar.xz
|
||||
retention-days: 5
|
||||
|
||||
linux:
|
||||
name: Linux (Generic)
|
||||
needs: source
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
# manylinux2014 is based on CentOS 7, but already has a lot of things
|
||||
# installed and preconfigured. It makes it easier to build OpenTTD.
|
||||
image: quay.io/pypa/manylinux2014_x86_64
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo "::group::Install dependencies"
|
||||
yum install -y \
|
||||
fontconfig-devel \
|
||||
freetype-devel \
|
||||
libicu-devel \
|
||||
libpng-devel \
|
||||
libpng-devel \
|
||||
lzo-devel \
|
||||
SDL2-devel \
|
||||
wget \
|
||||
xz-devel \
|
||||
zlib-devel \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
# The yum variant of fluidsynth depends on all possible audio drivers,
|
||||
# like jack, ALSA, pulseaudio, etc. This is not really useful for us,
|
||||
# as we route the output of fluidsynth back via our sound driver, and
|
||||
# as such do not use these audio driver outputs at all. So instead,
|
||||
# we compile fluidsynth ourselves, with as little dependencies as
|
||||
# possible. This currently means it picks up SDL2, but this is fine,
|
||||
# as we need SDL2 anyway.
|
||||
echo "::group::Install fluidsynth"
|
||||
wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz
|
||||
tar xf v2.1.6.tar.gz
|
||||
(
|
||||
cd fluidsynth-2.1.6
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake --build . -j $(nproc)
|
||||
cmake --install .
|
||||
)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DOPTION_PACKAGE_DEPENDENCIES=ON \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
cmake --build . -j $(nproc)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Create bundles
|
||||
run: |
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
echo "::group::Run CPack"
|
||||
cpack
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Cleanup"
|
||||
# Remove the sha256 files CPack generates; we will do this ourself at
|
||||
# the end of this workflow.
|
||||
rm -f bundles/*.sha256
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-linux-generic
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
linux-distro:
|
||||
name: Linux (Distros)
|
||||
needs: source
|
||||
|
||||
if: needs.source.outputs.is_tag == 'true'
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- container_image: "ubuntu:18.04"
|
||||
bundle_name: "bionic"
|
||||
- container_image: "ubuntu:20.04"
|
||||
bundle_name: "focal"
|
||||
- container_image: "ubuntu:20.10"
|
||||
bundle_name: "groovy"
|
||||
- container_image: "debian:buster"
|
||||
bundle_name: "buster"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: ${{ matrix.container_image }}
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo "::group::Update apt"
|
||||
apt-get update
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Install dependencies"
|
||||
apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
debhelper \
|
||||
g++ \
|
||||
git \
|
||||
make \
|
||||
openssl \
|
||||
libfontconfig-dev \
|
||||
libfluidsynth-dev \
|
||||
libicu-dev \
|
||||
liblzma-dev \
|
||||
liblzo2-dev \
|
||||
libsdl2-dev \
|
||||
lsb-release \
|
||||
zlib1g-dev \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(nproc) cores"
|
||||
# Ubuntu 18.04 cmake does not support -j so we pass the option to the native tool
|
||||
cmake --build . -- -j $(nproc)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Create bundles
|
||||
run: |
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
echo "::group::Run CPack"
|
||||
cpack
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Cleanup"
|
||||
# Remove the sha256 files CPack generates; we will do this ourself at
|
||||
# the end of this workflow.
|
||||
rm -f bundles/*.sha256
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-linux-${{ matrix.bundle_name }}
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
needs: source
|
||||
|
||||
runs-on: macos-10.15
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.9
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
run: |
|
||||
brew install pandoc
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
run: |
|
||||
echo "::set-output name=image::$ImageOS-$ImageVersion"
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /usr/local/share/vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-release-0 # Increase the number whenever dependencies are modified
|
||||
restore-keys: |
|
||||
${{ steps.key.outputs.image }}-vcpkg-release
|
||||
${{ steps.key.outputs.image }}-vcpkg-x64
|
||||
|
||||
- name: Prepare vcpkg
|
||||
run: |
|
||||
vcpkg install \
|
||||
liblzma:x64-osx \
|
||||
liblzma:arm64-osx \
|
||||
libpng:x64-osx \
|
||||
libpng:arm64-osx \
|
||||
lzo:x64-osx \
|
||||
lzo:arm64-osx \
|
||||
zlib:x64-osx \
|
||||
zlib:arm64-osx \
|
||||
# EOF
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Build tools
|
||||
run: |
|
||||
mkdir build-host
|
||||
cd build-host
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DOPTION_TOOLS_ONLY=ON \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build tools"
|
||||
echo "Running on $(sysctl -n hw.logicalcpu) cores"
|
||||
cmake --build . -j $(sysctl -n hw.logicalcpu) --target tools
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Import code signing certificates
|
||||
uses: Apple-Actions/import-codesign-certs@v1
|
||||
with:
|
||||
# The certificates in a PKCS12 file encoded as a base64 string
|
||||
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
|
||||
# The password used to import the PKCS12 file.
|
||||
p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
|
||||
# If this is run on a fork, there may not be a certificate set up - continue in this case
|
||||
continue-on-error: true
|
||||
|
||||
- name: Build arm64
|
||||
run: |
|
||||
mkdir build-arm64
|
||||
cd build-arm64
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_OSX_ARCHITECTURES=arm64 \
|
||||
-DVCPKG_TARGET_TRIPLET=arm64-osx \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(sysctl -n hw.logicalcpu) cores"
|
||||
cmake --build . -j $(sysctl -n hw.logicalcpu)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Build x64
|
||||
run: |
|
||||
mkdir build-x64
|
||||
cd build-x64
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
||||
-DVCPKG_TARGET_TRIPLET=x64-osx \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCPACK_BUNDLE_APPLE_CERT_APP=${{ secrets.APPLE_DEVELOPER_CERTIFICATE_ID }} \
|
||||
"-DCPACK_BUNDLE_APPLE_CODESIGN_PARAMETER=--deep -f --options runtime" \
|
||||
-DAPPLE_UNIVERSAL_PACKAGE=1 \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
echo "Running on $(sysctl -n hw.logicalcpu) cores"
|
||||
cmake --build . -j $(sysctl -n hw.logicalcpu)
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Create bundles
|
||||
run: |
|
||||
cd build-x64
|
||||
|
||||
echo "::group::Create universal binary"
|
||||
# Combine the `openttd` binaries from each build into a single file
|
||||
lipo -create -output openttd-universal ../build-*/openttd
|
||||
mv openttd-universal openttd
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Run CPack"
|
||||
cpack
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Cleanup"
|
||||
# Remove the sha256 files CPack generates; we will do this ourself at
|
||||
# the end of this workflow.
|
||||
rm -f bundles/*.sha256
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Install gon
|
||||
env:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
run: |
|
||||
brew tap mitchellh/gon
|
||||
brew install mitchellh/gon/gon
|
||||
|
||||
- name: Notarize
|
||||
env:
|
||||
AC_USERNAME: ${{ secrets.APPLE_DEVELOPER_APP_USERNAME }}
|
||||
AC_PASSWORD: ${{ secrets.APPLE_DEVELOPER_APP_PASSWORD }}
|
||||
run: |
|
||||
cd build-x64
|
||||
../os/macosx/notarize.sh
|
||||
|
||||
- name: Build zip
|
||||
run: |
|
||||
cd build-x64
|
||||
|
||||
pushd _CPack_Packages/*/Bundle/openttd-*/
|
||||
|
||||
# Remove the Applications symlink from the staging folder
|
||||
rm -f Applications
|
||||
|
||||
# Remove the original dmg built by CPack to avoid a conflict when resolving
|
||||
# the zip_filename variable below
|
||||
rm -f ../*.dmg
|
||||
|
||||
zip_filename=(../openttd-*)
|
||||
|
||||
# Package up the existing, notarised .app into a zip file
|
||||
zip -r -9 ${zip_filename}.zip OpenTTD.app
|
||||
|
||||
popd
|
||||
|
||||
# Now move it into place to be uploaded
|
||||
mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-macos-universal
|
||||
path: build-x64/bundles
|
||||
retention-days: 5
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
needs: source
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
host: x86
|
||||
- arch: x64
|
||||
host: x64
|
||||
- arch: arm64
|
||||
host: x64_arm64
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
- name: Unpack source
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
choco install pandoc
|
||||
|
||||
- name: Prepare cache key
|
||||
id: key
|
||||
shell: powershell
|
||||
run: |
|
||||
# Work around caching failure with GNU tar
|
||||
New-Item -Type Junction -Path vcpkg -Target c:\vcpkg
|
||||
|
||||
Write-Output "::set-output name=image::$env:ImageOS-$env:ImageVersion"
|
||||
|
||||
- name: Enable vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: vcpkg/installed
|
||||
key: ${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}-0 # Increase the number whenever dependencies are modified
|
||||
restore-keys: |
|
||||
${{ steps.key.outputs.image }}-vcpkg-${{ matrix.arch }}
|
||||
|
||||
- name: Prepare vcpkg
|
||||
shell: bash
|
||||
run: |
|
||||
vcpkg install --triplet=${{ matrix.arch }}-windows-static \
|
||||
liblzma \
|
||||
libpng \
|
||||
lzo \
|
||||
zlib \
|
||||
# EOF
|
||||
|
||||
- name: Install MSVC problem matcher
|
||||
uses: ammaraskar/msvc-problem-matcher@master
|
||||
|
||||
- name: Configure developer command prompt for tools
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: Build tools
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build-host
|
||||
cd build-host
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-GNinja \
|
||||
-DOPTION_TOOLS_ONLY=ON \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build . --target tools
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Configure developer command prompt for ${{ matrix.arch }}
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.host }}
|
||||
|
||||
- name: Build (with installer)
|
||||
if: needs.source.outputs.is_tag == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-GNinja \
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
|
||||
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \
|
||||
-DOPTION_USE_NSIS=ON \
|
||||
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build .
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Build (without installer)
|
||||
if: needs.source.outputs.is_tag != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
echo "::group::CMake"
|
||||
cmake ${GITHUB_WORKSPACE} \
|
||||
-GNinja \
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
|
||||
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \
|
||||
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
# EOF
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build"
|
||||
cmake --build .
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Create bundles
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${GITHUB_WORKSPACE}/build
|
||||
echo "::group::Run CPack"
|
||||
cpack
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Prepare PDB to be bundled"
|
||||
PDB=$(ls bundles/*.zip | cut -d/ -f2 | sed 's/.zip$/.pdb/')
|
||||
cp openttd.pdb bundles/${PDB}
|
||||
xz -9 bundles/${PDB}
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Cleanup"
|
||||
# Remove the sha256 files CPack generates; we will do this ourself at
|
||||
# the end of this workflow.
|
||||
rm -f bundles/*.sha256
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: openttd-windows-${{ matrix.arch }}
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
upload:
|
||||
name: Upload (AWS)
|
||||
needs:
|
||||
- source
|
||||
- docs
|
||||
- linux
|
||||
- linux-distro
|
||||
- macos
|
||||
- windows
|
||||
|
||||
# The 'linux' job can be skipped if it is a nightly. That normally causes
|
||||
# this job to be skipped too, unless we have this length boy :)
|
||||
# "always()" is important here, it is the keyword to use to stop skipping
|
||||
# this job if any dependency is skipped. It looks a bit silly, but it is
|
||||
# how GitHub Actions work ;)
|
||||
if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && (needs.linux-distro.result == 'success' || needs.linux-distro.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success'
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v2
|
||||
|
||||
- name: Calculate checksums
|
||||
run: |
|
||||
echo "::group::Move bundles to a single folder"
|
||||
mkdir bundles
|
||||
mv openttd-*/* bundles/
|
||||
cd bundles
|
||||
echo "::group::Build"
|
||||
|
||||
for i in $(ls openttd-*); do
|
||||
echo "::group::Calculating checksums for ${i}"
|
||||
openssl dgst -r -md5 -hex $i > $i.md5sum
|
||||
openssl dgst -r -sha1 -hex $i > $i.sha1sum
|
||||
openssl dgst -r -sha256 -hex $i > $i.sha256sum
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
- name: Upload bundles to AWS
|
||||
run: |
|
||||
aws s3 cp --recursive --only-show-errors bundles/ s3://${{ secrets.CDN_S3_BUCKET }}/${{ needs.source.outputs.folder }}/${{ needs.source.outputs.version }}/
|
||||
|
||||
# We do not invalidate the CloudFront distribution here. The trigger
|
||||
# for "New OpenTTD release" first updated the manifest files and
|
||||
# creates an index.html. We invalidate after that, so everything
|
||||
# becomes visible at once.
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
|
||||
|
||||
- name: Trigger 'New OpenTTD release'
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.DEPLOYMENT_TOKEN }}
|
||||
repository: OpenTTD/workflows
|
||||
event-type: ${{ needs.source.outputs.trigger_type }}
|
||||
client-payload: '{"version": "${{ needs.source.outputs.version }}", "folder": "${{ needs.source.outputs.folder }}"}'
|
||||
|
||||
upload-steam:
|
||||
name: Upload (Steam)
|
||||
needs:
|
||||
- source
|
||||
- linux
|
||||
- macos
|
||||
- windows
|
||||
|
||||
if: needs.source.outputs.trigger_type == 'new-master' || needs.source.outputs.trigger_type == 'new-tag'
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v2
|
||||
|
||||
- name: Setup steamcmd
|
||||
uses: CyberAndrii/setup-steamcmd@v1
|
||||
|
||||
- name: Generate Steam auth code
|
||||
id: steam-totp
|
||||
uses: CyberAndrii/steam-totp@v1
|
||||
with:
|
||||
shared_secret: ${{ secrets.STEAM_SHARED_SECRET }}
|
||||
|
||||
- name: Upload to Steam
|
||||
run: |
|
||||
echo "::group::Extracting source"
|
||||
mkdir source
|
||||
(
|
||||
cd source
|
||||
tar -xf ../internal-source/source.tar.gz --strip-components=1
|
||||
)
|
||||
echo "::endgroup::"
|
||||
|
||||
mkdir steam
|
||||
(
|
||||
cd steam
|
||||
|
||||
echo "::group::Prepare Win32"
|
||||
unzip ../openttd-windows-x86/openttd-*-windows-win32.zip
|
||||
mv openttd-*-windows-win32 steam-win32
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Prepare Win64"
|
||||
unzip ../openttd-windows-x64/openttd-*-windows-win64.zip
|
||||
mv openttd-*-windows-win64 steam-win64
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Prepare macOS"
|
||||
mkdir steam-macos
|
||||
(
|
||||
cd steam-macos
|
||||
unzip ../../openttd-macos-universal/openttd-*-macos-universal.zip
|
||||
)
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Prepare Linux"
|
||||
tar xvf ../openttd-linux-generic/openttd-*-linux-generic-amd64.tar.xz
|
||||
mv openttd-*-linux-generic-amd64 steam-linux
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Preparing build file"
|
||||
if [ "${{ needs.source.outputs.trigger_type }}" = "new-tag" ]; then
|
||||
BRANCH="testing"
|
||||
else
|
||||
BRANCH="nightly"
|
||||
fi
|
||||
cat ../source/os/steam/release.vdf | sed 's/@@DESCRIPTION@@/openttd-${{ needs.source.outputs.version }}/;s/@@BRANCH@@/'${BRANCH}'/' > release.vdf
|
||||
cat release.vdf
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Upload to Steam"
|
||||
steamcmd +login ${{ secrets.STEAM_USERNAME }} ${{ secrets.STEAM_PASSWORD }} ${{ steps.steam-totp.outputs.code }} +run_app_build $(pwd)/release.vdf +quit
|
||||
echo "::endgroup::"
|
||||
)
|
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,7 +0,0 @@
|
||||
/.vs
|
||||
/build*
|
||||
CMakeSettings.json
|
||||
docs/aidocs/*
|
||||
docs/gamedocs/*
|
||||
docs/source/*
|
||||
/out
|
372
CMakeLists.txt
372
CMakeLists.txt
@@ -1,372 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
if(NOT BINARY_NAME)
|
||||
set(BINARY_NAME openttd)
|
||||
endif()
|
||||
|
||||
project(${BINARY_NAME})
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the bin directory")
|
||||
endif()
|
||||
|
||||
# Debug mode by default.
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/os/emscripten/cmake")
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||
|
||||
# Use GNUInstallDirs to allow customisation
|
||||
# but set our own default data and bin dir
|
||||
if(NOT CMAKE_INSTALL_DATADIR)
|
||||
set(CMAKE_INSTALL_DATADIR "share/games")
|
||||
endif()
|
||||
if(NOT CMAKE_INSTALL_BINDIR)
|
||||
set(CMAKE_INSTALL_BINDIR "games")
|
||||
endif()
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(Options)
|
||||
set_options()
|
||||
set_directory_options()
|
||||
|
||||
include(Static)
|
||||
set_static_if_needed()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
set(CMAKE_CXX_EXTENSIONS NO)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
|
||||
|
||||
# An empty target for the tools
|
||||
add_custom_target(tools)
|
||||
|
||||
include(Endian)
|
||||
add_endian_definition()
|
||||
|
||||
include(CompileFlags)
|
||||
compile_flags()
|
||||
|
||||
if(APPLE OR UNIX)
|
||||
add_definitions(-DUNIX)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
find_package(Doxygen)
|
||||
endif()
|
||||
|
||||
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp")
|
||||
if(WIN32)
|
||||
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc")
|
||||
endif()
|
||||
|
||||
# Generate a target to determine version, which is execute every 'make' run
|
||||
add_custom_target(find_version
|
||||
${CMAKE_COMMAND}
|
||||
-DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated
|
||||
-DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR}
|
||||
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
BYPRODUCTS ${GENERATED_SOURCE_FILES}
|
||||
)
|
||||
|
||||
# Documentation
|
||||
if(DOXYGEN_EXECUTABLE)
|
||||
add_custom_target(docs)
|
||||
add_custom_target(docs_source
|
||||
${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Generating documentation for source"
|
||||
)
|
||||
add_dependencies(docs_source
|
||||
find_version
|
||||
)
|
||||
add_dependencies(docs
|
||||
docs_source
|
||||
)
|
||||
endif()
|
||||
|
||||
include(AddCustomXXXTimestamp)
|
||||
|
||||
if(OPTION_TOOLS_ONLY)
|
||||
if(HOST_BINARY_DIR)
|
||||
unset(HOST_BINARY_DIR CACHE)
|
||||
endif()
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# Avoid searching for headers in Frameworks, and libraries in LIBDIR.
|
||||
set(CMAKE_FIND_FRAMEWORK LAST)
|
||||
endif()
|
||||
|
||||
# Prefer -pthread over -lpthread, which is often the better option of the two.
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD YES)
|
||||
# Make sure we have Threads available.
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(ZLIB)
|
||||
find_package(LibLZMA)
|
||||
find_package(LZO)
|
||||
find_package(PNG)
|
||||
|
||||
if(NOT OPTION_DEDICATED)
|
||||
if(NOT WIN32)
|
||||
find_package(Allegro)
|
||||
if(NOT APPLE)
|
||||
find_package(Freetype)
|
||||
find_package(SDL2)
|
||||
if(NOT SDL2_FOUND)
|
||||
find_package(SDL)
|
||||
endif()
|
||||
find_package(Fluidsynth)
|
||||
find_package(Fontconfig)
|
||||
find_package(ICU OPTIONAL_COMPONENTS i18n lx)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(APPLE)
|
||||
find_package(Iconv)
|
||||
|
||||
find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
|
||||
find_library(AUDIOUNIT_LIBRARY AudioUnit)
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
find_library(QUARTZCORE_LIBRARY QuartzCore)
|
||||
endif()
|
||||
|
||||
if(NOT EMSCRIPTEN AND NOT OPTION_DEDICATED)
|
||||
find_package(OpenGL COMPONENTS OpenGL)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
find_package(Editbin REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(SSE)
|
||||
find_package(Xaudio2)
|
||||
|
||||
find_package(Grfcodec)
|
||||
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT IPO_FOUND)
|
||||
|
||||
show_options()
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT OPTION_DEDICATED)
|
||||
if(NOT SDL_FOUND AND NOT SDL2_FOUND AND NOT ALLEGRO_FOUND)
|
||||
message(FATAL_ERROR "SDL, SDL2 or Allegro is required for this platform")
|
||||
endif()
|
||||
endif()
|
||||
if(APPLE)
|
||||
if(NOT AUDIOTOOLBOX_LIBRARY)
|
||||
message(FATAL_ERROR "AudioToolbox is required for this platform")
|
||||
endif()
|
||||
if(NOT AUDIOUNIT_LIBRARY)
|
||||
message(FATAL_ERROR "AudioUnit is required for this platform")
|
||||
endif()
|
||||
if(NOT COCOA_LIBRARY)
|
||||
message(FATAL_ERROR "Cocoa is required for this platform")
|
||||
endif()
|
||||
if(NOT QUARTZCORE_LIBRARY)
|
||||
message(FATAL_ERROR "QuartzCore is required for this platform")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPTION_PACKAGE_DEPENDENCIES)
|
||||
if(NOT UNIX)
|
||||
message(FATAL_ERROR "Can only package dependencies on Linux")
|
||||
endif()
|
||||
if(OPTION_INSTALL_FHS)
|
||||
message(FATAL_ERROR "Cannot install in FHS folders when we are packaging dependencies")
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.16.0")
|
||||
message(FATAL_ERROR "OPTION_PACKAGE_DEPENDENCIES can only work with CMake 3.16+; you are using ${CMAKE_VERSION}")
|
||||
endif()
|
||||
|
||||
# If we are packaging dependencies, we do two things:
|
||||
# 1) set the RPATH to include $ORIGIN/lib; $ORIGIN (that literal string)
|
||||
# is a Linux indicator for "path where application is". In CMake, we
|
||||
# have to do this before add_executable() is executed.
|
||||
# 2) copy the libraries that we compile against to the "lib" folder.
|
||||
# This is done in InstallAndPackage.cmake.
|
||||
set(CMAKE_INSTALL_RPATH "\$ORIGIN/lib")
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
|
||||
endif()
|
||||
|
||||
include(SourceList)
|
||||
|
||||
# Needed by rev.cpp
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
# Needed by everything that uses Squirrel
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/squirrel/include)
|
||||
|
||||
include(MSVCFilters)
|
||||
|
||||
add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES})
|
||||
set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}")
|
||||
# All other files are added via target_sources()
|
||||
|
||||
if(MSVC)
|
||||
# Add DPI manifest to project; other WIN32 targets get this via ottdres.rc
|
||||
target_sources(openttd PRIVATE "${CMAKE_SOURCE_DIR}/os/windows/openttd.manifest")
|
||||
endif()
|
||||
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/media)
|
||||
|
||||
add_dependencies(openttd
|
||||
find_version)
|
||||
|
||||
target_link_libraries(openttd
|
||||
openttd::languages
|
||||
openttd::settings
|
||||
openttd::media
|
||||
openttd::basesets
|
||||
openttd::script_api
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
if(IPO_FOUND)
|
||||
set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE True)
|
||||
set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL True)
|
||||
set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO True)
|
||||
endif()
|
||||
set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
process_compile_flags()
|
||||
|
||||
include(LinkPackage)
|
||||
link_package(PNG TARGET PNG::PNG ENCOURAGED)
|
||||
link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED)
|
||||
link_package(LIBLZMA TARGET LibLZMA::LibLZMA ENCOURAGED)
|
||||
link_package(LZO)
|
||||
|
||||
if(NOT OPTION_DEDICATED)
|
||||
link_package(Fluidsynth)
|
||||
link_package(SDL)
|
||||
link_package(SDL2 TARGET SDL2::SDL2)
|
||||
link_package(Allegro)
|
||||
link_package(FREETYPE TARGET Freetype::Freetype)
|
||||
link_package(Fontconfig TARGET Fontconfig::Fontconfig)
|
||||
link_package(ICU_lx)
|
||||
link_package(ICU_i18n)
|
||||
|
||||
if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
|
||||
# SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
|
||||
# on Linux. For Windows, we need to link to OpenGL as we also have a win32
|
||||
# driver using it.
|
||||
add_definitions(-DWITH_OPENGL)
|
||||
message(STATUS "OpenGL found -- -DWITH_OPENGL -- (via SDL2)")
|
||||
else()
|
||||
link_package(OpenGL TARGET OpenGL::GL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
link_package(Iconv TARGET Iconv::Iconv)
|
||||
|
||||
target_link_libraries(openttd
|
||||
${AUDIOTOOLBOX_LIBRARY}
|
||||
${AUDIOUNIT_LIBRARY}
|
||||
${COCOA_LIBRARY}
|
||||
${QUARTZCORE_LIBRARY}
|
||||
)
|
||||
|
||||
add_definitions(
|
||||
-DWITH_COCOA
|
||||
)
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
add_library(WASM::WASM INTERFACE IMPORTED)
|
||||
|
||||
# Allow heap-growth, and start with a bigger memory size.
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s ALLOW_MEMORY_GROWTH=1")
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s INITIAL_MEMORY=33554432")
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s DISABLE_EXCEPTION_CATCHING=0")
|
||||
add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
|
||||
|
||||
# Export functions to Javascript.
|
||||
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||
|
||||
# Preload all the files we generate during build.
|
||||
# As we do not compile with FreeType / FontConfig, we also have no way to
|
||||
# render several languages (like Chinese, ..), so where do you draw the
|
||||
# line what languages to include and which not? In the end, especially as
|
||||
# the more languages you add the slower downloading becomes, we decided to
|
||||
# only ship the English language.
|
||||
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/baseset@/baseset")
|
||||
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/lang/english.lng@/lang/english.lng")
|
||||
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/ai@/ai")
|
||||
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/game@/game")
|
||||
|
||||
# We use IDBFS for persistent storage.
|
||||
target_link_libraries(WASM::WASM INTERFACE "-lidbfs.js")
|
||||
|
||||
# Use custom pre-js and shell.html.
|
||||
target_link_libraries(WASM::WASM INTERFACE "--pre-js ${CMAKE_SOURCE_DIR}/os/emscripten/pre.js")
|
||||
target_link_libraries(WASM::WASM INTERFACE "--shell-file ${CMAKE_SOURCE_DIR}/os/emscripten/shell.html")
|
||||
|
||||
# Build the .html (which builds the .js, .wasm, and .data too).
|
||||
set_target_properties(openttd PROPERTIES SUFFIX ".html")
|
||||
target_link_libraries(openttd WASM::WASM)
|
||||
endif()
|
||||
|
||||
if(NOT PERSONAL_DIR STREQUAL "(not set)")
|
||||
add_definitions(
|
||||
-DWITH_PERSONAL_DIR
|
||||
-DPERSONAL_DIR="${PERSONAL_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT SHARED_DIR STREQUAL "(not set)")
|
||||
add_definitions(
|
||||
-DWITH_SHARED_DIR
|
||||
-DSHARED_DIR="${SHARED_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT GLOBAL_DIR STREQUAL "(not set)")
|
||||
add_definitions(
|
||||
-DGLOBAL_DATA_DIR="${GLOBAL_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
link_package(SSE)
|
||||
|
||||
add_definitions_based_on_options()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(
|
||||
-DUNICODE
|
||||
-D_UNICODE
|
||||
-DWITH_UNISCRIBE
|
||||
)
|
||||
|
||||
target_link_libraries(openttd
|
||||
ws2_32
|
||||
winmm
|
||||
imm32
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions(-D_SQ64)
|
||||
endif()
|
||||
|
||||
include(CreateRegression)
|
||||
create_regression()
|
||||
|
||||
if(APPLE OR WIN32)
|
||||
find_package(Pandoc)
|
||||
endif()
|
||||
|
||||
include(InstallAndPackage)
|
128
COMPILING.md
128
COMPILING.md
@@ -1,128 +0,0 @@
|
||||
# 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 2017 or more recent.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
You can open the folder (as a CMake project). CMake will be detected, and you can compile from there.
|
||||
If libraries are installed but not found, you need to set VCPKG_TARGET_TRIPLET in CMake parameters.
|
||||
For Visual Studio 2017 you also need to set CMAKE_TOOLCHAIN_FILE.
|
||||
(Typical values are shown in the MSVC project file command line example)
|
||||
|
||||
Alternatively, you can create a MSVC project file via CMake. For this
|
||||
either download CMake from https://cmake.org/download/ or use the version
|
||||
that comes with vcpkg. After that, you can run something similar to this:
|
||||
|
||||
```powershell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake.exe .. -G'Visual Studio 16 2019' -DCMAKE_TOOLCHAIN_FILE="<location of vcpkg>\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows-static"
|
||||
```
|
||||
|
||||
Change `<location of vcpkg>` to where you have installed vcpkg. After this
|
||||
in the build folder are MSVC project files. MSVC can rebuild the project
|
||||
files himself via the `ZERO_CHECK` project.
|
||||
|
||||
## All other platforms
|
||||
Minimum required version of CMake is 3.9.
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
For more information on how to use CMake (including how to make Release builds),
|
||||
we urge you to read [their excellent manual](https://cmake.org/cmake/help/latest/guide/user-interaction/index.html).
|
||||
|
||||
## Supported compilers
|
||||
|
||||
Every compiler that is supported by CMake and supports C++17, should be
|
||||
able to compile OpenTTD. As the exact list of compilers changes constantly,
|
||||
we refer to the compiler manual to see if it supports C++17, and to CMake
|
||||
to see if it supports your compiler.
|
||||
|
||||
## 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/downloads/grfcodec-releases/latest.html.
|
||||
|
||||
Having GRFCodec installed can cause regeneration of the `.grf` files, which
|
||||
are written in the source directory. This can leave your repository in a
|
||||
modified state, as different GRFCodec versions can cause binary differences
|
||||
in the resulting `.grf` files. Also translations might have been added for
|
||||
the base sets which are not yet included in the base set information files.
|
||||
To avoid this behaviour, disable GRFCodec (and NFORenum) in CMake cache
|
||||
(`GRFCODEC_EXECUTABLE` and `NFORENUM_EXECUTABLE`).
|
||||
|
||||
## Developers settings
|
||||
|
||||
You can control some flags directly via `CXXFLAGS` (any combination
|
||||
of these flags will work fine too):
|
||||
|
||||
- `-DRANDOM_DEBUG`: this helps with debugging desyncs.
|
||||
- `-fno-inline`: this avoids creating inline functions; this can make
|
||||
debugging a lot easier.
|
||||
- `-O0`: this disables all optimizations; this can make debugging a
|
||||
lot easier.
|
||||
- `-p`: this enables profiling.
|
||||
|
||||
Always use a clean buildfolder if you changing `CXXFLAGS`, as this
|
||||
value is otherwise cached. Example use:
|
||||
|
||||
`CXXFLAGS="-fno-inline" cmake ..`
|
269
CONTRIBUTING.md
269
CONTRIBUTING.md
@@ -1,269 +0,0 @@
|
||||
|
||||
# Contributing to OpenTTD
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## 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/en/Development/IRC%20channel), 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.
|
||||
|
||||
* 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/en/Development/IRC%20channel) or the [forums](https://www.tt-forums.net/) to discuss these.
|
||||
|
||||
* Please use [the web translator](https://translator.openttd.org/) to submit corrections and improvements to translations of the game.
|
||||
|
||||
|
||||
## Bug reports
|
||||
|
||||
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||
Good bug reports are extremely helpful, so thanks!
|
||||
|
||||
Guidelines for bug reports:
|
||||
|
||||
0. Please don't report issues with games where you changed NewGRFs mid-game. (This can be verified with the `gamelog` console command in-game.)
|
||||
|
||||
1. Please don't report issues with modified versions of OpenTTD (patchpacks, unofficial ports, and similar).
|
||||
|
||||
2. **Use the GitHub issue search** — check if the issue has already been
|
||||
reported.
|
||||
|
||||
3. **Check if the issue has been fixed** — try to reproduce it using the latest `nightly` build of OpenTTD, available from https://www.openttd.org
|
||||
|
||||
4. **Isolate the problem** — ideally create reproducible steps with an attached savegame and screenshots. Try to use few or no NewGRFs, AIs etc if possible.
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more information.
|
||||
Please try to be as detailed as possible in your report.
|
||||
|
||||
* What is your environment?
|
||||
* What steps will reproduce the issue?
|
||||
* Which operating system(s) experience the problem?
|
||||
* What would you expect to be the outcome?
|
||||
|
||||
All these details will help people to fix any potential bugs.
|
||||
|
||||
Example:
|
||||
|
||||
> Short and descriptive example bug report title
|
||||
>
|
||||
> A summary of the issue and the OS environment in which it occurs. If
|
||||
> suitable, include the steps required to reproduce the bug.
|
||||
>
|
||||
> 1. This is the first step
|
||||
> 2. This is the second step
|
||||
> 3. Further steps, etc.
|
||||
>
|
||||
> Attached savegame
|
||||
> Attached screenshots showing the issue
|
||||
> Crashlogs if the bug causes a crash
|
||||
>
|
||||
> Any other information you want to share that is relevant to the issue being
|
||||
> reported. This might include the lines of code that you have identified as
|
||||
> 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 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.
|
||||
|
||||
For feature request we have a strict policy.
|
||||
|
||||
Keeping issues around with "a good idea" or "not really a bug but we should maybe fix it" turns out to have the reversed effect: nobody looks at it anymore.
|
||||
|
||||
Although we really appreciate feedback and ideas, we will close feature requests that we don't expect to fulfill in the next year.
|
||||
|
||||
Many of those ideas etc do have a place on the [forums](https://www.tt-forums.net); and if enough people like it, someone will stand up and make it.
|
||||
|
||||
It's usually best discuss in [irc](https://wiki.openttd.org/en/Development/IRC%20channel) before opening a feature request or working on a large feature in a fork.
|
||||
Discussion in irc can take time, but it can be productive and avoid disappointment :)
|
||||
|
||||
|
||||
## Pull requests
|
||||
|
||||
Good pull requests—patches, improvements, new features—are a fantastic help.
|
||||
|
||||
Pull requests should fit with the [goals of the project](./CONTRIBUTING.md#project-goals).
|
||||
|
||||
**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/en/Development/Coding%20style) must be complied with for pull requests to be accepted; this also includes [commit message format](https://wiki.openttd.org/en/Development/Coding%20style#commit-message).
|
||||
|
||||
Adhering to the following process is the best way to get your work included in the project:
|
||||
|
||||
1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<your-username>/OpenTTD.git openttd
|
||||
git clone https://github.com/OpenTTD/OpenTTD-git-hooks.git openttd_hooks
|
||||
cd openttd
|
||||
git remote add upstream https://github.com/OpenTTD/OpenTTD.git
|
||||
cd .git/hooks
|
||||
ln -s ../../../openttd_hooks/hooks/* .
|
||||
```
|
||||
|
||||
2. If you cloned a while ago, get the latest changes from upstream:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
3. Create a new topic branch (off the main project development branch) to
|
||||
contain your feature, change, or fix:
|
||||
|
||||
```bash
|
||||
git checkout upstream/master -b <topic-branch-name>
|
||||
```
|
||||
|
||||
4. Commit your changes in logical chunks. Please adhere to these [git commit message guidelines](https://wiki.openttd.org/en/Development/Coding%20style#commit-message) or your code is unlikely to be merged into the main project.
|
||||
Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public.
|
||||
|
||||
5. Locally rebase the upstream development branch into your topic branch:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
```
|
||||
|
||||
6. Push your topic branch up to your fork the first time:
|
||||
|
||||
```bash
|
||||
git push --set-upstream origin <topic-branch-name>
|
||||
```
|
||||
|
||||
And any time after that:
|
||||
|
||||
```bash
|
||||
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 pull request or patch, you agree to the [License](#license) and the [Privacy Notice](CONTRIBUTING.md#privacy-notice).
|
||||
|
||||
|
||||
### Pull request 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.
|
||||
|
||||
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.
|
||||
|
||||
Tip: [commit message format](https://wiki.openttd.org/en/Development/Coding%20style#commit-message) is a common reason for pull requests to fail validation.
|
||||
|
||||
|
||||
### 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/en/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:
|
||||
|
||||
- *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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### Attribution of this Contributing Guide
|
||||
|
||||
This contributing guide is adapted from [Bootstrap](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) under the [Creative Commons Attribution 3.0 Unported License](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE) terms for Bootstrap documentation.
|
||||
The GDPR notice is adapted from [rsyslog](https://github.com/rsyslog/rsyslog/blob/master/CONTRIBUTING.md) under the [GNU General Public License](https://github.com/rsyslog/rsyslog/blob/master/COPYING).
|
@@ -1,69 +1,65 @@
|
||||
This is the license which applies to OpenTTD with the exception of some
|
||||
3rd party modules. See [./README.md](./README.md) for details
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
GNU General Public License
|
||||
==========================
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
|
||||
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_
|
||||
Preamble
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
### 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
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
the GNU Library 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 +76,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,28 +87,30 @@ 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,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -133,24 +131,26 @@ 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
|
||||
@@ -168,8 +168,8 @@ access to copy from a designated place, then offering equivalent
|
||||
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.
|
||||
@@ -177,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
|
||||
@@ -186,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
|
||||
@@ -194,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
|
||||
@@ -225,8 +225,8 @@ 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
|
||||
@@ -234,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.
|
||||
@@ -247,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
|
||||
@@ -255,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
|
||||
@@ -267,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
|
||||
@@ -277,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.
|
||||
@@ -303,9 +303,10 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -317,23 +318,23 @@ 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
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@@ -1,12 +0,0 @@
|
||||
# Make the current version available to CPack
|
||||
set(CPACK_PACKAGE_VERSION "@REV_VERSION@")
|
||||
|
||||
# Name the output file with the correct version
|
||||
string(REPLACE "#CPACK_PACKAGE_VERSION#" "@REV_VERSION@" CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")
|
||||
|
||||
if (CPACK_BUNDLE_PLIST_SOURCE)
|
||||
# Rewrite the Info.plist.in to contain the correct version
|
||||
file(READ ${CPACK_BUNDLE_PLIST_SOURCE} INFO_PLIST_CONTENT)
|
||||
string(REPLACE "#CPACK_PACKAGE_VERSION#" "@REV_VERSION@" INFO_PLIST_CONTENT "${INFO_PLIST_CONTENT}")
|
||||
file(WRITE ${CPACK_BUNDLE_PLIST} "${INFO_PLIST_CONTENT}")
|
||||
endif (CPACK_BUNDLE_PLIST_SOURCE)
|
60
CREDITS.md
60
CREDITS.md
@@ -1,60 +0,0 @@
|
||||
### The OpenTTD team (in alphabetical order):
|
||||
|
||||
- Grzegorz Duczyński (adf88) - General coding (since 1.7.2)
|
||||
- Albert Hofkamp (Alberth) - GUI expert (since 0.7)
|
||||
- Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)
|
||||
- Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)
|
||||
- Christoph Elsenhans (frosch) - General coding (since 0.6)
|
||||
- Loïc Guilloux (glx) - Windows Expert (since 0.4.5)
|
||||
- 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)
|
||||
- Peter Nelson (peter1138) - Spiritual descendant from newGRF gods (since 0.4.5)
|
||||
- Ingo von Borstel (planetmaker) - General coding, Support (since 1.1)
|
||||
- Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)
|
||||
- José Soler (Terkhen) - General coding (since 1.0)
|
||||
- Leif Linse (Zuu) - AI/Game Script (since 1.2)
|
||||
|
||||
### Inactive Developers:
|
||||
|
||||
- Jean-François Claeys (Belugas) - GUI, newindustries and more (0.4.5 - 1.0)
|
||||
- Bjarni Corfitzen (Bjarni) - macOS port, coder and vehicles (0.3 - 0.7)
|
||||
- Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)
|
||||
- Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)
|
||||
- Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)
|
||||
- Attila Bán (MiHaMiX) - WebTranslator 1 and 2 (0.3 - 0.5)
|
||||
- Zdeněk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)
|
||||
- Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)
|
||||
- Patric Stout (TrueBrain) - NoProgrammer (0.3 - 1.2), sys op (active)
|
||||
- Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)
|
||||
|
||||
### Retired Developers:
|
||||
|
||||
- Tamás Faragó (Darkvater) - Ex-Lead coder (0.3 - 0.5)
|
||||
- Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)
|
||||
- Emil Djupfeld (egladil) - macOS port (0.4 - 0.6)
|
||||
- Simon Sasburg (HackyKid) - Bug fixer (0.4 - 0.4.5)
|
||||
- Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)
|
||||
- Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)
|
||||
- Petr Baudiš (pasky) - Many patches, newgrf support, etc. (0.3 - 0.3)
|
||||
- Benedikt Brüggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)
|
||||
- Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)
|
||||
|
||||
### Thanks to:
|
||||
|
||||
- Josef Drexler - For his great work on TTDPatch.
|
||||
- Marcin Grzegorczyk - For his TTDPatch work and documentation of Transport Tycoon Deluxe internals and track foundations
|
||||
- Stefan Meißner (sign_de) - For his work on the console
|
||||
- Mike Ragsdale - OpenTTD installer
|
||||
- Christian Rosentreter (tokai) - MorphOS / AmigaOS port
|
||||
- Richard Kempton (RichK67) - Additional airports, initial TGP implementation
|
||||
- Alberto Demichelis - Squirrel scripting language
|
||||
- L. Peter Deutsch - MD5 implementation
|
||||
- Michael Blunck - For revolutionizing TTD with awesome graphics
|
||||
- George - Canal graphics
|
||||
- Andrew Parkhouse (andythenorth) - River graphics
|
||||
- David Dallaston (Pikka) - Tram tracks
|
||||
- All Translators - For their support to make OpenTTD a truly international game
|
||||
- Bug Reporters - Thanks for all bug reports
|
||||
- Chris Sawyer - For an amazing game!
|
@@ -1,24 +1,16 @@
|
||||
# This file is part of OpenTTD.
|
||||
# OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
# OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Doxyfile 1.5.4
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "OpenTTD AI API"
|
||||
PROJECT_NUMBER = ${REV_VERSION}
|
||||
OUTPUT_DIRECTORY = ${CPACK_BINARY_DIR}/docs/ai-api/
|
||||
PROJECT_NAME = openttd
|
||||
OUTPUT_DIRECTORY = docs/source/
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class " \
|
||||
"The $name widget " \
|
||||
"The $name file " \
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
@@ -34,48 +26,43 @@ STRIP_FROM_PATH = ./
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 2
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = YES
|
||||
INTERNAL_DOCS = YES
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TESTLIST = NO
|
||||
GENERATE_BUGLIST = NO
|
||||
GENERATE_DEPRECATEDLIST= NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = NO
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
@@ -84,39 +71,40 @@ QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARN_FORMAT = "$file:$line: $text "
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = . ${FIND_VERSION_BINARY_DIR}/script/api
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = script_*.hpp \
|
||||
ai_*.hpp
|
||||
INPUT = ./
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
table/*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS = ai_includes.hpp
|
||||
EXCLUDE_SYMBOLS = GetClassName DECLARE_ENUM_AS_BIT_SET DECLARE_POSTFIX_INCREMENT
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER = "./doxygen_filter.sh AI"
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = NO
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -132,16 +120,16 @@ HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
GENERATE_HTMLHELP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = YES
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
TOC_EXPAND = YES
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 1
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = YES
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
@@ -170,7 +158,7 @@ RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_MAN = YES
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
@@ -179,6 +167,8 @@ MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
@@ -195,21 +185,22 @@ PERLMOD_MAKEVAR_PREFIX =
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = DOXYGEN_API
|
||||
EXPAND_AS_DEFINED = DEF_COMMAND
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE = ${CPACK_BINARY_DIR}/docs/openttd_ai_api.tag
|
||||
GENERATE_TAGFILE = openttd.tag
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -224,17 +215,17 @@ TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
350
Doxyfile.in
350
Doxyfile.in
@@ -1,350 +0,0 @@
|
||||
# This file is part of OpenTTD.
|
||||
# OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
# OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "OpenTTD Source"
|
||||
PROJECT_NUMBER = ${REV_VERSION}
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = ${CPACK_BINARY_DIR}/docs/source/
|
||||
CREATE_SUBDIRS = YES
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = ./
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 2
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
EXTRACT_ANON_NSPACES = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./src/
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
*.hpp
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS = */3rdparty \
|
||||
*/script/api
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH = ./docs/
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = YES
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = NO
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = WITH_ZLIB \
|
||||
WITH_LZO \
|
||||
WITH_LIBLZMA \
|
||||
WITH_SDL \
|
||||
WITH_PNG \
|
||||
WITH_FONTCONFIG \
|
||||
WITH_FREETYPE \
|
||||
WITH_ICU_I18N \
|
||||
WITH_ICU_LX \
|
||||
UNICODE \
|
||||
_UNICODE \
|
||||
_GNU_SOURCE \
|
||||
FINAL=
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE = ${CPACK_BINARY_DIR}/docs/openttd.tag
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
213
README.md
213
README.md
@@ -1,213 +0,0 @@
|
||||
# OpenTTD
|
||||
|
||||
## Table of contents
|
||||
|
||||
- 1.0) [About](#10-about)
|
||||
- 1.1) [Downloading OpenTTD](#11-downloading-openttd)
|
||||
- 1.2) [OpenTTD gameplay manual](#12-openttd-gameplay-manual)
|
||||
- 1.3) [Supported platforms](#13-supported-platforms)
|
||||
- 1.4) [Installing and running OpenTTD](#14-installing-and-running-openttd)
|
||||
- 1.5) [Add-on content / mods](#15-add-on-content--mods)
|
||||
- 1.6) [OpenTTD directories](#16-openttd-directories)
|
||||
- 1.7) [Compiling OpenTTD](#17-compiling-openttd)
|
||||
- 2.0) [Contact and community](#20-contact-and-community)
|
||||
- 2.1) [Contributing to OpenTTD](#21-contributing-to-openttd)
|
||||
- 2.2) [Reporting bugs](#22-reporting-bugs)
|
||||
- 2.3) [Translating](#23-translating)
|
||||
- 3.0) [Licensing](#30-licensing)
|
||||
- 4.0) [Credits](#40-credits)
|
||||
|
||||
## 1.0) About
|
||||
|
||||
OpenTTD is a transport simulation game based upon the popular game Transport Tycoon Deluxe, written by Chris Sawyer.
|
||||
It attempts to mimic the original game as closely as possible while extending it with new features.
|
||||
|
||||
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"](#30-licensing) below for details.
|
||||
|
||||
## 1.1) Downloading OpenTTD
|
||||
|
||||
OpenTTD can be downloaded from the [official OpenTTD website](https://www.openttd.org/).
|
||||
|
||||
Both 'stable' and 'nightly' versions are available for download:
|
||||
|
||||
- most people should choose the 'stable' version, as this has been more extensively tested
|
||||
- the 'nightly' version includes the latest changes and features, but may sometimes be less reliable
|
||||
|
||||
On some platforms OpenTTD will also be available via your OS package manager or a similar service.
|
||||
|
||||
|
||||
## 1.2) OpenTTD gameplay manual
|
||||
|
||||
OpenTTD has a [community-maintained wiki](https://wiki.openttd.org/), including a gameplay manual and tips.
|
||||
|
||||
|
||||
## 1.3) Supported platforms
|
||||
|
||||
OpenTTD has been ported to several platforms and operating systems.
|
||||
|
||||
The currently working platforms are:
|
||||
|
||||
- FreeBSD (SDL)
|
||||
- Haiku (SDL)
|
||||
- Linux (SDL)
|
||||
- macOS (universal) (Cocoa video and sound drivers)
|
||||
- OpenBSD (SDL)
|
||||
- OS/2 (SDL)
|
||||
- Windows (Win32 GDI (faster) or SDL)
|
||||
|
||||
### 1.3.1) Legacy support
|
||||
Platforms, languages and compilers change.
|
||||
We'll keep support going on old platforms as long as someone is interested in supporting them, except where it means the project can't move forward to keep up with language and compiler features.
|
||||
|
||||
We guarantee that every revision of OpenTTD will be able to load savegames from every older revision (excepting where the savegame is corrupt).
|
||||
Please report a bug if you find a save that doesn't load.
|
||||
|
||||
## 1.4) Installing and running OpenTTD
|
||||
|
||||
OpenTTD is usually straightforward to install, but for more help the wiki [includes an installation guide](https://wiki.openttd.org/en/Manual/Installation).
|
||||
|
||||
OpenTTD needs some additional graphics and sound files to run.
|
||||
|
||||
For some platforms these will be downloaded during the installation process if required.
|
||||
|
||||
For some platforms, you will need to refer to [the installation guide](https://wiki.openttd.org/en/Manual/Installation).
|
||||
|
||||
|
||||
### 1.4.1) Free graphics and sound files
|
||||
|
||||
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
|
||||
OpenMSX for music can be found at:
|
||||
|
||||
- https://www.openttd.org/download-opengfx for OpenGFX
|
||||
- https://www.openttd.org/download-opensfx for OpenSFX
|
||||
- https://www.openttd.org/download-openmsx for OpenMSX
|
||||
|
||||
Please follow the readme of these packages about the installation procedure.
|
||||
The Windows installer can optionally download and install these packages.
|
||||
|
||||
|
||||
### 1.4.2) Original Transport Tycoon Deluxe graphics and sound files
|
||||
|
||||
If you want to play with the original Transport Tycoon Deluxe data files you have to copy the data files from the CD-ROM into the baseset/ directory.
|
||||
It does not matter whether you copy them from the DOS or Windows version of Transport Tycoon Deluxe.
|
||||
The Windows install can optionally copy these files.
|
||||
|
||||
You need to copy the following files:
|
||||
- sample.cat
|
||||
- trg1r.grf or TRG1.GRF
|
||||
- trgcr.grf or TRGC.GRF
|
||||
- trghr.grf or TRGH.GRF
|
||||
- trgir.grf or TRGI.GRF
|
||||
- trgtr.grf or TRGT.GRF
|
||||
|
||||
|
||||
### 1.4.3) Original Transport Tycoon Deluxe music
|
||||
|
||||
If you want the Transport Tycoon Deluxe music, copy the appropriate files from the original game into the baseset folder.
|
||||
- TTD for Windows: All files in the gm/ folder (gm_tt00.gm up to gm_tt21.gm)
|
||||
- TTD for DOS: The GM.CAT file
|
||||
- Transport Tycoon Original: The GM.CAT file, but rename it to GM-TTO.CAT
|
||||
|
||||
|
||||
## 1.5) Add-on content / mods
|
||||
|
||||
OpenTTD features multiple types of add-on content, which modify gameplay in different ways.
|
||||
|
||||
Most types of add-on content can be downloaded within OpenTTD via the 'Check Online Content' button in the main menu.
|
||||
|
||||
Add-on content can also be installed manually, but that's more complicated; the [OpenTTD wiki](https://wiki.openttd.org/) may offer help with that, or the [OpenTTD directory structure guide](./docs/directory_structure.md).
|
||||
|
||||
### 1.5.1) AI opponents
|
||||
|
||||
OpenTTD comes without AI opponents, so if you want to play with AIs you have to download them.
|
||||
|
||||
The easiest way is via the 'Check Online Content' button in the main menu.
|
||||
|
||||
You can select some AIs that you think are compatible with your playing style.
|
||||
|
||||
AI help and discussions may also be found in the [AI section of the forum](https://www.tt-forums.net/viewforum.php?f=65).
|
||||
|
||||
### 1.5.2) Scenarios and height maps
|
||||
|
||||
Scenarios and heightmaps can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
### 1.5.3) NewGRFs
|
||||
|
||||
A wide range of add-content is available as NewGRFs, including vehicles, industries, stations, landscape objects, town names and more.
|
||||
|
||||
NewGRFs can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
See also the wiki [guide to NewGRFs](https://wiki.openttd.org/en/Manual/NewGRF) and [the forum graphics development section](https://www.tt-forums.net/viewforum.php?f=66).
|
||||
|
||||
### 1.5.4) Game scripts
|
||||
|
||||
Game scripts can provide additional challenges or changes to the standard OpenTTD gameplay, for example setting transport goals, or changing town growth behaviour.
|
||||
|
||||
Game scripts can be added via the 'Check Online Content' button in the main menu.
|
||||
|
||||
See also the wiki [guide to game scripts](https://wiki.openttd.org/en/Manual/Game%20script) and [the forum graphics game script section](https://www.tt-forums.net/viewforum.php?f=65).
|
||||
|
||||
### 1.6) OpenTTD directories
|
||||
|
||||
OpenTTD uses its own directory structure to store game data, add-on content etc.
|
||||
|
||||
For more information, see the [directory structure guide](./docs/directory_structure.md).
|
||||
|
||||
### 1.7) Compiling OpenTTD
|
||||
|
||||
If you want to compile OpenTTD from source, instructions can be found in [COMPILING.md](./COMPILING.md).
|
||||
|
||||
|
||||
## 2.0) Contact and Community
|
||||
|
||||
'Official' channels
|
||||
|
||||
- [OpenTTD website](https://www.openttd.org)
|
||||
- IRC chat using #openttd on irc.oftc.net [more info about our irc channel](https://wiki.openttd.org/en/Development/IRC%20channel)
|
||||
- [OpenTTD on Github](https://github.com/openTTD/) for code repositories and for reporting issues
|
||||
- [forum.openttd.org](https://forum.openttd.org/) - the primary community forum site for discussing OpenTTD and related games
|
||||
- [OpenTTD wiki](https://wiki.openttd.org/) community-maintained wiki, including topics like gameplay guide, detailed explanation of some game mechanics, how to use add-on content (mods) and much more
|
||||
|
||||
'Unofficial' channels
|
||||
|
||||
- the OpenTTD wiki has a [page listing OpenTTD communities](https://wiki.openttd.org/en/Community/Community) including some in languages other than English
|
||||
|
||||
|
||||
### 2.1) Contributing to OpenTTD
|
||||
|
||||
We welcome contributors to OpenTTD. More information for contributors can be found in [CONTRIBUTING.md](./CONTRIBUTING.md)
|
||||
|
||||
|
||||
### 2.2) Reporting bugs
|
||||
|
||||
Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRIBUTING.md#bug-reports) to help with this.
|
||||
|
||||
Desyncs in multiplayer are complex to debug and report (some software development skils are required).
|
||||
Instructions can be found in [debugging and reporting desyncs](./docs/debugging_desyncs.md).
|
||||
|
||||
|
||||
### 2.3) Translating
|
||||
|
||||
OpenTTD is translated into many languages. Translations are added and updated via the [online translation tool](https://translator.openttd.org).
|
||||
|
||||
|
||||
## 3.0) Licensing
|
||||
|
||||
OpenTTD is licensed under the GNU General Public License version 2.0.
|
||||
For the complete license text, see the file '[COPYING.md](./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 the Zlib license.
|
||||
See `src/3rdparty/squirrel/COPYRIGHT` for the complete license text.
|
||||
|
||||
The md5 implementation in `src/3rdparty/md5` is licensed under the Zlib license.
|
||||
See the comments in the source files in `src/3rdparty/md5` for the complete license text.
|
||||
|
||||
The implementations of Posix `getaddrinfo` and `getnameinfo` for OS/2 in `src/3rdparty/os2` are distributed partly under the GNU Lesser General Public License 2.1, and partly under the (3-clause) BSD license.
|
||||
The exact licensing terms can be found in `src/3rdparty/os2/getaddrinfo.c` resp. `src/3rdparty/os2/getnameinfo.c`.
|
||||
|
||||
|
||||
## 4.0 Credits
|
||||
|
||||
See [CREDITS.md](./CREDITS.md)
|
10
StdAfx.c
Normal file
10
StdAfx.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* $Id$ */
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// ttd.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
263
ai/ai.c
Normal file
263
ai/ai.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../openttd.h"
|
||||
#include "../variables.h"
|
||||
#include "../command.h"
|
||||
#include "../network.h"
|
||||
#include "ai.h"
|
||||
#include "default/default.h"
|
||||
|
||||
/**
|
||||
* Dequeues commands put in the queue via AI_PutCommandInQueue.
|
||||
*/
|
||||
static void AI_DequeueCommands(byte player)
|
||||
{
|
||||
AICommand *com, *entry_com;
|
||||
|
||||
entry_com = _ai_player[player].queue;
|
||||
|
||||
/* It happens that DoCommandP issues a new DoCommandAI which adds a new command
|
||||
* to this very same queue (don't argue about this, if it currently doesn't
|
||||
* happen I can tell you it will happen with AIScript -- TrueLight). If we
|
||||
* do not make the queue NULL, that commands will be dequeued immediatly.
|
||||
* Therefor we safe the entry-point to entry_com, and make the queue NULL, so
|
||||
* the new queue can be safely built up. */
|
||||
_ai_player[player].queue = NULL;
|
||||
_ai_player[player].queue_tail = NULL;
|
||||
|
||||
/* Dequeue all commands */
|
||||
while ((com = entry_com) != NULL) {
|
||||
_current_player = player;
|
||||
|
||||
/* Copy the DP back in place */
|
||||
_cmd_text = com->text;
|
||||
DoCommandP(com->tile, com->p1, com->p2, NULL, com->procc);
|
||||
|
||||
/* Free item */
|
||||
entry_com = com->next;
|
||||
if (com->text != NULL)
|
||||
free(com->text);
|
||||
free(com);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
|
||||
* will make infinite loops (AIScript).
|
||||
*/
|
||||
static void AI_PutCommandInQueue(byte player, uint tile, uint32 p1, uint32 p2, uint procc)
|
||||
{
|
||||
AICommand *com;
|
||||
|
||||
if (_ai_player[player].queue_tail == NULL) {
|
||||
/* There is no item in the queue yet, create the queue */
|
||||
_ai_player[player].queue = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue;
|
||||
} else {
|
||||
/* Add an item at the end */
|
||||
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
|
||||
}
|
||||
|
||||
/* This is our new item */
|
||||
com = _ai_player[player].queue_tail;
|
||||
|
||||
/* Assign the info */
|
||||
com->tile = tile;
|
||||
com->p1 = p1;
|
||||
com->p2 = p2;
|
||||
com->procc = procc;
|
||||
com->next = NULL;
|
||||
com->text = NULL;
|
||||
|
||||
/* Copy the cmd_text, if needed */
|
||||
if (_cmd_text != NULL) {
|
||||
com->text = strdup(_cmd_text);
|
||||
_cmd_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a raw DoCommand for the AI.
|
||||
*/
|
||||
int32 AI_DoCommand(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
PlayerID old_lp;
|
||||
int32 res = 0;
|
||||
char *tmp_cmdtext = NULL;
|
||||
|
||||
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
|
||||
* person.. should we check for those funny jokes?
|
||||
*/
|
||||
|
||||
/* The test already free _cmd_text in most cases, so let's backup the string, else we have a problem ;) */
|
||||
if (_cmd_text != NULL)
|
||||
tmp_cmdtext = strdup(_cmd_text);
|
||||
|
||||
/* First, do a test-run to see if we can do this */
|
||||
res = DoCommandByTile(tile, p1, p2, flags & ~DC_EXEC, procc);
|
||||
/* The command failed, or you didn't want to execute, or you are quering, return */
|
||||
if ((CmdFailed(res)) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
|
||||
if (tmp_cmdtext != NULL)
|
||||
free(tmp_cmdtext);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Recover _cmd_text */
|
||||
if (tmp_cmdtext != NULL)
|
||||
_cmd_text = tmp_cmdtext;
|
||||
|
||||
/* If we did a DC_EXEC, and the command did not return an error, execute it
|
||||
over the network */
|
||||
if (flags & DC_AUTO) procc |= CMD_AUTO;
|
||||
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
|
||||
|
||||
/* NetworkSend_Command needs _local_player to be set correctly, so
|
||||
adjust it, and put it back right after the function */
|
||||
old_lp = _local_player;
|
||||
_local_player = _current_player;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* Send the command */
|
||||
if (_networking)
|
||||
/* Network is easy, send it to his handler */
|
||||
NetworkSend_Command(tile, p1, p2, procc, NULL);
|
||||
else
|
||||
#endif
|
||||
/* If we execute BuildCommands directly in SP, we have a big problem with events
|
||||
* so we need to delay is for 1 tick */
|
||||
AI_PutCommandInQueue(_current_player, tile, p1, p2, procc);
|
||||
|
||||
/* Set _local_player back */
|
||||
_local_player = old_lp;
|
||||
|
||||
/* Free the temp _cmd_text var */
|
||||
if (tmp_cmdtext != NULL)
|
||||
free(tmp_cmdtext);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
|
||||
*/
|
||||
static void AI_RunTick(PlayerID player)
|
||||
{
|
||||
extern void AiNewDoGameLoop(Player *p);
|
||||
|
||||
Player *p = GetPlayer(player);
|
||||
_current_player = player;
|
||||
|
||||
if (_patches.ainew_active) {
|
||||
AiNewDoGameLoop(p);
|
||||
} else {
|
||||
/* Enable all kind of cheats the old AI needs in order to operate correctly... */
|
||||
_is_old_ai_player = true;
|
||||
AiDoGameLoop(p);
|
||||
_is_old_ai_player = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The gameloop for AIs.
|
||||
* Handles one tick for all the AIs.
|
||||
*/
|
||||
void AI_RunGameLoop(void)
|
||||
{
|
||||
/* Don't do anything if ai is disabled */
|
||||
if (!_ai.enabled) return;
|
||||
|
||||
/* Don't do anything if we are a network-client
|
||||
* (too bad when a client joins, he thinks the AIs are real, so it wants to control
|
||||
* them.. this avoids that, while loading a network game in singleplayer, does make
|
||||
* the AIs to continue ;))
|
||||
*/
|
||||
if (_networking && !_network_server && !_ai.network_client)
|
||||
return;
|
||||
|
||||
/* New tick */
|
||||
_ai.tick++;
|
||||
|
||||
/* Make sure the AI follows the difficulty rule.. */
|
||||
assert(_opt.diff.competitor_speed <= 4);
|
||||
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0)
|
||||
return;
|
||||
|
||||
/* Check for AI-client (so joining a network with an AI) */
|
||||
if (_ai.network_client && _ai_player[_ai.network_playas].active) {
|
||||
/* Run the script */
|
||||
AI_DequeueCommands(_ai.network_playas);
|
||||
AI_RunTick(_ai.network_playas);
|
||||
} else if (!_networking || _network_server) {
|
||||
/* Check if we want to run AIs (server or SP only) */
|
||||
Player *p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) {
|
||||
/* This should always be true, else something went wrong... */
|
||||
assert(_ai_player[p->index].active);
|
||||
|
||||
/* Run the script */
|
||||
AI_DequeueCommands(p->index);
|
||||
AI_RunTick(p->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_current_player = OWNER_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A new AI sees the day of light. You can do here what ever you think is needed.
|
||||
*/
|
||||
void AI_StartNewAI(PlayerID player)
|
||||
{
|
||||
assert(player < MAX_PLAYERS);
|
||||
|
||||
/* Called if a new AI is booted */
|
||||
_ai_player[player].active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This AI player died. Give it some chance to make a final puf.
|
||||
*/
|
||||
void AI_PlayerDied(PlayerID player)
|
||||
{
|
||||
if (_ai.network_client && _ai.network_playas == player)
|
||||
_ai.network_playas = OWNER_SPECTATOR;
|
||||
|
||||
/* Called if this AI died */
|
||||
_ai_player[player].active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize some AI-related stuff.
|
||||
*/
|
||||
void AI_Initialize(void)
|
||||
{
|
||||
bool ai_network_client = _ai.network_client;
|
||||
|
||||
/* First, make sure all AIs are DEAD! */
|
||||
AI_Uninitialize();
|
||||
|
||||
memset(&_ai, 0, sizeof(_ai));
|
||||
memset(&_ai_player, 0, sizeof(_ai_player));
|
||||
|
||||
_ai.network_client = ai_network_client;
|
||||
_ai.network_playas = OWNER_SPECTATOR;
|
||||
_ai.enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializer for AI-related stuff.
|
||||
*/
|
||||
void AI_Uninitialize(void)
|
||||
{
|
||||
Player* p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
|
||||
}
|
||||
}
|
112
ai/ai.h
Normal file
112
ai/ai.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef AI_H
|
||||
#define AI_H
|
||||
|
||||
#include "../functions.h"
|
||||
#include "../network.h"
|
||||
#include "../player.h"
|
||||
|
||||
/* How DoCommands look like for an AI */
|
||||
typedef struct AICommand {
|
||||
uint32 tile;
|
||||
uint32 p1;
|
||||
uint32 p2;
|
||||
uint32 procc;
|
||||
|
||||
char *text;
|
||||
uint uid;
|
||||
|
||||
struct AICommand *next;
|
||||
} AICommand;
|
||||
|
||||
/* The struct for an AIScript Player */
|
||||
typedef struct AIPlayer {
|
||||
bool active; //! Is this AI active?
|
||||
AICommand *queue; //! The commands that he has in his queue
|
||||
AICommand *queue_tail; //! The tail of this queue
|
||||
} AIPlayer;
|
||||
|
||||
/* The struct to keep some data about the AI in general */
|
||||
typedef struct AIStruct {
|
||||
/* General */
|
||||
bool enabled; //! Is AI enabled?
|
||||
uint tick; //! The current tick (something like _frame_counter, only for AIs)
|
||||
|
||||
/* For network-clients (a OpenTTD client who acts as an AI connected to a server) */
|
||||
bool network_client; //! Are we a network_client?
|
||||
uint8 network_playas; //! The current network player we are connected as
|
||||
} AIStruct;
|
||||
|
||||
VARDEF AIStruct _ai;
|
||||
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
|
||||
|
||||
// ai.c
|
||||
void AI_StartNewAI(PlayerID player);
|
||||
void AI_PlayerDied(PlayerID player);
|
||||
void AI_RunGameLoop(void);
|
||||
void AI_Initialize(void);
|
||||
void AI_Uninitialize(void);
|
||||
int32 AI_DoCommand(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
|
||||
/** Is it allowed to start a new AI.
|
||||
* This function checks some boundries to see if we should launch a new AI.
|
||||
* @return True if we can start a new AI.
|
||||
*/
|
||||
static inline bool AI_AllowNewAI(void)
|
||||
{
|
||||
/* If disabled, no AI */
|
||||
if (!_ai.enabled)
|
||||
return false;
|
||||
|
||||
/* If in network, but no server, no AI */
|
||||
if (_networking && !_network_server)
|
||||
return false;
|
||||
|
||||
/* If in network, and server, possible AI */
|
||||
if (_networking && _network_server) {
|
||||
/* Do we want AIs in multiplayer? */
|
||||
if (!_patches.ai_in_multiplayer)
|
||||
return false;
|
||||
|
||||
/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
|
||||
* system, because all commands are delayed by at least 1 tick, which causes
|
||||
* a big problem, because it uses variables that are only set AFTER the command
|
||||
* is really executed... */
|
||||
if (!_patches.ainew_active)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define AI_CHANCE16(a,b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
|
||||
#define AI_CHANCE16R(a,b,r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
|
||||
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
*/
|
||||
static inline uint AI_RandomRange(uint max)
|
||||
{
|
||||
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
|
||||
* but we pick InteractiveRandomRange if we are a network_server or network-client.
|
||||
*/
|
||||
if (_networking)
|
||||
return InteractiveRandomRange(max);
|
||||
else
|
||||
return RandomRange(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
*/
|
||||
static inline uint32 AI_Random(void)
|
||||
{
|
||||
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
|
||||
* but we pick InteractiveRandomRange if we are a network_server or network-client.
|
||||
*/
|
||||
if (_networking)
|
||||
return InteractiveRandom();
|
||||
else
|
||||
return Random();
|
||||
}
|
||||
|
||||
#endif /* AI_H */
|
3979
ai/default/default.c
Normal file
3979
ai/default/default.c
Normal file
File diff suppressed because it is too large
Load Diff
8
ai/default/default.h
Normal file
8
ai/default/default.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEFAULT_H
|
||||
#define DEFAULT_H
|
||||
|
||||
void AiDoGameLoop(Player*);
|
||||
|
||||
#endif
|
273
ai/trolly/build.c
Normal file
273
ai/trolly/build.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../engine.h"
|
||||
#include "../../station.h"
|
||||
#include "../../variables.h"
|
||||
#include "../ai.h"
|
||||
|
||||
// Build HQ
|
||||
// Params:
|
||||
// tile : tile where HQ is going to be build
|
||||
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
|
||||
{
|
||||
if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
|
||||
return false;
|
||||
AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Build station
|
||||
// Params:
|
||||
// type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
|
||||
// tile : tile where station is going to be build
|
||||
// length : in case of AI_TRAIN: length of station
|
||||
// numtracks : in case of AI_TRAIN: tracks of station
|
||||
// direction : the direction of the station
|
||||
// flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
|
||||
{
|
||||
if (type == AI_TRAIN)
|
||||
return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
|
||||
|
||||
if (type == AI_BUS)
|
||||
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
|
||||
return AI_DoCommand(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
}
|
||||
|
||||
|
||||
// Builds a brdige. The second best out of the ones available for this player
|
||||
// Params:
|
||||
// tile_a : starting point
|
||||
// tile_b : end point
|
||||
// flag : flag passed to DoCommand
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
|
||||
{
|
||||
int bridge_type, bridge_len, type, type2;
|
||||
|
||||
// Find a good bridgetype (the best money can buy)
|
||||
bridge_len = GetBridgeLength(tile_a, tile_b);
|
||||
type = type2 = 0;
|
||||
for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
type2 = type;
|
||||
type = bridge_type;
|
||||
// We found two bridges, exit
|
||||
if (type2 != 0) break;
|
||||
}
|
||||
}
|
||||
// There is only one bridge that can be build..
|
||||
if (type2 == 0 && type != 0) type2 = type;
|
||||
|
||||
// Now, simply, build the bridge!
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return AI_DoCommand(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
|
||||
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
}
|
||||
|
||||
|
||||
// Build the route part by part
|
||||
// Basicly what this function do, is build that amount of parts of the route
|
||||
// that go in the same direction. It sets 'part' to the last part of the route builded.
|
||||
// The return value is the cost for the builded parts
|
||||
//
|
||||
// Params:
|
||||
// PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
|
||||
// part : Which part we need to build
|
||||
//
|
||||
// TODO: skip already builded road-pieces (e.g.: cityroad)
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
|
||||
{
|
||||
int part = PathFinderInfo->position;
|
||||
byte *route_extra = PathFinderInfo->route_extra;
|
||||
TileIndex *route = PathFinderInfo->route;
|
||||
int dir;
|
||||
int old_dir = -1;
|
||||
int cost = 0;
|
||||
int res;
|
||||
// We need to calculate the direction with the parent of the parent.. so we skip
|
||||
// the first pieces and the last piece
|
||||
if (part < 1) part = 1;
|
||||
// When we are done, stop it
|
||||
if (part >= PathFinderInfo->route_length - 1) { PathFinderInfo->position = -2; return 0; }
|
||||
|
||||
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Tunnel code
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
|
||||
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal rail
|
||||
// Keep it doing till we go an other way
|
||||
if (route_extra[part-1] == 0 && route_extra[part] == 0) {
|
||||
while (route_extra[part] == 0) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// Build the tile
|
||||
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(res)) {
|
||||
// Problem.. let's just abort it all!
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
cost += res;
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
if (part >= PathFinderInfo->route_length - 1) break;
|
||||
}
|
||||
part--;
|
||||
}
|
||||
// We want to return the last position, so we go back one
|
||||
PathFinderInfo->position = part;
|
||||
} else {
|
||||
// Tunnel code
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
|
||||
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal road
|
||||
// Keep it doing till we go an other way
|
||||
// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
|
||||
// it will wait till the vehicle is gone..
|
||||
if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// There is already some road, and it is a bridge.. don't build!!!
|
||||
if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
|
||||
// Build the tile
|
||||
res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// Currently, we ignore CMD_ERRORs!
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CmdFailed(res)) cost += res;
|
||||
}
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
if (part >= PathFinderInfo->route_length - 1) break;
|
||||
}
|
||||
part--;
|
||||
// We want to return the last position, so we go back one
|
||||
}
|
||||
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
|
||||
PathFinderInfo->position = part;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
// This functions tries to find the best vehicle for this type of cargo
|
||||
// It returns vehicle_id or -1 if not found
|
||||
int AiNew_PickVehicle(Player *p)
|
||||
{
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
// Not supported yet
|
||||
return -1;
|
||||
} else {
|
||||
int start, count, i, ret = CMD_ERROR;
|
||||
start = _cargoc.ai_roadveh_start[p->ainew.cargo];
|
||||
count = _cargoc.ai_roadveh_count[p->ainew.cargo];
|
||||
|
||||
// Let's check it backwards.. we simply want to best engine available..
|
||||
for (i = start + count - 1; i >= start; i--) {
|
||||
// Is it availiable?
|
||||
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
|
||||
if (!HASBIT(GetEngine(i)->player_avail, _current_player) || GetEngine(i)->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
// Can we build it?
|
||||
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (!CmdFailed(ret)) break;
|
||||
}
|
||||
// We did not find a vehicle :(
|
||||
if (CmdFailed(ret)) return -1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Builds the best vehicle possible
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
|
||||
{
|
||||
int i = AiNew_PickVehicle(p);
|
||||
if (i == -1) return CMD_ERROR;
|
||||
|
||||
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
|
||||
|
||||
return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
|
||||
}
|
||||
|
||||
int AiNew_Build_Depot(Player *p, TileIndex tile, byte direction, byte flag)
|
||||
{
|
||||
static const byte _roadbits_by_dir[4] = {2,1,8,4};
|
||||
int ret, ret2;
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
|
||||
|
||||
ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (CmdFailed(ret)) return ret;
|
||||
// Try to build the road from the depot
|
||||
ret2 = AI_DoCommand(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
return ret + ret2;
|
||||
}
|
509
ai/trolly/pathfinder.c
Normal file
509
ai/trolly/pathfinder.c
Normal file
@@ -0,0 +1,509 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../depot.h"
|
||||
#include "../../variables.h"
|
||||
#include "../ai.h"
|
||||
|
||||
#define TEST_STATION_NO_DIR 0xFF
|
||||
|
||||
// Tests if a station can be build on the given spot
|
||||
// TODO: make it train compatible
|
||||
static bool TestCanBuildStationHere(TileIndex tile, byte dir)
|
||||
{
|
||||
Player *p = GetPlayer(_current_player);
|
||||
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
int32 ret;
|
||||
// TODO: currently we only allow spots that can be access from al 4 directions...
|
||||
// should be fixed!!!
|
||||
for (dir = 0; dir < 4; dir++) {
|
||||
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (!CmdFailed(ret)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if command succeeded, so the inverse of CmdFailed()
|
||||
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
}
|
||||
|
||||
|
||||
static bool IsRoad(TileIndex tile)
|
||||
{
|
||||
return
|
||||
// MP_STREET, but not a road depot?
|
||||
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
|
||||
// road tunnel?
|
||||
((_m[tile].m5 & 0x80) == 0 && (_m[tile].m5 & 0x4) == 0x4) ||
|
||||
// road bridge?
|
||||
((_m[tile].m5 & 0x80) != 0 && (_m[tile].m5 & 0x2) == 0x2)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Checks if a tile 'a' is between the tiles 'b' and 'c'
|
||||
#define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
|
||||
|
||||
|
||||
// Check if the current tile is in our end-area
|
||||
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
// It is not allowed to have a station on the end of a bridge or tunnel ;)
|
||||
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
|
||||
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
|
||||
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
|
||||
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
|
||||
return AYSTAR_DONE;
|
||||
}
|
||||
|
||||
|
||||
// Calculates the hash
|
||||
// Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
|
||||
static uint AiPathFinder_Hash(uint key1, uint key2)
|
||||
{
|
||||
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
|
||||
}
|
||||
|
||||
|
||||
// Clear the memory of all the things
|
||||
static void AyStar_AiPathFinder_Free(AyStar *aystar)
|
||||
{
|
||||
AyStarMain_Free(aystar);
|
||||
free(aystar);
|
||||
}
|
||||
|
||||
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
|
||||
// This creates the AiPathFinder
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
// Create AyStar
|
||||
AyStar *result = malloc(sizeof(AyStar));
|
||||
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
|
||||
// Set the function pointers
|
||||
result->CalculateG = AyStar_AiPathFinder_CalculateG;
|
||||
result->CalculateH = AyStar_AiPathFinder_CalculateH;
|
||||
result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
|
||||
result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
|
||||
result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
|
||||
|
||||
result->free = AyStar_AiPathFinder_Free;
|
||||
|
||||
// Set some information
|
||||
result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
|
||||
result->max_path_cost = 0;
|
||||
result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
result->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
start_node.node.tile = TileXY(x, y);
|
||||
result->addstart(result, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// To reuse AyStar we sometimes have to clean all the memory
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
aystar->clear(aystar);
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
aystar->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
start_node.node.tile = PathFinderInfo->start_tile_tl;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
if (!(IsTileType(TileXY(x, y), MP_CLEAR) || IsTileType(TileXY(x, y), MP_TREES))) continue;
|
||||
if (!TestCanBuildStationHere(TileXY(x, y), TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = TileXY(x, y);
|
||||
aystar->addstart(aystar, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The h-value, simple calculation
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, r2;
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
} else {
|
||||
// No direction, so just get the fastest route to the station
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
|
||||
}
|
||||
// See if the bottomright is faster than the topleft..
|
||||
if (r2 < r) r = r2;
|
||||
return r * AI_PATHFINDER_H_MULTIPLER;
|
||||
}
|
||||
|
||||
|
||||
// We found the end.. let's get the route back and put it in an array
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
uint i = 0;
|
||||
PathNode *parent = ¤t->path;
|
||||
|
||||
do {
|
||||
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
|
||||
PathFinderInfo->route[i++] = parent->node.tile;
|
||||
if (i > lengthof(PathFinderInfo->route)) {
|
||||
// We ran out of space for the PathFinder
|
||||
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
|
||||
PathFinderInfo->route_length = -1; // -1 indicates out of space
|
||||
return;
|
||||
}
|
||||
parent = parent->parent;
|
||||
} while (parent != NULL);
|
||||
PathFinderInfo->route_length = i;
|
||||
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
|
||||
}
|
||||
|
||||
|
||||
// What tiles are around us.
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
uint i;
|
||||
int ret;
|
||||
int dir;
|
||||
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
|
||||
aystar->num_neighbours = 0;
|
||||
|
||||
// Go through all surrounding tiles and check if they are within the limits
|
||||
for (i = 0; i < 4; i++) {
|
||||
TileIndex ctile = current->path.node.tile; // Current tile
|
||||
TileIndex atile = ctile + TileOffsByDir(i); // Adjacent tile
|
||||
|
||||
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
|
||||
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
|
||||
// We also directly test if the current tile can connect to this tile..
|
||||
// We do this simply by just building the tile!
|
||||
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
|
||||
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge... let's test the direction ;)
|
||||
if ((_m[atile].m5 & 1U) != (i & 1)) continue;
|
||||
// This problem only is valid for tunnels:
|
||||
// When the last tile was not yet a tunnel, check if we enter from the right side..
|
||||
if ((_m[atile].m5 & 0x80) == 0) {
|
||||
if (i != (_m[atile].m5 & 3U)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_m[ctile].m5 & 1U) != (i & 1)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
|
||||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
|
||||
// We are a bridge/tunnel, how cool!!
|
||||
// This means we can only point forward.. get the direction from the user_data
|
||||
if (i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
}
|
||||
dir = 0;
|
||||
|
||||
// First, check if we have a parent
|
||||
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
|
||||
// If not, this means we are at the starting station
|
||||
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// We do need a direction?
|
||||
if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
|
||||
// We are not pointing the right way, invalid tile
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (current->path.node.user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Rail check
|
||||
dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
|
||||
ret = AI_DoCommand(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(ret)) continue;
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
if (current->path.parent->parent != NULL) {
|
||||
// Check if we don't make a 90degree curve
|
||||
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
|
||||
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Road check
|
||||
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
|
||||
if (IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// We have a bridge, how nicely! We should mark it...
|
||||
dir = 0;
|
||||
} else {
|
||||
// It already has road.. check if we miss any bits!
|
||||
if ((_m[ctile].m5 & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~_m[ctile].m5;
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only destruct things if it is MP_CLEAR of MP_TREES
|
||||
if (dir != 0) {
|
||||
ret = AI_DoCommand(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (CmdFailed(ret)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The tile can be connected
|
||||
aystar->neighbours[aystar->num_neighbours].tile = atile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Next step, check for bridges and tunnels
|
||||
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
|
||||
TileInfo ti;
|
||||
// First we get the dir from this tile and his parent
|
||||
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
// It means we can only walk with the track, so the bridge has to be in the same direction
|
||||
TileIndex tile = current->path.node.tile;
|
||||
TileIndex new_tile = tile;
|
||||
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (ti.tileh != 0 ||
|
||||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
|
||||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
|
||||
for (;;) {
|
||||
new_tile += TileOffsByDir(dir);
|
||||
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
|
||||
|
||||
// Check if we hit the station-tile.. we don't like that!
|
||||
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
|
||||
|
||||
// Try building the bridge..
|
||||
ret = AI_DoCommand(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
if (CmdFailed(ret)) continue;
|
||||
// We can build a bridge here.. add him to the neighbours
|
||||
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
// We can only have 12 neighbours, and we need 1 left for tunnels
|
||||
if (aystar->num_neighbours == 11) break;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
|
||||
// For now, we check both sides for this tile.. terraforming gives fuzzy result
|
||||
if ((dir == 0 && ti.tileh == 12) ||
|
||||
(dir == 1 && ti.tileh == 6) ||
|
||||
(dir == 2 && ti.tileh == 3) ||
|
||||
(dir == 3 && ti.tileh == 9)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
|
||||
if (!CmdFailed(ret) && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern uint GetRailFoundation(uint tileh, uint bits);
|
||||
extern uint GetRoadFoundation(uint tileh, uint bits);
|
||||
extern uint GetBridgeFoundation(uint tileh, byte direction);
|
||||
enum {
|
||||
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
|
||||
};
|
||||
|
||||
// The most important function: it calculates the g-value
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, res = 0;
|
||||
TileInfo ti, parent_ti;
|
||||
|
||||
// Gather some information about the tile..
|
||||
FindLandscapeHeightByTile(&ti, current->tile);
|
||||
FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
|
||||
|
||||
// Check if we hit the end-tile
|
||||
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
|
||||
// We are at the end-tile, check if we had a direction or something...
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction) {
|
||||
// We are not pointing the right way, invalid tile
|
||||
return AYSTAR_INVALID_NODE;
|
||||
}
|
||||
// If it was valid, drop out.. we don't build on the endtile
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Give everything a small penalty
|
||||
res += AI_PATHFINDER_PENALTY;
|
||||
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
// Road has the lovely advantage it can use other road... check if
|
||||
// the current tile is road, and if so, give a good bonus
|
||||
if (IsRoad(current->tile)) {
|
||||
res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
|
||||
}
|
||||
}
|
||||
|
||||
// We should give a penalty when the tile is going up or down.. this is one way to do so!
|
||||
// Too bad we have to count it from the parent.. but that is not so bad.
|
||||
// We also dislike long routes on slopes, since they do not look too realistic
|
||||
// when there is a flat land all around, they are more expensive to build, and
|
||||
// especially they essentially block the ability to connect or cross the road
|
||||
// from one side.
|
||||
if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
|
||||
// Skip if the tile was from a bridge or tunnel
|
||||
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
r = GetRailFoundation(parent_ti.tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
|
||||
if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
} else {
|
||||
if (!(IsRoad(parent->path.node.tile) && IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE))) {
|
||||
r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
if (r >= 15 || r == 0)
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we part of a tunnel?
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
|
||||
// Tunnels are very expensive when build on long routes..
|
||||
// Ironicly, we are using BridgeCode here ;)
|
||||
r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
res += r + (r >> 8);
|
||||
}
|
||||
|
||||
// Are we part of a bridge?
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
|
||||
// That means for every length a penalty
|
||||
res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
// Check if we are going up or down, first for the starting point
|
||||
// In user_data[0] is at the 8th bit the direction
|
||||
if (!(BRIDGE_NO_FOUNDATION & (1 << parent_ti.tileh))) {
|
||||
if (GetBridgeFoundation(parent_ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
// Second for the end point
|
||||
if (!(BRIDGE_NO_FOUNDATION & (1 << ti.tileh))) {
|
||||
if (GetBridgeFoundation(ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
if (parent_ti.tileh == 0) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
if (ti.tileh == 0) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
|
||||
// To prevent the AI from taking the fastest way in tiles, but not the fastest way
|
||||
// in speed, we have to give a good penalty to direction changing
|
||||
// This way, we get almost the fastest way in tiles, and a very good speed on the track
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
if (parent->path.parent != NULL &&
|
||||
AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
|
||||
// When road exists, we don't like turning, but its free, so don't be to piggy about it
|
||||
if (IsRoad(parent->path.node.tile))
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
} else {
|
||||
// For rail we have 1 exeption: diagonal rail..
|
||||
// So we fetch 2 raildirection. That of the current one, and of the one before that
|
||||
if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
|
||||
int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
|
||||
int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
|
||||
// First, see if we are on diagonal path, that is better than straight path
|
||||
if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
|
||||
|
||||
// First see if they are different
|
||||
if (dir1 != dir2) {
|
||||
// dir 2 and 3 are 1 diagonal track, and 4 and 5.
|
||||
if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
|
||||
// It is not, so we changed of direction
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
if (parent->path.parent->parent->parent != NULL) {
|
||||
int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
|
||||
// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
|
||||
if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
|
||||
res += AI_PATHFINDER_CURVE_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (res < 0) ? 0 : res;
|
||||
}
|
124
ai/trolly/shared.c
Normal file
124
ai/trolly/shared.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../map.h"
|
||||
#include "trolly.h"
|
||||
#include "../../vehicle.h"
|
||||
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
// 0 = vert
|
||||
// 1 = horz
|
||||
// 2 = dig up-left
|
||||
// 3 = dig down-right
|
||||
// 4 = dig down-left
|
||||
// 5 = dig up-right
|
||||
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
if (y1 == y2 && y2 == y3) return 0;
|
||||
if (x1 == x2 && x2 == x3) return 1;
|
||||
if (y2 > y1) {
|
||||
if (x2 > x3) return 2;
|
||||
else return 4;
|
||||
}
|
||||
if (x2 > x1) {
|
||||
if (y2 > y3) return 2;
|
||||
else return 5;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
if (x2 > x3) return 5;
|
||||
else return 3;
|
||||
}
|
||||
if (x1 > x2) {
|
||||
if (y2 > y3) return 4;
|
||||
else return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
int r;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
r = 0;
|
||||
|
||||
if (x1 < x2) r += 8;
|
||||
if (y1 < y2) r += 1;
|
||||
if (x1 > x2) r += 2;
|
||||
if (y1 > y2) r += 4;
|
||||
|
||||
if (x2 < x3) r += 2;
|
||||
if (y2 < y3) r += 4;
|
||||
if (x2 > x3) r += 8;
|
||||
if (y2 > y3) r += 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Get's the direction between 2 tiles seen from tile_a
|
||||
int AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b)
|
||||
{
|
||||
if (TileY(tile_a) < TileY(tile_b)) return 1;
|
||||
if (TileY(tile_a) > TileY(tile_b)) return 3;
|
||||
if (TileX(tile_a) < TileX(tile_b)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This functions looks up if this vehicle is special for this AI
|
||||
// and returns his flag
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v) {
|
||||
int i;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
return p->ainew.special_vehicles[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found :(
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag) {
|
||||
int i, new_id = -1;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
p->ainew.special_vehicles[i].flag |= flag;
|
||||
return true;
|
||||
}
|
||||
if (new_id == -1 && p->ainew.special_vehicles[i].veh_id == 0 &&
|
||||
p->ainew.special_vehicles[i].flag == 0)
|
||||
new_id = i;
|
||||
}
|
||||
|
||||
// Out of special_vehicle spots :s
|
||||
if (new_id == -1) {
|
||||
DEBUG(ai, 1)("special_vehicles list is too small :(");
|
||||
return false;
|
||||
}
|
||||
p->ainew.special_vehicles[new_id].veh_id = v->index;
|
||||
p->ainew.special_vehicles[new_id].flag = flag;
|
||||
return true;
|
||||
}
|
1364
ai/trolly/trolly.c
Normal file
1364
ai/trolly/trolly.c
Normal file
File diff suppressed because it is too large
Load Diff
261
ai/trolly/trolly.h
Normal file
261
ai/trolly/trolly.h
Normal file
@@ -0,0 +1,261 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AI_TROLLY_H
|
||||
#define AI_TROLLY_H
|
||||
|
||||
#include "../../aystar.h"
|
||||
#include "../../player.h"
|
||||
|
||||
/*
|
||||
* These defines can be altered to change the behavoir of the AI
|
||||
*
|
||||
* WARNING:
|
||||
* This can also alter the AI in a negative way. I will never claim these settings
|
||||
* are perfect, but don't change them if you don't know what the effect is.
|
||||
*/
|
||||
|
||||
// How many times it the H multiplied. The higher, the more it will go straight to the
|
||||
// end point. The lower, how more it will find the route with the lowest cost.
|
||||
// also: the lower, the longer it takes before route is calculated..
|
||||
#define AI_PATHFINDER_H_MULTIPLER 100
|
||||
|
||||
// How many loops may AyStar do before it stops
|
||||
// 0 = infinite
|
||||
#define AI_PATHFINDER_LOOPS_PER_TICK 5
|
||||
|
||||
// How long may the AI search for one route?
|
||||
// 0 = infinite
|
||||
// This number is the number of tiles tested.
|
||||
// It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
|
||||
// to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
|
||||
// (that is: if the AI is on VERY FAST! :p
|
||||
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
|
||||
|
||||
// If you enable this, the AI is not allowed to make 90degree turns
|
||||
#define AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
|
||||
// Below are defines for the g-calculation
|
||||
|
||||
// Standard penalty given to a tile
|
||||
#define AI_PATHFINDER_PENALTY 150
|
||||
// The penalty given to a tile that is going up
|
||||
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
|
||||
// The penalty given to a tile which would have to use fundation
|
||||
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
|
||||
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
|
||||
// Same penalty, only for when road already exists
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
|
||||
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
|
||||
// a bonus for using diagonal track
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 95
|
||||
#else
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 75
|
||||
#endif
|
||||
// If a roadblock already exists, it gets a bonus
|
||||
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
|
||||
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
|
||||
#define AI_PATHFINDER_CURVE_PENALTY 200
|
||||
|
||||
// Penalty a bridge gets per length
|
||||
#define AI_PATHFINDER_BRIDGE_PENALTY 180
|
||||
// The penalty for a bridge going up
|
||||
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
|
||||
|
||||
// Tunnels are expensive...
|
||||
// Because of that, every tile the cost is increased with 1/8th of his value
|
||||
// This is also true if you are building a tunnel yourself
|
||||
#define AI_PATHFINDER_TUNNEL_PENALTY 350
|
||||
|
||||
/*
|
||||
* Ai_New defines
|
||||
*/
|
||||
|
||||
// How long may we search cities and industry for a new route?
|
||||
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
|
||||
|
||||
// How many days must there be between building the first station and the second station
|
||||
// within one city. This number is in days and should be more than 4 months.
|
||||
#define AI_CHECKCITY_DATE_BETWEEN 180
|
||||
|
||||
// How many cargo is needed for one station in a city?
|
||||
#define AI_CHECKCITY_CARGO_PER_STATION 60
|
||||
// How much cargo must there not be used in a city before we can build a new station?
|
||||
#define AI_CHECKCITY_NEEDED_CARGO 50
|
||||
// When there is already a station which takes the same good and the rating of that
|
||||
// city is higher then this numer, we are not going to attempt to build anything
|
||||
// there
|
||||
#define AI_CHECKCITY_CARGO_RATING 50
|
||||
// But, there is a chance of 1 out of this number, that we do ;)
|
||||
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
|
||||
// If a city is too small to contain a station, there is a small chance
|
||||
// that we still do so.. just to make the city bigger!
|
||||
#define AI_CHECKCITY_CITY_CHANCE 5
|
||||
|
||||
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
|
||||
// from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
|
||||
// of the cargo in the other station, both stations can be 96 units away from eachother, if the
|
||||
// next number is 0.4.
|
||||
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
|
||||
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
|
||||
// In whole tiles, the minimum distance for a truck route
|
||||
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
|
||||
|
||||
// The amount of tiles in a square from -X to +X that is scanned for a station spot
|
||||
// (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
|
||||
// Safe values are between 15 and 5
|
||||
#define AI_FINDSTATION_TILE_RANGE 10
|
||||
|
||||
// Building on normal speed goes very fast. Idle this amount of ticks between every
|
||||
// building part. It is calculated like this: (4 - competitor_speed) * num + 1
|
||||
// where competitor_speed is between 0 (very slow) to 4 (very fast)
|
||||
#define AI_BUILDPATH_PAUSE 10
|
||||
|
||||
// Minimum % of reliabilty a vehicle has to have before the AI buys it
|
||||
#define AI_VEHICLE_MIN_RELIABILTY 60
|
||||
|
||||
// The minimum amount of money a player should always have
|
||||
#define AI_MINIMUM_MONEY 15000
|
||||
|
||||
// If the most cheap route is build, how much is it going to cost..
|
||||
// This is to prevent the AI from trying to build a route which can not be paid for
|
||||
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
|
||||
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
|
||||
|
||||
// The minimum amount of money before we are going to repay any money
|
||||
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
|
||||
// How many repays do we do if we have enough money to do so?
|
||||
// Every repay is 10000
|
||||
#define AI_LOAN_REPAY 2
|
||||
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
|
||||
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
|
||||
|
||||
// If there is <num> time as much cargo in the station then the vehicle can handle
|
||||
// reuse the station instead of building a new one!
|
||||
#define AI_STATION_REUSE_MULTIPLER 2
|
||||
|
||||
// No more than this amount of vehicles per station..
|
||||
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
|
||||
|
||||
// How many thick between building 2 vehicles
|
||||
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS
|
||||
|
||||
// How many days must there between vehicle checks
|
||||
// The more often, the less non-money-making lines there will be
|
||||
// but the unfair it may seem to a human player
|
||||
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30
|
||||
|
||||
// How money profit does a vehicle needs to make to stay in order
|
||||
// This is the profit of this year + profit of last year
|
||||
// But also for vehicles that are just one year old. In other words:
|
||||
// Vehicles of 2 years do easier meet this setting then vehicles
|
||||
// of one year. This is a very good thing. New vehicles are filtered,
|
||||
// while old vehicles stay longer, because we do get less in return.
|
||||
#define AI_MINIMUM_ROUTE_PROFIT 1000
|
||||
|
||||
// A vehicle is considered lost when he his cargo is more than 180 days old
|
||||
#define AI_VEHICLE_LOST_DAYS 180
|
||||
|
||||
// How many times may the AI try to find a route before it gives up
|
||||
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8
|
||||
|
||||
/*
|
||||
* End of defines
|
||||
*/
|
||||
|
||||
// This stops 90degrees curves
|
||||
static const byte _illegal_curves[6] = {
|
||||
255, 255, // Horz and vert, don't have the effect
|
||||
5, // upleft and upright are not valid
|
||||
4, // downright and downleft are not valid
|
||||
2, // downleft and upleft are not valid
|
||||
3, // upright and downright are not valid
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_STATE_STARTUP = 0,
|
||||
AI_STATE_FIRST_TIME,
|
||||
AI_STATE_NOTHING,
|
||||
AI_STATE_WAKE_UP,
|
||||
AI_STATE_LOCATE_ROUTE,
|
||||
AI_STATE_FIND_STATION,
|
||||
AI_STATE_FIND_PATH,
|
||||
AI_STATE_FIND_DEPOT,
|
||||
AI_STATE_VERIFY_ROUTE,
|
||||
AI_STATE_BUILD_STATION,
|
||||
AI_STATE_BUILD_PATH,
|
||||
AI_STATE_BUILD_DEPOT,
|
||||
AI_STATE_BUILD_VEHICLE,
|
||||
AI_STATE_GIVE_ORDERS,
|
||||
AI_STATE_START_VEHICLE,
|
||||
AI_STATE_REPAY_MONEY,
|
||||
AI_STATE_CHECK_ALL_VEHICLES,
|
||||
AI_STATE_ACTION_DONE,
|
||||
AI_STATE_STOP, // Temporary function to stop the AI
|
||||
};
|
||||
|
||||
// Used for tbt (train/bus/truck)
|
||||
enum {
|
||||
AI_TRAIN = 0,
|
||||
AI_BUS,
|
||||
AI_TRUCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_ACTION_NONE = 0,
|
||||
AI_ACTION_BUS_ROUTE,
|
||||
AI_ACTION_TRUCK_ROUTE,
|
||||
AI_ACTION_REPAY_LOAN,
|
||||
AI_ACTION_CHECK_ALL_VEHICLES,
|
||||
};
|
||||
|
||||
// Used for from_type/to_type
|
||||
enum {
|
||||
AI_NO_TYPE = 0,
|
||||
AI_CITY,
|
||||
AI_INDUSTRY,
|
||||
};
|
||||
|
||||
// Flags for in the vehicle
|
||||
enum {
|
||||
AI_VEHICLEFLAG_SELL = 1,
|
||||
// Remember, flags must be in power of 2
|
||||
};
|
||||
|
||||
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
|
||||
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
|
||||
#define AI_STATION_RANGE TileXY(MapMaxX(), MapMaxY())
|
||||
|
||||
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
|
||||
|
||||
// Flags used in user_data
|
||||
#define AI_PATHFINDER_FLAG_BRIDGE 1
|
||||
#define AI_PATHFINDER_FLAG_TUNNEL 2
|
||||
|
||||
typedef void AiNew_StateFunction(Player *p);
|
||||
|
||||
// ai_new.c
|
||||
void AiNewDoGameLoop(Player *p);
|
||||
|
||||
// ai_pathfinder.c
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
|
||||
|
||||
// ai_shared.c
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
int AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag);
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
|
||||
|
||||
// ai_build.c
|
||||
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
|
||||
int AiNew_PickVehicle(Player *p);
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
|
||||
int AiNew_Build_Depot(Player *p, TileIndex tile, byte direction, byte flag);
|
||||
|
||||
#endif /* AI_TROLLY_H */
|
1995
aircraft_cmd.c
Normal file
1995
aircraft_cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
1195
aircraft_gui.c
Normal file
1195
aircraft_gui.c
Normal file
File diff suppressed because it is too large
Load Diff
383
airport.c
Normal file
383
airport.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
|
||||
static AirportFTAClass* CountryAirport;
|
||||
static AirportFTAClass* CityAirport;
|
||||
static AirportFTAClass* Oilrig;
|
||||
static AirportFTAClass* Heliport;
|
||||
static AirportFTAClass* MetropolitanAirport;
|
||||
static AirportFTAClass* InternationalAirport;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport);
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA);
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA);
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport);
|
||||
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
|
||||
static byte AirportBlockToString(uint32 block);*/
|
||||
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
// country airport
|
||||
CountryAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CountryAirport,
|
||||
_airport_terminal_country,
|
||||
NULL,
|
||||
16,
|
||||
ALL,
|
||||
_airport_fta_country,
|
||||
_airport_depots_country,
|
||||
lengthof(_airport_depots_country)
|
||||
);
|
||||
|
||||
// city airport
|
||||
CityAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CityAirport,
|
||||
_airport_terminal_city,
|
||||
NULL,
|
||||
19,
|
||||
ALL,
|
||||
_airport_fta_city,
|
||||
_airport_depots_city,
|
||||
lengthof(_airport_depots_city)
|
||||
);
|
||||
|
||||
// metropolitan airport
|
||||
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
MetropolitanAirport,
|
||||
_airport_terminal_metropolitan,
|
||||
NULL,
|
||||
20,
|
||||
ALL,
|
||||
_airport_fta_metropolitan,
|
||||
_airport_depots_metropolitan,
|
||||
lengthof(_airport_depots_metropolitan)
|
||||
);
|
||||
|
||||
// international airport
|
||||
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
InternationalAirport,
|
||||
_airport_terminal_international,
|
||||
_airport_helipad_international,
|
||||
37,
|
||||
ALL,
|
||||
_airport_fta_international,
|
||||
_airport_depots_international,
|
||||
lengthof(_airport_depots_international)
|
||||
);
|
||||
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
}
|
||||
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
AirportFTAClass_Destructor(Heliport);
|
||||
AirportFTAClass_Destructor(MetropolitanAirport);
|
||||
AirportFTAClass_Destructor(InternationalAirport);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups = 0;
|
||||
byte nofhelipadgroups = 0;
|
||||
const byte * curr;
|
||||
int i;
|
||||
nofterminals = nofhelipads = 0;
|
||||
|
||||
//now we read the number of terminals we have
|
||||
if (terminals != NULL) {
|
||||
i = terminals[0];
|
||||
nofterminalgroups = i;
|
||||
curr = terminals;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //we don't want to have an empty group
|
||||
nofterminals += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->terminals = terminals;
|
||||
|
||||
//read helipads
|
||||
if (helipads != NULL) {
|
||||
i = helipads[0];
|
||||
nofhelipadgroups = i;
|
||||
curr = helipads;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //no empty groups please
|
||||
nofhelipads += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->helipads = helipads;
|
||||
|
||||
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
|
||||
// same goes for helipads
|
||||
if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
|
||||
if (nofhelipads > MAX_HELIPADS) { printf("Currently only maximum of %2d helipads are supported (you wanted %2d)\n", MAX_HELIPADS, nofhelipads);}
|
||||
// terminals/helipads are divided into groups. Groups are computed by dividing the number
|
||||
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
|
||||
// will get the less # of terminals
|
||||
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
|
||||
Airport->nofelements = AirportGetNofElements(FA);
|
||||
// check
|
||||
if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
|
||||
assert(entry_point < Airport->nofelements);
|
||||
|
||||
Airport->acc_planes = acc_planes;
|
||||
Airport->entry_point = entry_point;
|
||||
Airport->airport_depots = depots;
|
||||
Airport->nof_depots = nof_depots;
|
||||
|
||||
|
||||
// build the state machine
|
||||
AirportBuildAutomata(Airport, FA);
|
||||
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d",
|
||||
Airport->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point
|
||||
);
|
||||
|
||||
|
||||
{
|
||||
byte ret = AirportTestFTA(Airport);
|
||||
if (ret != MAX_ELEMENTS) printf("ERROR with element: %d\n", ret - 1);
|
||||
assert(ret == MAX_ELEMENTS);
|
||||
}
|
||||
// print out full information
|
||||
// true -- full info including heading, block, etc
|
||||
// false -- short info, only position and next position
|
||||
//AirportPrintOut(Airport, false);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport)
|
||||
{
|
||||
int i;
|
||||
AirportFTA *current, *next;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = Airport->layout[i].next_in_chain;
|
||||
while (current != NULL) {
|
||||
next = current->next_in_chain;
|
||||
free(current);
|
||||
current = next;
|
||||
};
|
||||
}
|
||||
free(Airport->layout);
|
||||
free(Airport);
|
||||
}
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA)
|
||||
{
|
||||
int i;
|
||||
uint16 nofelements = 0;
|
||||
int temp = FA[0].position;
|
||||
|
||||
for (i = 0; i < MAX_ELEMENTS; i++) {
|
||||
if (temp != FA[i].position) {
|
||||
nofelements++;
|
||||
temp = FA[i].position;
|
||||
}
|
||||
if (FA[i].position == MAX_ELEMENTS) break;
|
||||
}
|
||||
return nofelements;
|
||||
}
|
||||
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA)
|
||||
{
|
||||
AirportFTA *FAutomata;
|
||||
AirportFTA *current;
|
||||
uint16 internalcounter, i;
|
||||
FAutomata = malloc(sizeof(AirportFTA) * Airport->nofelements);
|
||||
Airport->layout = FAutomata;
|
||||
internalcounter = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = &Airport->layout[i];
|
||||
current->position = FA[internalcounter].position;
|
||||
current->heading = FA[internalcounter].heading;
|
||||
current->block = FA[internalcounter].block;
|
||||
current->next_position = FA[internalcounter].next_in_chain;
|
||||
|
||||
// outgoing nodes from the same position, create linked list
|
||||
while (current->position == FA[internalcounter + 1].position) {
|
||||
AirportFTA* newNode = malloc(sizeof(AirportFTA));
|
||||
|
||||
newNode->position = FA[internalcounter + 1].position;
|
||||
newNode->heading = FA[internalcounter + 1].heading;
|
||||
newNode->block = FA[internalcounter + 1].block;
|
||||
newNode->next_position = FA[internalcounter + 1].next_in_chain;
|
||||
// create link
|
||||
current->next_in_chain = newNode;
|
||||
current = current->next_in_chain;
|
||||
internalcounter++;
|
||||
} // while
|
||||
current->next_in_chain = NULL;
|
||||
internalcounter++;
|
||||
}
|
||||
}
|
||||
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport)
|
||||
{
|
||||
byte position, i, next_element;
|
||||
AirportFTA *temp;
|
||||
next_element = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
position = Airport->layout[i].position;
|
||||
if (position != next_element) return i;
|
||||
temp = &Airport->layout[i];
|
||||
|
||||
do {
|
||||
if (temp->heading > MAX_HEADINGS && temp->heading != 255) return i;
|
||||
if (temp->heading == 0 && temp->next_in_chain != 0) return i;
|
||||
if (position != temp->position) return i;
|
||||
if (temp->next_position >= Airport->nofelements) return i;
|
||||
temp = temp->next_in_chain;
|
||||
} while (temp != NULL);
|
||||
next_element++;
|
||||
}
|
||||
return MAX_ELEMENTS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const char* const _airport_heading_strings[] = {
|
||||
"TO_ALL",
|
||||
"HANGAR",
|
||||
"TERM1",
|
||||
"TERM2",
|
||||
"TERM3",
|
||||
"TERM4",
|
||||
"TERM5",
|
||||
"TERM6",
|
||||
"HELIPAD1",
|
||||
"HELIPAD2",
|
||||
"TAKEOFF",
|
||||
"STARTTAKEOFF",
|
||||
"ENDTAKEOFF",
|
||||
"HELITAKEOFF",
|
||||
"FLYING",
|
||||
"LANDING",
|
||||
"ENDLANDING",
|
||||
"HELILANDING",
|
||||
"HELIENDLANDING",
|
||||
"DUMMY" // extra heading for 255
|
||||
};
|
||||
|
||||
static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report)
|
||||
{
|
||||
AirportFTA *temp;
|
||||
uint16 i;
|
||||
byte heading;
|
||||
|
||||
printf("(P = Current Position; NP = Next Position)\n");
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
temp = &Airport->layout[i];
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", temp->position, temp->next_position);
|
||||
}
|
||||
while (temp->next_in_chain != NULL) {
|
||||
temp = temp->next_in_chain;
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", temp->position, temp->next_position);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static byte AirportBlockToString(uint32 block)
|
||||
{
|
||||
byte i = 0;
|
||||
if (block & 0xffff0000) { block >>= 16; i += 16; }
|
||||
if (block & 0x0000ff00) { block >>= 8; i += 8; }
|
||||
if (block & 0x000000f0) { block >>= 4; i += 4; }
|
||||
if (block & 0x0000000c) { block >>= 2; i += 2; }
|
||||
if (block & 0x00000002) { i += 1; }
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
const AirportFTAClass* GetAirport(const byte airport_type)
|
||||
{
|
||||
AirportFTAClass *Airport = NULL;
|
||||
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
// needs constant change if more airports are added
|
||||
switch (airport_type) {
|
||||
case AT_SMALL: Airport = CountryAirport; break;
|
||||
case AT_LARGE: Airport = CityAirport; break;
|
||||
case AT_METROPOLITAN: Airport = MetropolitanAirport; break;
|
||||
case AT_HELIPORT: Airport = Heliport; break;
|
||||
case AT_OILRIG: Airport = Oilrig; break;
|
||||
case AT_INTERNATIONAL: Airport = InternationalAirport; break;
|
||||
default:
|
||||
#ifdef DEBUG__
|
||||
printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n");
|
||||
#endif
|
||||
assert(airport_type <= AT_INTERNATIONAL);
|
||||
}
|
||||
return Airport;
|
||||
}
|
||||
|
||||
uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
// 1980-1-1 is --> 21915
|
||||
// 1990-1-1 is --> 25568
|
||||
if (_date >= 21915) SETBIT(bytemask, 3); // metropilitan airport 1980
|
||||
if (_date >= 25568) SETBIT(bytemask, 4); // international airport 1990
|
||||
return bytemask;
|
||||
}
|
60
airport.h
Normal file
60
airport.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_H
|
||||
#define AIRPORT_H
|
||||
|
||||
#include "airport_movement.h"
|
||||
|
||||
enum {MAX_TERMINALS = 6};
|
||||
enum {MAX_HELIPADS = 2};
|
||||
|
||||
// Airport types
|
||||
enum {
|
||||
AT_SMALL = 0,
|
||||
AT_LARGE = 1,
|
||||
AT_HELIPORT = 2,
|
||||
AT_METROPOLITAN = 3,
|
||||
AT_INTERNATIONAL = 4,
|
||||
AT_OILRIG = 15
|
||||
};
|
||||
|
||||
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
|
||||
enum {
|
||||
AIRCRAFT_ONLY = 0,
|
||||
ALL = 1,
|
||||
HELICOPTERS_ONLY = 2
|
||||
};
|
||||
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAClass {
|
||||
byte nofelements; // number of positions the airport consists of
|
||||
const byte *terminals;
|
||||
const byte *helipads;
|
||||
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
|
||||
byte acc_planes; // accept airplanes or helicopters or both
|
||||
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
|
||||
byte nof_depots; // number of depots this airport has
|
||||
struct AirportFTA *layout; // state machine for airport
|
||||
} AirportFTAClass;
|
||||
|
||||
// internal structure used in openttd - Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTA {
|
||||
byte position; // the position that an airplane is at
|
||||
byte next_position; // next position from this position
|
||||
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
|
||||
byte heading; // heading (current orders), guiding an airplane to its target on an airport
|
||||
struct AirportFTA *next_in_chain; // possible extra movement choices from this position
|
||||
} AirportFTA;
|
||||
|
||||
void InitializeAirports(void);
|
||||
void UnInitializeAirports(void);
|
||||
const AirportFTAClass* GetAirport(const byte airport_type);
|
||||
|
||||
/** Get buildable airport bitmask.
|
||||
* @return get all buildable airports at this given time, bitmasked.
|
||||
* Bit 0 means the small airport is buildable, etc.
|
||||
* @todo set availability of airports by year, instead of airplane
|
||||
*/
|
||||
uint32 GetValidAirports(void);
|
||||
|
||||
#endif /* AIRPORT_H */
|
251
airport_gui.c
Normal file
251
airport_gui.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
#include "station.h"
|
||||
#include "airport.h"
|
||||
#include "depot.h"
|
||||
|
||||
static byte _selected_airport_type;
|
||||
|
||||
static void ShowBuildAirportPicker(void);
|
||||
|
||||
|
||||
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceAirport(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
|
||||
}
|
||||
|
||||
static void PlaceAir_DemolishArea(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, 4);
|
||||
}
|
||||
|
||||
|
||||
static void BuildAirClick_Airport(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 3, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
}
|
||||
|
||||
static void BuildAirClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_air_button_proc[] = {
|
||||
BuildAirClick_Airport,
|
||||
BuildAirClick_Demolish,
|
||||
BuildAirClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget - 3 >= 0)
|
||||
_build_air_button_proc[e->click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch (e->keypress.keycode) {
|
||||
case '1': BuildAirClick_Airport(w); break;
|
||||
case '2': BuildAirClick_Demolish(w); break;
|
||||
case 'l': BuildAirClick_Landscaping(w); break;
|
||||
default: return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG: {
|
||||
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->place.pt.x != -1) {
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(w);
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != 0)
|
||||
WP(w,def_d).close = true;
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _air_toolbar_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static const WindowDesc _air_toolbar_desc = {
|
||||
640-86, 22, 86, 36,
|
||||
WC_BUILD_TOOLBAR,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_air_toolbar_widgets,
|
||||
BuildAirToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildAirToolbar(void)
|
||||
{
|
||||
if (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDescFront(&_air_toolbar_desc, 0);
|
||||
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int sel;
|
||||
int rad = 4; // default catchment radious
|
||||
uint32 avail_airports;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
|
||||
sel = _selected_airport_type;
|
||||
avail_airports = GetValidAirports();
|
||||
|
||||
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
|
||||
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
|
||||
|
||||
/* 'Country Airport' starts at widget 3, and if its bit is set, it is
|
||||
* available, so take its opposite value to set the disabled_state. There
|
||||
* are only 5 available airports, so XOR with 0x1F (1 1111) */
|
||||
w->disabled_state = (avail_airports ^ 0x1F) << 3;
|
||||
|
||||
_selected_airport_type = sel;
|
||||
// select default the coverage area to 'Off' (8)
|
||||
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
|
||||
SetTileSelectSize(_airport_size_x[sel],_airport_size_y[sel]);
|
||||
|
||||
if (_patches.modified_catchment) {
|
||||
switch (sel) {
|
||||
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
|
||||
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
|
||||
case AT_SMALL: rad = CA_AIR_SMALL; break;
|
||||
case AT_LARGE: rad = CA_AIR_LARGE; break;
|
||||
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
|
||||
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
// strings such as 'Size' and 'Coverage Area'
|
||||
DrawStringCentered(74, 16, STR_305B_SIZE, 0);
|
||||
DrawStringCentered(74, 78, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(2, 104, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK: {
|
||||
switch (e->click.widget) {
|
||||
case 3: case 4: case 5: case 6: case 7:
|
||||
_selected_airport_type = e->click.widget - 3;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 8: case 9:
|
||||
_station_show_coverage = e->click.widget - 8;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_MOUSELOOP: {
|
||||
if (WP(w,def_d).close) {
|
||||
DeleteWindow(w);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close) ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_airport_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 130, 0x0, STR_NULL},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_airport_desc = {
|
||||
-1, -1, 148, 131, // height, 130+1
|
||||
WC_BUILD_STATION,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_airport_picker_widgets,
|
||||
BuildAirportPickerWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildAirportPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_airport_desc);
|
||||
}
|
||||
|
||||
void InitializeAirportGui(void)
|
||||
{
|
||||
_selected_airport_type = AT_SMALL;
|
||||
_last_built_aircraft_depot_tile = 0;
|
||||
}
|
469
airport_movement.h
Normal file
469
airport_movement.h
Normal file
@@ -0,0 +1,469 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_MOVEMENT_H
|
||||
#define AIRPORT_MOVEMENT_H
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
typedef struct AirportMovingData {
|
||||
int x,y;
|
||||
byte flag;
|
||||
byte direction;
|
||||
} AirportMovingData;
|
||||
|
||||
// state machine input struct (from external file, etc.)
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAbuildup {
|
||||
byte position; // the position that an airplane is at
|
||||
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
|
||||
uint32 block; // the block this position is on on the airport (st->airport_flags)
|
||||
byte next_in_chain; // next position from this position
|
||||
} AirportFTAbuildup;
|
||||
|
||||
enum {
|
||||
AMED_NOSPDCLAMP = 1<<0,
|
||||
AMED_TAKEOFF = 1<<1,
|
||||
AMED_SLOWTURN = 1<<2,
|
||||
AMED_LAND = 1<<3,
|
||||
AMED_EXACTPOS = 1<<4,
|
||||
AMED_BRAKE = 1<<5,
|
||||
AMED_HELI_RAISE = 1<<6,
|
||||
AMED_HELI_LOWER = 1<<7,
|
||||
};
|
||||
|
||||
enum {MAX_ELEMENTS = 255};
|
||||
enum {MAX_HEADINGS = 18};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////***********Movement States on Airports********************//////
|
||||
// headings target
|
||||
enum {
|
||||
TO_ALL = 0,
|
||||
HANGAR = 1,
|
||||
TERM1 = 2,
|
||||
TERM2 = 3,
|
||||
TERM3 = 4,
|
||||
TERM4 = 5,
|
||||
TERM5 = 6,
|
||||
TERM6 = 7,
|
||||
HELIPAD1 = 8,
|
||||
HELIPAD2 = 9,
|
||||
TAKEOFF = 10,
|
||||
STARTTAKEOFF = 11,
|
||||
ENDTAKEOFF = 12,
|
||||
HELITAKEOFF = 13,
|
||||
FLYING = 14,
|
||||
LANDING = 15,
|
||||
ENDLANDING = 16,
|
||||
HELILANDING = 17,
|
||||
HELIENDLANDING = 18
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////**********Movement Blocks on Airports*********************//////
|
||||
// blocks (eg_airport_flags)
|
||||
enum {
|
||||
TERM1_block = 1 << 0,
|
||||
TERM2_block = 1 << 1,
|
||||
TERM3_block = 1 << 2,
|
||||
TERM4_block = 1 << 3,
|
||||
TERM5_block = 1 << 4,
|
||||
TERM6_block = 1 << 5,
|
||||
HELIPAD1_block = 1 << 6,
|
||||
HELIPAD2_block = 1 << 7,
|
||||
RUNWAY_IN_OUT_block = 1 << 8,
|
||||
RUNWAY_IN_block = 1 << 8,
|
||||
AIRPORT_BUSY_block = 1 << 8,
|
||||
RUNWAY_OUT_block = 1 << 9,
|
||||
TAXIWAY_BUSY_block = 1 << 10,
|
||||
OUT_WAY_block = 1 << 11,
|
||||
IN_WAY_block = 1 << 12,
|
||||
AIRPORT_ENTRANCE_block = 1 << 13,
|
||||
TERM_GROUP1_block = 1 << 14,
|
||||
TERM_GROUP2_block = 1 << 15,
|
||||
HANGAR2_AREA_block = 1 << 16,
|
||||
TERM_GROUP2_ENTER1_block = 1 << 17,
|
||||
TERM_GROUP2_ENTER2_block = 1 << 18,
|
||||
TERM_GROUP2_EXIT1_block = 1 << 19,
|
||||
TERM_GROUP2_EXIT2_block = 1 << 20,
|
||||
PRE_HELIPAD_block = 1 << 21,
|
||||
NOTHING_block = 1 << 30
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////*********Movement Positions on Airports********************///////
|
||||
// Country Airfield (small) 4x3
|
||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||
{ 53, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 53, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 32, 23,AMED_EXACTPOS,7}, // 02 Terminal 1
|
||||
{ 10, 23,AMED_EXACTPOS,7}, // 03 Terminal 2
|
||||
{ 43, 37,0,0}, // 04 Going towards terminal 2
|
||||
{ 24, 37,0,0}, // 05 Going towards terminal 2
|
||||
{ 53, 37,0,0}, // 06 Going for takeoff
|
||||
{ 61, 40,AMED_EXACTPOS,1}, // 07 Taxi to start of runway (takeoff)
|
||||
{ 3, 40,AMED_NOSPDCLAMP,0}, // 08 Accelerate to end of runway
|
||||
{-79, 40,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 09 Take off
|
||||
{177, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 10 Fly to landing position in air
|
||||
{ 56, 40,AMED_NOSPDCLAMP | AMED_LAND,0}, // 11 Going down for land
|
||||
{ 3, 40,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 12 Just landed, brake until end of runway
|
||||
{ 7, 40,0,0}, // 13 Just landed, turn around and taxi 1 square
|
||||
{ 53, 40,0,0}, // 14 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 15 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 16 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 17 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (south)
|
||||
{ 44, 37,AMED_HELI_RAISE,0}, // 19 Helicopter takeoff
|
||||
{ 44, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 In position above landing spot helicopter
|
||||
{ 44, 40,AMED_HELI_LOWER,0} // 21 Helicopter landing
|
||||
};
|
||||
|
||||
// City Airport (large) 6x6
|
||||
static const AirportMovingData _airport_moving_data_town[25] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 80, 27,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 63,0,0}, // 07 Taxi to Airport center
|
||||
{ 58, 71,0,0}, // 08 Towards takeoff
|
||||
{ 72, 85,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 85,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 85,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 85,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 20, 87,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 36, 71,0,0}, // 17 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 22 Helicopter takeoff
|
||||
{ 28, 74,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 23 In position above landing spot helicopter
|
||||
{ 28, 74,AMED_HELI_LOWER,0} // 24 Helicopter landing
|
||||
};
|
||||
|
||||
// Metropolitan Airport (metropolitan) - 2 runways
|
||||
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 70, 33,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 58,0,0}, // 07 Taxi to Airport center
|
||||
{ 72, 58,0,0}, // 08 Towards takeoff
|
||||
{ 72, 69,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 69,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 69,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 69,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 21, 85,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 21, 69,0,0}, // 17 On Runway-out taxiing to In-Way
|
||||
{ 21, 54,AMED_EXACTPOS,5}, // 18 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 22 Fly around waiting for a landing spot (south)
|
||||
{ 44, 58,0,0}, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 24 Helicopter takeoff
|
||||
{ 15, 54,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 25 Get in position above landing spot helicopter
|
||||
{ 15, 54,AMED_HELI_LOWER,0} // 26 Helicopter landing
|
||||
};
|
||||
|
||||
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
|
||||
static const AirportMovingData _airport_moving_data_international[51] = {
|
||||
{ 7, 55,AMED_EXACTPOS,3}, // 00 In Hangar 1
|
||||
{100, 21,AMED_EXACTPOS,3}, // 01 In Hangar 2
|
||||
{ 7, 70,0,0}, // 02 Taxi to right outside depot
|
||||
{100, 36,0,0}, // 03 Taxi to right outside depot
|
||||
{ 38, 70,AMED_EXACTPOS,5}, // 04 Terminal 1
|
||||
{ 38, 54,AMED_EXACTPOS,5}, // 05 Terminal 2
|
||||
{ 38, 38,AMED_EXACTPOS,5}, // 06 Terminal 3
|
||||
{ 70, 70,AMED_EXACTPOS,1}, // 07 Terminal 4
|
||||
{ 70, 54,AMED_EXACTPOS,1}, // 08 Terminal 5
|
||||
{ 70, 38,AMED_EXACTPOS,1}, // 09 Terminal 6
|
||||
{104, 71,AMED_EXACTPOS,1}, // 10 Helipad 1
|
||||
{104, 55,AMED_EXACTPOS,1}, // 11 Helipad 2
|
||||
{ 22, 87,0,0}, // 12 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 60, 87,0,0}, // 13 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 66, 87,0,0}, // 14 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 87,AMED_EXACTPOS,7}, // 15 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 70,0,0}, // 16 In Front of Terminal 4 / Helipad 1
|
||||
{ 86, 54,0,0}, // 17 In Front of Terminal 5 / Helipad 2
|
||||
{ 86, 38,0,0}, // 18 In Front of Terminal 6
|
||||
{ 86, 22,0,0}, // 19 Towards Terminals Takeoff (Taxiway)
|
||||
{ 66, 22,0,0}, // 20 Towards Terminals Takeoff (Taxiway)
|
||||
{ 60, 22,0,0}, // 21 Towards Terminals Takeoff (Taxiway)
|
||||
{ 38, 22,0,0}, // 22 Towards Terminals Takeoff (Taxiway)
|
||||
{ 22, 70,0,0}, // 23 In Front of Terminal 1
|
||||
{ 22, 58,0,0}, // 24 In Front of Terminal 2
|
||||
{ 22, 38,0,0}, // 25 In Front of Terminal 3
|
||||
{ 22, 22,AMED_EXACTPOS,7}, // 26 Going for Takeoff
|
||||
{ 22, 6,0,0}, // 27 On Runway-out, prepare for takeoff
|
||||
{ 3, 6,AMED_EXACTPOS,5}, // 28 Accelerate to end of runway
|
||||
{ 60, 6,AMED_NOSPDCLAMP,0}, // 29 Release control of runway, for smoother movement
|
||||
{105, 6,AMED_NOSPDCLAMP,0}, // 30 End of runway
|
||||
{190, 6,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 31 Take off
|
||||
{193,104,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 32 Fly to landing position in air
|
||||
{105,104,AMED_NOSPDCLAMP | AMED_LAND,0}, // 33 Going down for land
|
||||
{ 3,104,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 34 Just landed, brake until end of runway
|
||||
{ 12,104,0,0}, // 35 Just landed, turn around and taxi 1 square
|
||||
{ 7, 84,0,0}, // 36 Taxi from runway to crossing
|
||||
{-31,209,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 37 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 38 Fly around waiting for a landing spot (north-west)
|
||||
{273, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 39 Fly around waiting for a landing spot (south-west)
|
||||
{305, 81,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 40 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 41 Bufferspace before helipad
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 42 Bufferspace before helipad
|
||||
{ 96, 71,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 43 Get in position for Helipad1
|
||||
{ 96, 55,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 44 Get in position for Helipad2
|
||||
{ 96, 71,AMED_HELI_LOWER,0}, // 45 Land at Helipad1
|
||||
{ 96, 55,AMED_HELI_LOWER,0}, // 46 Land at Helipad2
|
||||
{104, 71,AMED_HELI_RAISE,0}, // 47 Takeoff Helipad1
|
||||
{104, 55,AMED_HELI_RAISE,0}, // 48 Takeoff Helipad2
|
||||
{104, 32,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 49 Go to position for Hangarentrance in air
|
||||
{104, 32,AMED_HELI_LOWER,0} // 50 Land in HANGAR2_AREA to go to hangar
|
||||
};
|
||||
|
||||
// Heliport (heliport)
|
||||
static const AirportMovingData _airport_moving_data_heliport[9] = {
|
||||
{ 5, 9,AMED_EXACTPOS,1}, // 0 - At heliport terminal
|
||||
{ 2, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ -3, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ -3, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 2, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 59,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - Circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - Circle #2 (north-west)
|
||||
{ 49,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - Circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - Circle #4 (south)
|
||||
};
|
||||
|
||||
// Oilrig
|
||||
static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
{ 31, 9,AMED_EXACTPOS,1}, // 0 - At oilrig terminal
|
||||
{ 28, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ 23, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ 23, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 28, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 69,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - circle #2 (north-west)
|
||||
{ 69,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - circle #4 (south)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
// first element of depots array tells us how many depots there are (to know size of array)
|
||||
// this may be changed later when airports are moved to external file
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,AIRPORT_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM1,TERM1_block,2}, {1,TERM2,0,4}, {1,HELITAKEOFF,0,19}, {1,0,0,6},
|
||||
{ 2,TERM1,TERM1_block,1},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,255,AIRPORT_BUSY_block,0}, {4,TERM2,0,5}, {4,HANGAR,0,1}, {4,TAKEOFF,0,6}, {4,HELITAKEOFF,0,1},
|
||||
{ 5,255,AIRPORT_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,0,0,4},
|
||||
{ 6,0,AIRPORT_BUSY_block,7},
|
||||
// takeoff
|
||||
{ 7,TAKEOFF,AIRPORT_BUSY_block,8},
|
||||
{ 8,STARTTAKEOFF,NOTHING_block,9},
|
||||
{ 9,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{10,FLYING,NOTHING_block,15}, {10,LANDING,0,11}, {10,HELILANDING,0,20},
|
||||
{11,LANDING,AIRPORT_BUSY_block,12},
|
||||
{12,0,AIRPORT_BUSY_block,13},
|
||||
{13,ENDLANDING,AIRPORT_BUSY_block,14}, {13,TERM2,0,5}, {13,0,0,14},
|
||||
{14,0,AIRPORT_BUSY_block,1},
|
||||
// In air
|
||||
{15,0,NOTHING_block,16},
|
||||
{16,0,NOTHING_block,17},
|
||||
{17,0,NOTHING_block,18},
|
||||
{18,0,NOTHING_block,10},
|
||||
{19,HELITAKEOFF,NOTHING_block,0},
|
||||
{20,HELILANDING,AIRPORT_BUSY_block,21},
|
||||
{21,HELIENDLANDING,AIRPORT_BUSY_block,1},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_city[] = {{5, 0}};
|
||||
static const byte _airport_terminal_city[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1}, {0,TAKEOFF,OUT_WAY_block,1}, {0,0,0,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7}, {2,TAKEOFF,OUT_WAY_block,7}, {2,0,0,7},
|
||||
{ 3,TERM2,TERM2_block,5}, {3,TAKEOFF,OUT_WAY_block,5}, {3,0,0,5},
|
||||
{ 4,TERM3,TERM3_block,5}, {4,TAKEOFF,OUT_WAY_block,5}, {4,0,0,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,OUT_WAY_block,8}, {7,HELITAKEOFF,0,22}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_IN_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_IN_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,18}, {13,LANDING,0,14}, {13,HELILANDING,0,23},
|
||||
{14,LANDING,RUNWAY_IN_OUT_block,15},
|
||||
{15,0,RUNWAY_IN_OUT_block,16},
|
||||
{16,0,RUNWAY_IN_OUT_block,17},
|
||||
{17,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{18,0,NOTHING_block,19},
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{22,HELITAKEOFF,NOTHING_block,0},
|
||||
{23,HELILANDING,IN_WAY_block,24},
|
||||
{24,HELIENDLANDING,IN_WAY_block,17},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = {{5, 0}};
|
||||
static const byte _airport_terminal_metropolitan[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,TERM3,TERM3_block,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,0,8}, {7,HELITAKEOFF,0,23}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,19}, {13,LANDING,0,14}, {13,HELILANDING,0,25},
|
||||
{14,LANDING,RUNWAY_IN_block,15},
|
||||
{15,0,RUNWAY_IN_block,16},
|
||||
{16,255,RUNWAY_IN_block,0}, {16,ENDLANDING,IN_WAY_block,17},
|
||||
{17,255,RUNWAY_OUT_block,0}, {17,ENDLANDING,IN_WAY_block,18},
|
||||
{18,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,22},
|
||||
{22,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{23,0,NOTHING_block,24},
|
||||
{24,HELITAKEOFF,NOTHING_block,0},
|
||||
{25,HELILANDING,IN_WAY_block,26},
|
||||
{26,HELIENDLANDING,IN_WAY_block,18},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_international[] = {{0, 3}, {6, 1}};
|
||||
static const byte _airport_terminal_international[] = {2, 3, 3};
|
||||
static const byte _airport_helipad_international[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0,HANGAR,NOTHING_block,2}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER1_block,1}, {0,HELITAKEOFF,HELIPAD1_block,2}, {0,0,0,2},
|
||||
{ 1,HANGAR,NOTHING_block,3}, {1,255,HANGAR2_AREA_block,1}, {1,HELITAKEOFF,HELIPAD2_block,3}, {1,0,0,3},
|
||||
{ 2,255,AIRPORT_ENTRANCE_block,0}, {2,HANGAR,0,0}, {2,TERM4,0,12}, {2,TERM5,0,12}, {2,TERM6,0,12}, {2,HELIPAD1,0,12}, {2,HELIPAD2,0,12}, {2,HELITAKEOFF,0,12}, {2,0,0,23},
|
||||
{ 3,255,HANGAR2_AREA_block,0}, {3,HANGAR,0,1}, {3,0,0,18},
|
||||
{ 4,TERM1,TERM1_block,23}, {4,HANGAR,AIRPORT_ENTRANCE_block,23}, {4,0,0,23},
|
||||
{ 5,TERM2,TERM2_block,24}, {5,HANGAR,AIRPORT_ENTRANCE_block,24}, {5,0,0,24},
|
||||
{ 6,TERM3,TERM3_block,25}, {6,HANGAR,AIRPORT_ENTRANCE_block,25}, {6,0,0,25},
|
||||
{ 7,TERM4,TERM4_block,16}, {7,HANGAR,HANGAR2_AREA_block,16}, {7,0,0,16},
|
||||
{ 8,TERM5,TERM5_block,17}, {8,HANGAR,HANGAR2_AREA_block,17}, {8,0,0,17},
|
||||
{ 9,TERM6,TERM6_block,18}, {9,HANGAR,HANGAR2_AREA_block,18}, {9,0,0,18},
|
||||
{10,HELIPAD1,HELIPAD1_block,10}, {10,HANGAR,HANGAR2_AREA_block,16}, {10,HELITAKEOFF,0,47},
|
||||
{11,HELIPAD2,HELIPAD2_block,11}, {11,HANGAR,HANGAR2_AREA_block,17}, {11,HELITAKEOFF,0,48},
|
||||
{12,0,TERM_GROUP2_ENTER1_block,13},
|
||||
{13,0,TERM_GROUP2_ENTER1_block,14},
|
||||
{14,0,TERM_GROUP2_ENTER2_block,15},
|
||||
{15,0,TERM_GROUP2_ENTER2_block,16},
|
||||
{16,255,TERM_GROUP2_block,0}, {16,TERM4,TERM4_block,7}, {16,HELIPAD1,HELIPAD1_block,10}, {16,HELITAKEOFF,HELIPAD1_block,10}, {16,0,0,17},
|
||||
{17,255,TERM_GROUP2_block,0}, {17,TERM5,TERM5_block,8}, {17,TERM4,0,16}, {17,HELIPAD1,0,16}, {17,HELIPAD2,HELIPAD2_block,11}, {17,HELITAKEOFF,HELIPAD2_block,11}, {17,0,0,18},
|
||||
{18,255,TERM_GROUP2_block,0}, {18,TERM6,TERM6_block,9}, {18,TAKEOFF,0,19}, {18,HANGAR,HANGAR2_AREA_block,3}, {18,0,0,17},
|
||||
{19,0,TERM_GROUP2_EXIT1_block,20},
|
||||
{20,0,TERM_GROUP2_EXIT1_block,21},
|
||||
{21,0,TERM_GROUP2_EXIT2_block,22},
|
||||
{22,0,TERM_GROUP2_EXIT2_block,26},
|
||||
{23,255,TERM_GROUP1_block,0}, {23,TERM1,TERM1_block,4}, {23,HANGAR,AIRPORT_ENTRANCE_block,2}, {23,0,0,24},
|
||||
{24,255,TERM_GROUP1_block,0}, {24,TERM2,TERM2_block,5}, {24,TERM1,0,23}, {24,HANGAR,0,23}, {24,0,0,25},
|
||||
{25,255,TERM_GROUP1_block,0}, {25,TERM3,TERM3_block,6}, {25,TAKEOFF,0,26}, {25,0,0,24},
|
||||
{26,255,TAXIWAY_BUSY_block,0}, {26,TAKEOFF,0,27}, {26,0,0,25},
|
||||
{27,0,OUT_WAY_block,28},
|
||||
// takeoff
|
||||
{28,TAKEOFF,OUT_WAY_block,29},
|
||||
{29,0,RUNWAY_OUT_block,30},
|
||||
{30,STARTTAKEOFF,NOTHING_block,31},
|
||||
{31,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{32,FLYING,NOTHING_block,37}, {32,LANDING,0,33}, {32,HELILANDING,0,41},
|
||||
{33,LANDING,RUNWAY_IN_block,34},
|
||||
{34,0,RUNWAY_IN_block,35},
|
||||
{35,0,RUNWAY_IN_block,36},
|
||||
{36,ENDLANDING,IN_WAY_block,36}, {36,255,TERM_GROUP1_block,0}, {36,255,TERM_GROUP2_ENTER1_block,1}, {36,TERM4,0,12}, {36,TERM5,0,12}, {36,TERM6,0,12}, {36,0,0,2},
|
||||
// In Air
|
||||
{37,0,NOTHING_block,38},
|
||||
{38,0,NOTHING_block,39},
|
||||
{39,0,NOTHING_block,40},
|
||||
{40,0,NOTHING_block,32},
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{41,HELILANDING,PRE_HELIPAD_block,42},
|
||||
{42,HELIENDLANDING,PRE_HELIPAD_block,42}, {42,HELIPAD1,0,43}, {42,HELIPAD2,0,44}, {42,HANGAR,0,49},
|
||||
{43,0,NOTHING_block,45},
|
||||
{44,0,NOTHING_block,46},
|
||||
// landing
|
||||
{45,255,NOTHING_block,0}, {45,HELIPAD1,HELIPAD1_block,10},
|
||||
{46,255,NOTHING_block,0}, {46,HELIPAD2,HELIPAD2_block,11},
|
||||
// Helicopter -- takeoff
|
||||
{47,HELITAKEOFF,NOTHING_block,0},
|
||||
{48,HELITAKEOFF,NOTHING_block,0},
|
||||
{49,0,HANGAR2_AREA_block,50}, // need to go to hangar when waiting in air
|
||||
{50,0,HANGAR2_AREA_block,3},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = {1, 1};
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{0,HELIPAD1,HELIPAD1_block,1},
|
||||
{1,HELITAKEOFF,NOTHING_block,0}, // takeoff
|
||||
{2,255,AIRPORT_BUSY_block,0}, {2,HELILANDING,0,3}, {2,HELITAKEOFF,0,1},
|
||||
{3,HELILANDING,AIRPORT_BUSY_block,4},
|
||||
{4,HELIENDLANDING,AIRPORT_BUSY_block,4}, {4,HELIPAD1,HELIPAD1_block,0}, {4,HELITAKEOFF,0,2},
|
||||
// In Air
|
||||
{5,0,NOTHING_block,6},
|
||||
{6,0,NOTHING_block,7},
|
||||
{7,0,NOTHING_block,8},
|
||||
{8,FLYING,NOTHING_block,5}, {8,HELILANDING,HELIPAD1_block,2}, // landing
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
#endif /* AIRPORT_MOVEMENT_H */
|
280
aystar.c
Normal file
280
aystar.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file has the core function for AyStar
|
||||
* AyStar is a fast pathfinding routine and is used for things like
|
||||
* AI_pathfinding and Train_pathfinding.
|
||||
* For more information about AyStar (A* Algorithm), you can look at
|
||||
* http://en.wikipedia.org/wiki/A-star_search_algorithm
|
||||
*/
|
||||
|
||||
/*
|
||||
* Friendly reminder:
|
||||
* Call (AyStar).free() when you are done with Aystar. It reserves a lot of memory
|
||||
* And when not free'd, it can cause system-crashes.
|
||||
* Also remember that when you stop an algorithm before it is finished, your
|
||||
* should call clear() yourself!
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "aystar.h"
|
||||
// This looks in the Hash if a node exists in ClosedList
|
||||
// If so, it returns the PathNode, else NULL
|
||||
static PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
// This adds a node to the ClosedList
|
||||
// It makes a copy of the data
|
||||
static void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node)
|
||||
{
|
||||
// Add a node to the ClosedList
|
||||
PathNode *new_node = malloc(sizeof(PathNode));
|
||||
*new_node = *node;
|
||||
Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
|
||||
}
|
||||
|
||||
// Checks if a node is in the OpenList
|
||||
// If so, it returns the OpenListNode, else NULL
|
||||
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
// Gets the best node from OpenList
|
||||
// returns the best node, or NULL of none is found
|
||||
// Also it deletes the node from the OpenList
|
||||
static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
|
||||
{
|
||||
// Return the item the Queue returns.. the best next OpenList item.
|
||||
OpenListNode* res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
|
||||
if (res != NULL)
|
||||
Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Adds a node to the OpenList
|
||||
// It makes a copy of node, and puts the pointer of parent in the struct
|
||||
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g)
|
||||
{
|
||||
// Add a new Node to the OpenList
|
||||
OpenListNode* new_node = malloc(sizeof(OpenListNode));
|
||||
new_node->g = g;
|
||||
new_node->path.parent = parent;
|
||||
new_node->path.node = *node;
|
||||
Hash_Set(&aystar->OpenListHash, node->tile, node->direction, new_node);
|
||||
|
||||
// Add it to the queue
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks one tile and calculate his f-value
|
||||
* return values:
|
||||
* AYSTAR_DONE : indicates we are done
|
||||
*/
|
||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
|
||||
int new_f, new_g, new_h;
|
||||
PathNode *closedlist_parent;
|
||||
OpenListNode *check;
|
||||
|
||||
// Check the new node against the ClosedList
|
||||
if (AyStarMain_ClosedList_IsInList(aystar, current) != NULL) return AYSTAR_DONE;
|
||||
|
||||
// Calculate the G-value for this node
|
||||
new_g = aystar->CalculateG(aystar, current, parent);
|
||||
// If the value was INVALID_NODE, we don't do anything with this node
|
||||
if (new_g == AYSTAR_INVALID_NODE) return AYSTAR_DONE;
|
||||
|
||||
// There should not be given any other error-code..
|
||||
assert(new_g >= 0);
|
||||
// Add the parent g-value to the new g-value
|
||||
new_g += parent->g;
|
||||
if (aystar->max_path_cost != 0 && (uint)new_g > aystar->max_path_cost) return AYSTAR_DONE;
|
||||
|
||||
// Calculate the h-value
|
||||
new_h = aystar->CalculateH(aystar, current, parent);
|
||||
// There should not be given any error-code..
|
||||
assert(new_h >= 0);
|
||||
|
||||
// The f-value if g + h
|
||||
new_f = new_g + new_h;
|
||||
|
||||
// Get the pointer to the parent in the ClosedList (the currentone is to a copy of the one in the OpenList)
|
||||
closedlist_parent = AyStarMain_ClosedList_IsInList(aystar, &parent->path.node);
|
||||
|
||||
// Check if this item is already in the OpenList
|
||||
if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
|
||||
uint i;
|
||||
// Yes, check if this g value is lower..
|
||||
if (new_g > check->g) return AYSTAR_DONE;
|
||||
aystar->OpenListQueue.del(&aystar->OpenListQueue, check, 0);
|
||||
// It is lower, so change it to this item
|
||||
check->g = new_g;
|
||||
check->path.parent = closedlist_parent;
|
||||
/* Copy user data, will probably have changed */
|
||||
for (i=0;i<lengthof(current->user_data);i++)
|
||||
check->path.node.user_data[i] = current->user_data[i];
|
||||
// Readd him in the OpenListQueue
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
|
||||
} else {
|
||||
// A new node, add him to the OpenList
|
||||
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
|
||||
}
|
||||
|
||||
return AYSTAR_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is the core of AyStar. It handles one item and checks
|
||||
* his neighbour items. If they are valid, they are added to be checked too.
|
||||
* return values:
|
||||
* AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
|
||||
* has been found.
|
||||
* AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
|
||||
* reached.
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
|
||||
*/
|
||||
int AyStarMain_Loop(AyStar *aystar) {
|
||||
int i, r;
|
||||
|
||||
// Get the best node from OpenList
|
||||
OpenListNode *current = AyStarMain_OpenList_Pop(aystar);
|
||||
// If empty, drop an error
|
||||
if (current == NULL) return AYSTAR_EMPTY_OPENLIST;
|
||||
|
||||
// Check for end node and if found, return that code
|
||||
if (aystar->EndNodeCheck(aystar, current) == AYSTAR_FOUND_END_NODE) {
|
||||
if (aystar->FoundEndNode != NULL)
|
||||
aystar->FoundEndNode(aystar, current);
|
||||
free(current);
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
}
|
||||
|
||||
// Add the node to the ClosedList
|
||||
AyStarMain_ClosedList_Add(aystar, ¤t->path);
|
||||
|
||||
// Load the neighbours
|
||||
aystar->GetNeighbours(aystar, current);
|
||||
|
||||
// Go through all neighbours
|
||||
for (i=0;i<aystar->num_neighbours;i++) {
|
||||
// Check and add them to the OpenList if needed
|
||||
r = aystar->checktile(aystar, &aystar->neighbours[i], current);
|
||||
}
|
||||
|
||||
// Free the node
|
||||
free(current);
|
||||
|
||||
if (aystar->max_search_nodes != 0 && Hash_Size(&aystar->ClosedListHash) >= aystar->max_search_nodes)
|
||||
/* We've expanded enough nodes */
|
||||
return AYSTAR_LIMIT_REACHED;
|
||||
else
|
||||
// Return that we are still busy
|
||||
return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function frees the memory it allocated
|
||||
*/
|
||||
void AyStarMain_Free(AyStar *aystar) {
|
||||
aystar->OpenListQueue.free(&aystar->OpenListQueue, false);
|
||||
/* 2nd argument above is false, below is true, to free the values only
|
||||
* once */
|
||||
delete_Hash(&aystar->OpenListHash, true);
|
||||
delete_Hash(&aystar->ClosedListHash, true);
|
||||
#ifdef AYSTAR_DEBUG
|
||||
printf("[AyStar] Memory free'd\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This function make the memory go back to zero
|
||||
* This function should be called when you are using the same instance again.
|
||||
*/
|
||||
void AyStarMain_Clear(AyStar *aystar) {
|
||||
// Clean the Queue, but not the elements within. That will be done by
|
||||
// the hash.
|
||||
aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
|
||||
// Clean the hashes
|
||||
clear_Hash(&aystar->OpenListHash, true);
|
||||
clear_Hash(&aystar->ClosedListHash, true);
|
||||
|
||||
#ifdef AYSTAR_DEBUG
|
||||
printf("[AyStar] Cleared AyStar\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the function you call to run AyStar.
|
||||
* return values:
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found an end node.
|
||||
* AYSTAR_NO_PATH : indicates that there was no path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
|
||||
* When the algorithm is done (when the return value is not AYSTAR_STILL_BUSY)
|
||||
* aystar->clear() is called. Note that when you stop the algorithm halfway,
|
||||
* you should still call clear() yourself!
|
||||
*/
|
||||
int AyStarMain_Main(AyStar *aystar) {
|
||||
int r, i = 0;
|
||||
// Loop through the OpenList
|
||||
// Quit if result is no AYSTAR_STILL_BUSY or is more than loops_per_tick
|
||||
while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
|
||||
#ifdef AYSTAR_DEBUG
|
||||
if (r == AYSTAR_FOUND_END_NODE)
|
||||
printf("[AyStar] Found path!\n");
|
||||
else if (r == AYSTAR_EMPTY_OPENLIST)
|
||||
printf("[AyStar] OpenList run dry, no path found\n");
|
||||
else if (r == AYSTAR_LIMIT_REACHED)
|
||||
printf("[AyStar] Exceeded search_nodes, no path found\n");
|
||||
#endif
|
||||
if (r != AYSTAR_STILL_BUSY)
|
||||
/* We're done, clean up */
|
||||
aystar->clear(aystar);
|
||||
|
||||
// Check result-value
|
||||
if (r == AYSTAR_FOUND_END_NODE) return AYSTAR_FOUND_END_NODE;
|
||||
// Check if we have some left in the OpenList
|
||||
if (r == AYSTAR_EMPTY_OPENLIST || r == AYSTAR_LIMIT_REACHED) return AYSTAR_NO_PATH;
|
||||
|
||||
// Return we are still busy
|
||||
return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a node from where to start an algorithm. Multiple nodes can be added
|
||||
* if wanted. You should make sure that clear() is called before adding nodes
|
||||
* if the AyStar has been used before (though the normal main loop calls
|
||||
* clear() automatically when the algorithm finishes
|
||||
* g is the cost for starting with this node.
|
||||
*/
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g) {
|
||||
#ifdef AYSTAR_DEBUG
|
||||
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
|
||||
TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
|
||||
#endif
|
||||
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
|
||||
}
|
||||
|
||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
|
||||
// Allocated the Hash for the OpenList and ClosedList
|
||||
init_Hash(&aystar->OpenListHash, hash, num_buckets);
|
||||
init_Hash(&aystar->ClosedListHash, hash, num_buckets);
|
||||
|
||||
// Set up our sorting queue
|
||||
// BinaryHeap allocates a block of 1024 nodes
|
||||
// When thatone gets full it reserves an otherone, till this number
|
||||
// That is why it can stay this high
|
||||
init_BinaryHeap(&aystar->OpenListQueue, 102400);
|
||||
|
||||
aystar->addstart = AyStarMain_AddStartNode;
|
||||
aystar->main = AyStarMain_Main;
|
||||
aystar->loop = AyStarMain_Loop;
|
||||
aystar->free = AyStarMain_Free;
|
||||
aystar->clear = AyStarMain_Clear;
|
||||
aystar->checktile = AyStarMain_CheckTile;
|
||||
}
|
179
aystar.h
Normal file
179
aystar.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file has the header for AyStar
|
||||
* AyStar is a fast pathfinding routine and is used for things like
|
||||
* AI_pathfinding and Train_pathfinding.
|
||||
* For more information about AyStar (A* Algorithm), you can look at
|
||||
* http://en.wikipedia.org/wiki/A-star_search_algorithm
|
||||
*/
|
||||
|
||||
#ifndef AYSTAR_H
|
||||
#define AYSTAR_H
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
//#define AYSTAR_DEBUG
|
||||
enum {
|
||||
AYSTAR_FOUND_END_NODE,
|
||||
AYSTAR_EMPTY_OPENLIST,
|
||||
AYSTAR_STILL_BUSY,
|
||||
AYSTAR_NO_PATH,
|
||||
AYSTAR_LIMIT_REACHED,
|
||||
AYSTAR_DONE
|
||||
};
|
||||
|
||||
enum{
|
||||
AYSTAR_INVALID_NODE = -1,
|
||||
};
|
||||
|
||||
typedef struct AyStarNode AyStarNode;
|
||||
struct AyStarNode {
|
||||
TileIndex tile;
|
||||
uint direction;
|
||||
uint user_data[2];
|
||||
};
|
||||
|
||||
// The resulting path has nodes looking like this.
|
||||
typedef struct PathNode PathNode;
|
||||
struct PathNode {
|
||||
AyStarNode node;
|
||||
// The parent of this item
|
||||
PathNode *parent;
|
||||
};
|
||||
|
||||
// For internal use only
|
||||
// We do not save the h-value, because it is only needed to calculate the f-value.
|
||||
// h-value should _always_ be the distance left to the end-tile.
|
||||
typedef struct OpenListNode OpenListNode;
|
||||
struct OpenListNode {
|
||||
int g;
|
||||
PathNode path;
|
||||
};
|
||||
|
||||
typedef struct AyStar AyStar;
|
||||
/*
|
||||
* This function is called to check if the end-tile is found
|
||||
* return values can be:
|
||||
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
|
||||
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
|
||||
*/
|
||||
/*
|
||||
* The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is
|
||||
* part of OpenListNode and so it could be accessed without any problems.
|
||||
* The good part about OpenListNode is, and how AIs use it, that you can
|
||||
* access the parent of the current node, and so check if you, for example
|
||||
* don't try to enter the file tile with a 90-degree curve. So please, leave
|
||||
* this an OpenListNode, it works just fine -- TrueLight
|
||||
*/
|
||||
typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
/*
|
||||
* This function is called to calculate the G-value for AyStar Algorithm.
|
||||
* return values can be:
|
||||
* AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable)
|
||||
* Any value >= 0 : the g-value for this tile
|
||||
*/
|
||||
typedef int32 AyStar_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
|
||||
/*
|
||||
* This function is called to calculate the H-value for AyStar Algorithm.
|
||||
* Mostly, this must result the distance (Manhattan way) between the
|
||||
* current point and the end point
|
||||
* return values can be:
|
||||
* Any value >= 0 : the h-value for this tile
|
||||
*/
|
||||
typedef int32 AyStar_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
|
||||
/*
|
||||
* This function request the tiles around the current tile and put them in tiles_around
|
||||
* tiles_around is never resetted, so if you are not using directions, just leave it alone.
|
||||
* Warning: never add more tiles_around than memory allocated for it.
|
||||
*/
|
||||
typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
/*
|
||||
* If the End Node is found, this function is called.
|
||||
* It can do, for example, calculate the route and put that in an array
|
||||
*/
|
||||
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
// For internal use, see aystar.c
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node, uint g);
|
||||
typedef int AyStar_Main(AyStar *aystar);
|
||||
typedef int AyStar_Loop(AyStar *aystar);
|
||||
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
typedef void AyStar_Free(AyStar *aystar);
|
||||
typedef void AyStar_Clear(AyStar *aystar);
|
||||
|
||||
struct AyStar {
|
||||
/* These fields should be filled before initting the AyStar, but not changed
|
||||
* afterwards (except for user_data and user_path)! (free and init again to change them) */
|
||||
|
||||
/* These should point to the application specific routines that do the
|
||||
* actual work */
|
||||
AyStar_CalculateG* CalculateG;
|
||||
AyStar_CalculateH* CalculateH;
|
||||
AyStar_GetNeighbours* GetNeighbours;
|
||||
AyStar_EndNodeCheck* EndNodeCheck;
|
||||
AyStar_FoundEndNode* FoundEndNode;
|
||||
|
||||
/* These are completely untouched by AyStar, they can be accesed by
|
||||
* the application specific routines to input and output data.
|
||||
* user_path should typically contain data about the resulting path
|
||||
* afterwards, user_target should typically contain information about
|
||||
* what where looking for, and user_data can contain just about
|
||||
* everything */
|
||||
void *user_path;
|
||||
void *user_target;
|
||||
uint user_data[10];
|
||||
|
||||
/* How many loops are there called before AyStarMain_Main gives
|
||||
* control back to the caller. 0 = until done */
|
||||
byte loops_per_tick;
|
||||
/* If the g-value goes over this number, it stops searching
|
||||
* 0 = infinite */
|
||||
uint max_path_cost;
|
||||
/* The maximum amount of nodes that will be expanded, 0 = infinite */
|
||||
uint max_search_nodes;
|
||||
|
||||
/* These should be filled with the neighbours of a tile by
|
||||
* GetNeighbours */
|
||||
AyStarNode neighbours[12];
|
||||
byte num_neighbours;
|
||||
|
||||
/* These will contain the methods for manipulating the AyStar. Only
|
||||
* main() should be called externally */
|
||||
AyStar_AddStartNode* addstart;
|
||||
AyStar_Main* main;
|
||||
AyStar_Loop* loop;
|
||||
AyStar_Free* free;
|
||||
AyStar_Clear* clear;
|
||||
AyStar_CheckTile* checktile;
|
||||
|
||||
/* These will contain the open and closed lists */
|
||||
|
||||
/* The actual closed list */
|
||||
Hash ClosedListHash;
|
||||
/* The open queue */
|
||||
Queue OpenListQueue;
|
||||
/* An extra hash to speed up the process of looking up an element in
|
||||
* the open list */
|
||||
Hash OpenListHash;
|
||||
};
|
||||
|
||||
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
|
||||
int AyStarMain_Main(AyStar *aystar);
|
||||
int AyStarMain_Loop(AyStar *aystar);
|
||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
void AyStarMain_Free(AyStar *aystar);
|
||||
void AyStarMain_Clear(AyStar *aystar);
|
||||
|
||||
/* Initialize an AyStar. You should fill all appropriate fields before
|
||||
* callling init_AyStar (see the declaration of AyStar for which fields are
|
||||
* internal */
|
||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets);
|
||||
|
||||
|
||||
#endif /* AYSTAR_H */
|
@@ -1,381 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("0.7 API compatibility in effect:");
|
||||
AILog.Info(" - AITown::GetLastMonthProduction's behaviour has slightly changed.");
|
||||
AILog.Info(" - AISubsidy::GetDestination returns STATION_INVALID for awarded subsidies.");
|
||||
AILog.Info(" - AISubsidy::GetSource returns STATION_INVALID for awarded subsidies.");
|
||||
|
||||
AISign.GetMaxSignID <- function()
|
||||
{
|
||||
local list = AISignList();
|
||||
local max_id = 0;
|
||||
foreach (id, d in list) {
|
||||
if (id > max_id) max_id = id;
|
||||
}
|
||||
return max_id;
|
||||
}
|
||||
|
||||
AITile.GetHeight <- function(tile)
|
||||
{
|
||||
if (!AIMap.IsValidTile(tile)) return -1;
|
||||
|
||||
return AITile.GetCornerHeight(tile, AITile.CORNER_N);
|
||||
}
|
||||
|
||||
AIOrder.ChangeOrder <- function(vehicle_id, order_position, order_flags)
|
||||
{
|
||||
return AIOrder.SetOrderFlags(vehicle_id, order_position, order_flags);
|
||||
}
|
||||
|
||||
AIWaypoint.WAYPOINT_INVALID <- 0xFFFF;
|
||||
|
||||
AISubsidy.SourceIsTown <- function(subsidy_id)
|
||||
{
|
||||
if (!AISubsidy.IsValidSubsidy(subsidy_id) || AISubsidy.IsAwarded(subsidy_id)) return false;
|
||||
|
||||
return AISubsidy.GetSourceType(subsidy_id) == AISubsidy.SPT_TOWN;
|
||||
}
|
||||
|
||||
AISubsidy.GetSource <- function(subsidy_id)
|
||||
{
|
||||
if (!AISubsidy.IsValidSubsidy(subsidy_id)) return AIBaseStation.STATION_INVALID;
|
||||
|
||||
if (AISubsidy.IsAwarded(subsidy_id)) {
|
||||
return AIBaseStation.STATION_INVALID;
|
||||
}
|
||||
|
||||
return AISubsidy.GetSourceIndex(subsidy_id);
|
||||
}
|
||||
|
||||
AISubsidy.DestinationIsTown <- function(subsidy_id)
|
||||
{
|
||||
if (!AISubsidy.IsValidSubsidy(subsidy_id) || AISubsidy.IsAwarded(subsidy_id)) return false;
|
||||
|
||||
return AISubsidy.GetDestinationType(subsidy_id) == AISubsidy.SPT_TOWN;
|
||||
}
|
||||
|
||||
AISubsidy.GetDestination <- function(subsidy_id)
|
||||
{
|
||||
if (!AISubsidy.IsValidSubsidy(subsidy_id)) return AIBaseStation.STATION_INVALID;
|
||||
|
||||
if (AISubsidy.IsAwarded(subsidy_id)) {
|
||||
return AIBaseStation.STATION_INVALID;
|
||||
}
|
||||
|
||||
return AISubsidy.GetDestinationIndex(subsidy_id);
|
||||
}
|
||||
|
||||
AITown.GetMaxProduction <- function(town_id, cargo_id)
|
||||
{
|
||||
return AITown.GetLastMonthProduction(town_id, cargo_id);
|
||||
}
|
||||
|
||||
AIRail.RemoveRailWaypoint <- function(tile)
|
||||
{
|
||||
return AIRail.RemoveRailWaypointTileRect(tile, tile, true);
|
||||
}
|
||||
|
||||
AIRail.RemoveRailStationTileRect <- function(tile, tile2)
|
||||
{
|
||||
return AIRail.RemoveRailStationTileRectangle(tile, tile2, false);
|
||||
}
|
||||
|
||||
AIVehicle.SkipToVehicleOrder <- function(vehicle_id, order_position)
|
||||
{
|
||||
return AIOrder.SkipToOrder(vehicle_id, order_position);
|
||||
}
|
||||
|
||||
AIEngine.IsValidEngine <- function(engine_id)
|
||||
{
|
||||
return AIEngine.IsBuildable(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetName <- AIEngine.GetName;
|
||||
AIEngine.GetName <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return null;
|
||||
return AIEngine._GetName(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetCargoType <- AIEngine.GetCargoType;
|
||||
AIEngine.GetCargoType <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return 255;
|
||||
return AIEngine._GetCargoType(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._CanRefitCargo <- AIEngine.CanRefitCargo;
|
||||
AIEngine.CanRefitCargo <- function(engine_id, cargo_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._CanRefitCargo(engine_id, cargo_id);
|
||||
}
|
||||
|
||||
AIEngine._CanPullCargo <- AIEngine.CanPullCargo;
|
||||
AIEngine.CanPullCargo <- function(engine_id, cargo_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._CanPullCargo(engine_id, cargo_id);
|
||||
}
|
||||
|
||||
AIEngine._GetCapacity <- AIEngine.GetCapacity;
|
||||
AIEngine.GetCapacity <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetCapacity(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetReliability <- AIEngine.GetReliability;
|
||||
AIEngine.GetReliability <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetReliability(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetMaxSpeed <- AIEngine.GetMaxSpeed;
|
||||
AIEngine.GetMaxSpeed <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetMaxSpeed(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetPrice <- AIEngine.GetPrice;
|
||||
AIEngine.GetPrice <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetPrice(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetMaxAge <- AIEngine.GetMaxAge;
|
||||
AIEngine.GetMaxAge <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetMaxAge(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetRunningCost <- AIEngine.GetRunningCost;
|
||||
AIEngine.GetRunningCost <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetRunningCost(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetPower <- AIEngine.GetPower;
|
||||
AIEngine.GetPower <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetPower(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetWeight <- AIEngine.GetWeight;
|
||||
AIEngine.GetWeight <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetWeight(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetMaxTractiveEffort <- AIEngine.GetMaxTractiveEffort;
|
||||
AIEngine.GetMaxTractiveEffort <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetMaxTractiveEffort(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetDesignDate <- AIEngine.GetDesignDate;
|
||||
AIEngine.GetDesignDate <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetDesignDate(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetVehicleType <- AIEngine.GetVehicleType;
|
||||
AIEngine.GetVehicleType <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return AIVehicle.VT_INVALID;
|
||||
return AIEngine._GetVehicleType(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._IsWagon <- AIEngine.IsWagon;
|
||||
AIEngine.IsWagon <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._IsWagon(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._CanRunOnRail <- AIEngine.CanRunOnRail;
|
||||
AIEngine.CanRunOnRail <- function(engine_id, track_rail_type)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._CanRunOnRail(engine_id, track_rail_type);
|
||||
}
|
||||
|
||||
AIEngine._HasPowerOnRail <- AIEngine.HasPowerOnRail;
|
||||
AIEngine.HasPowerOnRail <- function(engine_id, track_rail_type)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._HasPowerOnRail(engine_id, track_rail_type);
|
||||
}
|
||||
|
||||
AIEngine._GetRoadType <- AIEngine.GetRoadType;
|
||||
AIEngine.GetRoadType <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return AIRoad.ROADTYPE_INVALID;
|
||||
return AIEngine._GetRoadType(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetRailType <- AIEngine.GetRailType;
|
||||
AIEngine.GetRailType <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return AIRail.RAILTYPE_INVALID;
|
||||
return AIEngine._GetRailType(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._IsArticulated <- AIEngine.IsArticulated;
|
||||
AIEngine.IsArticulated <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return false;
|
||||
return AIEngine._IsArticulated(engine_id);
|
||||
}
|
||||
|
||||
AIEngine._GetPlaneType <- AIEngine.GetPlaneType;
|
||||
AIEngine.GetPlaneType <- function(engine_id)
|
||||
{
|
||||
if (!AIEngine.IsBuildable(engine_id)) return -1;
|
||||
return AIEngine._GetPlaneType(engine_id);
|
||||
}
|
||||
|
||||
_AIWaypointList <- AIWaypointList;
|
||||
class AIWaypointList extends _AIWaypointList {
|
||||
constructor()
|
||||
{
|
||||
::_AIWaypointList.constructor(AIWaypoint.WAYPOINT_RAIL);
|
||||
}
|
||||
}
|
||||
|
||||
AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
|
||||
AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
|
||||
{
|
||||
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
|
||||
|
||||
return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
|
||||
}
|
||||
|
||||
AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
|
||||
AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
|
||||
{
|
||||
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
|
||||
|
||||
return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
|
||||
}
|
||||
|
||||
AIBridgeList.HasNext <-
|
||||
AIBridgeList_Length.HasNext <-
|
||||
AICargoList.HasNext <-
|
||||
AICargoList_IndustryAccepting.HasNext <-
|
||||
AICargoList_IndustryProducing.HasNext <-
|
||||
AIDepotList.HasNext <-
|
||||
AIEngineList.HasNext <-
|
||||
AIGroupList.HasNext <-
|
||||
AIIndustryList.HasNext <-
|
||||
AIIndustryList_CargoAccepting.HasNext <-
|
||||
AIIndustryList_CargoProducing.HasNext <-
|
||||
AIIndustryTypeList.HasNext <-
|
||||
AIList.HasNext <-
|
||||
AIRailTypeList.HasNext <-
|
||||
AISignList.HasNext <-
|
||||
AIStationList.HasNext <-
|
||||
AIStationList_Vehicle.HasNext <-
|
||||
AISubsidyList.HasNext <-
|
||||
AITileList.HasNext <-
|
||||
AITileList_IndustryAccepting.HasNext <-
|
||||
AITileList_IndustryProducing.HasNext <-
|
||||
AITileList_StationType.HasNext <-
|
||||
AITownList.HasNext <-
|
||||
AIVehicleList.HasNext <-
|
||||
AIVehicleList_DefaultGroup.HasNext <-
|
||||
AIVehicleList_Group.HasNext <-
|
||||
AIVehicleList_SharedOrders.HasNext <-
|
||||
AIVehicleList_Station.HasNext <-
|
||||
AIWaypointList.HasNext <-
|
||||
AIWaypointList_Vehicle.HasNext <-
|
||||
function()
|
||||
{
|
||||
return !this.IsEnd();
|
||||
}
|
||||
|
||||
AIIndustry._IsCargoAccepted <- AIIndustry.IsCargoAccepted;
|
||||
AIIndustry.IsCargoAccepted <- function(industry_id, cargo_id)
|
||||
{
|
||||
return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
AIAbstractList <- AIList;
|
||||
|
||||
AIList.ChangeItem <- AIList.SetValue;
|
||||
|
||||
AIRail.ERR_NONUNIFORM_STATIONS_DISABLED <- 0xFFFF;
|
||||
|
||||
AICompany.GetCompanyValue <- function(company)
|
||||
{
|
||||
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
|
||||
}
|
||||
|
||||
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
|
||||
|
||||
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
|
||||
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
|
||||
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
|
||||
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
|
||||
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
|
||||
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
|
||||
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
|
||||
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
|
||||
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
|
||||
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
|
||||
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
|
||||
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
|
||||
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
|
||||
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
|
||||
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
|
||||
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
|
||||
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
|
||||
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
|
||||
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
|
||||
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
|
||||
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
|
||||
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
|
||||
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
|
||||
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
|
||||
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
|
||||
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
|
||||
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
|
||||
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
|
||||
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
|
||||
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
|
||||
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
|
||||
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
|
||||
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
|
||||
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.0 API compatibility in effect.");
|
||||
|
||||
AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
|
||||
AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
|
||||
{
|
||||
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
|
||||
|
||||
return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
|
||||
}
|
||||
|
||||
AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
|
||||
AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
|
||||
{
|
||||
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
|
||||
|
||||
return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
|
||||
}
|
||||
|
||||
AIBridgeList.HasNext <-
|
||||
AIBridgeList_Length.HasNext <-
|
||||
AICargoList.HasNext <-
|
||||
AICargoList_IndustryAccepting.HasNext <-
|
||||
AICargoList_IndustryProducing.HasNext <-
|
||||
AIDepotList.HasNext <-
|
||||
AIEngineList.HasNext <-
|
||||
AIGroupList.HasNext <-
|
||||
AIIndustryList.HasNext <-
|
||||
AIIndustryList_CargoAccepting.HasNext <-
|
||||
AIIndustryList_CargoProducing.HasNext <-
|
||||
AIIndustryTypeList.HasNext <-
|
||||
AIList.HasNext <-
|
||||
AIRailTypeList.HasNext <-
|
||||
AISignList.HasNext <-
|
||||
AIStationList.HasNext <-
|
||||
AIStationList_Vehicle.HasNext <-
|
||||
AISubsidyList.HasNext <-
|
||||
AITileList.HasNext <-
|
||||
AITileList_IndustryAccepting.HasNext <-
|
||||
AITileList_IndustryProducing.HasNext <-
|
||||
AITileList_StationType.HasNext <-
|
||||
AITownList.HasNext <-
|
||||
AIVehicleList.HasNext <-
|
||||
AIVehicleList_DefaultGroup.HasNext <-
|
||||
AIVehicleList_Depot.HasNext <-
|
||||
AIVehicleList_Group.HasNext <-
|
||||
AIVehicleList_SharedOrders.HasNext <-
|
||||
AIVehicleList_Station.HasNext <-
|
||||
AIWaypointList.HasNext <-
|
||||
AIWaypointList_Vehicle.HasNext <-
|
||||
function()
|
||||
{
|
||||
return !this.IsEnd();
|
||||
}
|
||||
|
||||
AIIndustry._IsCargoAccepted <- AIIndustry.IsCargoAccepted;
|
||||
AIIndustry.IsCargoAccepted <- function(industry_id, cargo_id)
|
||||
{
|
||||
return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
AIAbstractList <- AIList;
|
||||
|
||||
AIList.ChangeItem <- AIList.SetValue;
|
||||
|
||||
AIRail.ERR_NONUNIFORM_STATIONS_DISABLED <- 0xFFFF;
|
||||
|
||||
AICompany.GetCompanyValue <- function(company)
|
||||
{
|
||||
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
|
||||
}
|
||||
|
||||
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
|
||||
|
||||
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
|
||||
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
|
||||
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
|
||||
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
|
||||
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
|
||||
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
|
||||
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
|
||||
AIEvent.AI_ET_COMPANY_ASK_MERGER <- AIEvent.ET_COMPANY_ASK_MERGER;
|
||||
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
|
||||
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
|
||||
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
|
||||
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
|
||||
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
|
||||
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
|
||||
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
|
||||
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
|
||||
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
|
||||
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
|
||||
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
|
||||
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
|
||||
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
|
||||
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
|
||||
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
|
||||
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
|
||||
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
|
||||
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
|
||||
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
|
||||
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
|
||||
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
|
||||
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
|
||||
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
|
||||
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
|
||||
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
|
||||
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
|
||||
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.1 API compatibility in effect.");
|
||||
|
||||
AICompany.GetCompanyValue <- function(company)
|
||||
{
|
||||
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
|
||||
}
|
||||
|
||||
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
|
||||
|
||||
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
|
||||
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
|
||||
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
|
||||
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
|
||||
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
|
||||
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
|
||||
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
|
||||
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
|
||||
AIEvent.AI_ET_COMPANY_ASK_MERGER <- AIEvent.ET_COMPANY_ASK_MERGER;
|
||||
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
|
||||
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
|
||||
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
|
||||
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
|
||||
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
|
||||
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
|
||||
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
|
||||
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
|
||||
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
|
||||
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
|
||||
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
|
||||
AIEvent.AI_ET_TOWN_FOUNDED <- AIEvent.ET_TOWN_FOUNDED;
|
||||
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
|
||||
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
|
||||
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
|
||||
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
|
||||
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
|
||||
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
|
||||
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
|
||||
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
|
||||
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
|
||||
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
|
||||
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
|
||||
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
|
||||
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
|
||||
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
|
||||
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
|
||||
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
|
||||
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.10 API compatibility in effect.");
|
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.2 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.3 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.4 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.5 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.6 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.7 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.8 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
AIBridge._GetName <- AIBridge.GetName;
|
||||
AIBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.9 adds parent_group_id to CreateGroup function */
|
||||
AIGroup._CreateGroup <- AIGroup.CreateGroup;
|
||||
AIGroup.CreateGroup <- function(vehicle_type)
|
||||
{
|
||||
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AILog.Info("1.9 API compatibility in effect.");
|
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.10 API compatibility in effect.");
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.2 API compatibility in effect.");
|
||||
|
||||
GSTown._SetGrowthRate <- GSTown.SetGrowthRate;
|
||||
GSTown.SetGrowthRate <- function(town_id, days_between_town_growth)
|
||||
{
|
||||
/* Growth rate 0 caused resetting the custom growth rate. While this was undocumented, it was used nevertheless (ofc). */
|
||||
if (days_between_town_growth == 0) days_between_town_growth = GSTown.TOWN_GROWTH_NORMAL;
|
||||
return GSTown._SetGrowthRate(town_id, days_between_town_growth);
|
||||
}
|
||||
|
||||
/* 1.5 adds a game element reference to the news. */
|
||||
GSNews._Create <- GSNews.Create;
|
||||
GSNews.Create <- function(type, text, company)
|
||||
{
|
||||
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
|
||||
}
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.3 API compatibility in effect.");
|
||||
|
||||
GSTown._SetGrowthRate <- GSTown.SetGrowthRate;
|
||||
GSTown.SetGrowthRate <- function(town_id, days_between_town_growth)
|
||||
{
|
||||
/* Growth rate 0 caused resetting the custom growth rate. While this was undocumented, it was used nevertheless (ofc). */
|
||||
if (days_between_town_growth == 0) days_between_town_growth = GSTown.TOWN_GROWTH_NORMAL;
|
||||
return GSTown._SetGrowthRate(town_id, days_between_town_growth);
|
||||
}
|
||||
|
||||
/* 1.5 adds a game element reference to the news. */
|
||||
GSNews._Create <- GSNews.Create;
|
||||
GSNews.Create <- function(type, text, company)
|
||||
{
|
||||
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
|
||||
}
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.4 API compatibility in effect.");
|
||||
|
||||
/* 1.5 adds a game element reference to the news. */
|
||||
GSNews._Create <- GSNews.Create;
|
||||
GSNews.Create <- function(type, text, company)
|
||||
{
|
||||
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
|
||||
}
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
||||
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.5 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.6 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.7 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.8 API compatibility in effect.");
|
||||
|
||||
/* 1.9 adds a vehicle type parameter. */
|
||||
GSBridge._GetName <- GSBridge.GetName;
|
||||
GSBridge.GetName <- function(bridge_id)
|
||||
{
|
||||
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
|
||||
}
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
GSLog.Info("1.9 API compatibility in effect.");
|
||||
|
||||
/* 1.11 adds a tile parameter. */
|
||||
GSCompany._ChangeBankBalance <- GSCompany.ChangeBankBalance;
|
||||
GSCompany.ChangeBankBalance <- function(company, delta, expenses_type)
|
||||
{
|
||||
return GSCompany._ChangeBankBalance(company, delta, expenses_type, GSMap.TILE_INVALID);
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
start_ai MyAI
|
||||
|
@@ -1,2 +0,0 @@
|
||||
# Show a MOTD
|
||||
say "Welcome..."
|
25
bridge.h
Normal file
25
bridge.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bridge.h Header file for bridges */
|
||||
|
||||
#ifndef BRIDGE_H
|
||||
#define BRIDGE_H
|
||||
|
||||
/** Struct containing information about a single bridge type
|
||||
*/
|
||||
typedef struct Bridge {
|
||||
byte avail_year; ///< the year in which the bridge becomes available
|
||||
byte min_length; ///< the minimum length of the bridge (not counting start and end tile)
|
||||
byte max_length; ///< the maximum length of the bridge (not counting start and end tile)
|
||||
uint16 price; ///< the relative price of the bridge
|
||||
uint16 speed; ///< maximum travel speed
|
||||
PalSpriteID sprite; ///< the sprite which is used in the GUI (possibly with a recolor sprite)
|
||||
StringID material; ///< the string that contains the bridge description
|
||||
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
|
||||
byte flags; ///< bit 0 set: disable drawing of far pillars.
|
||||
} Bridge;
|
||||
|
||||
extern const Bridge orig_bridge[MAX_BRIDGES];
|
||||
extern Bridge _bridge[MAX_BRIDGES];
|
||||
|
||||
#endif /* BRIDGE_H */
|
167
bridge_gui.c
Normal file
167
bridge_gui.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bridge_gui.c Graphical user interface for bridge construction*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
#include "sound.h"
|
||||
#include "variables.h"
|
||||
#include "bridge.h"
|
||||
|
||||
static struct BridgeData {
|
||||
uint count;
|
||||
TileIndex start_tile;
|
||||
TileIndex end_tile;
|
||||
byte type;
|
||||
byte indexes[MAX_BRIDGES];
|
||||
int32 costs[MAX_BRIDGES];
|
||||
} _bridgedata;
|
||||
|
||||
void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
|
||||
}
|
||||
|
||||
static void BuildBridge(Window *w, int i)
|
||||
{
|
||||
DeleteWindow(w);
|
||||
DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
|
||||
_bridgedata.indexes[i] | (_bridgedata.type << 8), CcBuildBridge,
|
||||
CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
|
||||
}
|
||||
|
||||
static void BuildBridgeWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT: {
|
||||
uint i;
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
for (i = 0; i < 4 && i + w->vscroll.pos < _bridgedata.count; i++) {
|
||||
const Bridge *b = &_bridge[_bridgedata.indexes[i + w->vscroll.pos]];
|
||||
|
||||
SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
|
||||
SetDParam(1, (b->speed >> 4) * 10);
|
||||
SetDParam(0, b->material);
|
||||
DrawSprite(b->sprite, 3, 15 + i * 22);
|
||||
|
||||
DrawString(44, 15 + i * 22 , STR_500D, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
uint i = e->keypress.keycode - '1';
|
||||
if (i < 9 && i < _bridgedata.count) {
|
||||
e->keypress.cont = false;
|
||||
BuildBridge(w, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget == 2) {
|
||||
uint ind = ((int)e->click.pt.y - 14) / 22;
|
||||
if (ind < 4 && (ind += w->vscroll.pos) < _bridgedata.count)
|
||||
BuildBridge(w, ind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
static const Widget _build_road_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_road_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_road_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, byte bridge_type)
|
||||
{
|
||||
uint j = 0;
|
||||
int32 ret;
|
||||
StringID errmsg;
|
||||
|
||||
DeleteWindowById(WC_BUILD_BRIDGE, 0);
|
||||
|
||||
_bridgedata.type = bridge_type;
|
||||
_bridgedata.start_tile = start;
|
||||
_bridgedata.end_tile = end;
|
||||
|
||||
errmsg = INVALID_STRING_ID;
|
||||
|
||||
// only query bridge building possibility once, result is the same for all bridges!
|
||||
// returns CMD_ERROR on failure, and price on success
|
||||
ret = DoCommandByTile(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
errmsg = _error_message;
|
||||
} else {
|
||||
// check which bridges can be built
|
||||
int bridge_len; // length of the middle parts of the bridge
|
||||
int tot_bridgedata_len; // total length of bridge
|
||||
|
||||
// get absolute bridge length
|
||||
bridge_len = GetBridgeLength(start, end);
|
||||
tot_bridgedata_len = bridge_len + 2;
|
||||
|
||||
tot_bridgedata_len = CalcBridgeLenCostFactor(tot_bridgedata_len);
|
||||
|
||||
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
const Bridge *b = &_bridge[bridge_type];
|
||||
// bridge is accepted, add to list
|
||||
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
|
||||
_bridgedata.costs[j] = ret + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
|
||||
_bridgedata.indexes[j] = bridge_type;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bridgedata.count = j;
|
||||
|
||||
if (j != 0) {
|
||||
Window *w = AllocateWindowDesc((_bridgedata.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
|
||||
w->vscroll.cap = 4;
|
||||
w->vscroll.count = (byte)j;
|
||||
} else {
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
|
||||
}
|
||||
}
|
84
callback_table.c
Normal file
84
callback_table.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "callback_table.h"
|
||||
#include "functions.h"
|
||||
|
||||
// If you add a callback for DoCommandP, also add the callback in here
|
||||
// see below for the full list!
|
||||
// If you don't do it, it won't work across the network!!
|
||||
|
||||
/* aircraft_gui.c */
|
||||
CommandCallback CcBuildAircraft;
|
||||
CommandCallback CcCloneAircraft;
|
||||
|
||||
/* airport_gui.c */
|
||||
CommandCallback CcBuildAirport;
|
||||
|
||||
/* bridge_gui.c */
|
||||
CommandCallback CcBuildBridge;
|
||||
|
||||
/* dock_gui.c */
|
||||
CommandCallback CcBuildDocks;
|
||||
CommandCallback CcBuildCanal;
|
||||
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
CommandCallback CcBuildTown;
|
||||
|
||||
/* rail_gui.c */
|
||||
CommandCallback CcPlaySound1E;
|
||||
CommandCallback CcRailDepot;
|
||||
CommandCallback CcStation;
|
||||
CommandCallback CcBuildRailTunnel;
|
||||
|
||||
/* road_gui.c */
|
||||
CommandCallback CcPlaySound1D;
|
||||
CommandCallback CcBuildRoadTunnel;
|
||||
CommandCallback CcRoadDepot;
|
||||
|
||||
/* roadveh_gui.c */
|
||||
CommandCallback CcBuildRoadVeh;
|
||||
CommandCallback CcCloneRoadVeh;
|
||||
|
||||
/* ship_gui.c */
|
||||
CommandCallback CcBuildShip;
|
||||
CommandCallback CcCloneShip;
|
||||
|
||||
/* train_gui.c */
|
||||
CommandCallback CcBuildWagon;
|
||||
CommandCallback CcBuildLoco;
|
||||
CommandCallback CcCloneTrain;
|
||||
|
||||
CommandCallback *_callback_table[] = {
|
||||
/* 0x00 */ NULL,
|
||||
/* 0x01 */ CcBuildAircraft,
|
||||
/* 0x02 */ CcBuildAirport,
|
||||
/* 0x03 */ CcBuildBridge,
|
||||
/* 0x04 */ CcBuildCanal,
|
||||
/* 0x05 */ CcBuildDocks,
|
||||
/* 0x06 */ CcBuildLoco,
|
||||
/* 0x07 */ CcBuildRoadVeh,
|
||||
/* 0x08 */ CcBuildShip,
|
||||
/* 0x09 */ CcBuildTown,
|
||||
/* 0x0A */ CcBuildRoadTunnel,
|
||||
/* 0x0B */ CcBuildRailTunnel,
|
||||
/* 0x0C */ CcBuildWagon,
|
||||
/* 0x0D */ CcRoadDepot,
|
||||
/* 0x0E */ CcRailDepot,
|
||||
/* 0x0F */ CcPlaceSign,
|
||||
/* 0x10 */ CcPlaySound10,
|
||||
/* 0x11 */ CcPlaySound1D,
|
||||
/* 0x12 */ CcPlaySound1E,
|
||||
/* 0x13 */ CcStation,
|
||||
/* 0x14 */ CcTerraform,
|
||||
/* 0x15 */ CcCloneAircraft,
|
||||
/* 0x16 */ CcCloneRoadVeh,
|
||||
/* 0x17 */ CcCloneShip,
|
||||
/* 0x18 */ CcCloneTrain,
|
||||
};
|
||||
|
||||
const int _callback_table_count = lengthof(_callback_table);
|
11
callback_table.h
Normal file
11
callback_table.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef CALLBACK_TABLE_H
|
||||
#define CALLBACK_TABLE_H
|
||||
|
||||
#include "functions.h"
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
|
||||
#endif /* CALLBACK_TABLE_H */
|
6913
changelog.txt
6913
changelog.txt
File diff suppressed because it is too large
Load Diff
837
clear_cmd.c
Normal file
837
clear_cmd.c
Normal file
@@ -0,0 +1,837 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "variables.h"
|
||||
#include "table/sprites.h"
|
||||
|
||||
typedef struct TerraformerHeightMod {
|
||||
TileIndex tile;
|
||||
byte height;
|
||||
} TerraformerHeightMod;
|
||||
|
||||
typedef struct TerraformerState {
|
||||
int height[4];
|
||||
uint32 flags;
|
||||
|
||||
int direction;
|
||||
int modheight_count;
|
||||
int tile_table_count;
|
||||
|
||||
int32 cost;
|
||||
|
||||
TileIndex *tile_table;
|
||||
TerraformerHeightMod *modheight;
|
||||
|
||||
} TerraformerState;
|
||||
|
||||
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TileIndex *t;
|
||||
int count;
|
||||
|
||||
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) return -1;
|
||||
|
||||
t = ts->tile_table;
|
||||
for (count = ts->tile_table_count; count != 0; count--, t++) {
|
||||
if (*t == tile) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformerHeightMod *mod = ts->modheight;
|
||||
int count;
|
||||
|
||||
for (count = ts->modheight_count; count != 0; count--, mod++) {
|
||||
if (mod->tile == tile) return mod->height;
|
||||
}
|
||||
|
||||
return TileHeight(tile);
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
int count;
|
||||
TileIndex *t;
|
||||
|
||||
count = ts->tile_table_count;
|
||||
|
||||
if (count >= 625) return;
|
||||
|
||||
for(t = ts->tile_table; count != 0; count--,t++) {
|
||||
if (*t == tile) return;
|
||||
}
|
||||
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, 0));
|
||||
TerraformAddDirtyTile(ts, tile);
|
||||
}
|
||||
|
||||
static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
|
||||
{
|
||||
int r;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
|
||||
return r;
|
||||
|
||||
if (!IsTileType(tile, MP_RAILWAY)) {
|
||||
int32 ret = DoCommandByTile(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
_terraform_err_tile = tile;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ts->cost += ret;
|
||||
}
|
||||
|
||||
if (ts->tile_table_count >= 625) return -1;
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height)
|
||||
{
|
||||
int nh;
|
||||
TerraformerHeightMod *mod;
|
||||
int count;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if (height < 0) {
|
||||
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
|
||||
return false;
|
||||
}
|
||||
|
||||
_error_message = STR_1004_TOO_HIGH;
|
||||
|
||||
if (height > 15) return false;
|
||||
|
||||
nh = TerraformGetHeightOfTile(ts, tile);
|
||||
if (nh < 0 || height == nh) return false;
|
||||
|
||||
if (TerraformProc(ts, tile, 0) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
|
||||
|
||||
mod = ts->modheight;
|
||||
count = ts->modheight_count;
|
||||
|
||||
for (;;) {
|
||||
if (count == 0) {
|
||||
if (ts->modheight_count >= 576)
|
||||
return false;
|
||||
ts->modheight_count++;
|
||||
break;
|
||||
}
|
||||
if (mod->tile == tile) break;
|
||||
mod++;
|
||||
count--;
|
||||
}
|
||||
|
||||
mod->tile = tile;
|
||||
mod->height = (byte)height;
|
||||
|
||||
ts->cost += _price.terraform;
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for(ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
if (!TerraformTileHeight(ts, tile, r+direction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Terraform land
|
||||
* @param x,y coordinates to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
TileIndex tile;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
TileIndex tile_table_data[625];
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_error_message = INVALID_STRING_ID;
|
||||
_terraform_err_tile = 0;
|
||||
|
||||
ts.direction = direction = p2 ? 1 : -1;
|
||||
ts.flags = flags;
|
||||
ts.modheight_count = ts.tile_table_count = 0;
|
||||
ts.cost = 0;
|
||||
ts.modheight = modheight_data;
|
||||
ts.tile_table = tile_table_data;
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
/* Make an extra check for map-bounds cause we add tiles to the originating tile */
|
||||
if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
|
||||
|
||||
if (p1 & 1) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(1, 0),
|
||||
TileHeight(tile + TileDiffXY(1, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(1, 1),
|
||||
TileHeight(tile + TileDiffXY(1, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(0, 1),
|
||||
TileHeight(tile + TileDiffXY(0, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(0, 0),
|
||||
TileHeight(tile + TileDiffXY(0, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
{ /* Check if tunnel or track would take damage */
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
uint a, b, c, d, r, min;
|
||||
TileIndex tile = *ti;
|
||||
|
||||
_terraform_err_tile = tile;
|
||||
|
||||
a = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
|
||||
b = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
|
||||
c = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
|
||||
d = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
|
||||
|
||||
r = GetTileh(a, b, c, d, &min);
|
||||
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
if (IsSteepTileh(r)) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
|
||||
|
||||
if (IsPlainRailTile(tile)) {
|
||||
extern const TrackBits _valid_tileh_slopes[2][15];
|
||||
if (GetTrackBits(tile) & ~_valid_tileh_slopes[0][r]) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
|
||||
} else return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
|
||||
}
|
||||
|
||||
if (direction == -1 && !CheckTunnelInWay(tile, min)) return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
|
||||
|
||||
_terraform_err_tile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Clear the landscape at the tiles */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* change the height */
|
||||
{
|
||||
int count;
|
||||
TerraformerHeightMod *mod;
|
||||
|
||||
mod = ts.modheight;
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
TileIndex til = mod->tile;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally mark the dirty tiles dirty */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ts.cost;
|
||||
}
|
||||
|
||||
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param x,y end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
TileIndex tile;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 >= MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = TileHeight(p1);
|
||||
|
||||
ex >>= 4; ey >>= 4;
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TileXY(sx, sy);
|
||||
|
||||
size_x = ex-sx+1;
|
||||
size_y = ey-sy+1;
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IsTileType(tile, MP_UNMOVABLE) && _m[tile].m5 == 3 &&
|
||||
IsTileOwner(tile, _current_player))
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
|
||||
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
ModifyTile(tile,
|
||||
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
||||
3 /* map5 */
|
||||
);
|
||||
}
|
||||
|
||||
return cost + _price.purchase_land * 10;
|
||||
}
|
||||
|
||||
|
||||
static int32 ClearTile_Clear(TileIndex tile, byte flags)
|
||||
{
|
||||
static const int32 null = 0;
|
||||
static const int32* clear_price_table[] = {
|
||||
&null,
|
||||
&_price.clear_1,
|
||||
&_price.clear_1,
|
||||
&_price.clear_1,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
};
|
||||
const int32 *price = clear_price_table[GB(_m[tile].m5, 0, 5)];
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return *price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
if (!IsTileType(tile, MP_UNMOVABLE) || _m[tile].m5 != 3) return CMD_ERROR;
|
||||
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
|
||||
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC)
|
||||
DoClearSquare(tile);
|
||||
|
||||
return - _price.purchase_land * 2;
|
||||
}
|
||||
|
||||
|
||||
#include "table/clear_land.h"
|
||||
|
||||
|
||||
void DrawClearLandTile(const TileInfo *ti, byte set)
|
||||
{
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19);
|
||||
}
|
||||
|
||||
void DrawHillyLandTile(const TileInfo *ti)
|
||||
{
|
||||
if (ti->tileh != 0) {
|
||||
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh]);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawClearLandFence(const TileInfo *ti)
|
||||
{
|
||||
byte m4 = _m[ti->tile].m4;
|
||||
byte z = ti->z;
|
||||
|
||||
if (ti->tileh & 2) {
|
||||
z += 8;
|
||||
if (ti->tileh == 0x17) z += 8;
|
||||
}
|
||||
|
||||
if (GB(m4, 5, 3) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GB(m4, 5, 3) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
|
||||
if (GB(m4, 2, 3) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GB(m4, 2, 3) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawTile_Clear(TileInfo *ti)
|
||||
{
|
||||
switch (GB(ti->map5, 2, 3)) {
|
||||
case 0:
|
||||
DrawClearLandTile(ti, GB(ti->map5, 0, 2));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
DrawHillyLandTile(ti);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
DrawGroundSprite(_clear_land_sprites_1[GB(_m[ti->tile].m3, 0, 4)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DrawGroundSprite(_clear_land_sprites_2[GB(ti->map5, 0, 2)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
DrawGroundSprite(_clear_land_sprites_3[GB(ti->map5, 0, 2)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawClearLandFence(ti);
|
||||
}
|
||||
|
||||
static uint GetSlopeZ_Clear(const TileInfo* ti)
|
||||
{
|
||||
return GetPartialZ(ti->x & 0xF, ti->y & 0xF, ti->tileh) + ti->z;
|
||||
}
|
||||
|
||||
static uint GetSlopeTileh_Clear(const TileInfo *ti)
|
||||
{
|
||||
return ti->tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static void AnimateTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte self;
|
||||
byte neighbour;
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_CLEAR:
|
||||
self = (GB(_m[tile].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
self = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
|
||||
case MP_CLEAR:
|
||||
neighbour = (GB(_m[TILE_ADDXY(tile, 1, 0)].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
neighbour = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GB(_m[tile].m4, 5, 3) == 0) {
|
||||
if (self != neighbour) {
|
||||
SB(_m[tile].m4, 5, 3, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SB(_m[tile].m4, 5, 3, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
|
||||
case MP_CLEAR:
|
||||
neighbour = (GB(_m[TILE_ADDXY(tile, 0, 1)].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
neighbour = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GB(_m[tile].m4, 2, 3) == 0) {
|
||||
if (self != neighbour) {
|
||||
SB(_m[tile].m4, 2, 3, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SB(_m[tile].m4, 2, 3, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
|
||||
/* convert into snowy tiles */
|
||||
static void TileLoopClearAlps(TileIndex tile)
|
||||
{
|
||||
int k;
|
||||
byte m5,tmp;
|
||||
|
||||
/* distance from snow line, in steps of 8 */
|
||||
k = GetTileZ(tile) - _opt.snow_line;
|
||||
|
||||
m5 = _m[tile].m5 & 0x1C;
|
||||
tmp = _m[tile].m5 & 3;
|
||||
|
||||
if (k < -8) {
|
||||
/* snow_m2_down */
|
||||
if (m5 != 0x10)
|
||||
return;
|
||||
if (tmp == 0)
|
||||
m5 = 3;
|
||||
} else if (k == -8) {
|
||||
/* snow_m1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 0) {
|
||||
m5 = (tmp - 1) + 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k < 8) {
|
||||
/* snow_0 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 1) {
|
||||
m5 = 1;
|
||||
if (tmp != 0)
|
||||
m5 = tmp - 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k == 8) {
|
||||
/* snow_p1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 2) {
|
||||
m5 = 2;
|
||||
if (tmp <= 2)
|
||||
m5 = tmp + 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else {
|
||||
/* snow_p2_up */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 3) {
|
||||
m5 = tmp + 1 + 0x10;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
_m[tile].m5 = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoopClearDesert(TileIndex tile)
|
||||
{
|
||||
if ((_m[tile].m5 & 0x1C) == 0x14) return;
|
||||
|
||||
if (GetMapExtraBits(tile) == 1) {
|
||||
_m[tile].m5 = 0x17;
|
||||
} else {
|
||||
if (GetMapExtraBits(tile + TileDiffXY( 1, 0)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY(-1, 0)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY( 0, 1)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY( 0, -1)) != 1)
|
||||
return;
|
||||
_m[tile].m5 = 0x15;
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoop_Clear(TileIndex tile)
|
||||
{
|
||||
byte m5,m3;
|
||||
|
||||
TileLoopClearHelper(tile);
|
||||
|
||||
if (_opt.landscape == LT_DESERT) {
|
||||
TileLoopClearDesert(tile);
|
||||
} else if (_opt.landscape == LT_HILLY) {
|
||||
TileLoopClearAlps(tile);
|
||||
}
|
||||
|
||||
m5 = _m[tile].m5;
|
||||
if ((m5 & 0x1C) == 0x10 || (m5 & 0x1C) == 0x14) return;
|
||||
|
||||
if ((m5 & 0x1C) != 0xC) {
|
||||
if ((m5 & 3) == 3) return;
|
||||
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_m[tile].m5 = m5;
|
||||
return;
|
||||
}
|
||||
/* did overflow, so continue */
|
||||
} else {
|
||||
m5 = (GB(Random(), 0, 8) > 21) ? 2 : 6;
|
||||
}
|
||||
m5++;
|
||||
} else if (_game_mode != GM_EDITOR) {
|
||||
/* handle farm field */
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_m[tile].m5 = m5;
|
||||
return;
|
||||
}
|
||||
/* overflowed */
|
||||
m3 = _m[tile].m3 + 1;
|
||||
assert( (m3 & 0xF) != 0);
|
||||
if ( (m3 & 0xF) >= 9) /* NOTE: will not work properly if m3&0xF == 0xF */
|
||||
m3 &= ~0xF;
|
||||
_m[tile].m3 = m3;
|
||||
}
|
||||
|
||||
_m[tile].m5 = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
uint i;
|
||||
TileIndex tile;
|
||||
|
||||
/* add hills */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
|
||||
do {
|
||||
tile = RandomTile();
|
||||
if (IsTileType(tile, MP_CLEAR)) SB(_m[tile].m5, 2, 2, 1);
|
||||
} while (--i);
|
||||
|
||||
/* add grey squares */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
|
||||
do {
|
||||
uint32 r = Random();
|
||||
tile = RandomTileSeed(r);
|
||||
if (IsTileType(tile, MP_CLEAR)) {
|
||||
uint j = GB(r, 16, 4) + 5;
|
||||
for(;;) {
|
||||
TileIndex tile_new;
|
||||
|
||||
SB(_m[tile].m5, 2, 2, 2);
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + TileOffsByDir(GB(Random(), 0, 2));
|
||||
} while (!IsTileType(tile_new, MP_CLEAR));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
static void ClickTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const StringID _clear_land_str[] = {
|
||||
STR_080B_ROUGH_LAND,
|
||||
STR_080A_ROCKS,
|
||||
STR_080E_FIELDS,
|
||||
STR_080F_SNOW_COVERED_LAND,
|
||||
STR_0810_DESERT,
|
||||
0,
|
||||
0,
|
||||
STR_080C_BARE_LAND,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
};
|
||||
|
||||
static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
uint i = GB(_m[tile].m5, 2, 3);
|
||||
if (i == 0) i = GB(_m[tile].m5, 0, 2) + 8;
|
||||
td->str = _clear_land_str[i - 1];
|
||||
td->owner = GetTileOwner(tile);
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * 8;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, /* draw_tile_proc */
|
||||
GetSlopeZ_Clear, /* get_slope_z_proc */
|
||||
ClearTile_Clear, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Clear, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
|
||||
ClickTile_Clear, /* click_tile_proc */
|
||||
AnimateTile_Clear, /* animate_tile_proc */
|
||||
TileLoop_Clear, /* tile_loop_clear */
|
||||
ChangeTileOwner_Clear, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
NULL, /* vehicle_leave_tile_proc */
|
||||
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
|
||||
};
|
@@ -1,145 +0,0 @@
|
||||
macro(_parse_arguments_with_multi_hack ORIGINAL_COMMAND_LINE)
|
||||
# cmake_parse_arguments() put all the MULTIS in a single variable; you
|
||||
# lose the ability to see for example multiple COMMANDs. To be able to
|
||||
# passthrough multiple MULTIS, we add a marker after every MULTI. This
|
||||
# allows us to reassemble the correct amount again before giving it to
|
||||
# the wrapped command with _reassemble_command_line().
|
||||
|
||||
set(COMMAND_LINE "${ORIGINAL_COMMAND_LINE}")
|
||||
|
||||
foreach(MULTI IN LISTS MULTIS)
|
||||
string(REPLACE "${MULTI}" "${MULTI};:::" COMMAND_LINE "${COMMAND_LINE}")
|
||||
endforeach()
|
||||
|
||||
cmake_parse_arguments(PARAM "${OPTIONS}" "${SINGLES}" "${MULTIS}" ${COMMAND_LINE})
|
||||
endmacro()
|
||||
|
||||
macro(_reassemble_command_line)
|
||||
# Reassemble the command line as we original got it.
|
||||
set(NEW_COMMAND_LINE ${PARAM_UNPARSED_ARGUMENTS})
|
||||
|
||||
foreach(OPTION IN LISTS OPTIONS)
|
||||
if(PARAM_${OPTION})
|
||||
list(APPEND NEW_COMMAND_LINE "${OPTION}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(SINGLE IN LISTS SINGLES)
|
||||
if(PARAM_${SINGLE})
|
||||
list(APPEND NEW_COMMAND_LINE "${SINGLE}" "${PARAM_${SINGLE}}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(MULTI IN LISTS MULTIS)
|
||||
if(PARAM_${MULTI})
|
||||
# Replace our special marker with the name of the MULTI again. This
|
||||
# restores for example multiple COMMANDs again.
|
||||
string(REPLACE ":::" "${MULTI}" PARAM_${MULTI} "${PARAM_${MULTI}}")
|
||||
list(APPEND NEW_COMMAND_LINE "${PARAM_${MULTI}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Generated files can be older than their dependencies, causing useless
|
||||
# regenerations. This function replaces each file in OUTPUT with a .timestamp
|
||||
# file, adds a command to touch it and move the original file in BYPRODUCTS,
|
||||
# before calling add_custom_command().
|
||||
#
|
||||
# Note: Any add_custom_target() depending on files in original OUTPUT must use
|
||||
# add_custom_target_timestamp() instead to have the correct dependencies.
|
||||
#
|
||||
# add_custom_command_timestamp(OUTPUT output1 [output2 ...]
|
||||
# COMMAND command1 [ARGS] [args1...]
|
||||
# [COMMAND command2 [ARGS] [args2...] ...]
|
||||
# [MAIN_DEPENDENCY depend]
|
||||
# [DEPENDS [depends...]]
|
||||
# [BYPRODUCTS [files...]]
|
||||
# [IMPLICIT_DEPENDS <lang1> depend1
|
||||
# [<lang2> depend2] ...]
|
||||
# [WORKING_DIRECTORY dir]
|
||||
# [COMMENT comment]
|
||||
# [VERBATIM] [APPEND] [USES_TERMINAL])
|
||||
function(add_custom_command_timestamp)
|
||||
set(OPTIONS VERBATIM APPEND USES_TERMINAL)
|
||||
set(SINGLES MAIN_DEPENDENCY WORKING_DIRECTORY COMMENT)
|
||||
set(MULTIS OUTPUT COMMAND DEPENDS BYPRODUCTS IMPLICIT_DEPENDS)
|
||||
|
||||
_parse_arguments_with_multi_hack("${ARGN}")
|
||||
|
||||
# Create a list of all the OUTPUTs (by removing our magic marker)
|
||||
string(REPLACE ":::;" "" OUTPUTS "${PARAM_OUTPUT}")
|
||||
|
||||
# Reset the OUTPUT and BYPRODUCTS as an empty list (if needed).
|
||||
# Because they are MULTIS, we need to add our special marker here.
|
||||
set(PARAM_OUTPUT ":::")
|
||||
if(NOT PARAM_BYPRODUCTS)
|
||||
set(PARAM_BYPRODUCTS ":::")
|
||||
endif()
|
||||
|
||||
foreach(OUTPUT IN LISTS OUTPUTS)
|
||||
# For every output, we add a 'cmake -E touch' entry to update the
|
||||
# timestamp on each run.
|
||||
get_filename_component(OUTPUT_FILENAME ${OUTPUT} NAME)
|
||||
string(APPEND PARAM_COMMAND ";:::;${CMAKE_COMMAND};-E;touch;${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILENAME}.timestamp")
|
||||
|
||||
# We change the OUTPUT to a '.timestamp' variant, and make the real
|
||||
# output a byproduct.
|
||||
list(APPEND PARAM_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILENAME}.timestamp)
|
||||
list(APPEND PARAM_BYPRODUCTS ${OUTPUT})
|
||||
|
||||
# Mark this file as being a byproduct; we use this again with
|
||||
# add_custom_target_timestamp() to know if we should point to the
|
||||
# '.timestamp' variant or not.
|
||||
set_source_files_properties(${OUTPUT} PROPERTIES BYPRODUCT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILENAME}.timestamp)
|
||||
endforeach()
|
||||
|
||||
# Reassemble and call the wrapped command
|
||||
_reassemble_command_line()
|
||||
add_custom_command(${NEW_COMMAND_LINE})
|
||||
endfunction()
|
||||
|
||||
# Generated files can be older than their dependencies, causing useless
|
||||
# regenerations. This function adds a .timestamp file for each file in DEPENDS
|
||||
# replaced by add_custom_command_timestamp(), before calling add_custom_target().
|
||||
#
|
||||
# add_custom_target_timestamp(Name [ALL] [command1 [args1...]]
|
||||
# [COMMAND command2 [args2...] ...]
|
||||
# [DEPENDS depend depend depend ... ]
|
||||
# [BYPRODUCTS [files...]]
|
||||
# [WORKING_DIRECTORY dir]
|
||||
# [COMMENT comment]
|
||||
# [VERBATIM] [USES_TERMINAL]
|
||||
# [SOURCES src1 [src2...]])
|
||||
function(add_custom_target_timestamp)
|
||||
set(OPTIONS VERBATIM USES_TERMINAL)
|
||||
set(SINGLES WORKING_DIRECTORY COMMENT)
|
||||
set(MULTIS COMMAND DEPENDS BYPRODUCTS SOURCES)
|
||||
# ALL is missing, as the order is important here. It will be picked up
|
||||
# by ${PARAM_UNPARSED_ARGUMENTS} when reassembling the command line.
|
||||
|
||||
_parse_arguments_with_multi_hack("${ARGN}")
|
||||
|
||||
# Create a list of all the DEPENDs (by removing our magic marker)
|
||||
string(REPLACE ":::;" "" DEPENDS "${PARAM_DEPENDS}")
|
||||
|
||||
# Reset the DEPEND as an empty list.
|
||||
# Because it is a MULTI, we need to add our special marker here.
|
||||
set(PARAM_DEPENDS ":::")
|
||||
|
||||
foreach(DEPEND IN LISTS DEPENDS)
|
||||
# Check if the output is produced by add_custom_command_timestamp()
|
||||
get_source_file_property(BYPRODUCT ${DEPEND} BYPRODUCT)
|
||||
|
||||
if(BYPRODUCT STREQUAL "NOTFOUND")
|
||||
# If it is not, just keep it as DEPEND
|
||||
list(APPEND PARAM_DEPENDS "${DEPEND}")
|
||||
else()
|
||||
# If it is, the BYPRODUCT property points to the timestamp we want to depend on
|
||||
list(APPEND PARAM_DEPENDS "${BYPRODUCT}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Reassemble and call the wrapped command
|
||||
_reassemble_command_line()
|
||||
add_custom_target(${NEW_COMMAND_LINE})
|
||||
endfunction()
|
@@ -1,161 +0,0 @@
|
||||
# Macro which contains all bits to setup the compile flags correctly.
|
||||
#
|
||||
# compile_flags()
|
||||
#
|
||||
macro(compile_flags)
|
||||
if(MSVC)
|
||||
# Switch to MT (static) instead of MD (dynamic) binary
|
||||
|
||||
# For MSVC two generators are available
|
||||
# - a command line generator (Ninja) using CMAKE_BUILD_TYPE to specify the
|
||||
# configuration of the build tree
|
||||
# - an IDE generator (Visual Studio) using CMAKE_CONFIGURATION_TYPES to
|
||||
# specify all configurations that will be available in the generated solution
|
||||
list(APPEND MSVC_CONFIGS "${CMAKE_BUILD_TYPE}" "${CMAKE_CONFIGURATION_TYPES}")
|
||||
|
||||
# Set usage of static runtime for all configurations
|
||||
foreach(MSVC_CONFIG ${MSVC_CONFIGS})
|
||||
string(TOUPPER "CMAKE_CXX_FLAGS_${MSVC_CONFIG}" MSVC_FLAGS)
|
||||
string(REPLACE "/MD" "/MT" ${MSVC_FLAGS} "${${MSVC_FLAGS}}")
|
||||
endforeach()
|
||||
|
||||
# "If /Zc:rvalueCast is specified, the compiler follows section 5.4 of the
|
||||
# C++11 standard". We need C++11 for the way we use threads.
|
||||
add_compile_options(/Zc:rvalueCast)
|
||||
|
||||
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# Enable multi-threaded compilation.
|
||||
add_compile_options(/MP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add some -D flags for Debug builds. We cannot use add_definitions(), because
|
||||
# it does not appear to support the $<> tags.
|
||||
add_compile_options(
|
||||
"$<$<CONFIG:Debug>:-D_DEBUG>"
|
||||
"$<$<NOT:$<CONFIG:Debug>>:-D_FORTIFY_SOURCE=2>" # FORTIFY_SOURCE should only be used in non-debug builds (requires -O1+)
|
||||
)
|
||||
if(MINGW)
|
||||
add_link_options(
|
||||
"$<$<NOT:$<CONFIG:Debug>>:-fstack-protector>" # Prevent undefined references when _FORTIFY_SOURCE > 0
|
||||
)
|
||||
endif()
|
||||
|
||||
# Prepare a generator that checks if we are not a debug, and don't have asserts
|
||||
# on. We need this later on to set some compile options for stable releases.
|
||||
set(IS_STABLE_RELEASE "$<AND:$<NOT:$<CONFIG:Debug>>,$<NOT:$<BOOL:${OPTION_USE_ASSERTS}>>>")
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/W3)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
add_compile_options(
|
||||
-W
|
||||
-Wall
|
||||
-Wcast-qual
|
||||
-Wextra
|
||||
-Wsign-compare
|
||||
-Wundef
|
||||
-Wpointer-arith
|
||||
-Wwrite-strings
|
||||
-Wredundant-decls
|
||||
-Wformat-security
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wnon-virtual-dtor
|
||||
|
||||
# Often parameters are unused, which is fine.
|
||||
-Wno-unused-parameter
|
||||
# We use 'ABCD' multichar for SaveLoad chunks identifiers
|
||||
-Wno-multichar
|
||||
|
||||
# Compilers complains about that we break strict-aliasing.
|
||||
# On most places we don't see how to fix it, and it doesn't
|
||||
# break anything. So disable strict-aliasing to make the
|
||||
# compiler all happy.
|
||||
-fno-strict-aliasing
|
||||
)
|
||||
|
||||
# When we are a stable release (Release build + USE_ASSERTS not set),
|
||||
# assertations are off, which trigger a lot of warnings. We disable
|
||||
# these warnings for these releases.
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_compile_options(
|
||||
"$<${IS_STABLE_RELEASE}:-Wno-unused-variable>"
|
||||
"$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-parameter>"
|
||||
"$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-variable>"
|
||||
)
|
||||
else()
|
||||
add_compile_options(
|
||||
"$<${IS_STABLE_RELEASE}:-Wno-unused-variable>"
|
||||
"$<${IS_STABLE_RELEASE}:-Wno-unused-parameter>"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Ninja processes the output so the output from the compiler
|
||||
# isn't directly to a terminal; hence, the default is
|
||||
# non-coloured output. We can override this to get nicely
|
||||
# coloured output, but since that might yield odd results with
|
||||
# IDEs, we extract it to an option.
|
||||
if(OPTION_FORCE_COLORED_OUTPUT)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
add_compile_options (-fdiagnostics-color=always)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
add_compile_options (-fcolor-diagnostics)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("-flifetime-dse=1" LIFETIME_DSE_FOUND)
|
||||
|
||||
add_compile_options(
|
||||
# GCC 4.2+ automatically assumes that signed overflows do
|
||||
# not occur in signed arithmetics, whereas we are not
|
||||
# sure that they will not happen. It furthermore complains
|
||||
# about its own optimized code in some places.
|
||||
"-fno-strict-overflow"
|
||||
|
||||
# Prevent optimisation supposing enums are in a range specified by the standard
|
||||
# For details, see http://gcc.gnu.org/PR43680
|
||||
"-fno-tree-vrp"
|
||||
|
||||
# -flifetime-dse=2 (default since GCC 6) doesn't play
|
||||
# well with our custom pool item allocator
|
||||
"$<$<BOOL:${LIFETIME_DSE_FOUND}>:-flifetime-dse=1>"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if (NOT CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("-mno-sse4" NO_SSE4_FOUND)
|
||||
|
||||
if(NO_SSE4_FOUND)
|
||||
add_compile_options(
|
||||
# Don't use SSE4 for general sources to increase compatibility.
|
||||
-mno-sse4
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
add_compile_options(
|
||||
-Wall
|
||||
# warning #873: function ... ::operator new ... has no corresponding operator delete ...
|
||||
-wd873
|
||||
# warning #1292: unknown attribute "fallthrough"
|
||||
-wd1292
|
||||
# warning #1899: multicharacter character literal (potential portability problem)
|
||||
-wd1899
|
||||
# warning #2160: anonymous union qualifier is ignored
|
||||
-wd2160
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "No warning flags are set for this compiler yet; please consider creating a Pull Request to add support for this compiler.")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
# rdynamic is used to get useful stack traces from crash reports.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
|
||||
endif()
|
||||
endmacro()
|
@@ -1,50 +0,0 @@
|
||||
# Macro which contains all bits and pieces to create a single grf file based
|
||||
# on NFO and PNG files.
|
||||
#
|
||||
# create_grf_command()
|
||||
#
|
||||
function(create_grf_command)
|
||||
set(EXTRA_PNG_SOURCE_FILES ${ARGV})
|
||||
|
||||
get_filename_component(GRF_SOURCE_FOLDER_NAME "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
|
||||
get_filename_component(GRF_BINARY_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../${GRF_SOURCE_FOLDER_NAME}.grf ABSOLUTE)
|
||||
file(GLOB_RECURSE GRF_PNG_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.png)
|
||||
file(GLOB_RECURSE GRF_NFO_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.nfo)
|
||||
set(GRF_PNG_SOURCE_FILES ${GRF_PNG_SOURCE_FILES} ${EXTRA_PNG_SOURCE_FILES})
|
||||
|
||||
# Copy over all the PNG files to the correct folder
|
||||
foreach(GRF_PNG_SOURCE_FILE IN LISTS GRF_PNG_SOURCE_FILES)
|
||||
get_filename_component(GRF_PNG_SOURCE_FILE_NAME "${GRF_PNG_SOURCE_FILE}" NAME)
|
||||
set(GRF_PNG_BINARY_FILE "${CMAKE_CURRENT_BINARY_DIR}/sprites/${GRF_PNG_SOURCE_FILE_NAME}")
|
||||
|
||||
add_custom_command(OUTPUT ${GRF_PNG_BINARY_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${GRF_PNG_SOURCE_FILE}
|
||||
${GRF_PNG_BINARY_FILE}
|
||||
MAIN_DEPENDENCY ${GRF_PNG_SOURCE_FILE}
|
||||
COMMENT "Copying ${GRF_PNG_SOURCE_FILE_NAME} sprite file"
|
||||
)
|
||||
|
||||
list(APPEND GRF_PNG_BINARY_FILES ${GRF_PNG_BINARY_FILE})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(OUTPUT ${GRF_BINARY_FILE}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DGRF_SOURCE_FOLDER=${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-DGRF_BINARY_FILE=${GRF_BINARY_FILE}
|
||||
-DNFORENUM_EXECUTABLE=${NFORENUM_EXECUTABLE}
|
||||
-DGRFCODEC_EXECUTABLE=${GRFCODEC_EXECUTABLE}
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake
|
||||
MAIN_DEPENDENCY ${GRF_NFO_SOURCE_FILES}
|
||||
DEPENDS ${GRF_PNG_BINARY_FILES}
|
||||
${CMAKE_SOURCE_DIR}/cmake/scripts/CreateGRF.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating ${GRF_SOURCE_FOLDER_NAME}.grf"
|
||||
)
|
||||
|
||||
# For conviance, if you want to only test building the GRF
|
||||
add_custom_target(${GRF_SOURCE_FOLDER_NAME}.grf
|
||||
DEPENDS
|
||||
${GRF_BINARY_FILE}
|
||||
)
|
||||
endfunction()
|
@@ -1,86 +0,0 @@
|
||||
# Macro which contains all bits and pieces to create the regression tests.
|
||||
# This creates both a standalone target 'regression', and it integrates with
|
||||
# 'ctest'. The first is prefered, as it is more verbose, and takes care of
|
||||
# dependencies correctly.
|
||||
#
|
||||
# create_regression()
|
||||
#
|
||||
macro(create_regression)
|
||||
# Find all the files in the regression folder; they need to be copied to the
|
||||
# build folder before we can run the regression
|
||||
file(GLOB_RECURSE REGRESSION_SOURCE_FILES ${CMAKE_SOURCE_DIR}/regression/*)
|
||||
foreach(REGRESSION_SOURCE_FILE IN LISTS REGRESSION_SOURCE_FILES)
|
||||
string(REPLACE "${CMAKE_SOURCE_DIR}/regression/" "" REGRESSION_SOURCE_FILE_NAME "${REGRESSION_SOURCE_FILE}")
|
||||
string(CONCAT REGRESSION_BINARY_FILE "${CMAKE_BINARY_DIR}/ai/" "${REGRESSION_SOURCE_FILE_NAME}")
|
||||
|
||||
if("${REGRESSION_SOURCE_FILE_NAME}" STREQUAL "regression.cfg")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${REGRESSION_BINARY_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${REGRESSION_SOURCE_FILE}
|
||||
${REGRESSION_BINARY_FILE}
|
||||
MAIN_DEPENDENCY ${REGRESSION_SOURCE_FILE}
|
||||
COMMENT "Copying ${REGRESSION_SOURCE_FILE_NAME} regression file"
|
||||
)
|
||||
|
||||
list(APPEND REGRESSION_BINARY_FILES ${REGRESSION_BINARY_FILE})
|
||||
endforeach()
|
||||
|
||||
# Copy the regression configuration in a special folder, so all autogenerated
|
||||
# folders end up in the same place after running regression.
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/regression/regression.cfg
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_SOURCE_DIR}/regression/regression.cfg
|
||||
${CMAKE_BINARY_DIR}/regression/regression.cfg
|
||||
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/regression/regression.cfg
|
||||
COMMENT "Copying ${REGRESSION_SOURCE_FILE_NAME} regression file"
|
||||
)
|
||||
list(APPEND REGRESSION_BINARY_FILES ${CMAKE_BINARY_DIR}/regression/regression.cfg)
|
||||
|
||||
# Create a new target which copies all regression files
|
||||
add_custom_target(regression_files
|
||||
ALL # this is needed because 'make test' doesn't resolve dependencies, and otherwise this is never executed
|
||||
DEPENDS
|
||||
${REGRESSION_BINARY_FILES}
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
|
||||
# Find all the tests we have, and create a target for them
|
||||
file(GLOB REGRESSION_TESTS ${CMAKE_SOURCE_DIR}/regression/*)
|
||||
foreach(REGRESSION_TEST IN LISTS REGRESSION_TESTS)
|
||||
get_filename_component(REGRESSION_TEST_NAME "${REGRESSION_TEST}" NAME)
|
||||
|
||||
if("${REGRESSION_TEST_NAME}" STREQUAL "regression.cfg")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
add_custom_target(regression_${REGRESSION_TEST_NAME}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOPENTTD_EXECUTABLE=$<TARGET_FILE:openttd>
|
||||
-DEDITBIN_EXECUTABLE=${EDITBIN_EXECUTABLE}
|
||||
-DREGRESSION_TEST=${REGRESSION_TEST_NAME}
|
||||
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/Regression.cmake"
|
||||
DEPENDS openttd regression_files
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running regression test ${REGRESSION_TEST_NAME}"
|
||||
)
|
||||
|
||||
# Also make sure that 'make test' runs the regression
|
||||
add_test(NAME regression_${REGRESSION_TEST_NAME}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOPENTTD_EXECUTABLE=$<TARGET_FILE:openttd>
|
||||
-DEDITBIN_EXECUTABLE=${EDITBIN_EXECUTABLE}
|
||||
-DREGRESSION_TEST=${REGRESSION_TEST_NAME}
|
||||
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/Regression.cmake"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
list(APPEND REGRESSION_TARGETS regression_${REGRESSION_TEST_NAME})
|
||||
endforeach()
|
||||
|
||||
# Create a new target which runs the regression
|
||||
add_custom_target(regression
|
||||
DEPENDS ${REGRESSION_TARGETS})
|
||||
endmacro()
|
@@ -1,14 +0,0 @@
|
||||
# Add the definitions to indicate which endian we are building for.
|
||||
#
|
||||
# add_endian_definition()
|
||||
#
|
||||
function(add_endian_definition)
|
||||
include(TestBigEndian)
|
||||
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
|
||||
|
||||
if(IS_BIG_ENDIAN)
|
||||
add_definitions(-DTTD_ENDIAN=TTD_BIG_ENDIAN)
|
||||
else()
|
||||
add_definitions(-DTTD_ENDIAN=TTD_LITTLE_ENDIAN)
|
||||
endif()
|
||||
endfunction()
|
@@ -1,65 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
FindAllegro
|
||||
-------
|
||||
|
||||
Finds the allegro library.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``Allegro_FOUND``
|
||||
True if the system has the allegro library.
|
||||
``Allegro_INCLUDE_DIRS``
|
||||
Include directories needed to use allegro.
|
||||
``Allegro_LIBRARIES``
|
||||
Libraries needed to link to allegro.
|
||||
``Allegro_VERSION``
|
||||
The version of the allegro library which was found.
|
||||
|
||||
Cache Variables
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
``Allegro_INCLUDE_DIR``
|
||||
The directory containing ``allegro.h``.
|
||||
``Allegro_LIBRARY``
|
||||
The path to the allegro library.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_Allegro QUIET allegro<5)
|
||||
|
||||
find_path(Allegro_INCLUDE_DIR
|
||||
NAMES allegro.h
|
||||
PATHS ${PC_Allegro_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(Allegro_LIBRARY
|
||||
NAMES alleg
|
||||
PATHS ${PC_Allegro_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(Allegro_VERSION ${PC_Allegro_VERSION})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Allegro
|
||||
FOUND_VAR Allegro_FOUND
|
||||
REQUIRED_VARS
|
||||
Allegro_LIBRARY
|
||||
Allegro_INCLUDE_DIR
|
||||
VERSION_VAR Allegro_VERSION
|
||||
)
|
||||
|
||||
if(Allegro_FOUND)
|
||||
set(Allegro_LIBRARIES ${Allegro_LIBRARY})
|
||||
set(Allegro_INCLUDE_DIRS ${Allegro_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
Allegro_INCLUDE_DIR
|
||||
Allegro_LIBRARY
|
||||
)
|
@@ -1,30 +0,0 @@
|
||||
# Autodetect editbin. Only useful for MSVC.
|
||||
|
||||
if(NOT EDITBIN_DIRECTORY)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
get_filename_component(MSVC_COMPILE_DIRECTORY ${CMAKE_CXX_COMPILER} DIRECTORY)
|
||||
set(EDITBIN_DIRECTORY ${MSVC_COMPILE_DIRECTORY})
|
||||
else()
|
||||
# For clang-cl build
|
||||
# find editbin.exe from environmental variable VCToolsInstallDir
|
||||
set(EDITBIN_DIRECTORY "$ENV{VCToolsInstallDir}/bin/Hostx64/x64")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(CHECK_START "Finding editbin.exe")
|
||||
find_program(
|
||||
EDITBIN_EXECUTABLE editbin.exe
|
||||
HINTS ${EDITBIN_DIRECTORY}
|
||||
)
|
||||
|
||||
if(EDITBIN_EXECUTABLE)
|
||||
message(CHECK_PASS "found")
|
||||
else()
|
||||
message(CHECK_FAIL "not found , please manually specify EDITBIN_DIRECTORY")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Editbin
|
||||
FOUND_VAR EDITBIN_FOUND
|
||||
REQUIRED_VARS EDITBIN_EXECUTABLE
|
||||
)
|
@@ -1,65 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
FindFluidsynth
|
||||
-------
|
||||
|
||||
Finds the fluidsynth library.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``Fluidsynth_FOUND``
|
||||
True if the system has the fluidsynth library.
|
||||
``Fluidsynth_INCLUDE_DIRS``
|
||||
Include directories needed to use fluidsynth.
|
||||
``Fluidsynth_LIBRARIES``
|
||||
Libraries needed to link to fluidsynth.
|
||||
``Fluidsynth_VERSION``
|
||||
The version of the fluidsynth library which was found.
|
||||
|
||||
Cache Variables
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
``Fluidsynth_INCLUDE_DIR``
|
||||
The directory containing ``fluidsynth.h``.
|
||||
``Fluidsynth_LIBRARY``
|
||||
The path to the fluidsynth library.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_Fluidsynth QUIET fluidsynth)
|
||||
|
||||
find_path(Fluidsynth_INCLUDE_DIR
|
||||
NAMES fluidsynth.h
|
||||
PATHS ${PC_Fluidsynth_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(Fluidsynth_LIBRARY
|
||||
NAMES fluidsynth
|
||||
PATHS ${PC_Fluidsynth_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(Fluidsynth_VERSION ${PC_Fluidsynth_VERSION})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Fluidsynth
|
||||
FOUND_VAR Fluidsynth_FOUND
|
||||
REQUIRED_VARS
|
||||
Fluidsynth_LIBRARY
|
||||
Fluidsynth_INCLUDE_DIR
|
||||
VERSION_VAR Fluidsynth_VERSION
|
||||
)
|
||||
|
||||
if(Fluidsynth_FOUND)
|
||||
set(Fluidsynth_LIBRARIES ${Fluidsynth_LIBRARY})
|
||||
set(Fluidsynth_INCLUDE_DIRS ${Fluidsynth_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
Fluidsynth_INCLUDE_DIR
|
||||
Fluidsynth_LIBRARY
|
||||
)
|
@@ -1,101 +0,0 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindFontconfig
|
||||
--------------
|
||||
|
||||
Find Fontconfig headers and library.
|
||||
|
||||
Imported Targets
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``Fontconfig::Fontconfig``
|
||||
The Fontconfig library, if found.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables in your project:
|
||||
|
||||
``Fontconfig_FOUND``
|
||||
true if (the requested version of) Fontconfig is available.
|
||||
``Fontconfig_VERSION``
|
||||
the version of Fontconfig.
|
||||
``Fontconfig_LIBRARIES``
|
||||
the libraries to link against to use Fontconfig.
|
||||
``Fontconfig_INCLUDE_DIRS``
|
||||
where to find the Fontconfig headers.
|
||||
``Fontconfig_COMPILE_OPTIONS``
|
||||
this should be passed to target_compile_options(), if the
|
||||
target is not used for linking
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PKG_FONTCONFIG QUIET fontconfig)
|
||||
set(Fontconfig_COMPILE_OPTIONS ${PKG_FONTCONFIG_CFLAGS_OTHER})
|
||||
set(Fontconfig_VERSION ${PKG_FONTCONFIG_VERSION})
|
||||
|
||||
find_path( Fontconfig_INCLUDE_DIR
|
||||
NAMES
|
||||
fontconfig/fontconfig.h
|
||||
HINTS
|
||||
${PKG_FONTCONFIG_INCLUDE_DIRS}
|
||||
/usr/X11/include
|
||||
)
|
||||
|
||||
find_library( Fontconfig_LIBRARY
|
||||
NAMES
|
||||
fontconfig
|
||||
PATHS
|
||||
${PKG_FONTCONFIG_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(Fontconfig_INCLUDE_DIR AND NOT Fontconfig_VERSION)
|
||||
file(STRINGS ${Fontconfig_INCLUDE_DIR}/fontconfig/fontconfig.h _contents REGEX "^#define[ \t]+FC_[A-Z]+[ \t]+[0-9]+$")
|
||||
unset(Fontconfig_VERSION)
|
||||
foreach(VPART MAJOR MINOR REVISION)
|
||||
foreach(VLINE ${_contents})
|
||||
if(VLINE MATCHES "^#define[\t ]+FC_${VPART}[\t ]+([0-9]+)$")
|
||||
set(Fontconfig_VERSION_PART "${CMAKE_MATCH_1}")
|
||||
if(Fontconfig_VERSION)
|
||||
string(APPEND Fontconfig_VERSION ".${Fontconfig_VERSION_PART}")
|
||||
else()
|
||||
set(Fontconfig_VERSION "${Fontconfig_VERSION_PART}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Fontconfig
|
||||
FOUND_VAR
|
||||
Fontconfig_FOUND
|
||||
REQUIRED_VARS
|
||||
Fontconfig_LIBRARY
|
||||
Fontconfig_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
Fontconfig_VERSION
|
||||
)
|
||||
|
||||
|
||||
if(Fontconfig_FOUND AND NOT TARGET Fontconfig::Fontconfig)
|
||||
add_library(Fontconfig::Fontconfig UNKNOWN IMPORTED)
|
||||
set_target_properties(Fontconfig::Fontconfig PROPERTIES
|
||||
IMPORTED_LOCATION "${Fontconfig_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Fontconfig_COMPILE_OPTIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Fontconfig_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Fontconfig_LIBRARY Fontconfig_INCLUDE_DIR)
|
||||
|
||||
if(Fontconfig_FOUND)
|
||||
set(Fontconfig_LIBRARIES ${Fontconfig_LIBRARY})
|
||||
set(Fontconfig_INCLUDE_DIRS ${Fontconfig_INCLUDE_DIR})
|
||||
endif()
|
@@ -1,13 +0,0 @@
|
||||
# Autodetect grfcodec and nforenum.
|
||||
#
|
||||
|
||||
find_program(GRFCODEC_EXECUTABLE grfcodec)
|
||||
find_program(NFORENUM_EXECUTABLE nforenum)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Grfcodec
|
||||
FOUND_VAR GRFCODEC_FOUND
|
||||
REQUIRED_VARS
|
||||
GRFCODEC_EXECUTABLE
|
||||
NFORENUM_EXECUTABLE
|
||||
)
|
@@ -1,69 +0,0 @@
|
||||
# CMake provides a FindICU module since version 3.7.
|
||||
# But it doesn't use pkgconfig, doesn't set expected variables,
|
||||
# And it returns incomplete dependencies if only some modules are searched.
|
||||
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindICU
|
||||
-------
|
||||
|
||||
Finds components of the ICU library.
|
||||
|
||||
Accepted components are: uc, i18n, le, lx, io
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``ICU_FOUND``
|
||||
True if components of ICU library are found.
|
||||
``ICU_VERSION``
|
||||
The version of the ICU library which was found.
|
||||
``ICU_<c>_FOUND``
|
||||
True if the system has the <c> component of ICU library.
|
||||
``ICU_<c>_INCLUDE_DIRS``
|
||||
Include directories needed to use the <c> component of ICU library.
|
||||
``ICU_<c>_LIBRARIES``
|
||||
Libraries needed to link to the <c> component of ICU library.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
|
||||
set(ICU_KNOWN_COMPONENTS "uc" "i18n" "le" "lx" "io")
|
||||
|
||||
foreach(MOD_NAME IN LISTS ICU_FIND_COMPONENTS)
|
||||
if(NOT MOD_NAME IN_LIST ICU_KNOWN_COMPONENTS)
|
||||
message(FATAL_ERROR "Unknown ICU component: ${MOD_NAME}")
|
||||
endif()
|
||||
pkg_check_modules(PC_ICU_${MOD_NAME} QUIET icu-${MOD_NAME})
|
||||
|
||||
# Check the libraries returned by pkg-config really exist.
|
||||
unset(PC_LIBRARIES)
|
||||
foreach(LIBRARY IN LISTS PC_ICU_${MOD_NAME}_LIBRARIES)
|
||||
unset(PC_LIBRARY CACHE)
|
||||
find_library(PC_LIBRARY NAMES ${LIBRARY})
|
||||
if(NOT PC_LIBRARY)
|
||||
unset(PC_ICU_${MOD_NAME}_FOUND)
|
||||
endif()
|
||||
list(APPEND PC_LIBRARIES ${PC_LIBRARY})
|
||||
endforeach()
|
||||
unset(PC_LIBRARY CACHE)
|
||||
|
||||
if(${PC_ICU_${MOD_NAME}_FOUND})
|
||||
set(ICU_COMPONENT_FOUND TRUE)
|
||||
set(ICU_${MOD_NAME}_FOUND TRUE)
|
||||
set(ICU_${MOD_NAME}_LIBRARIES ${PC_LIBRARIES})
|
||||
set(ICU_${MOD_NAME}_INCLUDE_DIRS ${PC_ICU_${MOD_NAME}_INCLUDE_DIRS})
|
||||
set(ICU_VERSION ${PC_ICU_${MOD_NAME}_VERSION})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ICU
|
||||
FOUND_VAR ICU_FOUND
|
||||
REQUIRED_VARS ICU_COMPONENT_FOUND
|
||||
VERSION_VAR ICU_VERSION
|
||||
HANDLE_COMPONENTS
|
||||
)
|
@@ -1,133 +0,0 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindIconv
|
||||
---------
|
||||
|
||||
This module finds the ``iconv()`` POSIX.1 functions on the system.
|
||||
These functions might be provided in the regular C library or externally
|
||||
in the form of an additional library.
|
||||
|
||||
The following variables are provided to indicate iconv support:
|
||||
|
||||
.. variable:: Iconv_FOUND
|
||||
|
||||
Variable indicating if the iconv support was found.
|
||||
|
||||
.. variable:: Iconv_INCLUDE_DIRS
|
||||
|
||||
The directories containing the iconv headers.
|
||||
|
||||
.. variable:: Iconv_LIBRARIES
|
||||
|
||||
The iconv libraries to be linked.
|
||||
|
||||
.. variable:: Iconv_IS_BUILT_IN
|
||||
|
||||
A variable indicating whether iconv support is stemming from the
|
||||
C library or not. Even if the C library provides `iconv()`, the presence of
|
||||
an external `libiconv` implementation might lead to this being false.
|
||||
|
||||
Additionally, the following :prop_tgt:`IMPORTED` target is being provided:
|
||||
|
||||
.. variable:: Iconv::Iconv
|
||||
|
||||
Imported target for using iconv.
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
.. variable:: Iconv_INCLUDE_DIR
|
||||
|
||||
The directory containing the iconv headers.
|
||||
|
||||
.. variable:: Iconv_LIBRARY
|
||||
|
||||
The iconv library (if not implicitly given in the C library).
|
||||
|
||||
.. note::
|
||||
On POSIX platforms, iconv might be part of the C library and the cache
|
||||
variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
include(CMakePushCheckState)
|
||||
if(CMAKE_C_COMPILER_LOADED)
|
||||
include(CheckCSourceCompiles)
|
||||
elseif(CMAKE_CXX_COMPILER_LOADED)
|
||||
include(CheckCXXSourceCompiles)
|
||||
else()
|
||||
# If neither C nor CXX are loaded, implicit iconv makes no sense.
|
||||
set(Iconv_IS_BUILT_IN NO)
|
||||
endif()
|
||||
|
||||
# iconv can only be provided in libc on a POSIX system.
|
||||
# If any cache variable is already set, we'll skip this test.
|
||||
if(NOT DEFINED Iconv_IS_BUILT_IN)
|
||||
if(UNIX AND NOT DEFINED Iconv_INCLUDE_DIR AND NOT DEFINED Iconv_LIBRARY)
|
||||
cmake_push_check_state(RESET)
|
||||
# We always suppress the message here: Otherwise on supported systems
|
||||
# not having iconv in their C library (e.g. those using libiconv)
|
||||
# would always display a confusing "Looking for iconv - not found" message
|
||||
set(CMAKE_FIND_QUIETLY TRUE)
|
||||
# The following code will not work, but it's sufficient to see if it compiles.
|
||||
# Note: libiconv will define the iconv functions as macros, so CheckSymbolExists
|
||||
# will not yield correct results.
|
||||
set(Iconv_IMPLICIT_TEST_CODE
|
||||
"
|
||||
#include <stddef.h>
|
||||
#include <iconv.h>
|
||||
int main() {
|
||||
char *a, *b;
|
||||
size_t i, j;
|
||||
iconv_t ic;
|
||||
ic = iconv_open(\"to\", \"from\");
|
||||
iconv(ic, &a, &i, &b, &j);
|
||||
iconv_close(ic);
|
||||
}
|
||||
"
|
||||
)
|
||||
if(CMAKE_C_COMPILER_LOADED)
|
||||
check_c_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
|
||||
else()
|
||||
check_cxx_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
else()
|
||||
set(Iconv_IS_BUILT_IN NO)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT Iconv_IS_BUILT_IN)
|
||||
find_path(Iconv_INCLUDE_DIR
|
||||
NAMES "iconv.h"
|
||||
DOC "iconv include directory")
|
||||
set(Iconv_LIBRARY_NAMES "iconv" "libiconv")
|
||||
else()
|
||||
set(Iconv_INCLUDE_DIR "" CACHE FILEPATH "iconv include directory")
|
||||
set(Iconv_LIBRARY_NAMES "c")
|
||||
endif()
|
||||
|
||||
find_library(Iconv_LIBRARY
|
||||
NAMES ${Iconv_LIBRARY_NAMES}
|
||||
DOC "iconv library (potentially the C library)")
|
||||
|
||||
mark_as_advanced(Iconv_INCLUDE_DIR)
|
||||
mark_as_advanced(Iconv_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if(NOT Iconv_IS_BUILT_IN)
|
||||
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
|
||||
else()
|
||||
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY)
|
||||
endif()
|
||||
|
||||
if(Iconv_FOUND)
|
||||
set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
|
||||
set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
|
||||
if(NOT TARGET Iconv::Iconv)
|
||||
add_library(Iconv::Iconv INTERFACE IMPORTED)
|
||||
endif()
|
||||
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
|
||||
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
|
||||
endif()
|
@@ -1,89 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
FindLZO
|
||||
-------
|
||||
|
||||
Finds the LZO library.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``LZO_FOUND``
|
||||
True if the system has the LZO library.
|
||||
``LZO_INCLUDE_DIRS``
|
||||
Include directories needed to use LZO.
|
||||
``LZO_LIBRARIES``
|
||||
Libraries needed to link to LZO.
|
||||
``LZO_VERSION``
|
||||
The version of the LZO library which was found.
|
||||
|
||||
Cache Variables
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
``LZO_INCLUDE_DIR``
|
||||
The directory containing ``lzo/lzo1x.h``.
|
||||
``LZO_LIBRARY``
|
||||
The path to the LZO library.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LZO QUIET lzo2)
|
||||
|
||||
find_path(LZO_INCLUDE_DIR
|
||||
NAMES lzo/lzo1x.h
|
||||
PATHS ${PC_LZO_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(LZO_LIBRARY
|
||||
NAMES lzo2
|
||||
PATHS ${PC_LZO_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
# With vcpkg, the library path should contain both 'debug' and 'optimized'
|
||||
# entries (see target_link_libraries() documentation for more information)
|
||||
#
|
||||
# NOTE: we only patch up when using vcpkg; the same issue might happen
|
||||
# when not using vcpkg, but this is non-trivial to fix, as we have no idea
|
||||
# what the paths are. With vcpkg we do. And we only official support vcpkg
|
||||
# with Windows.
|
||||
#
|
||||
# NOTE: this is based on the assumption that the debug file has the same
|
||||
# name as the optimized file. This is not always the case, but so far
|
||||
# experiences has shown that in those case vcpkg CMake files do the right
|
||||
# thing.
|
||||
if(VCPKG_TOOLCHAIN AND LZO_LIBRARY)
|
||||
if(LZO_LIBRARY MATCHES "/debug/")
|
||||
set(LZO_LIBRARY_DEBUG ${LZO_LIBRARY})
|
||||
string(REPLACE "/debug/lib/" "/lib/" LZO_LIBRARY_RELEASE ${LZO_LIBRARY})
|
||||
else()
|
||||
set(LZO_LIBRARY_RELEASE ${LZO_LIBRARY})
|
||||
string(REPLACE "/lib/" "/debug/lib/" LZO_LIBRARY_DEBUG ${LZO_LIBRARY})
|
||||
endif()
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(LZO)
|
||||
endif()
|
||||
|
||||
set(LZO_VERSION ${PC_LZO_VERSION})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LZO
|
||||
FOUND_VAR LZO_FOUND
|
||||
REQUIRED_VARS
|
||||
LZO_LIBRARY
|
||||
LZO_INCLUDE_DIR
|
||||
VERSION_VAR LZO_VERSION
|
||||
)
|
||||
|
||||
if(LZO_FOUND)
|
||||
set(LZO_LIBRARIES ${LZO_LIBRARY})
|
||||
set(LZO_INCLUDE_DIRS ${LZO_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
LZO_INCLUDE_DIR
|
||||
LZO_LIBRARY
|
||||
)
|
@@ -1,3 +0,0 @@
|
||||
if(NOT EXISTS ${PANDOC_EXECUTABLE})
|
||||
find_program(PANDOC_EXECUTABLE pandoc)
|
||||
endif()
|
@@ -1,17 +0,0 @@
|
||||
# Autodetect if SSE4.1 can be used. If so, the assumption is, so can the other
|
||||
# SSE version (SSE 2.0, SSSE 3.0).
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set(CMAKE_REQUIRED_FLAGS "-msse4.1")
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <xmmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
int main() { return 0; }"
|
||||
SSE_FOUND
|
||||
)
|
@@ -1,19 +0,0 @@
|
||||
# Autodetect if xaudio2 can be used.
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <cstdio>
|
||||
#include <windows.h>
|
||||
|
||||
#undef NTDDI_VERSION
|
||||
#undef _WIN32_WINNT
|
||||
|
||||
#define NTDDI_VERSION NTDDI_WIN8
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WIN8
|
||||
|
||||
#include <xaudio2.h>
|
||||
int main() { printf(\"%s\\\\n\", XAUDIO2_DLL_A); return 0; }"
|
||||
XAUDIO2_FOUND
|
||||
)
|
@@ -1,222 +0,0 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# If requested, use FHS layout; otherwise fall back to a flat layout.
|
||||
if(OPTION_INSTALL_FHS)
|
||||
set(BINARY_DESTINATION_DIR "${CMAKE_INSTALL_BINDIR}")
|
||||
set(DATA_DESTINATION_DIR "${CMAKE_INSTALL_DATADIR}/${BINARY_NAME}")
|
||||
set(DOCS_DESTINATION_DIR "${CMAKE_INSTALL_DOCDIR}")
|
||||
set(MAN_DESTINATION_DIR "${CMAKE_INSTALL_MANDIR}")
|
||||
else()
|
||||
if(APPLE)
|
||||
set(BINARY_DESTINATION_DIR "../MacOS")
|
||||
else()
|
||||
set(BINARY_DESTINATION_DIR ".")
|
||||
endif()
|
||||
set(DATA_DESTINATION_DIR ".")
|
||||
set(DOCS_DESTINATION_DIR ".")
|
||||
set(MAN_DESTINATION_DIR ".")
|
||||
endif()
|
||||
|
||||
install(TARGETS openttd
|
||||
RUNTIME
|
||||
DESTINATION ${BINARY_DESTINATION_DIR}
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
install(DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/lang
|
||||
${CMAKE_BINARY_DIR}/baseset
|
||||
${CMAKE_SOURCE_DIR}/bin/ai
|
||||
${CMAKE_SOURCE_DIR}/bin/game
|
||||
${CMAKE_SOURCE_DIR}/bin/scripts
|
||||
DESTINATION ${DATA_DESTINATION_DIR}
|
||||
COMPONENT language_files)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_SOURCE_DIR}/COPYING.md
|
||||
${CMAKE_SOURCE_DIR}/README.md
|
||||
${CMAKE_SOURCE_DIR}/changelog.txt
|
||||
${CMAKE_SOURCE_DIR}/docs/multiplayer.md
|
||||
${CMAKE_SOURCE_DIR}/known-bugs.txt
|
||||
DESTINATION ${DOCS_DESTINATION_DIR}
|
||||
COMPONENT docs)
|
||||
|
||||
# A Linux manual only makes sense when using FHS. Otherwise it is a very odd
|
||||
# file with little context to what it is.
|
||||
if(OPTION_INSTALL_FHS)
|
||||
set(MAN_SOURCE_FILE ${CMAKE_SOURCE_DIR}/docs/openttd.6)
|
||||
set(MAN_BINARY_FILE ${CMAKE_BINARY_DIR}/docs/${BINARY_NAME}.6)
|
||||
install(CODE
|
||||
"
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${MAN_SOURCE_FILE} ${MAN_BINARY_FILE})
|
||||
execute_process(COMMAND gzip -9 -n -f ${MAN_BINARY_FILE})
|
||||
"
|
||||
COMPONENT manual)
|
||||
install(FILES
|
||||
${MAN_BINARY_FILE}.gz
|
||||
DESTINATION ${MAN_DESTINATION_DIR}/man6
|
||||
COMPONENT manual)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
install(DIRECTORY
|
||||
${CMAKE_BINARY_DIR}/media/icons
|
||||
${CMAKE_BINARY_DIR}/media/pixmaps
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}
|
||||
COMPONENT media)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_BINARY_DIR}/media/${BINARY_NAME}.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications
|
||||
COMPONENT menu)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(ARCHITECTURE "amd64")
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ARCHITECTURE)
|
||||
endif()
|
||||
|
||||
# Windows is a bit more annoying to detect; using the size of void pointer
|
||||
# seems to be the most robust.
|
||||
if(WIN32)
|
||||
# Check if the MSVC platform has been defined
|
||||
if ("$ENV{Platform}" STREQUAL "arm64")
|
||||
set(ARCHITECTURE "arm64")
|
||||
else()
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(ARCHITECTURE "win64")
|
||||
else()
|
||||
set(ARCHITECTURE "win32")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" ARCHITECTURE)
|
||||
endif()
|
||||
|
||||
set(CPACK_SYSTEM_NAME "${ARCHITECTURE}")
|
||||
|
||||
set(CPACK_PACKAGE_NAME "openttd")
|
||||
set(CPACK_PACKAGE_VENDOR "OpenTTD")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "OpenTTD")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenTTD")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.openttd.org/")
|
||||
set(CPACK_PACKAGE_CONTACT "OpenTTD <info@openttd.org>")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenTTD")
|
||||
set(CPACK_PACKAGE_CHECKSUM "SHA256")
|
||||
|
||||
if((APPLE OR WIN32) AND EXISTS ${PANDOC_EXECUTABLE})
|
||||
execute_process(COMMAND ${PANDOC_EXECUTABLE} "${CMAKE_SOURCE_DIR}/COPYING.md" -s -o "${CMAKE_BINARY_DIR}/COPYING.rtf")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/COPYING.rtf")
|
||||
else()
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING.md")
|
||||
endif()
|
||||
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
||||
set(CPACK_MONOLITHIC_INSTALL YES)
|
||||
set(CPACK_PACKAGE_EXECUTABLES "openttd;OpenTTD")
|
||||
set(CPACK_STRIP_FILES YES)
|
||||
set(CPACK_OUTPUT_FILE_PREFIX "bundles")
|
||||
|
||||
if(APPLE)
|
||||
set(CPACK_GENERATOR "Bundle")
|
||||
include(PackageBundle)
|
||||
|
||||
if (APPLE_UNIVERSAL_PACKAGE)
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-macos-universal")
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-macos-${CPACK_SYSTEM_NAME}")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
if(OPTION_USE_NSIS)
|
||||
list(APPEND CPACK_GENERATOR "NSIS")
|
||||
include(PackageNSIS)
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-windows-${CPACK_SYSTEM_NAME}")
|
||||
elseif(UNIX)
|
||||
# With FHS, we can create deb/rpm/... Without it, they would be horribly broken
|
||||
# and not work. The other way around is also true; with FHS they are not
|
||||
# usable, and only flat formats work.
|
||||
if(OPTION_PACKAGE_DEPENDENCIES)
|
||||
set(CPACK_GENERATOR "TXZ")
|
||||
set(PLATFORM "generic")
|
||||
elseif(NOT OPTION_INSTALL_FHS)
|
||||
set(CPACK_GENERATOR "TXZ")
|
||||
set(PLATFORM "unknown")
|
||||
else()
|
||||
find_program(LSB_RELEASE_EXEC lsb_release)
|
||||
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
|
||||
OUTPUT_VARIABLE LSB_RELEASE_ID
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(LSB_RELEASE_ID)
|
||||
if(LSB_RELEASE_ID STREQUAL "Ubuntu" OR LSB_RELEASE_ID STREQUAL "Debian")
|
||||
execute_process(COMMAND ${LSB_RELEASE_EXEC} -cs
|
||||
OUTPUT_VARIABLE LSB_RELEASE_CODENAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
string(TOLOWER "${LSB_RELEASE_ID}-${LSB_RELEASE_CODENAME}" PLATFORM)
|
||||
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
include(PackageDeb)
|
||||
else()
|
||||
set(UNSUPPORTED_PLATFORM_NAME "LSB-based Linux distribution '${LSB_RELEASE_ID}'")
|
||||
endif()
|
||||
elseif(EXISTS "/etc/os-release")
|
||||
file(STRINGS "/etc/os-release" OS_RELEASE_CONTENTS REGEX "^ID=")
|
||||
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
|
||||
set(DISTRO_ID ${CMAKE_MATCH_1})
|
||||
if(DISTRO_ID STREQUAL "arch")
|
||||
set(PLATFORM "arch")
|
||||
set(CPACK_GENERATOR "TXZ")
|
||||
else()
|
||||
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution '${DISTRO_ID}' from /etc/os-release")
|
||||
endif()
|
||||
else()
|
||||
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution")
|
||||
endif()
|
||||
|
||||
if(NOT PLATFORM)
|
||||
set(PLATFORM "generic")
|
||||
set(CPACK_GENERATOR "TXZ")
|
||||
message(WARNING "Unknown ${UNSUPPORTED_PLATFORM_NAME} found for packaging; can only pack to a txz. Please consider creating a Pull Request to add support for this distribution.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-linux-${PLATFORM}-${CPACK_SYSTEM_NAME}")
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown OS found for packaging; please consider creating a Pull Request to add support for this OS.")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
|
||||
if(OPTION_PACKAGE_DEPENDENCIES)
|
||||
# Install all dependencies we can resolve, with the exception of ones that
|
||||
# every Linux machine should have. This should make this build as generic
|
||||
# as possible, where it runs on any machine with the same or newer libc
|
||||
# than the one this is compiled with.
|
||||
# We copy these libraries into lib/ folder, so they can be found on game
|
||||
# startup. See comment in root CMakeLists.txt for how this works exactly.
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
RESOLVED_DEPENDENCIES_VAR DEPENDENCIES
|
||||
UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPENDENCIES
|
||||
EXECUTABLES openttd
|
||||
POST_EXCLUDE_REGEXES "ld-linux|libc.so|libdl.so|libm.so|libgcc_s.so|libpthread.so|librt.so|libstdc...so")
|
||||
file(INSTALL
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib"
|
||||
FILES ${DEPENDENCIES}
|
||||
FOLLOW_SYMLINK_CHAIN)
|
||||
|
||||
# This should not be possible, but error out when a dependency cannot
|
||||
# be resolved.
|
||||
list(LENGTH UNRESOLVED_DEPENDENCIES UNRESOLVED_LENGTH)
|
||||
if(${UNRESOLVED_LENGTH} GREATER 0)
|
||||
message(FATAL_ERROR "Unresolved dependencies: ${UNRESOLVED_DEPENDENCIES}")
|
||||
endif()
|
||||
]])
|
||||
endif()
|
@@ -1,23 +0,0 @@
|
||||
function(link_package NAME)
|
||||
cmake_parse_arguments(LP "ENCOURAGED" "TARGET" "" ${ARGN})
|
||||
|
||||
if(${NAME}_FOUND)
|
||||
string(TOUPPER "${NAME}" UCNAME)
|
||||
add_definitions(-DWITH_${UCNAME})
|
||||
# Some libraries' cmake packages (looking at you, SDL2) leave trailing whitespace in the link commands,
|
||||
# which (later) cmake considers to be an error. Work around this with by stripping the incoming string.
|
||||
if(LP_TARGET AND TARGET ${LP_TARGET})
|
||||
string(STRIP "${LP_TARGET}" LP_TARGET)
|
||||
target_link_libraries(openttd ${LP_TARGET})
|
||||
message(STATUS "${NAME} found -- -DWITH_${UCNAME} -- ${LP_TARGET}")
|
||||
else()
|
||||
string(STRIP "${${NAME}_LIBRARY}" ${NAME}_LIBRARY)
|
||||
string(STRIP "${${NAME}_LIBRARIES}" ${NAME}_LIBRARIES)
|
||||
include_directories(${${NAME}_INCLUDE_DIRS} ${${NAME}_INCLUDE_DIR})
|
||||
target_link_libraries(openttd ${${NAME}_LIBRARIES} ${${NAME}_LIBRARY})
|
||||
message(STATUS "${NAME} found -- -DWITH_${UCNAME} -- ${${NAME}_INCLUDE_DIRS} ${${NAME}_INCLUDE_DIR} -- ${${NAME}_LIBRARIES} ${${NAME}_LIBRARY}")
|
||||
endif()
|
||||
elseif(LP_ENCOURAGED)
|
||||
message(WARNING "${NAME} not found; compiling OpenTTD without ${NAME} is strongly disencouraged")
|
||||
endif()
|
||||
endfunction()
|
@@ -1,39 +0,0 @@
|
||||
# Add source group filters for use in generated projects.
|
||||
|
||||
source_group("AI Core" REGULAR_EXPRESSION "src/ai/")
|
||||
source_group("Blitters" REGULAR_EXPRESSION "src/blitter/")
|
||||
source_group("Core Source Code" REGULAR_EXPRESSION "src/core/")
|
||||
source_group("Game Core" REGULAR_EXPRESSION "src/game/")
|
||||
source_group("MD5" REGULAR_EXPRESSION "src/3rdparty/md5/")
|
||||
source_group("Misc" REGULAR_EXPRESSION "src/misc/")
|
||||
source_group("Music" REGULAR_EXPRESSION "src/music/")
|
||||
source_group("Network Core" REGULAR_EXPRESSION "src/network/core/")
|
||||
source_group("OSX" REGULAR_EXPRESSION "src/os/macosx/")
|
||||
source_group("Pathfinder" REGULAR_EXPRESSION "src/pathfinder/")
|
||||
source_group("Save/Load handlers" REGULAR_EXPRESSION "src/saveload/")
|
||||
source_group("Sound" REGULAR_EXPRESSION "src/sound/")
|
||||
source_group("Sprite loaders" REGULAR_EXPRESSION "src/spriteloader/")
|
||||
source_group("Squirrel" REGULAR_EXPRESSION "src/3rdparty/squirrel/squirrel/")
|
||||
source_group("Tables" REGULAR_EXPRESSION "src/table/")
|
||||
source_group("Video" REGULAR_EXPRESSION "src/video/")
|
||||
source_group("Video/GL" REGULAR_EXPRESSION "src/3rdparty/opengl/")
|
||||
source_group("Widgets" REGULAR_EXPRESSION "src/widgets/")
|
||||
source_group("Windows files" REGULAR_EXPRESSION "src/os/windows/|\.rc$")
|
||||
|
||||
# Last directive for each file wins, so make sure NPF/YAPF are after the generic pathfinder filter.
|
||||
source_group("NPF" REGULAR_EXPRESSION "src/pathfinder/npf/")
|
||||
source_group("YAPF" REGULAR_EXPRESSION "src/pathfinder/yapf/")
|
||||
|
||||
source_group("Script" REGULAR_EXPRESSION "src/script/")
|
||||
source_group("Script API Implementation" REGULAR_EXPRESSION "src/script/api/")
|
||||
source_group("Script API" REGULAR_EXPRESSION "src/script/api/.*\.hpp$")
|
||||
source_group("AI API" REGULAR_EXPRESSION "src/script/api/ai_")
|
||||
source_group("Game API" REGULAR_EXPRESSION "src/script/api/game_")
|
||||
|
||||
# Placed last to ensure any of the previous directory filters are overridden.
|
||||
source_group("Command handlers" REGULAR_EXPRESSION "_cmd\.cpp$")
|
||||
source_group("Drivers" REGULAR_EXPRESSION "_driver\.hpp$")
|
||||
source_group("GUI Source Code" REGULAR_EXPRESSION "_gui\.cpp$")
|
||||
source_group("Map Accessors" REGULAR_EXPRESSION "_map\.(cpp|h)$")
|
||||
source_group("NewGRF" REGULAR_EXPRESSION "newgrf.*cpp$")
|
||||
source_group("Squirrel headers" REGULAR_EXPRESSION "src/3rdparty/squirrel/squirrel/.*\.h$")
|
@@ -1,107 +0,0 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Set the options for the directories (personal, shared, global).
|
||||
#
|
||||
# set_directory_options()
|
||||
#
|
||||
function(set_directory_options)
|
||||
if(APPLE)
|
||||
set(DEFAULT_PERSONAL_DIR "Documents/OpenTTD")
|
||||
set(DEFAULT_SHARED_DIR "/Library/Application Support/OpenTTD")
|
||||
set(DEFAULT_GLOBAL_DIR "(not set)")
|
||||
elseif(WIN32)
|
||||
set(DEFAULT_PERSONAL_DIR "OpenTTD")
|
||||
set(DEFAULT_SHARED_DIR "(not set)")
|
||||
set(DEFAULT_GLOBAL_DIR "(not set)")
|
||||
elseif(UNIX)
|
||||
set(DEFAULT_PERSONAL_DIR ".${BINARY_NAME}")
|
||||
set(DEFAULT_SHARED_DIR "(not set)")
|
||||
set(DEFAULT_GLOBAL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${BINARY_NAME}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown OS found; please consider creating a Pull Request to add support for this OS.")
|
||||
endif()
|
||||
|
||||
if(NOT PERSONAL_DIR)
|
||||
set(PERSONAL_DIR "${DEFAULT_PERSONAL_DIR}" CACHE STRING "Personal directory")
|
||||
message(STATUS "Detecting Personal Data directory - ${PERSONAL_DIR}")
|
||||
endif()
|
||||
|
||||
if(NOT SHARED_DIR)
|
||||
set(SHARED_DIR "${DEFAULT_SHARED_DIR}" CACHE STRING "Shared directory")
|
||||
message(STATUS "Detecting Shared Data directory - ${SHARED_DIR}")
|
||||
endif()
|
||||
|
||||
if(NOT GLOBAL_DIR)
|
||||
set(GLOBAL_DIR "${DEFAULT_GLOBAL_DIR}" CACHE STRING "Global directory")
|
||||
message(STATUS "Detecting Global Data directory - ${GLOBAL_DIR}")
|
||||
endif()
|
||||
|
||||
set(HOST_BINARY_DIR "" CACHE PATH "Full path to native cmake build directory")
|
||||
endfunction()
|
||||
|
||||
# Set some generic options that influence what is being build.
|
||||
#
|
||||
# set_options()
|
||||
#
|
||||
function(set_options)
|
||||
option(OPTION_PACKAGE_DEPENDENCIES "Copy dependencies into lib/ for easy packaging (Linux only)" OFF)
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT OPTION_PACKAGE_DEPENDENCIES)
|
||||
set(DEFAULT_OPTION_INSTALL_FHS ON)
|
||||
else()
|
||||
set(DEFAULT_OPTION_INSTALL_FHS OFF)
|
||||
endif()
|
||||
|
||||
option(OPTION_FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." OFF)
|
||||
|
||||
option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF)
|
||||
option(OPTION_INSTALL_FHS "Install with Filesystem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS})
|
||||
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" OFF)
|
||||
if(EMSCRIPTEN)
|
||||
# Although pthreads is supported, it is not in a way yet that is
|
||||
# useful for us.
|
||||
option(OPTION_USE_THREADS "Use threads" OFF)
|
||||
else()
|
||||
option(OPTION_USE_THREADS "Use threads" ON)
|
||||
endif()
|
||||
option(OPTION_USE_NSIS "Use NSIS to create windows installer; enable only for stable releases" OFF)
|
||||
option(OPTION_TOOLS_ONLY "Build only tools target" OFF)
|
||||
option(OPTION_DOCS_ONLY "Build only docs target" OFF)
|
||||
|
||||
if (OPTION_DOCS_ONLY)
|
||||
set(OPTION_TOOLS_ONLY ON PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Show the values of the generic options.
|
||||
#
|
||||
# show_options()
|
||||
#
|
||||
function(show_options)
|
||||
message(STATUS "Option Package Dependencies - ${OPTION_PACKAGE_DEPENDENCIES}")
|
||||
message(STATUS "Option Dedicated - ${OPTION_DEDICATED}")
|
||||
message(STATUS "Option Install FHS - ${OPTION_INSTALL_FHS}")
|
||||
message(STATUS "Option Use assert - ${OPTION_USE_ASSERTS}")
|
||||
message(STATUS "Option Use threads - ${OPTION_USE_THREADS}")
|
||||
message(STATUS "Option Use NSIS - ${OPTION_USE_NSIS}")
|
||||
endfunction()
|
||||
|
||||
# Add the definitions for the options that are selected.
|
||||
#
|
||||
# add_definitions_based_on_options()
|
||||
#
|
||||
function(add_definitions_based_on_options)
|
||||
if(OPTION_DEDICATED)
|
||||
add_definitions(-DDEDICATED)
|
||||
endif()
|
||||
|
||||
if(NOT OPTION_USE_THREADS)
|
||||
add_definitions(-DNO_THREADS)
|
||||
endif()
|
||||
|
||||
if(OPTION_USE_ASSERTS)
|
||||
add_definitions(-DWITH_ASSERT)
|
||||
else()
|
||||
add_definitions(-DNDEBUG)
|
||||
endif()
|
||||
endfunction()
|
@@ -1,25 +0,0 @@
|
||||
string(TIMESTAMP CURRENT_YEAR "%Y")
|
||||
|
||||
set(CPACK_BUNDLE_NAME "OpenTTD")
|
||||
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/os/macosx/openttd.icns")
|
||||
set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist")
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/os/macosx/splash.png")
|
||||
set(CPACK_DMG_FORMAT "UDBZ")
|
||||
|
||||
# Create a temporary Info.plist.in, where we will fill in the version via
|
||||
# CPackProperties.cmake.in. This because at this point in time the version
|
||||
# is not yet known.
|
||||
configure_file("${CMAKE_SOURCE_DIR}/os/macosx/Info.plist.in" "${CMAKE_CURRENT_BINARY_DIR}/Info.plist.in")
|
||||
set(CPACK_BUNDLE_PLIST_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Info.plist.in")
|
||||
|
||||
# Delay fixup_bundle() till the install step; this makes sure all executables
|
||||
# exists and it can do its job.
|
||||
install(
|
||||
CODE
|
||||
"
|
||||
include(BundleUtilities)
|
||||
set(BU_CHMOD_BUNDLE_ITEMS TRUE)
|
||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/../MacOS/openttd\" \"\" \"\")
|
||||
"
|
||||
DESTINATION .
|
||||
COMPONENT Runtime)
|
@@ -1,3 +0,0 @@
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${ARCHITECTURE}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
@@ -1,39 +0,0 @@
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
|
||||
set(CPACK_NSIS_HELP_LINK "${CPACK_PACKAGE_HOMEPAGE_URL}")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "${CPACK_PACKAGE_HOMEPAGE_URL}")
|
||||
set(CPACK_NSIS_CONTACT "${CPACK_PACKAGE_CONTACT}")
|
||||
|
||||
# NSIS uses this for the icon in the top left of the installer
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/os/windows\\\\nsis-top.bmp")
|
||||
|
||||
# Set other icons and bitmaps for NSIS
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/os/windows\\\\openttd.ico")
|
||||
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/os/windows\\\\openttd.ico")
|
||||
set(CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP "${CMAKE_SOURCE_DIR}/os/windows\\\\nsis-welcome.bmp")
|
||||
set(CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP "${CMAKE_SOURCE_DIR}/os/windows\\\\nsis-welcome.bmp")
|
||||
|
||||
# Use the icon of the application
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "openttd.exe")
|
||||
# Tell NSIS the binary will be in the root
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
|
||||
# Add detail information on the NSIS installer executable. CPack doesn't
|
||||
# support this out of the box, so we use CPACK_NSIS_DEFINES for this.
|
||||
|
||||
# \\\ are needed, because this value is generated in another CPack file,
|
||||
# which is used. So one \ is to escape here, the second to escape in the
|
||||
# CPack file, which we have to escape here (hence: 3 \).
|
||||
set(CPACK_NSIS_DEFINES "
|
||||
; Version Info
|
||||
Var AddWinPrePopulate
|
||||
VIProductVersion \\\"0.0.0.0\\\"
|
||||
VIAddVersionKey \\\"ProductName\\\" \\\"OpenTTD Installer for Windows\\\"
|
||||
VIAddVersionKey \\\"Comments\\\" \\\"Installs OpenTTD \\\${VERSION}\\\"
|
||||
VIAddVersionKey \\\"CompanyName\\\" \\\"OpenTTD Developers\\\"
|
||||
VIAddVersionKey \\\"FileDescription\\\" \\\"Installs OpenTTD \\\${VERSION}\\\"
|
||||
VIAddVersionKey \\\"ProductVersion\\\" \\\"\\\${VERSION}\\\"
|
||||
VIAddVersionKey \\\"InternalName\\\" \\\"InstOpenTTD\\\"
|
||||
VIAddVersionKey \\\"FileVersion\\\" \\\"0.0.0.0\\\"
|
||||
VIAddVersionKey \\\"LegalCopyright\\\" \\\" \\\"
|
||||
"
|
||||
)
|
@@ -1,63 +0,0 @@
|
||||
# Add a file to be compiled.
|
||||
#
|
||||
# add_files([file1 ...] CONDITION condition [condition ...])
|
||||
#
|
||||
# CONDITION is a complete statement that can be evaluated with if().
|
||||
# If it evaluates true, the source files will be added; otherwise not.
|
||||
# For example: ADD_IF SDL_FOUND AND Allegro_FOUND
|
||||
#
|
||||
function(add_files)
|
||||
cmake_parse_arguments(PARAM "" "" "CONDITION" ${ARGN})
|
||||
set(PARAM_FILES "${PARAM_UNPARSED_ARGUMENTS}")
|
||||
|
||||
if(PARAM_CONDITION)
|
||||
if(NOT (${PARAM_CONDITION}))
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(FILE IN LISTS PARAM_FILES)
|
||||
target_sources(openttd PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${FILE})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# This function works around an 'issue' with CMake, where
|
||||
# set_source_files_properties() only works in the scope of the file. We want
|
||||
# to set properties for the source file on a more global level. To solve this,
|
||||
# this function records the flags you want, and a macro adds them in the root
|
||||
# CMakeLists.txt.
|
||||
# See this URL for more information on the issue:
|
||||
# http://cmake.3232098.n2.nabble.com/scope-of-set-source-files-properties-td4766111.html
|
||||
#
|
||||
# set_compile_flags([file1 ...] COMPILE_FLAGS cflag [cflag ...])
|
||||
#
|
||||
function(set_compile_flags)
|
||||
cmake_parse_arguments(PARAM "" "" "COMPILE_FLAGS" ${ARGN})
|
||||
set(PARAM_FILES "${PARAM_UNPARSED_ARGUMENTS}")
|
||||
|
||||
get_property(SOURCE_PROPERTIES GLOBAL PROPERTY source_properties)
|
||||
|
||||
foreach(FILE IN LISTS PARAM_FILES)
|
||||
list(APPEND SOURCE_PROPERTIES "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}::${PARAM_COMPILE_FLAGS}")
|
||||
endforeach()
|
||||
|
||||
set_property(GLOBAL PROPERTY source_properties "${SOURCE_PROPERTIES}")
|
||||
endfunction()
|
||||
|
||||
# Call this macro in the same CMakeLists.txt and after add_executable().
|
||||
# This makes sure all the COMPILE_FLAGS of set_compile_flags() are set
|
||||
# correctly.
|
||||
#
|
||||
# process_compile_flags()
|
||||
#
|
||||
function(process_compile_flags)
|
||||
get_property(SOURCE_PROPERTIES GLOBAL PROPERTY source_properties)
|
||||
|
||||
foreach(ENTRY ${SOURCE_PROPERTIES})
|
||||
string(REPLACE "::" ";" ENTRY "${ENTRY}")
|
||||
list(GET ENTRY 0 FILE)
|
||||
list(GET ENTRY 1 PROPERTIES)
|
||||
|
||||
set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS ${PROPERTIES})
|
||||
endforeach()
|
||||
endfunction()
|
@@ -1,14 +0,0 @@
|
||||
# Set static linking if the platform requires it.
|
||||
#
|
||||
# set_static()
|
||||
#
|
||||
function(set_static_if_needed)
|
||||
if(MINGW)
|
||||
# Let exectutables run outside MinGW environment
|
||||
# Force searching static libs
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" PARENT_SCOPE)
|
||||
|
||||
# Force static linking
|
||||
link_libraries(-static -static-libgcc -static-libstdc++)
|
||||
endif()
|
||||
endfunction()
|
@@ -1,63 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
#
|
||||
# Create a single baseset meta file with the correct translations.
|
||||
#
|
||||
|
||||
if(NOT BASESET_SOURCE_FILE)
|
||||
message(FATAL_ERROR "Script needs BASESET_SOURCE_FILE defined")
|
||||
endif()
|
||||
if(NOT BASESET_BINARY_FILE)
|
||||
message(FATAL_ERROR "Script needs BASESET_BINARY_FILE defined")
|
||||
endif()
|
||||
if(NOT BASESET_EXTRAGRF_FILE)
|
||||
message(FATAL_ERROR "Script needs BASESET_EXTRAGRF_FILE defined")
|
||||
endif()
|
||||
|
||||
set(ARGC 1)
|
||||
set(ARG_READ NO)
|
||||
|
||||
# Read all the arguments given to CMake; we are looking for -- and everything
|
||||
# that follows. Those are our language files.
|
||||
while(ARGC LESS CMAKE_ARGC)
|
||||
set(ARG ${CMAKE_ARGV${ARGC}})
|
||||
|
||||
if(ARG_READ)
|
||||
list(APPEND LANG_SOURCE_FILES "${ARG}")
|
||||
endif()
|
||||
|
||||
if(ARG STREQUAL "--")
|
||||
set(ARG_READ YES)
|
||||
endif()
|
||||
|
||||
math(EXPR ARGC "${ARGC} + 1")
|
||||
endwhile()
|
||||
|
||||
# Place holder format is @<ini_key>_<str_id>@
|
||||
file(STRINGS "${BASESET_SOURCE_FILE}" PLACE_HOLDER REGEX "^@")
|
||||
string(REGEX REPLACE "@([^_]+).*@" "\\1" INI_KEY "${PLACE_HOLDER}")
|
||||
string(REGEX REPLACE "@[^_]+_(.*)@" "\\1" STR_ID "${PLACE_HOLDER}")
|
||||
string(REGEX REPLACE "@(.*)@" "\\1" PLACE_HOLDER "${PLACE_HOLDER}")
|
||||
|
||||
# Get the translations
|
||||
foreach(LANGFILE IN LISTS LANG_SOURCE_FILES)
|
||||
file(STRINGS "${LANGFILE}" LANGLINES REGEX "^(##isocode|${STR_ID})" ENCODING UTF-8)
|
||||
string(FIND "${LANGLINES}" "${STR_ID}" HAS_STR_ID)
|
||||
if(HAS_STR_ID LESS 0)
|
||||
continue()
|
||||
endif()
|
||||
string(REGEX REPLACE "##isocode ([^;]+).*" "\\1" ISOCODE "${LANGLINES}")
|
||||
if("${ISOCODE}" STREQUAL "en_GB")
|
||||
string(REGEX REPLACE "[^:]*:(.*)" "${INI_KEY} = \\1" LANGLINES "${LANGLINES}")
|
||||
else()
|
||||
string(REGEX REPLACE "[^:]*:(.*)" "${INI_KEY}.${ISOCODE} = \\1" LANGLINES "${LANGLINES}")
|
||||
endif()
|
||||
list(APPEND ${PLACE_HOLDER} ${LANGLINES})
|
||||
endforeach()
|
||||
list(SORT ${PLACE_HOLDER})
|
||||
string(REPLACE ";" "\n" ${PLACE_HOLDER} "${${PLACE_HOLDER}}")
|
||||
|
||||
# Get the grf md5
|
||||
file(MD5 ${BASESET_EXTRAGRF_FILE} ORIG_EXTRA_GRF_MD5)
|
||||
|
||||
configure_file(${BASESET_SOURCE_FILE} ${BASESET_BINARY_FILE})
|
@@ -1,44 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
#
|
||||
# Create a single GRF file based on sprites/<grfname>.nfo and sprites/*.png
|
||||
# files.
|
||||
#
|
||||
|
||||
if(NOT NFORENUM_EXECUTABLE)
|
||||
message(FATAL_ERROR "Script needs NFORENUM_EXECUTABLE defined")
|
||||
endif()
|
||||
if(NOT GRFCODEC_EXECUTABLE)
|
||||
message(FATAL_ERROR "Script needs GRFCODEC_EXECUTABLE defined")
|
||||
endif()
|
||||
if(NOT GRF_SOURCE_FOLDER)
|
||||
message(FATAL_ERROR "Script needs GRF_SOURCE_FOLDER defined")
|
||||
endif()
|
||||
if(NOT GRF_BINARY_FILE)
|
||||
message(FATAL_ERROR "Script needs GRF_BINARY_FILE defined")
|
||||
endif()
|
||||
|
||||
get_filename_component(GRF_SOURCE_FOLDER_NAME "${GRF_SOURCE_FOLDER}" NAME)
|
||||
|
||||
file(WRITE sprites/${GRF_SOURCE_FOLDER_NAME}.nfo "")
|
||||
file(READ ${GRF_SOURCE_FOLDER}/${GRF_SOURCE_FOLDER_NAME}.nfo NFO_LINES)
|
||||
# Replace ; with \;, and make a list out of this based on \n
|
||||
string(REPLACE ";" "\\;" NFO_LINES "${NFO_LINES}")
|
||||
string(REPLACE "\n" ";" NFO_LINES "${NFO_LINES}")
|
||||
|
||||
foreach(NFO_LINE IN LISTS NFO_LINES)
|
||||
# Recover the ; that was really in the text (and not a newline)
|
||||
string(REPLACE "\\;" ";" NFO_LINE "${NFO_LINE}")
|
||||
|
||||
if(NFO_LINE MATCHES "^#include")
|
||||
string(REGEX REPLACE "^#include \"(.*)\"$" "\\1" INCLUDE_FILE ${NFO_LINE})
|
||||
file(READ ${GRF_SOURCE_FOLDER}/${INCLUDE_FILE} INCLUDE_LINES)
|
||||
file(APPEND sprites/${GRF_SOURCE_FOLDER_NAME}.nfo "${INCLUDE_LINES}")
|
||||
else()
|
||||
file(APPEND sprites/${GRF_SOURCE_FOLDER_NAME}.nfo "${NFO_LINE}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
execute_process(COMMAND ${NFORENUM_EXECUTABLE} -s sprites/${GRF_SOURCE_FOLDER_NAME}.nfo)
|
||||
execute_process(COMMAND ${GRFCODEC_EXECUTABLE} -n -s -e -p1 ${GRF_SOURCE_FOLDER_NAME}.grf)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${GRF_SOURCE_FOLDER_NAME}.grf ${GRF_BINARY_FILE})
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user