mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-13 17:49:10 +00:00
Compare commits
183 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1cf141fab5 | ||
|
f6d62e18e0 | ||
|
9097f2b1d4 | ||
|
84d1c4e8c5 | ||
|
68d1b29e19 | ||
|
76d427fdfd | ||
|
4b6e53b31c | ||
|
f167d9bc50 | ||
|
28235ceaaf | ||
|
ca55aa310b | ||
|
3baf4aa4a2 | ||
|
dbaf192ba0 | ||
|
9f333a98bc | ||
|
13259028b1 | ||
|
4ecd0b659d | ||
|
515849e764 | ||
|
ed4a9edba5 | ||
|
b83f6733ca | ||
|
b0e8d229ee | ||
|
fe8bb8da91 | ||
|
a221bece84 | ||
|
cd32a5f18c | ||
|
a6c7987a43 | ||
|
10b6fc898b | ||
|
e3a245369e | ||
|
71347cae43 | ||
|
5edc24e66a | ||
|
7fff0a71f2 | ||
|
79a7bf75a0 | ||
|
526b2ae81b | ||
|
aa6a621f0a | ||
|
141da0127f | ||
|
95adb04eae | ||
|
516a01c761 | ||
|
c40f10d6d4 | ||
|
4f757bb914 | ||
|
aafb49b3c4 | ||
|
4bbc264c72 | ||
|
f042798507 | ||
|
909edb84af | ||
|
906a606418 | ||
|
2c6a0e46a9 | ||
|
236237740a | ||
|
3a195edcad | ||
|
c50cf74889 | ||
|
4b6d1f9027 | ||
|
c9c087e858 | ||
|
ac66e29910 | ||
|
b7749bde91 | ||
|
635eff5e51 | ||
|
4cd6870777 | ||
|
54cfb12334 | ||
|
2d746c52c8 | ||
|
cb001e017a | ||
|
9bee2fc641 | ||
|
7399e107e1 | ||
|
70db6b3f40 | ||
|
ac6aefa07b | ||
|
c04f0af19b | ||
|
c8c8667dc8 | ||
|
a0688e8d85 | ||
|
c85022e3db | ||
|
be39b87154 | ||
|
71aa3a4de2 | ||
|
f7fd8eca21 | ||
|
ab77a35093 | ||
|
a808b77b2b | ||
|
52a0d04473 | ||
|
64f7b3a059 | ||
|
b70c3613fa | ||
|
3158cdaa7a | ||
|
140abde4ef | ||
|
850f73719f | ||
|
d2ce2009b5 | ||
|
6ad4716dc1 | ||
|
0ec558f99f | ||
|
41727b6e23 | ||
|
c559703312 | ||
|
1e7cca8f8b | ||
|
759d155b08 | ||
|
11b1c6f2ee | ||
|
98f77876e6 | ||
|
5a703390ec | ||
|
e925f8b2c3 | ||
|
01e3d92118 | ||
|
9321458918 | ||
|
cd6d6d32d3 | ||
|
5bfdc6e75a | ||
|
274f841c61 | ||
|
2b8a0dfacb | ||
|
4ba3761ab1 | ||
|
93586cb6b6 | ||
|
c4768438b7 | ||
|
b3b28dced2 | ||
|
3b2bcbf0f0 | ||
|
1cdfa87b21 | ||
|
9e3f020ae8 | ||
|
36134a7285 | ||
|
edc2ac8bbf | ||
|
c92b6e1e8b | ||
|
524919326b | ||
|
2d3a64ffcc | ||
|
9aa9579283 | ||
|
3f987f460d | ||
|
23e62bfb15 | ||
|
bbbe65e1e5 | ||
|
e3c71534e1 | ||
|
f8b2fb4484 | ||
|
87bbb7a413 | ||
|
61b95ff1fc | ||
|
0543461f5e | ||
|
4e3652f337 | ||
|
1584e061eb | ||
|
03bfa6e525 | ||
|
5467635bf9 | ||
|
47c158bbc5 | ||
|
4e1c7b8197 | ||
|
1ec915e1c8 | ||
|
b30c56d15a | ||
|
c3fcb2ef2a | ||
|
1a5957ef7f | ||
|
0867ed49a3 | ||
|
6c3b245d88 | ||
|
a74b15af79 | ||
|
ac3b1883ed | ||
|
40245ce496 | ||
|
c73bbe531e | ||
|
8576c2cc40 | ||
|
1778566ab8 | ||
|
a4bab5f17f | ||
|
06367834c6 | ||
|
f08141ae48 | ||
|
25059d28df | ||
|
b57b2224e9 | ||
|
70920944d8 | ||
|
06b5d32983 | ||
|
34f8ab2f81 | ||
|
315ec78344 | ||
|
0bf1d6c49d | ||
|
6f291a7e6d | ||
|
04d77258c5 | ||
|
fbfa0b8009 | ||
|
8960b5740f | ||
|
30fadfb54b | ||
|
b342991853 | ||
|
0a635c692e | ||
|
0a211097ac | ||
|
1277599c30 | ||
|
bae0695ac9 | ||
|
630f81c382 | ||
|
2684cb2525 | ||
|
610b6e3953 | ||
|
563857d5bd | ||
|
58d18a3ef3 | ||
|
0b7ab719f3 | ||
|
f5439821c1 | ||
|
d11a6a439a | ||
|
99096b83bd | ||
|
75c538962d | ||
|
51cd7bd43b | ||
|
0b67caa8ad | ||
|
4ec96ba2d0 | ||
|
b93e8d6c71 | ||
|
ac945ced7e | ||
|
5c190a0c33 | ||
|
b5715acaf8 | ||
|
0e7701fbe6 | ||
|
59167f686e | ||
|
0adf61e7fa | ||
|
6fa93f4a7a | ||
|
f3424f51bc | ||
|
6c8f12de78 | ||
|
953fc9e196 | ||
|
737220f39c | ||
|
e00a47d47d | ||
|
cf52f00f46 | ||
|
d4b335fffb | ||
|
652e834ee7 | ||
|
dfab8c779b | ||
|
bbdbdf3818 | ||
|
0264283116 | ||
|
6f97748c80 | ||
|
65d6403497 |
45
.gitignore
vendored
45
.gitignore
vendored
@@ -1,45 +0,0 @@
|
||||
bin/*
|
||||
!bin/ai
|
||||
bin/ai/*
|
||||
!bin/ai/compat*.nut
|
||||
!bin/ai/regression
|
||||
!bin/data
|
||||
bin/baseset/*
|
||||
!bin/baseset/openttd.grf
|
||||
!bin/baseset/opntitle.dat
|
||||
!bin/baseset/orig_extra.grf
|
||||
!bin/baseset/orig_*.obg
|
||||
!bin/baseset/orig_*.obs
|
||||
!bin/baseset/no_sound.obs
|
||||
!bin/baseset/no_music.obm
|
||||
!bin/baseset/orig_*.obm
|
||||
!bin/scripts
|
||||
bin/scripts/*
|
||||
!bin/scripts/*.example
|
||||
!bin/scripts/readme.txt
|
||||
|
||||
bundle/*
|
||||
bundles/*
|
||||
docs/aidocs/*
|
||||
docs/gamedocs/*
|
||||
docs/source/*
|
||||
media/openttd.desktop
|
||||
media/openttd.desktop.install
|
||||
objs/*
|
||||
projects/Debug
|
||||
projects/Release
|
||||
projects/*.ncb
|
||||
projects/*.suo
|
||||
projects/*.sdf
|
||||
projects/*.opensdf
|
||||
projects/*.vcproj.*.user
|
||||
projects/*.vcxproj.user
|
||||
src/rev.cpp
|
||||
src/os/windows/ottdres.rc
|
||||
|
||||
/Makefile*
|
||||
!/Makefile.msvc
|
||||
/config.*
|
||||
!/config.lib
|
||||
!*.in
|
||||
*.tmp
|
29
.hgignore
29
.hgignore
@@ -1,29 +0,0 @@
|
||||
syntax: glob
|
||||
|
||||
.svn
|
||||
bin/baseset/openttd.32.bmp
|
||||
bin/lang/*
|
||||
bin/openttd*
|
||||
bin/*.cfg
|
||||
bundle/*
|
||||
bundles/*
|
||||
config.cache*
|
||||
config.log
|
||||
config.pwd
|
||||
docs/aidocs/*
|
||||
docs/gamedocs/*
|
||||
docs/source/*
|
||||
Makefile
|
||||
Makefile.am
|
||||
Makefile.bundle
|
||||
media/openttd.desktop
|
||||
media/openttd.desktop.install
|
||||
objs/*
|
||||
projects/*.ncb
|
||||
projects/*.suo
|
||||
projects/*.sdf
|
||||
projects/*.opensdf
|
||||
projects/*.vcproj.*.user
|
||||
projects/*.vcxproj.user
|
||||
src/rev.cpp
|
||||
src/os/windows/ottdres.rc
|
7
BUGS
Normal file
7
BUGS
Normal file
@@ -0,0 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
KNOWN BUGS / PROBLEMS:
|
||||
|
||||
Normal and elrail depots look the same. Use 'X' (transparent buildings)
|
||||
to distinguish between them
|
||||
Missing curors / icons for construction (currently using the conventional ones)
|
4
COPYING
4
COPYING
@@ -1,7 +1,3 @@
|
||||
This is the license which applies to OpenTTD with the exception of some
|
||||
3rd party modules. See readme.txt for details
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
31
Doxyfile
31
Doxyfile
@@ -1,17 +1,11 @@
|
||||
# $Id$
|
||||
|
||||
# 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
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = OpenTTD
|
||||
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" \
|
||||
@@ -33,6 +27,7 @@ STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 2
|
||||
@@ -82,22 +77,22 @@ WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./src/
|
||||
INPUT = ./
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
*.hpp
|
||||
table/*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS = */3rdparty */.svn */script/api
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =./docs/
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
@@ -163,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
|
||||
@@ -190,19 +185,19 @@ 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 = ENABLE_NETWORK WITH_ZLIB WITH_LZO WITH_LZMA WITH_SDL WITH_PNG WITH_FONTCONFIG WITH_FREETYPE WITH_ICU_SORT WITH_ICU_LAYOUT UNICODE _UNICODE _GNU_SOURCE FINAL=
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE = objs/openttd.tag
|
||||
GENERATE_TAGFILE = openttd.tag
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
@@ -225,6 +220,8 @@ DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
|
@@ -1,229 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
#
|
||||
# Creation of bundles
|
||||
#
|
||||
|
||||
# The revision is needed for the bundle name and creating an OSX application bundle.
|
||||
# Detect the revision
|
||||
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
|
||||
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
|
||||
|
||||
# Make sure we have something in REV
|
||||
ifeq ($(REV),)
|
||||
REV := norev000
|
||||
endif
|
||||
|
||||
ifndef BUNDLE_NAME
|
||||
BUNDLE_NAME = openttd-custom-$(REV)-$(OS)
|
||||
endif
|
||||
|
||||
# An OSX application bundle needs the data files, lang files and openttd executable in a different location.
|
||||
ifdef OSXAPP
|
||||
AI_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/ai
|
||||
GAME_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/game
|
||||
BASESET_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/baseset
|
||||
LANG_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/lang
|
||||
TTD_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/MacOS
|
||||
else
|
||||
AI_DIR = $(BUNDLE_DIR)/ai
|
||||
GAME_DIR = $(BUNDLE_DIR)/game
|
||||
BASESET_DIR = $(BUNDLE_DIR)/baseset
|
||||
LANG_DIR = $(BUNDLE_DIR)/lang
|
||||
TTD_DIR = $(BUNDLE_DIR)
|
||||
endif
|
||||
|
||||
bundle: all
|
||||
@echo '[BUNDLE] Constructing bundle'
|
||||
$(Q)rm -rf "$(BUNDLE_DIR)"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/docs"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/media"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/scripts"
|
||||
$(Q)mkdir -p "$(TTD_DIR)"
|
||||
$(Q)mkdir -p "$(AI_DIR)"
|
||||
$(Q)mkdir -p "$(GAME_DIR)"
|
||||
$(Q)mkdir -p "$(BASESET_DIR)"
|
||||
$(Q)mkdir -p "$(LANG_DIR)"
|
||||
ifdef OSXAPP
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources"
|
||||
$(Q)echo "APPL????" > "$(BUNDLE_DIR)/$(OSXAPP)/Contents/PkgInfo"
|
||||
$(Q)cp "$(ROOT_DIR)/os/macosx/openttd.icns" "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/openttd.icns"
|
||||
$(Q)$(ROOT_DIR)/os/macosx/plistgen.sh "$(BUNDLE_DIR)/$(OSXAPP)" "$(REV)"
|
||||
$(Q)cp "$(ROOT_DIR)/os/macosx/splash.png" "$(BASESET_DIR)"
|
||||
endif
|
||||
ifeq ($(OS),UNIX)
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.32.bmp" "$(BASESET_DIR)/"
|
||||
endif
|
||||
$(Q)cp "$(BIN_DIR)/$(TTD)" "$(TTD_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/ai/"compat_*.nut "$(AI_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/game/"compat_*.nut "$(GAME_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/baseset/"*.grf "$(BASESET_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/baseset/"*.obg "$(BASESET_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/baseset/"*.obs "$(BASESET_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/baseset/opntitle.dat" "$(BASESET_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/baseset/"*.obm "$(BASESET_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/lang/"*.lng "$(LANG_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/readme.txt" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/COPYING" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.txt" "$(BUNDLE_DIR)/docs/"
|
||||
$(Q)cp "$(ROOT_DIR)/changelog.txt" "$(BUNDLE_DIR)/"
|
||||
ifdef MAN_DIR
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/man/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/openttd.6" "$(BUNDLE_DIR)/man/"
|
||||
$(Q)gzip -9 "$(BUNDLE_DIR)/man/openttd.6"
|
||||
endif
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/"
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd."*.png "$(BUNDLE_DIR)/media/"
|
||||
$(Q)cp "$(BIN_DIR)/scripts/"* "$(BUNDLE_DIR)/scripts/"
|
||||
ifdef MENU_DIR
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/"
|
||||
$(Q)$(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.translation.awk" "$(SRC_DIR)/lang/"*.txt | LC_ALL=C $(SORT) | $(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.filter.awk" >> "$(BUNDLE_DIR)/media/openttd.desktop"
|
||||
$(Q)sed s/=openttd/=$(BINARY_NAME)/g "$(BUNDLE_DIR)/media/openttd.desktop" > "$(ROOT_DIR)/media/openttd.desktop.install"
|
||||
endif
|
||||
ifeq ($(TTD), openttd.exe)
|
||||
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/readme.txt" "$(BUNDLE_DIR)/COPYING" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt"
|
||||
ifeq ($(OS), DOS)
|
||||
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi/cwsdpmi.txt" "$(BUNDLE_DIR)/docs/"
|
||||
ifndef STRIP
|
||||
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi/cwsdpmi.exe" "$(TTD_DIR)/"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
### Packing the current bundle into several compressed file formats ###
|
||||
#
|
||||
# Zips & dmgs do not contain a root folder, i.e. they have files in the root of the zip/dmg.
|
||||
# gzip, bzip2 and lha archives have a root folder, with the same name as the bundle.
|
||||
#
|
||||
# One can supply a custom name by adding BUNDLE_NAME:=<name> to the make command.
|
||||
#
|
||||
bundle_zip: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).zip'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)cd "$(BUNDLE_DIR)" && zip -r $(shell if test -z "$(VERBOSE)"; then echo '-q'; fi) "$(BUNDLES_DIR)/$(BUNDLE_NAME).zip" .
|
||||
|
||||
bundle_7z: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).7z'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)cd "$(BUNDLE_DIR)" && 7z a "$(BUNDLES_DIR)/$(BUNDLE_NAME).7z" .
|
||||
|
||||
bundle_gzip: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.gz'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.gzip" && tar -zc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.gz" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.gzip"
|
||||
|
||||
bundle_bzip2: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.bz2'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.bzip2" && tar -jc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.bz2" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.bzip2"
|
||||
|
||||
bundle_lzma: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.lzma'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.lzma/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lzma/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.lzma" && tar --lzma -c$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.lzma" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.lzma"
|
||||
|
||||
bundle_xz: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.xz'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.xz/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.xz/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.xz" && tar --xz -c$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.xz" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.xz"
|
||||
|
||||
bundle_lha: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).lha'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.lha" && lha ao6 "$(BUNDLES_DIR)/$(BUNDLE_NAME).lha" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.lha"
|
||||
|
||||
bundle_dmg: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).dmg'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/" "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
$(Q)hdiutil create -ov -format UDZO -srcfolder "$(BUNDLES_DIR)/OpenTTD $(REV)" "$(BUNDLES_DIR)/$(BUNDLE_NAME).dmg"
|
||||
$(Q)rm -fr "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
|
||||
bundle_exe: all
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)unix2dos "$(ROOT_DIR)/docs/"*.txt "$(ROOT_DIR)/readme.txt" "$(ROOT_DIR)/COPYING" "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt"
|
||||
$(Q)cd $(ROOT_DIR)/os/windows/installer && makensis.exe //DVERSION_INCLUDE=version_$(PLATFORM).txt install.nsi
|
||||
$(Q)mv $(ROOT_DIR)/os/windows/installer/*$(PLATFORM).exe "$(BUNDLES_DIR)/$(BUNDLE_NAME).exe"
|
||||
|
||||
ifdef OSXAPP
|
||||
install:
|
||||
@echo '[INSTALL] Cannot install the OSX Application Bundle'
|
||||
else
|
||||
install: bundle
|
||||
@echo '[INSTALL] Installing OpenTTD'
|
||||
$(Q)install -d "$(INSTALL_BINARY_DIR)"
|
||||
$(Q)install -d "$(INSTALL_ICON_DIR)"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/ai"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/game"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/baseset"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/lang"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/scripts"
|
||||
ifeq ($(TTD), openttd.exe)
|
||||
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}.exe"
|
||||
else
|
||||
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}"
|
||||
endif
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/lang/"* "$(INSTALL_DATA_DIR)/lang"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/ai/"* "$(INSTALL_DATA_DIR)/ai"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/game/"* "$(INSTALL_DATA_DIR)/game"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/baseset/"* "$(INSTALL_DATA_DIR)/baseset"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/scripts/"* "$(INSTALL_DATA_DIR)/scripts"
|
||||
ifndef DO_NOT_INSTALL_DOCS
|
||||
$(Q)install -d "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/readme.txt" "$(BUNDLE_DIR)/known-bugs.txt" "$(INSTALL_DOC_DIR)"
|
||||
endif
|
||||
ifndef DO_NOT_INSTALL_CHANGELOG
|
||||
$(Q)install -d "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/changelog.txt" "$(INSTALL_DOC_DIR)"
|
||||
endif
|
||||
ifndef DO_NOT_INSTALL_LICENSE
|
||||
$(Q)install -d "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING" "$(INSTALL_DOC_DIR)"
|
||||
endif
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)/${BINARY_NAME}.32.xpm"
|
||||
ifdef ICON_THEME_DIR
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/16x16/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.16.png" "$(INSTALL_ICON_THEME_DIR)/16x16/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/32x32/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.png" "$(INSTALL_ICON_THEME_DIR)/32x32/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/48x48/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.48.png" "$(INSTALL_ICON_THEME_DIR)/48x48/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/64x64/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.64.png" "$(INSTALL_ICON_THEME_DIR)/64x64/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/128x128/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.128.png" "$(INSTALL_ICON_THEME_DIR)/128x128/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/256x256/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.256.png" "$(INSTALL_ICON_THEME_DIR)/256x256/apps/${BINARY_NAME}.png"
|
||||
else
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/"*.png "$(INSTALL_ICON_DIR)"
|
||||
endif
|
||||
ifdef MAN_DIR
|
||||
ifndef DO_NOT_INSTALL_MAN
|
||||
$(Q)install -d "$(INSTALL_MAN_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/man/openttd.6.gz" "$(INSTALL_MAN_DIR)/${BINARY_NAME}.6.gz"
|
||||
endif
|
||||
endif
|
||||
ifdef MENU_DIR
|
||||
$(Q)install -d "$(INSTALL_MENU_DIR)"
|
||||
$(Q)install -m 644 "$(ROOT_DIR)/media/openttd.desktop.install" "$(INSTALL_MENU_DIR)/${BINARY_NAME}.desktop"
|
||||
endif
|
||||
endif # OSXAPP
|
100
Makefile.grf.in
100
Makefile.grf.in
@@ -1,100 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
#
|
||||
# Building requires GRFCodec.
|
||||
#
|
||||
# Recent versions (including sources) can be found at:
|
||||
# http://www.openttd.org/download-grfcodec
|
||||
#
|
||||
# The mercurial repository can be found at:
|
||||
# http://hg.openttdcoop.org/grfcodec
|
||||
#
|
||||
|
||||
|
||||
ROOT_DIR = !!ROOT_DIR!!
|
||||
GRF_DIR = $(ROOT_DIR)/media/extra_grf
|
||||
BASESET_DIR = $(ROOT_DIR)/media/baseset
|
||||
LANG_DIR = $(ROOT_DIR)/src/lang
|
||||
BIN_DIR = !!BIN_DIR!!/baseset
|
||||
OBJS_DIR = !!GRF_OBJS_DIR!!
|
||||
OS = !!OS!!
|
||||
STAGE = !!STAGE!!
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
GRFCODEC := !!GRFCODEC!!
|
||||
NFORENUM := !!NFORENUM!!
|
||||
CC_BUILD := !!CC_BUILD!!
|
||||
MD5SUM := $(shell [ "$(OS)" = "OSX" ] && echo "md5 -r" || echo "md5sum")
|
||||
|
||||
# Some "should not be changed" settings.
|
||||
NFO_FILES := $(GRF_DIR)/*.nfo $(GRF_DIR)/rivers/*.nfo
|
||||
PNG_FILES := $(GRF_DIR)/*.png $(GRF_DIR)/rivers/*.png
|
||||
|
||||
# Build the GRF.
|
||||
ifdef GRFCODEC
|
||||
all: $(BIN_DIR)/openttd.grf $(BIN_DIR)/orig_extra.grf $(BIN_DIR)/orig_dos.obg $(BIN_DIR)/orig_dos_de.obg $(BIN_DIR)/orig_win.obg $(BIN_DIR)/orig_dos.obs $(BIN_DIR)/orig_win.obs $(BIN_DIR)/no_sound.obs $(BIN_DIR)/orig_win.obm $(BIN_DIR)/no_music.obm
|
||||
else
|
||||
all:
|
||||
endif
|
||||
|
||||
$(OBJS_DIR)/langfiles.tmp: $(LANG_DIR)/*.txt
|
||||
$(E) '$(STAGE) Collecting baseset translations'
|
||||
$(Q) cat $^ > $@
|
||||
|
||||
$(BIN_DIR)/%.obg: $(BASESET_DIR)/%.obg $(BIN_DIR)/orig_extra.grf $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
|
||||
$(E) '$(STAGE) Updating $(notdir $@)'
|
||||
$(Q) sed 's/^ORIG_EXTRA.GRF = *[0-9a-f]*$$/ORIG_EXTRA.GRF = '`$(MD5SUM) $(BIN_DIR)/orig_extra.grf | sed 's@ .*@@'`'/' $< > $@.tmp
|
||||
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $@.tmp >$@
|
||||
$(Q) rm $@.tmp
|
||||
|
||||
$(BIN_DIR)/%.obs: $(BASESET_DIR)/%.obs $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
|
||||
$(E) '$(STAGE) Updating $(notdir $@)'
|
||||
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $< >$@
|
||||
|
||||
$(BIN_DIR)/%.obm: $(BASESET_DIR)/%.obm $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
|
||||
$(E) '$(STAGE) Updating $(notdir $@)'
|
||||
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $< >$@
|
||||
|
||||
# Compile extra grf
|
||||
$(BIN_DIR)/openttd.grf: $(PNG_FILES) $(NFO_FILES) $(GRF_DIR)/assemble_nfo.awk
|
||||
$(E) '$(STAGE) Assembling openttd.nfo'
|
||||
$(Q)-mkdir -p $(OBJS_DIR)/sprites
|
||||
$(Q)-cp $(PNG_FILES) $(OBJS_DIR)/sprites 2> /dev/null
|
||||
$(Q) awk -f $(GRF_DIR)/assemble_nfo.awk $(GRF_DIR)/openttd.nfo > $(OBJS_DIR)/sprites/openttd.nfo
|
||||
$(Q) $(NFORENUM) -s $(OBJS_DIR)/sprites/openttd.nfo
|
||||
$(E) '$(STAGE) Compiling openttd.grf'
|
||||
$(Q) $(GRFCODEC) -n -s -e -p1 $(OBJS_DIR)/openttd.grf
|
||||
$(Q)cp $(OBJS_DIR)/openttd.grf $(BIN_DIR)/openttd.grf
|
||||
|
||||
# The copy operation of PNG_FILES is duplicated from the target 'openttd.grf', thus those targets may not run in parallel.
|
||||
$(BIN_DIR)/orig_extra.grf: $(PNG_FILES) $(NFO_FILES) $(GRF_DIR)/assemble_nfo.awk | $(BIN_DIR)/openttd.grf
|
||||
$(E) '$(STAGE) Assembling orig_extra.nfo'
|
||||
$(Q)-mkdir -p $(OBJS_DIR)/sprites
|
||||
$(Q)-cp $(PNG_FILES) $(OBJS_DIR)/sprites 2> /dev/null
|
||||
$(Q) awk -f $(GRF_DIR)/assemble_nfo.awk $(GRF_DIR)/orig_extra.nfo > $(OBJS_DIR)/sprites/orig_extra.nfo
|
||||
$(Q) $(NFORENUM) -s $(OBJS_DIR)/sprites/orig_extra.nfo
|
||||
$(E) '$(STAGE) Compiling orig_extra.grf'
|
||||
$(Q) $(GRFCODEC) -n -s -e -p1 $(OBJS_DIR)/orig_extra.grf
|
||||
$(Q)cp $(OBJS_DIR)/orig_extra.grf $(BIN_DIR)/orig_extra.grf
|
||||
|
||||
# Clean up temporary files.
|
||||
clean:
|
||||
$(Q)rm -f *.bak *.grf
|
||||
|
||||
# Clean up temporary files
|
||||
mrproper: clean
|
||||
$(Q)rm -fr sprites
|
||||
|
||||
.PHONY: all mrproper depend clean
|
187
Makefile.in
187
Makefile.in
@@ -1,187 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
include Makefile.am
|
||||
|
||||
CONFIG_CACHE_PWD = !!CONFIG_CACHE_PWD!!
|
||||
CONFIG_CACHE_SOURCE_LIST = !!CONFIG_CACHE_SOURCE_LIST!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
ICON_THEME_DIR = !!ICON_THEME_DIR!!
|
||||
MAN_DIR = !!MAN_DIR!!
|
||||
MENU_DIR = !!MENU_DIR!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
ROOT_DIR = !!ROOT_DIR!!
|
||||
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
|
||||
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
|
||||
INSTALL_DIR = !!INSTALL_DIR!!
|
||||
INSTALL_BINARY_DIR = "$(INSTALL_DIR)/"!!BINARY_DIR!!
|
||||
INSTALL_MAN_DIR = "$(INSTALL_DIR)/$(MAN_DIR)"
|
||||
INSTALL_MENU_DIR = "$(INSTALL_DIR)/$(MENU_DIR)"
|
||||
INSTALL_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!!
|
||||
INSTALL_ICON_THEME_DIR = "$(INSTALL_DIR)/$(ICON_THEME_DIR)"
|
||||
INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!!
|
||||
INSTALL_DOC_DIR = "$(INSTALL_DIR)/"!!DOC_DIR!!
|
||||
SOURCE_LIST = !!SOURCE_LIST!!
|
||||
CONFIGURE_FILES = !!CONFIGURE_FILES!!
|
||||
BINARY_NAME = !!BINARY_NAME!!
|
||||
STRIP = !!STRIP!!
|
||||
TTD = !!TTD!!
|
||||
TTDS = $(SRC_DIRS:%=%/$(TTD))
|
||||
OS = !!OS!!
|
||||
OSXAPP = !!OSXAPP!!
|
||||
LIPO = !!LIPO!!
|
||||
AWK = !!AWK!!
|
||||
SORT = !!SORT!!
|
||||
DISTCC = !!DISTCC!!
|
||||
|
||||
RES := $(shell if [ ! -f $(CONFIG_CACHE_PWD) ] || [ "`pwd`" != "`cat $(CONFIG_CACHE_PWD)`" ]; then echo "`pwd`" > $(CONFIG_CACHE_PWD); fi )
|
||||
RES := $(shell if [ ! -f $(CONFIG_CACHE_SOURCE_LIST) ] || [ -n "`cmp $(CONFIG_CACHE_SOURCE_LIST) $(SOURCE_LIST) 2>/dev/null`" ]; then cp $(SOURCE_LIST) $(CONFIG_CACHE_SOURCE_LIST); fi )
|
||||
|
||||
all: config.pwd config.cache
|
||||
ifdef DISTCC
|
||||
@if [ -z "`echo '$(MFLAGS)' | grep '\-j'`" ]; then echo; echo "WARNING: you enabled distcc support, but you don't seem to be using the -jN paramter"; echo; fi
|
||||
endif
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir all || exit 1; \
|
||||
done
|
||||
ifdef LIPO
|
||||
# Lipo is an OSX thing. If it is defined, it means we are building for universal,
|
||||
# and so we have have to combine the binaries into one big binary
|
||||
|
||||
# Remove the last binary made by the last compiled target
|
||||
$(Q)rm -f $(BIN_DIR)/$(TTD)
|
||||
# Make all the binaries into one
|
||||
$(Q)$(LIPO) -create -output $(BIN_DIR)/$(TTD) $(TTDS)
|
||||
endif
|
||||
|
||||
help:
|
||||
@echo "Available make commands:"
|
||||
@echo ""
|
||||
@echo "Compilation:"
|
||||
@echo " all compile the executable and the lang files"
|
||||
@echo " lang compile the lang files only"
|
||||
@echo "Clean up:"
|
||||
@echo " clean remove the files generated during compilation"
|
||||
@echo " mrproper remove the files generated during configuration and compilation"
|
||||
@echo "Run after compilation:"
|
||||
@echo " run execute openttd after the compilation"
|
||||
@echo " run-gdb execute openttd in debug mode after the compilation"
|
||||
@echo " run-prof execute openttd in profiling mode after the compilation"
|
||||
@echo "Installation:"
|
||||
@echo " install install the compiled files and the data-files after the compilation"
|
||||
@echo " bundle create the base for an installation bundle"
|
||||
@echo " bundle_zip create the zip installation bundle"
|
||||
@echo " bundle_gzip create the gzip installation bundle"
|
||||
@echo " bundle_bzip2 create the bzip2 installation bundle"
|
||||
@echo " bundle_lha create the lha installation bundle"
|
||||
@echo " bundle_dmg create the dmg installation bundle"
|
||||
|
||||
config.pwd: $(CONFIG_CACHE_PWD)
|
||||
$(MAKE) reconfigure
|
||||
|
||||
config.cache: $(CONFIG_CACHE_SOURCE_LIST) $(CONFIGURE_FILES)
|
||||
$(MAKE) reconfigure
|
||||
|
||||
reconfigure:
|
||||
ifeq ($(shell if test -f config.cache; then echo 1; fi), 1)
|
||||
@echo "----------------"
|
||||
@echo "The system detected that source.list or any configure file is altered."
|
||||
@echo " Going to reconfigure with last known settings..."
|
||||
@echo "----------------"
|
||||
# Make sure we don't lock config.cache
|
||||
@$(shell cat config.cache | sed 's@\\ @\\\\ @g') || exit 1
|
||||
@echo "----------------"
|
||||
@echo "Reconfig done. Please re-execute make."
|
||||
@echo "----------------"
|
||||
else
|
||||
@echo "----------------"
|
||||
@echo "Have not found a configuration, please run configure first."
|
||||
@echo "----------------"
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
clean:
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir clean; \
|
||||
done
|
||||
$(Q)rm -rf $(BUNDLE_TARGET)
|
||||
|
||||
lang:
|
||||
@for dir in $(LANG_DIRS); do \
|
||||
$(MAKE) -C $$dir all; \
|
||||
done
|
||||
|
||||
mrproper:
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir mrproper; \
|
||||
done
|
||||
# Don't be tempted to merge these two for loops. Doing that breaks make
|
||||
# --dry-run, since make has this "feature" that it always runs commands
|
||||
# containing $(MAKE), even when --dry-run is passed. The objective is of
|
||||
# course to also get a dry-run of submakes, but make is not smart enough
|
||||
# to see that a for loop runs both a submake and an actual command.
|
||||
@for dir in $(DIRS); do \
|
||||
rm -f $$dir/Makefile; \
|
||||
done
|
||||
$(Q)rm -rf objs
|
||||
$(Q)rm -f Makefile Makefile.am Makefile.bundle
|
||||
$(Q)rm -f media/openttd.desktop media/openttd.desktop.install
|
||||
$(Q)rm -f $(CONFIG_CACHE_SOURCE_LIST) config.cache config.pwd config.log $(CONFIG_CACHE_PWD)
|
||||
# directories for bundle generation
|
||||
$(Q)rm -rf $(BUNDLE_DIR)
|
||||
$(Q)rm -rf $(BUNDLES_DIR)
|
||||
# output of profiling
|
||||
$(Q)rm -f $(BIN_DIR)/gmon.out
|
||||
# output of generating 'API' documentation
|
||||
$(Q)rm -rf $(ROOT_DIR)/docs/source
|
||||
$(Q)rm -rf $(ROOT_DIR)/docs/aidocs
|
||||
$(Q)rm -rf $(ROOT_DIR)/docs/gamedocs
|
||||
# directories created by OpenTTD on regression testing
|
||||
$(Q)rm -rf $(BIN_DIR)/ai/regression/content_download $(BIN_DIR)/ai/regression/save $(BIN_DIR)/ai/regression/scenario
|
||||
distclean: mrproper
|
||||
|
||||
maintainer-clean: distclean
|
||||
$(Q)rm -f $(BIN_DIR)/baseset/openttd.grf $(BIN_DIR)/baseset/orig_extra.grf $(BIN_DIR)/baseset/*.obg $(BIN_DIR)/baseset/*.obs $(BIN_DIR)/baseset/*.obm
|
||||
|
||||
depend:
|
||||
@for dir in $(SRC_DIRS); do \
|
||||
$(MAKE) -C $$dir depend; \
|
||||
done
|
||||
|
||||
run: all
|
||||
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS)
|
||||
|
||||
run-gdb: all
|
||||
$(Q)cd !!BIN_DIR!! && gdb --ex run --args ./!!TTD!! $(OPENTTD_ARGS)
|
||||
|
||||
run-prof: all
|
||||
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS) && gprof !!TTD!! | less
|
||||
|
||||
regression: all
|
||||
$(Q)cd !!BIN_DIR!! && sh ai/regression/run.sh
|
||||
test: regression
|
||||
|
||||
%.o:
|
||||
@for dir in $(SRC_DIRS); do \
|
||||
$(MAKE) -C $$dir $(@:src/%=%); \
|
||||
done
|
||||
|
||||
%.lng:
|
||||
@for dir in $(LANG_DIRS); do \
|
||||
$(MAKE) -C $$dir $@; \
|
||||
done
|
||||
|
||||
.PHONY: test distclean mrproper clean
|
||||
|
||||
include Makefile.bundle
|
105
Makefile.lang.in
105
Makefile.lang.in
@@ -1,105 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
STRGEN = !!STRGEN!!
|
||||
ENDIAN_CHECK = !!ENDIAN_CHECK!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
LANG_DIR = !!LANG_DIR!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
LANGS_SRC = $(shell ls $(LANG_DIR)/*.txt)
|
||||
LANGS = $(LANGS_SRC:$(LANG_DIR)/%.txt=%.lng)
|
||||
CXX_BUILD = !!CXX_BUILD!!
|
||||
CFLAGS_BUILD = !!CFLAGS_BUILD!!
|
||||
CXXFLAGS_BUILD= !!CXXFLAGS_BUILD!!
|
||||
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
|
||||
STRGEN_FLAGS = !!STRGEN_FLAGS!!
|
||||
STAGE = !!STAGE!!
|
||||
LANG_SUPPRESS = !!LANG_SUPPRESS!!
|
||||
LANG_OBJS_DIR = !!LANG_OBJS_DIR!!
|
||||
|
||||
ifeq ($(LANG_SUPPRESS), yes)
|
||||
LANG_ERRORS = >/dev/null 2>&1
|
||||
endif
|
||||
|
||||
# Make sure endian_host.h is reachable as if it was in the src/ dir
|
||||
CFLAGS_BUILD += -I $(LANG_OBJS_DIR)
|
||||
|
||||
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
RES := $(shell mkdir -p $(BIN_DIR)/lang )
|
||||
|
||||
all: table/strings.h $(LANGS)
|
||||
|
||||
strgen_base.o: $(SRC_DIR)/strgen/strgen_base.cpp $(SRC_DIR)/strgen/strgen.h endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
strgen.o: $(SRC_DIR)/strgen/strgen.cpp $(SRC_DIR)/strgen/strgen.h endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
string.o: $(SRC_DIR)/string.cpp endian_host.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
lang/english.txt: $(LANG_DIR)/english.txt
|
||||
$(Q)mkdir -p lang
|
||||
$(Q)cp $(LANG_DIR)/english.txt lang/english.txt
|
||||
|
||||
$(STRGEN): alloc_func.o string.o strgen_base.o strgen.o getoptdata.o
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $^ -o $@
|
||||
|
||||
table/strings.h: lang/english.txt $(STRGEN)
|
||||
$(E) '$(STAGE) Generating $@'
|
||||
@mkdir -p table
|
||||
$(Q)./$(STRGEN) -s $(LANG_DIR) -d table
|
||||
|
||||
$(LANGS): %.lng: $(LANG_DIR)/%.txt $(STRGEN) lang/english.txt
|
||||
$(E) '$(STAGE) Compiling language $(*F)'
|
||||
$(Q)./$(STRGEN) $(STRGEN_FLAGS) -s $(LANG_DIR) -d $(LANG_OBJS_DIR) $< $(LANG_ERRORS) && cp $@ $(BIN_DIR)/lang || true # Do not fail all languages when one fails
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_host.h: $(ENDIAN_CHECK)
|
||||
$(E) '$(STAGE) Testing endianness for host'
|
||||
$(Q)./$(ENDIAN_CHECK) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
|
||||
|
||||
depend:
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up language files'
|
||||
$(Q)rm -f strgen.o string.o alloc_func.o getoptdata.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* $(ENDIAN_TARGETS)
|
||||
|
||||
mrproper: clean
|
||||
$(Q)rm -rf $(BIN_DIR)/lang
|
||||
|
||||
%.lng:
|
||||
@echo '$(STAGE) No such language: $(@:%.lng=%)'
|
||||
|
||||
.PHONY: all mrproper depend clean
|
@@ -1,47 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
#
|
||||
# Makefile for creating bundles of MSVC's binaries in the same way as we make
|
||||
# the zip bundles for ALL other OSes.
|
||||
#
|
||||
# Usage: make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=openttd-<version>-win[32|64]
|
||||
# or make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=OTTD-win[32|64]-nightly-<revision>
|
||||
#
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
AWK = "awk"
|
||||
ROOT_DIR := $(shell pwd)
|
||||
BIN_DIR = "$(ROOT_DIR)/bin"
|
||||
SRC_DIR = "$(ROOT_DIR)/src"
|
||||
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
|
||||
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
|
||||
TTD = openttd.exe
|
||||
PDB = openttd.pdb
|
||||
MODE = Release
|
||||
TARGET := $(shell echo $(PLATFORM) | sed "s@win64@x64@;s@win32@Win32@")
|
||||
|
||||
all:
|
||||
$(Q)cp objs/$(TARGET)/$(MODE)/$(TTD) $(BIN_DIR)/$(TTD)
|
||||
|
||||
include Makefile.bundle.in
|
||||
|
||||
bundle_pdb:
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).pdb.xz'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)cp objs/$(TARGET)/Release/$(PDB) $(BUNDLES_DIR)/$(BUNDLE_NAME).pdb
|
||||
$(Q)xz -9 $(BUNDLES_DIR)/$(BUNDLE_NAME).pdb
|
||||
|
||||
regression: all
|
||||
$(Q)cp bin/$(TTD) bin/openttd
|
||||
$(Q)cd bin && sh ai/regression/run.sh
|
@@ -1,78 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
SETTINGSGEN = !!SETTINGSGEN!!
|
||||
ENDIAN_CHECK = !!ENDIAN_CHECK!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
CXX_BUILD = !!CXX_BUILD!!
|
||||
CFLAGS_BUILD = !!CFLAGS_BUILD!!
|
||||
CXXFLAGS_BUILD = !!CXXFLAGS_BUILD!!
|
||||
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
|
||||
STAGE = !!STAGE!!
|
||||
SETTING_OBJS_DIR = !!SETTING_OBJS_DIR!!
|
||||
|
||||
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
all: table/settings.h
|
||||
|
||||
settingsgen.o: $(SRC_DIR)/settingsgen/settingsgen.cpp $(SRC_DIR)/string_func.h $(SRC_DIR)/strings_type.h $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/ini_type.h $(SRC_DIR)/core/smallvec_type.hpp $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
|
||||
|
||||
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
|
||||
|
||||
getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
|
||||
|
||||
string.o: $(SRC_DIR)/string.cpp endian_host.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
|
||||
|
||||
ini_load.o: $(SRC_DIR)/ini_load.cpp $(SRC_DIR)/core/alloc_func.hpp $(SRC_DIR)/core/mem_func.hpp $(SRC_DIR)/ini_type.h $(SRC_DIR)/string_func.h $(SRC_DIR)/safeguards.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
|
||||
|
||||
$(SETTINGSGEN): alloc_func.o string.o ini_load.o settingsgen.o getoptdata.o
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $^ -o $@
|
||||
|
||||
table/settings.h: $(SETTINGSGEN) $(SRC_DIR)/table/settings.h.preamble $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
|
||||
$(E) '$(STAGE) Generating $@'
|
||||
@mkdir -p table
|
||||
$(Q)./$(SETTINGSGEN) -o table/settings.h -b $(SRC_DIR)/table/settings.h.preamble -a $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_host.h: $(ENDIAN_CHECK)
|
||||
$(E) '$(STAGE) Testing endianness for host'
|
||||
$(Q)./$(ENDIAN_CHECK) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
|
||||
|
||||
depend:
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up settings files'
|
||||
$(Q)rm -f settingsgen.o alloc_func.o getoptdata.o ini_load.o $(SETTINGSGEN) $(ENDIAN_TARGETS) table/settings.h
|
||||
|
||||
mrproper: clean
|
||||
|
||||
.PHONY: all mrproper depend clean
|
315
Makefile.src.in
315
Makefile.src.in
@@ -1,315 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# 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/>.
|
||||
|
||||
CC_HOST = !!CC_HOST!!
|
||||
CXX_HOST = !!CXX_HOST!!
|
||||
CC_BUILD = !!CC_BUILD!!
|
||||
CXX_BUILD = !!CXX_BUILD!!
|
||||
WINDRES = !!WINDRES!!
|
||||
STRIP = !!STRIP!!
|
||||
CFLAGS = !!CFLAGS!!
|
||||
CFLAGS_BUILD = !!CFLAGS_BUILD!!
|
||||
CXXFLAGS = !!CXXFLAGS!!
|
||||
CXXFLAGS_BUILD = !!CXXFLAGS_BUILD!!
|
||||
LIBS = !!LIBS!!
|
||||
LDFLAGS = !!LDFLAGS!!
|
||||
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
|
||||
ROOT_DIR = !!ROOT_DIR!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
LANG_DIR = !!LANG_DIR!!
|
||||
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
|
||||
LANG_OBJS_DIR = !!LANG_OBJS_DIR!!
|
||||
SETTING_OBJS_DIR= !!SETTING_OBJS_DIR!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!!
|
||||
MEDIA_DIR = !!MEDIA_DIR!!
|
||||
TTD = !!TTD!!
|
||||
STRGEN = !!STRGEN!!
|
||||
ENDIAN_CHECK = !!ENDIAN_CHECK!!
|
||||
DEPEND = !!DEPEND!!
|
||||
ENDIAN_FORCE = !!ENDIAN_FORCE!!
|
||||
OS = !!OS!!
|
||||
STAGE = !!STAGE!!
|
||||
MAKEDEPEND = !!MAKEDEPEND!!
|
||||
CFLAGS_MAKEDEP = !!CFLAGS_MAKEDEP!!
|
||||
SORT = !!SORT!!
|
||||
AWK = !!AWK!!
|
||||
CONFIG_CACHE_COMPILER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_COMPILER!!
|
||||
CONFIG_CACHE_LINKER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_LINKER!!
|
||||
CONFIG_CACHE_ENDIAN = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_ENDIAN!!
|
||||
CONFIG_CACHE_SOURCE = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_SOURCE!!
|
||||
CONFIG_CACHE_VERSION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_VERSION!!
|
||||
|
||||
OBJS_C := !!OBJS_C!!
|
||||
OBJS_CPP := !!OBJS_CPP!!
|
||||
OBJS_MM := !!OBJS_MM!!
|
||||
OBJS_RC := !!OBJS_RC!!
|
||||
OBJS := $(OBJS_C) $(OBJS_CPP) $(OBJS_MM) $(OBJS_RC)
|
||||
SRCS := !!SRCS!!
|
||||
|
||||
# All C-files depend on those 3 files
|
||||
FILE_DEP := $(CONFIG_CACHE_COMPILER) endian_target.h
|
||||
# Create all dirs and subdirs
|
||||
RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
|
||||
|
||||
# Make sure endian_target.h is reasable as if it was in the src/ dir
|
||||
CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
|
||||
CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
|
||||
ifdef SCRIPT_SRC_DIR
|
||||
CFLAGS_MAKEDEP += -I $(SCRIPT_SRC_DIR)
|
||||
endif
|
||||
|
||||
ENDIAN_TARGETS := endian_target.h $(ENDIAN_CHECK)
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
# Our default target
|
||||
all: $(BIN_DIR)/$(TTD)
|
||||
|
||||
# This are 2 rules that are pointing back to STRGEN stuff.
|
||||
# There is not really a need to have them here, but in case
|
||||
# some weirdo wants to run 'make' in the 'src' dir and expects
|
||||
# the languages to be recompiled, this catches that case and
|
||||
# takes care of it nicely.
|
||||
$(LANG_OBJS_DIR)/$(STRGEN):
|
||||
$(MAKE) -C $(LANG_OBJS_DIR) $(STRGEN)
|
||||
|
||||
$(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
|
||||
$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
|
||||
|
||||
# Always run version detection, so we always have an accurate modified
|
||||
# flag
|
||||
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
|
||||
MODIFIED := $(shell echo "$(VERSIONS)" | cut -f 3 -d' ')
|
||||
|
||||
# Use autodetected revisions
|
||||
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
|
||||
REV_NR := $(shell echo "$(VERSIONS)" | cut -f 2 -d' ')
|
||||
|
||||
# Make sure we have something in REV and REV_NR
|
||||
ifeq ($(REV),)
|
||||
REV := norev000
|
||||
endif
|
||||
ifeq ($(REV_NR),)
|
||||
REV_NR := 0
|
||||
endif
|
||||
|
||||
# This helps to recompile if flags change
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_COMPILER) 2>/dev/null`" != "$(CFLAGS) $(CXXFLAGS)" ]; then echo "$(CFLAGS) $(CXXFLAGS)" > $(CONFIG_CACHE_COMPILER); fi )
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_LINKER) 2>/dev/null`" != "$(LDFLAGS) $(LIBS)" ]; then echo "$(LDFLAGS) $(LIBS)" > $(CONFIG_CACHE_LINKER); fi )
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_ENDIAN) 2>/dev/null`" != "$(ENDIAN_FORCE)" ]; then echo "$(ENDIAN_FORCE)" > $(CONFIG_CACHE_ENDIAN); fi )
|
||||
|
||||
# If there is a change in the source-file-list, make sure we recheck the deps
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_SOURCE) 2>/dev/null`" != "$(SRCS)" ]; then echo "$(SRCS)" > $(CONFIG_CACHE_SOURCE); fi )
|
||||
# If there is a change in the revision, make sure we recompile rev.cpp
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_VERSION) 2>/dev/null`" != "$(REV) $(MODIFIED)" ]; then echo "$(REV) $(MODIFIED)" > $(CONFIG_CACHE_VERSION); fi )
|
||||
|
||||
ifndef MAKEDEPEND
|
||||
# The slow, but always correct, dep-check
|
||||
DEP_MASK := %.d
|
||||
DEPS := $(OBJS:%.o=%.d)
|
||||
|
||||
# Only include the deps if we are compiling everything
|
||||
ifeq ($(filter $(ENDIAN_TARGETS) %.o clean mrproper, $(MAKECMDGOALS)),)
|
||||
-include $(DEPS)
|
||||
else
|
||||
# In case we want to compile a single target, include the .d file for it
|
||||
ifneq ($(filter %.o, $(MAKECMDGOALS)),)
|
||||
SINGLE_DEP := $(filter %.o, $(MAKECMDGOALS))
|
||||
-include $(SINGLE_DEP:%.o=%.d)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Find the deps via GCC. Rarely wrong, but a bit slow
|
||||
|
||||
$(OBJS_C:%.o=%.d): %.d: $(SRC_DIR)/%.c $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.c=%.c)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_CPP:%.o=%.d): %.d: $(SRC_DIR)/%.cpp $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_MM:%.o=%.d): %.d: $(SRC_DIR)/%.mm $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_RC:%.o=%.d): %.d: $(SRC_DIR)/%.rc $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.rc=%.rc)'
|
||||
$(Q)touch $@
|
||||
|
||||
else
|
||||
# The much faster, but can be wrong, dep-check
|
||||
DEP_MASK :=
|
||||
DEPS := Makefile.dep
|
||||
|
||||
# Only include the deps if we are not cleaning
|
||||
ifeq ($(filter $(ENDIAN_TARGETS) depend clean mrproper, $(MAKECMDGOALS)),)
|
||||
-include Makefile.dep
|
||||
endif
|
||||
|
||||
ifeq ("$(SRC_OBJS_DIR)/$(DEPEND)","$(MAKEDEPEND)")
|
||||
DEP := $(MAKEDEPEND)
|
||||
$(SRC_OBJS_DIR)/$(DEPEND): $(SRC_DIR)/depend/depend.cpp
|
||||
$(E) '$(STAGE) Compiling and linking $(DEPEND)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) -o $@ $<
|
||||
endif
|
||||
|
||||
# Make sure that only 'make depend' ALWAYS triggers a recheck
|
||||
ifeq ($(filter depend, $(MAKECMDGOALS)),)
|
||||
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(CONFIG_CACHE_SOURCE) $(DEP)
|
||||
else
|
||||
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(DEP) FORCE
|
||||
endif
|
||||
$(E) '$(STAGE) DEP CHECK (all files)'
|
||||
$(Q)rm -f Makefile.dep.tmp
|
||||
$(Q)touch Makefile.dep.tmp
|
||||
|
||||
# Calculate the deps via makedepend
|
||||
$(Q)$(MAKEDEPEND) -f$(SRC_OBJS_DIR)/Makefile.dep.tmp -o.o -Y -v -- $(CFLAGS_MAKEDEP) -- $(SRCS:%=$(SRC_DIR)/%) 2>/dev/null
|
||||
|
||||
# Convert x:/... paths to /x/... for mingw
|
||||
ifeq ($(OS), MINGW)
|
||||
@cat Makefile.dep.tmp | sed 's@/\([a-zA-Z]\):\/@\/\1\/@g' > Makefile.dep.tmp.mingw
|
||||
@cp Makefile.dep.tmp.mingw Makefile.dep.tmp
|
||||
@rm -f Makefile.dep.tmp.mingw
|
||||
endif
|
||||
|
||||
# Remove all comments and includes that don't start with $(SRC_DIR)
|
||||
# Remove $(SRC_DIR) from object-file-name
|
||||
@$(AWK) ' \
|
||||
/^# DO NOT/ { print $$0 ; next} \
|
||||
/^#/ {next} \
|
||||
/: / { \
|
||||
left = NF - 1; \
|
||||
for (n = 2; n <= NF; n++) { \
|
||||
if (match($$n, "^$(ROOT_DIR)") == 0) { \
|
||||
$$n = ""; \
|
||||
left--; \
|
||||
} \
|
||||
} \
|
||||
gsub("$(SRC_DIR)/", "", $$1); \
|
||||
if (left > 0) { \
|
||||
print $$0; \
|
||||
$$1 = "Makefile.dep:"; \
|
||||
print $$0; \
|
||||
} \
|
||||
next \
|
||||
} \
|
||||
{ \
|
||||
print $$0 \
|
||||
} \
|
||||
' < Makefile.dep.tmp | sed 's@ *@ @g;s@ $$@@' | LC_ALL=C $(SORT) > Makefile.dep
|
||||
|
||||
$(Q)rm -f Makefile.dep.tmp Makefile.dep.tmp.bak
|
||||
|
||||
endif
|
||||
|
||||
# Avoid problems with deps if a .h/.hpp/.hpp.sq file is deleted without the deps
|
||||
# being updated. Now the Makefile continues, the deps are recreated
|
||||
# and all will be fine.
|
||||
%.h %.hpp %.hpp.sq:
|
||||
@true
|
||||
|
||||
|
||||
# Compile all the files according to the targets
|
||||
|
||||
$(OBJS_C): %.o: $(SRC_DIR)/%.c $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.c=%.c)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(filter-out %sse2.o, $(filter-out %ssse3.o, $(filter-out %sse4.o, $(OBJS_CPP)))): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(filter %sse2.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -msse2 -o $@ $<
|
||||
|
||||
$(filter %ssse3.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -mssse3 -o $@ $<
|
||||
|
||||
$(filter %sse4.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -msse4.1 -o $@ $<
|
||||
|
||||
$(OBJS_MM): %.o: $(SRC_DIR)/%.mm $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJS_RC): %.o: $(SRC_DIR)/%.rc $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
|
||||
$(Q)$(WINDRES) -o $@ -I `basename $<` $<
|
||||
|
||||
$(BIN_DIR)/$(TTD): $(TTD)
|
||||
$(Q)cp $(TTD) $(BIN_DIR)/$(TTD)
|
||||
ifeq ($(OS), UNIX)
|
||||
$(Q)cp $(MEDIA_DIR)/openttd.32.bmp $(BIN_DIR)/baseset/
|
||||
endif
|
||||
ifeq ($(OS), OSX)
|
||||
$(Q)cp $(ROOT_DIR)/os/macosx/splash.png $(BIN_DIR)/baseset/
|
||||
endif
|
||||
|
||||
$(TTD): $(OBJS) $(CONFIG_CACHE_LINKER)
|
||||
$(E) '$(STAGE) Linking $@'
|
||||
ifeq ($(OS), PSP)
|
||||
# Because of a bug in the PSP GCC tools, linking via CXX results
|
||||
# in total chaos and more problems then you can handle. So we need
|
||||
# CC to link OpenTTD for PSP
|
||||
$(Q)+$(CC_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
else
|
||||
$(Q)+$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
endif
|
||||
ifdef STRIP
|
||||
$(Q)$(STRIP) $@
|
||||
endif
|
||||
ifeq ($(OS), DOS)
|
||||
$(E) '$(STAGE) Adding CWSDPMI stub to $@'
|
||||
$(Q)$(ROOT_DIR)/os/dos/make_dos_binary_selfcontained.sh $(SRC_OBJS_DIR)/$@
|
||||
endif
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN)
|
||||
$(E) '$(STAGE) Testing endianness for target'
|
||||
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
|
||||
|
||||
# Revision files
|
||||
|
||||
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
|
||||
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!MODIFIED!!@$(MODIFIED)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/rev.cpp
|
||||
|
||||
$(SRC_DIR)/os/windows/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/os/windows/ottdres.rc.in
|
||||
$(Q)cat $(SRC_DIR)/os/windows/ottdres.rc.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/os/windows/ottdres.rc
|
||||
|
||||
FORCE:
|
||||
|
||||
depend: $(DEPS)
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up object files'
|
||||
$(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(DEPEND) $(TTD:%=$(BIN_DIR)/%) $(BIN_DIR)/baseset/openttd.32.bmp $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS)
|
||||
|
||||
mrproper: clean
|
||||
$(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/os/windows/ottdres.rc
|
||||
|
||||
%.o:
|
||||
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
|
||||
|
||||
.PHONY: all mrproper depend clean FORCE
|
247
ai/ai.c
Normal file
247
ai/ai.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../openttd.h"
|
||||
#include "../variables.h"
|
||||
#include "../command.h"
|
||||
#include "../network.h"
|
||||
#include "ai.h"
|
||||
#include "default/default.h"
|
||||
|
||||
/**
|
||||
* Dequeues commands put in the queue via AI_PutCommandInQueue.
|
||||
*/
|
||||
static void AI_DequeueCommands(PlayerID player)
|
||||
{
|
||||
AICommand *com, *entry_com;
|
||||
|
||||
entry_com = _ai_player[player].queue;
|
||||
|
||||
/* It happens that DoCommandP issues a new DoCommandAI which adds a new command
|
||||
* to this very same queue (don't argue about this, if it currently doesn't
|
||||
* happen I can tell you it will happen with AIScript -- TrueLight). If we
|
||||
* do not make the queue NULL, that commands will be dequeued immediatly.
|
||||
* Therefor we safe the entry-point to entry_com, and make the queue NULL, so
|
||||
* the new queue can be safely built up. */
|
||||
_ai_player[player].queue = NULL;
|
||||
_ai_player[player].queue_tail = NULL;
|
||||
|
||||
/* Dequeue all commands */
|
||||
while ((com = entry_com) != NULL) {
|
||||
_current_player = player;
|
||||
|
||||
_cmd_text = com->text;
|
||||
DoCommandP(com->tile, com->p1, com->p2, com->callback, com->procc);
|
||||
|
||||
/* Free item */
|
||||
entry_com = com->next;
|
||||
free(com->text);
|
||||
free(com);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
|
||||
* will make infinite loops (AIScript).
|
||||
*/
|
||||
static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCallback* callback)
|
||||
{
|
||||
AICommand *com;
|
||||
|
||||
if (_ai_player[player].queue_tail == NULL) {
|
||||
/* There is no item in the queue yet, create the queue */
|
||||
_ai_player[player].queue = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue;
|
||||
} else {
|
||||
/* Add an item at the end */
|
||||
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
|
||||
}
|
||||
|
||||
/* This is our new item */
|
||||
com = _ai_player[player].queue_tail;
|
||||
|
||||
/* Assign the info */
|
||||
com->tile = tile;
|
||||
com->p1 = p1;
|
||||
com->p2 = p2;
|
||||
com->procc = procc;
|
||||
com->callback = callback;
|
||||
com->next = NULL;
|
||||
com->text = NULL;
|
||||
|
||||
/* Copy the cmd_text, if needed */
|
||||
if (_cmd_text != NULL) {
|
||||
com->text = strdup(_cmd_text);
|
||||
_cmd_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a raw DoCommand for the AI.
|
||||
*/
|
||||
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
|
||||
{
|
||||
PlayerID old_lp;
|
||||
int32 res = 0;
|
||||
const char* tmp_cmdtext;
|
||||
|
||||
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
|
||||
* person.. should we check for those funny jokes?
|
||||
*/
|
||||
|
||||
/* The test already resets _cmd_text, so backup the pointer */
|
||||
tmp_cmdtext = _cmd_text;
|
||||
|
||||
/* First, do a test-run to see if we can do this */
|
||||
res = DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc);
|
||||
/* The command failed, or you didn't want to execute, or you are quering, return */
|
||||
if (CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Restore _cmd_text */
|
||||
_cmd_text = tmp_cmdtext;
|
||||
|
||||
/* If we did a DC_EXEC, and the command did not return an error, execute it
|
||||
* over the network */
|
||||
if (flags & DC_AUTO) procc |= CMD_AUTO;
|
||||
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
|
||||
|
||||
/* NetworkSend_Command needs _local_player to be set correctly, so
|
||||
* adjust it, and put it back right after the function */
|
||||
old_lp = _local_player;
|
||||
_local_player = _current_player;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* Send the command */
|
||||
if (_networking) {
|
||||
/* Network is easy, send it to his handler */
|
||||
NetworkSend_Command(tile, p1, p2, procc, callback);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
/* If we execute BuildCommands directly in SP, we have a big problem with events
|
||||
* so we need to delay is for 1 tick */
|
||||
AI_PutCommandInQueue(_current_player, tile, p1, p2, procc, callback);
|
||||
}
|
||||
|
||||
/* Set _local_player back */
|
||||
_local_player = old_lp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
|
||||
*/
|
||||
static void AI_RunTick(PlayerID player)
|
||||
{
|
||||
extern void AiNewDoGameLoop(Player *p);
|
||||
|
||||
Player *p = GetPlayer(player);
|
||||
_current_player = player;
|
||||
|
||||
if (_patches.ainew_active) {
|
||||
AiNewDoGameLoop(p);
|
||||
} else {
|
||||
/* Enable all kind of cheats the old AI needs in order to operate correctly... */
|
||||
_is_old_ai_player = true;
|
||||
AiDoGameLoop(p);
|
||||
_is_old_ai_player = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The gameloop for AIs.
|
||||
* Handles one tick for all the AIs.
|
||||
*/
|
||||
void AI_RunGameLoop(void)
|
||||
{
|
||||
/* Don't do anything if ai is disabled */
|
||||
if (!_ai.enabled) return;
|
||||
|
||||
/* Don't do anything if we are a network-client, or the AI has been disabled */
|
||||
if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
|
||||
|
||||
/* New tick */
|
||||
_ai.tick++;
|
||||
|
||||
/* Make sure the AI follows the difficulty rule.. */
|
||||
assert(_opt.diff.competitor_speed <= 4);
|
||||
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
|
||||
|
||||
/* Check for AI-client (so joining a network with an AI) */
|
||||
if (!_networking || _network_server) {
|
||||
/* Check if we want to run AIs (server or SP only) */
|
||||
const Player* p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) {
|
||||
/* This should always be true, else something went wrong... */
|
||||
assert(_ai_player[p->index].active);
|
||||
|
||||
/* Run the script */
|
||||
AI_DequeueCommands(p->index);
|
||||
AI_RunTick(p->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_current_player = OWNER_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A new AI sees the day of light. You can do here what ever you think is needed.
|
||||
*/
|
||||
void AI_StartNewAI(PlayerID player)
|
||||
{
|
||||
assert(IsValidPlayer(player));
|
||||
|
||||
/* Called if a new AI is booted */
|
||||
_ai_player[player].active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This AI player died. Give it some chance to make a final puf.
|
||||
*/
|
||||
void AI_PlayerDied(PlayerID player)
|
||||
{
|
||||
/* Called if this AI died */
|
||||
_ai_player[player].active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize some AI-related stuff.
|
||||
*/
|
||||
void AI_Initialize(void)
|
||||
{
|
||||
/* First, make sure all AIs are DEAD! */
|
||||
AI_Uninitialize();
|
||||
|
||||
memset(&_ai, 0, sizeof(_ai));
|
||||
memset(&_ai_player, 0, sizeof(_ai_player));
|
||||
|
||||
_ai.enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializer for AI-related stuff.
|
||||
*/
|
||||
void AI_Uninitialize(void)
|
||||
{
|
||||
const Player* p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
|
||||
}
|
||||
}
|
111
ai/ai.h
Normal file
111
ai/ai.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef AI_H
|
||||
#define AI_H
|
||||
|
||||
#include "../functions.h"
|
||||
#include "../network.h"
|
||||
#include "../player.h"
|
||||
#include "../command.h"
|
||||
|
||||
/* How DoCommands look like for an AI */
|
||||
typedef struct AICommand {
|
||||
uint32 tile;
|
||||
uint32 p1;
|
||||
uint32 p2;
|
||||
uint32 procc;
|
||||
CommandCallback* callback;
|
||||
|
||||
char *text;
|
||||
uint uid;
|
||||
|
||||
struct AICommand *next;
|
||||
} AICommand;
|
||||
|
||||
/* The struct for an AIScript Player */
|
||||
typedef struct AIPlayer {
|
||||
bool active; ///< Is this AI active?
|
||||
AICommand *queue; ///< The commands that he has in his queue
|
||||
AICommand *queue_tail; ///< The tail of this queue
|
||||
} AIPlayer;
|
||||
|
||||
/* The struct to keep some data about the AI in general */
|
||||
typedef struct AIStruct {
|
||||
/* General */
|
||||
bool enabled; ///< Is AI enabled?
|
||||
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
|
||||
} AIStruct;
|
||||
|
||||
VARDEF AIStruct _ai;
|
||||
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
|
||||
|
||||
// ai.c
|
||||
void AI_StartNewAI(PlayerID player);
|
||||
void AI_PlayerDied(PlayerID player);
|
||||
void AI_RunGameLoop(void);
|
||||
void AI_Initialize(void);
|
||||
void AI_Uninitialize(void);
|
||||
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
|
||||
|
||||
/** Is it allowed to start a new AI.
|
||||
* This function checks some boundries to see if we should launch a new AI.
|
||||
* @return True if we can start a new AI.
|
||||
*/
|
||||
static inline bool AI_AllowNewAI(void)
|
||||
{
|
||||
/* If disabled, no AI */
|
||||
if (!_ai.enabled)
|
||||
return false;
|
||||
|
||||
/* If in network, but no server, no AI */
|
||||
if (_networking && !_network_server)
|
||||
return false;
|
||||
|
||||
/* If in network, and server, possible AI */
|
||||
if (_networking && _network_server) {
|
||||
/* Do we want AIs in multiplayer? */
|
||||
if (!_patches.ai_in_multiplayer)
|
||||
return false;
|
||||
|
||||
/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
|
||||
* system, because all commands are delayed by at least 1 tick, which causes
|
||||
* a big problem, because it uses variables that are only set AFTER the command
|
||||
* is really executed... */
|
||||
if (!_patches.ainew_active)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define AI_CHANCE16(a,b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
|
||||
#define AI_CHANCE16R(a,b,r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
|
||||
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
*/
|
||||
static inline uint AI_RandomRange(uint max)
|
||||
{
|
||||
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
|
||||
* but we pick InteractiveRandomRange if we are a network_server or network-client.
|
||||
*/
|
||||
if (_networking)
|
||||
return InteractiveRandomRange(max);
|
||||
else
|
||||
return RandomRange(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
*/
|
||||
static inline uint32 AI_Random(void)
|
||||
{
|
||||
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
|
||||
* but we pick InteractiveRandomRange if we are a network_server or network-client.
|
||||
*/
|
||||
if (_networking)
|
||||
return InteractiveRandom();
|
||||
else
|
||||
return Random();
|
||||
}
|
||||
|
||||
#endif /* AI_H */
|
3920
ai/default/default.c
Normal file
3920
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
|
324
ai/trolly/build.c
Normal file
324
ai/trolly/build.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../road_map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../vehicle.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../engine.h"
|
||||
#include "../../station.h"
|
||||
#include "../../variables.h"
|
||||
#include "../../bridge.h"
|
||||
#include "../ai.h"
|
||||
|
||||
// Build HQ
|
||||
// Params:
|
||||
// tile : tile where HQ is going to be build
|
||||
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
|
||||
{
|
||||
if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
|
||||
return false;
|
||||
AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Build station
|
||||
// Params:
|
||||
// type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
|
||||
// tile : tile where station is going to be build
|
||||
// length : in case of AI_TRAIN: length of station
|
||||
// numtracks : in case of AI_TRAIN: tracks of station
|
||||
// direction : the direction of the station
|
||||
// flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
|
||||
{
|
||||
if (type == AI_TRAIN)
|
||||
return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
|
||||
|
||||
if (type == AI_BUS)
|
||||
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
|
||||
return AI_DoCommand(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
}
|
||||
|
||||
|
||||
// Builds a brdige. The second best out of the ones available for this player
|
||||
// Params:
|
||||
// tile_a : starting point
|
||||
// tile_b : end point
|
||||
// flag : flag passed to DoCommand
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
|
||||
{
|
||||
int bridge_type, bridge_len, type, type2;
|
||||
|
||||
// Find a good bridgetype (the best money can buy)
|
||||
bridge_len = GetBridgeLength(tile_a, tile_b);
|
||||
type = type2 = 0;
|
||||
for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
type2 = type;
|
||||
type = bridge_type;
|
||||
// We found two bridges, exit
|
||||
if (type2 != 0) break;
|
||||
}
|
||||
}
|
||||
// There is only one bridge that can be built
|
||||
if (type2 == 0 && type != 0) type2 = type;
|
||||
|
||||
// Now, simply, build the bridge!
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
} else {
|
||||
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Build the route part by part
|
||||
// Basicly what this function do, is build that amount of parts of the route
|
||||
// that go in the same direction. It sets 'part' to the last part of the route builded.
|
||||
// The return value is the cost for the builded parts
|
||||
//
|
||||
// Params:
|
||||
// PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
|
||||
// part : Which part we need to build
|
||||
//
|
||||
// TODO: skip already builded road-pieces (e.g.: cityroad)
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
|
||||
{
|
||||
int part = PathFinderInfo->position;
|
||||
byte *route_extra = PathFinderInfo->route_extra;
|
||||
TileIndex *route = PathFinderInfo->route;
|
||||
int dir;
|
||||
int old_dir = -1;
|
||||
int cost = 0;
|
||||
int res;
|
||||
// We need to calculate the direction with the parent of the parent.. so we skip
|
||||
// the first pieces and the last piece
|
||||
if (part < 1) part = 1;
|
||||
// When we are done, stop it
|
||||
if (part >= PathFinderInfo->route_length - 1) {
|
||||
PathFinderInfo->position = -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Tunnel code
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
|
||||
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal rail
|
||||
// Keep it doing till we go an other way
|
||||
if (route_extra[part - 1] == 0 && route_extra[part] == 0) {
|
||||
while (route_extra[part] == 0) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// Build the tile
|
||||
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(res)) {
|
||||
// Problem.. let's just abort it all!
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
cost += res;
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
if (part >= PathFinderInfo->route_length - 1) break;
|
||||
}
|
||||
part--;
|
||||
}
|
||||
// We want to return the last position, so we go back one
|
||||
PathFinderInfo->position = part;
|
||||
} else {
|
||||
// Tunnel code
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
|
||||
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal road
|
||||
// Keep it doing till we go an other way
|
||||
// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
|
||||
// it will wait till the vehicle is gone..
|
||||
if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// There is already some road, and it is a bridge.. don't build!!!
|
||||
if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
|
||||
// Build the tile
|
||||
res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// Currently, we ignore CMD_ERRORs!
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai,0)("Darn, the route could not be built.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CmdFailed(res)) cost += res;
|
||||
}
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
if (part >= PathFinderInfo->route_length - 1) break;
|
||||
}
|
||||
part--;
|
||||
// We want to return the last position, so we go back one
|
||||
}
|
||||
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
|
||||
PathFinderInfo->position = part;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
// This functions tries to find the best vehicle for this type of cargo
|
||||
// It returns INVALID_ENGINE if not suitable engine is found
|
||||
EngineID AiNew_PickVehicle(Player *p)
|
||||
{
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
// Not supported yet
|
||||
return INVALID_ENGINE;
|
||||
} else {
|
||||
EngineID best_veh_index = INVALID_ENGINE;
|
||||
int32 best_veh_rating = 0;
|
||||
EngineID start = ROAD_ENGINES_INDEX;
|
||||
EngineID end = ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES;
|
||||
EngineID i;
|
||||
|
||||
/* Loop through all road vehicles */
|
||||
for (i = start; i != end; i++) {
|
||||
const RoadVehicleInfo *rvi = RoadVehInfo(i);
|
||||
const Engine* e = GetEngine(i);
|
||||
int32 rating;
|
||||
int32 ret;
|
||||
|
||||
/* Skip vehicles which can't take our cargo type */
|
||||
if (rvi->cargo_type != p->ainew.cargo && !CanRefitTo(i, p->ainew.cargo)) continue;
|
||||
|
||||
// Is it availiable?
|
||||
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
|
||||
if (!HASBIT(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
|
||||
/* Rate and compare the engine by speed & capacity */
|
||||
rating = rvi->max_speed * rvi->capacity;
|
||||
if (rating <= best_veh_rating) continue;
|
||||
|
||||
// Can we build it?
|
||||
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (CmdFailed(ret)) continue;
|
||||
|
||||
best_veh_rating = rating;
|
||||
best_veh_index = i;
|
||||
}
|
||||
|
||||
return best_veh_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
Player* p = GetPlayer(_current_player);
|
||||
|
||||
if (success) {
|
||||
p->ainew.state = AI_STATE_GIVE_ORDERS;
|
||||
p->ainew.veh_id = _new_vehicle_id;
|
||||
|
||||
if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
|
||||
/* Cargo type doesn't match, so refit it */
|
||||
if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
|
||||
/* Refit failed, so sell the vehicle */
|
||||
DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* XXX this should be handled more gracefully */
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Builds the best vehicle possible
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
|
||||
{
|
||||
EngineID i = AiNew_PickVehicle(p);
|
||||
|
||||
if (i == INVALID_ENGINE) return CMD_ERROR;
|
||||
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
|
||||
|
||||
if (flag & DC_EXEC) {
|
||||
return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
|
||||
} else {
|
||||
return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
|
||||
}
|
||||
}
|
||||
|
||||
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
|
||||
{
|
||||
int ret, ret2;
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
|
||||
} else {
|
||||
ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (CmdFailed(ret)) return ret;
|
||||
// Try to build the road from the depot
|
||||
ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
return ret + ret2;
|
||||
}
|
||||
}
|
510
ai/trolly/pathfinder.c
Normal file
510
ai/trolly/pathfinder.c
Normal file
@@ -0,0 +1,510 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../bridge_map.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../depot.h"
|
||||
#include "../../tunnel_map.h"
|
||||
#include "../../bridge.h"
|
||||
#include "../ai.h"
|
||||
|
||||
#define TEST_STATION_NO_DIR 0xFF
|
||||
|
||||
// Tests if a station can be build on the given spot
|
||||
// TODO: make it train compatible
|
||||
static bool TestCanBuildStationHere(TileIndex tile, byte dir)
|
||||
{
|
||||
Player *p = GetPlayer(_current_player);
|
||||
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
int32 ret;
|
||||
// TODO: currently we only allow spots that can be access from al 4 directions...
|
||||
// should be fixed!!!
|
||||
for (dir = 0; dir < 4; dir++) {
|
||||
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (!CmdFailed(ret)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if command succeeded, so the inverse of CmdFailed()
|
||||
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
}
|
||||
|
||||
|
||||
static bool IsRoad(TileIndex tile)
|
||||
{
|
||||
return
|
||||
// MP_STREET, but not a road depot?
|
||||
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
|
||||
(IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) ||
|
||||
(IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Checks if a tile 'a' is between the tiles 'b' and 'c'
|
||||
#define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
|
||||
|
||||
|
||||
// Check if the current tile is in our end-area
|
||||
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
const Ai_PathFinderInfo* PathFinderInfo = aystar->user_target;
|
||||
|
||||
// It is not allowed to have a station on the end of a bridge or tunnel ;)
|
||||
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
|
||||
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
|
||||
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
|
||||
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
|
||||
return AYSTAR_DONE;
|
||||
}
|
||||
|
||||
|
||||
// Calculates the hash
|
||||
// Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
|
||||
static uint AiPathFinder_Hash(uint key1, uint key2)
|
||||
{
|
||||
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
|
||||
}
|
||||
|
||||
|
||||
// Clear the memory of all the things
|
||||
static void AyStar_AiPathFinder_Free(AyStar *aystar)
|
||||
{
|
||||
AyStarMain_Free(aystar);
|
||||
free(aystar);
|
||||
}
|
||||
|
||||
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
|
||||
// This creates the AiPathFinder
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
// Create AyStar
|
||||
AyStar *result = malloc(sizeof(AyStar));
|
||||
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
|
||||
// Set the function pointers
|
||||
result->CalculateG = AyStar_AiPathFinder_CalculateG;
|
||||
result->CalculateH = AyStar_AiPathFinder_CalculateH;
|
||||
result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
|
||||
result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
|
||||
result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
|
||||
|
||||
result->free = AyStar_AiPathFinder_Free;
|
||||
|
||||
// Set some information
|
||||
result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
|
||||
result->max_path_cost = 0;
|
||||
result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
result->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
start_node.node.tile = TileXY(x, y);
|
||||
result->addstart(result, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// To reuse AyStar we sometimes have to clean all the memory
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
aystar->clear(aystar);
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
aystar->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
start_node.node.tile = PathFinderInfo->start_tile_tl;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
TileIndex tile = TileXY(x, y);
|
||||
|
||||
if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
|
||||
if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = tile;
|
||||
aystar->addstart(aystar, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The h-value, simple calculation
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
const Ai_PathFinderInfo* PathFinderInfo = aystar->user_target;
|
||||
int r, r2;
|
||||
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDiagDir(PathFinderInfo->end_direction));
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
|
||||
} else {
|
||||
// No direction, so just get the fastest route to the station
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
|
||||
}
|
||||
// See if the bottomright is faster than the topleft..
|
||||
if (r2 < r) r = r2;
|
||||
return r * AI_PATHFINDER_H_MULTIPLER;
|
||||
}
|
||||
|
||||
|
||||
// We found the end.. let's get the route back and put it in an array
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
uint i = 0;
|
||||
PathNode *parent = ¤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 + TileOffsByDiagDir(i); // Adjacent tile
|
||||
|
||||
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
|
||||
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
|
||||
// We also directly test if the current tile can connect to this tile..
|
||||
// We do this simply by just building the tile!
|
||||
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
|
||||
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
|
||||
if (IsTunnel(atile)) {
|
||||
if (GetTunnelDirection(atile) != i) continue;
|
||||
} else {
|
||||
if ((_m[atile].m5 & 1U) != DiagDirToAxis(i)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_m[ctile].m5 & 1U) != (i & 1)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
|
||||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
|
||||
// We are a bridge/tunnel, how cool!!
|
||||
// This means we can only point forward.. get the direction from the user_data
|
||||
if (i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
}
|
||||
dir = 0;
|
||||
|
||||
// First, check if we have a parent
|
||||
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
|
||||
// If not, this means we are at the starting station
|
||||
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// We do need a direction?
|
||||
if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
|
||||
// We are not pointing the right way, invalid tile
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (current->path.node.user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
// Rail check
|
||||
dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
|
||||
ret = AI_DoCommand(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(ret)) continue;
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
if (current->path.parent->parent != NULL) {
|
||||
// Check if we don't make a 90degree curve
|
||||
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
|
||||
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Road check
|
||||
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
|
||||
if (IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// We have a bridge, how nicely! We should mark it...
|
||||
dir = 0;
|
||||
} else {
|
||||
// It already has road.. check if we miss any bits!
|
||||
if ((_m[ctile].m5 & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~_m[ctile].m5;
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only destruct things if it is MP_CLEAR of MP_TREES
|
||||
if (dir != 0) {
|
||||
ret = AI_DoCommand(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (CmdFailed(ret)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The tile can be connected
|
||||
aystar->neighbours[aystar->num_neighbours].tile = atile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Next step, check for bridges and tunnels
|
||||
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
|
||||
// First we get the dir from this tile and his parent
|
||||
DiagDirection dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
// It means we can only walk with the track, so the bridge has to be in the same direction
|
||||
TileIndex tile = current->path.node.tile;
|
||||
TileIndex new_tile = tile;
|
||||
Slope tileh = GetTileSlope(tile, NULL);
|
||||
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (tileh != SLOPE_FLAT ||
|
||||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_STREET)) ||
|
||||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
|
||||
for (;;) {
|
||||
new_tile += TileOffsByDiagDir(dir);
|
||||
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
|
||||
|
||||
// Check if we hit the station-tile.. we don't like that!
|
||||
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
|
||||
|
||||
// Try building the bridge..
|
||||
ret = AI_DoCommand(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
if (CmdFailed(ret)) continue;
|
||||
// We can build a bridge here.. add him to the neighbours
|
||||
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
// We can only have 12 neighbours, and we need 1 left for tunnels
|
||||
if (aystar->num_neighbours == 11) break;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be built on slopes corresponding to the direction
|
||||
// For now, we check both sides for this tile.. terraforming gives fuzzy result
|
||||
if ((dir == DIAGDIR_NE && tileh == SLOPE_NE) ||
|
||||
(dir == DIAGDIR_SE && tileh == SLOPE_SE) ||
|
||||
(dir == DIAGDIR_SW && tileh == SLOPE_SW) ||
|
||||
(dir == DIAGDIR_NW && tileh == SLOPE_NW)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
tileh = GetTileSlope(_build_tunnel_endtile, NULL);
|
||||
if (!CmdFailed(ret) && (tileh == SLOPE_SW || tileh == SLOPE_SE || tileh == SLOPE_NW || tileh == SLOPE_NE)) {
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern uint GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c
|
||||
extern uint GetRoadFoundation(Slope tileh, uint bits); // XXX function declaration in .c
|
||||
extern uint GetBridgeFoundation(Slope tileh, Axis); // XXX function declaration in .c
|
||||
enum {
|
||||
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
|
||||
};
|
||||
|
||||
// The most important function: it calculates the g-value
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, res = 0;
|
||||
Slope tileh = GetTileSlope(current->tile, NULL);
|
||||
Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
|
||||
|
||||
// Check if we hit the end-tile
|
||||
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
|
||||
// We are at the end-tile, check if we had a direction or something...
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction) {
|
||||
// We are not pointing the right way, invalid tile
|
||||
return AYSTAR_INVALID_NODE;
|
||||
}
|
||||
// If it was valid, drop out.. we don't build on the endtile
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Give everything a small penalty
|
||||
res += AI_PATHFINDER_PENALTY;
|
||||
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
// Road has the lovely advantage it can use other road... check if
|
||||
// the current tile is road, and if so, give a good bonus
|
||||
if (IsRoad(current->tile)) {
|
||||
res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
|
||||
}
|
||||
}
|
||||
|
||||
// We should give a penalty when the tile is going up or down.. this is one way to do so!
|
||||
// Too bad we have to count it from the parent.. but that is not so bad.
|
||||
// We also dislike long routes on slopes, since they do not look too realistic
|
||||
// when there is a flat land all around, they are more expensive to build, and
|
||||
// especially they essentially block the ability to connect or cross the road
|
||||
// from one side.
|
||||
if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
|
||||
// Skip if the tile was from a bridge or tunnel
|
||||
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
r = GetRailFoundation(parent_tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
|
||||
if (r >= 15 || (r == 0 && HASBIT(BRIDGE_NO_FOUNDATION, tileh))) {
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
} else {
|
||||
if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
|
||||
r = GetRoadFoundation(parent_tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
if (r >= 15 || r == 0) {
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we part of a tunnel?
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
|
||||
// Tunnels are very expensive when build on long routes..
|
||||
// Ironicly, we are using BridgeCode here ;)
|
||||
r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
res += r + (r >> 8);
|
||||
}
|
||||
|
||||
// Are we part of a bridge?
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
|
||||
// That means for every length a penalty
|
||||
res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
// Check if we are going up or down, first for the starting point
|
||||
// In user_data[0] is at the 8th bit the direction
|
||||
if (!HASBIT(BRIDGE_NO_FOUNDATION, parent_tileh)) {
|
||||
if (GetBridgeFoundation(parent_tileh, (current->user_data[0] >> 8) & 1) < 15) {
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
}
|
||||
// Second for the end point
|
||||
if (!HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
|
||||
if (GetBridgeFoundation(tileh, (current->user_data[0] >> 8) & 1) < 15) {
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
}
|
||||
if (parent_tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
if (tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
|
||||
// To prevent the AI from taking the fastest way in tiles, but not the fastest way
|
||||
// in speed, we have to give a good penalty to direction changing
|
||||
// This way, we get almost the fastest way in tiles, and a very good speed on the track
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
if (parent->path.parent != NULL &&
|
||||
AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
|
||||
// When road exists, we don't like turning, but its free, so don't be to piggy about it
|
||||
if (IsRoad(parent->path.node.tile)) {
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For rail we have 1 exeption: diagonal rail..
|
||||
// So we fetch 2 raildirection. That of the current one, and of the one before that
|
||||
if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
|
||||
int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
|
||||
int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
|
||||
// First, see if we are on diagonal path, that is better than straight path
|
||||
if (dir1 > 1) res -= AI_PATHFINDER_DIAGONAL_BONUS;
|
||||
|
||||
// First see if they are different
|
||||
if (dir1 != dir2) {
|
||||
// dir 2 and 3 are 1 diagonal track, and 4 and 5.
|
||||
if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
|
||||
// It is not, so we changed of direction
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
if (parent->path.parent->parent->parent != NULL) {
|
||||
int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
|
||||
// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
|
||||
if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
|
||||
res += AI_PATHFINDER_CURVE_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (res < 0) ? 0 : res;
|
||||
}
|
118
ai/trolly/shared.c
Normal file
118
ai/trolly/shared.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../map.h"
|
||||
#include "trolly.h"
|
||||
#include "../../vehicle.h"
|
||||
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
// 0 = vert
|
||||
// 1 = horz
|
||||
// 2 = dig up-left
|
||||
// 3 = dig down-right
|
||||
// 4 = dig down-left
|
||||
// 5 = dig up-right
|
||||
|
||||
uint x1 = TileX(tile_a);
|
||||
uint x2 = TileX(tile_b);
|
||||
uint x3 = TileX(tile_c);
|
||||
|
||||
uint y1 = TileY(tile_a);
|
||||
uint y2 = TileY(tile_b);
|
||||
uint y3 = TileY(tile_c);
|
||||
|
||||
if (y1 == y2 && y2 == y3) return 0;
|
||||
if (x1 == x2 && x2 == x3) return 1;
|
||||
if (y2 > y1) return x2 > x3 ? 2 : 4;
|
||||
if (x2 > x1) return y2 > y3 ? 2 : 5;
|
||||
if (y1 > y2) return x2 > x3 ? 5 : 3;
|
||||
if (x1 > x2) return y2 > y3 ? 4 : 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
int r;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
r = 0;
|
||||
|
||||
if (x1 < x2) r += 8;
|
||||
if (y1 < y2) r += 1;
|
||||
if (x1 > x2) r += 2;
|
||||
if (y1 > y2) r += 4;
|
||||
|
||||
if (x2 < x3) r += 2;
|
||||
if (y2 < y3) r += 4;
|
||||
if (x2 > x3) r += 8;
|
||||
if (y2 > y3) r += 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Get's the direction between 2 tiles seen from tile_a
|
||||
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b)
|
||||
{
|
||||
if (TileY(tile_a) < TileY(tile_b)) return DIAGDIR_SE;
|
||||
if (TileY(tile_a) > TileY(tile_b)) return DIAGDIR_NW;
|
||||
if (TileX(tile_a) < TileX(tile_b)) return DIAGDIR_SW;
|
||||
return DIAGDIR_NE;
|
||||
}
|
||||
|
||||
|
||||
// This functions looks up if this vehicle is special for this AI
|
||||
// and returns his flag
|
||||
uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
return p->ainew.special_vehicles[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found :(
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
|
||||
{
|
||||
int new_id = -1;
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
p->ainew.special_vehicles[i].flag |= flag;
|
||||
return true;
|
||||
}
|
||||
if (new_id == -1 &&
|
||||
p->ainew.special_vehicles[i].veh_id == 0 &&
|
||||
p->ainew.special_vehicles[i].flag == 0) {
|
||||
new_id = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Out of special_vehicle spots :s
|
||||
if (new_id == -1) {
|
||||
DEBUG(ai, 1)("special_vehicles list is too small :(");
|
||||
return false;
|
||||
}
|
||||
p->ainew.special_vehicles[new_id].veh_id = v->index;
|
||||
p->ainew.special_vehicles[new_id].flag = flag;
|
||||
return true;
|
||||
}
|
1356
ai/trolly/trolly.c
Normal file
1356
ai/trolly/trolly.c
Normal file
File diff suppressed because it is too large
Load Diff
262
ai/trolly/trolly.h
Normal file
262
ai/trolly/trolly.h
Normal file
@@ -0,0 +1,262 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AI_TROLLY_H
|
||||
#define AI_TROLLY_H
|
||||
|
||||
#include "../../aystar.h"
|
||||
#include "../../player.h"
|
||||
|
||||
/*
|
||||
* These defines can be altered to change the behavoir of the AI
|
||||
*
|
||||
* WARNING:
|
||||
* This can also alter the AI in a negative way. I will never claim these settings
|
||||
* are perfect, but don't change them if you don't know what the effect is.
|
||||
*/
|
||||
|
||||
// How many times it the H multiplied. The higher, the more it will go straight to the
|
||||
// end point. The lower, how more it will find the route with the lowest cost.
|
||||
// also: the lower, the longer it takes before route is calculated..
|
||||
#define AI_PATHFINDER_H_MULTIPLER 100
|
||||
|
||||
// How many loops may AyStar do before it stops
|
||||
// 0 = infinite
|
||||
#define AI_PATHFINDER_LOOPS_PER_TICK 5
|
||||
|
||||
// How long may the AI search for one route?
|
||||
// 0 = infinite
|
||||
// This number is the number of tiles tested.
|
||||
// It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
|
||||
// to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
|
||||
// (that is: if the AI is on VERY FAST! :p
|
||||
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
|
||||
|
||||
// If you enable this, the AI is not allowed to make 90degree turns
|
||||
#define AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
|
||||
// Below are defines for the g-calculation
|
||||
|
||||
// Standard penalty given to a tile
|
||||
#define AI_PATHFINDER_PENALTY 150
|
||||
// The penalty given to a tile that is going up
|
||||
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
|
||||
// The penalty given to a tile which would have to use fundation
|
||||
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
|
||||
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
|
||||
// Same penalty, only for when road already exists
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
|
||||
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
|
||||
// a bonus for using diagonal track
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 95
|
||||
#else
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 75
|
||||
#endif
|
||||
// If a roadblock already exists, it gets a bonus
|
||||
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
|
||||
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
|
||||
#define AI_PATHFINDER_CURVE_PENALTY 200
|
||||
|
||||
// Penalty a bridge gets per length
|
||||
#define AI_PATHFINDER_BRIDGE_PENALTY 180
|
||||
// The penalty for a bridge going up
|
||||
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
|
||||
|
||||
// Tunnels are expensive...
|
||||
// Because of that, every tile the cost is increased with 1/8th of his value
|
||||
// This is also true if you are building a tunnel yourself
|
||||
#define AI_PATHFINDER_TUNNEL_PENALTY 350
|
||||
|
||||
/*
|
||||
* Ai_New defines
|
||||
*/
|
||||
|
||||
// How long may we search cities and industry for a new route?
|
||||
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
|
||||
|
||||
// How many days must there be between building the first station and the second station
|
||||
// within one city. This number is in days and should be more than 4 months.
|
||||
#define AI_CHECKCITY_DATE_BETWEEN 180
|
||||
|
||||
// How many cargo is needed for one station in a city?
|
||||
#define AI_CHECKCITY_CARGO_PER_STATION 60
|
||||
// How much cargo must there not be used in a city before we can build a new station?
|
||||
#define AI_CHECKCITY_NEEDED_CARGO 50
|
||||
// When there is already a station which takes the same good and the rating of that
|
||||
// city is higher then this numer, we are not going to attempt to build anything
|
||||
// there
|
||||
#define AI_CHECKCITY_CARGO_RATING 50
|
||||
// But, there is a chance of 1 out of this number, that we do ;)
|
||||
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
|
||||
// If a city is too small to contain a station, there is a small chance
|
||||
// that we still do so.. just to make the city bigger!
|
||||
#define AI_CHECKCITY_CITY_CHANCE 5
|
||||
|
||||
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
|
||||
// from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
|
||||
// of the cargo in the other station, both stations can be 96 units away from eachother, if the
|
||||
// next number is 0.4.
|
||||
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
|
||||
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
|
||||
// In whole tiles, the minimum distance for a truck route
|
||||
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
|
||||
|
||||
// The amount of tiles in a square from -X to +X that is scanned for a station spot
|
||||
// (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
|
||||
// Safe values are between 15 and 5
|
||||
#define AI_FINDSTATION_TILE_RANGE 10
|
||||
|
||||
// Building on normal speed goes very fast. Idle this amount of ticks between every
|
||||
// building part. It is calculated like this: (4 - competitor_speed) * num + 1
|
||||
// where competitor_speed is between 0 (very slow) to 4 (very fast)
|
||||
#define AI_BUILDPATH_PAUSE 10
|
||||
|
||||
// Minimum % of reliabilty a vehicle has to have before the AI buys it
|
||||
#define AI_VEHICLE_MIN_RELIABILTY 60
|
||||
|
||||
// The minimum amount of money a player should always have
|
||||
#define AI_MINIMUM_MONEY 15000
|
||||
|
||||
// If the most cheap route is build, how much is it going to cost..
|
||||
// This is to prevent the AI from trying to build a route which can not be paid for
|
||||
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
|
||||
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
|
||||
|
||||
// The minimum amount of money before we are going to repay any money
|
||||
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
|
||||
// How many repays do we do if we have enough money to do so?
|
||||
// Every repay is 10000
|
||||
#define AI_LOAN_REPAY 2
|
||||
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
|
||||
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
|
||||
|
||||
// If there is <num> time as much cargo in the station then the vehicle can handle
|
||||
// reuse the station instead of building a new one!
|
||||
#define AI_STATION_REUSE_MULTIPLER 2
|
||||
|
||||
// No more than this amount of vehicles per station..
|
||||
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
|
||||
|
||||
// How many thick between building 2 vehicles
|
||||
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS
|
||||
|
||||
// How many days must there between vehicle checks
|
||||
// The more often, the less non-money-making lines there will be
|
||||
// but the unfair it may seem to a human player
|
||||
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30
|
||||
|
||||
// How money profit does a vehicle needs to make to stay in order
|
||||
// This is the profit of this year + profit of last year
|
||||
// But also for vehicles that are just one year old. In other words:
|
||||
// Vehicles of 2 years do easier meet this setting then vehicles
|
||||
// of one year. This is a very good thing. New vehicles are filtered,
|
||||
// while old vehicles stay longer, because we do get less in return.
|
||||
#define AI_MINIMUM_ROUTE_PROFIT 1000
|
||||
|
||||
// A vehicle is considered lost when he his cargo is more than 180 days old
|
||||
#define AI_VEHICLE_LOST_DAYS 180
|
||||
|
||||
// How many times may the AI try to find a route before it gives up
|
||||
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8
|
||||
|
||||
/*
|
||||
* End of defines
|
||||
*/
|
||||
|
||||
// This stops 90degrees curves
|
||||
static const byte _illegal_curves[6] = {
|
||||
255, 255, // Horz and vert, don't have the effect
|
||||
5, // upleft and upright are not valid
|
||||
4, // downright and downleft are not valid
|
||||
2, // downleft and upleft are not valid
|
||||
3, // upright and downright are not valid
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_STATE_STARTUP = 0,
|
||||
AI_STATE_FIRST_TIME,
|
||||
AI_STATE_NOTHING,
|
||||
AI_STATE_WAKE_UP,
|
||||
AI_STATE_LOCATE_ROUTE,
|
||||
AI_STATE_FIND_STATION,
|
||||
AI_STATE_FIND_PATH,
|
||||
AI_STATE_FIND_DEPOT,
|
||||
AI_STATE_VERIFY_ROUTE,
|
||||
AI_STATE_BUILD_STATION,
|
||||
AI_STATE_BUILD_PATH,
|
||||
AI_STATE_BUILD_DEPOT,
|
||||
AI_STATE_BUILD_VEHICLE,
|
||||
AI_STATE_WAIT_FOR_BUILD,
|
||||
AI_STATE_GIVE_ORDERS,
|
||||
AI_STATE_START_VEHICLE,
|
||||
AI_STATE_REPAY_MONEY,
|
||||
AI_STATE_CHECK_ALL_VEHICLES,
|
||||
AI_STATE_ACTION_DONE,
|
||||
AI_STATE_STOP, // Temporary function to stop the AI
|
||||
};
|
||||
|
||||
// Used for tbt (train/bus/truck)
|
||||
enum {
|
||||
AI_TRAIN = 0,
|
||||
AI_BUS,
|
||||
AI_TRUCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_ACTION_NONE = 0,
|
||||
AI_ACTION_BUS_ROUTE,
|
||||
AI_ACTION_TRUCK_ROUTE,
|
||||
AI_ACTION_REPAY_LOAN,
|
||||
AI_ACTION_CHECK_ALL_VEHICLES,
|
||||
};
|
||||
|
||||
// Used for from_type/to_type
|
||||
enum {
|
||||
AI_NO_TYPE = 0,
|
||||
AI_CITY,
|
||||
AI_INDUSTRY,
|
||||
};
|
||||
|
||||
// Flags for in the vehicle
|
||||
enum {
|
||||
AI_VEHICLEFLAG_SELL = 1,
|
||||
// Remember, flags must be in power of 2
|
||||
};
|
||||
|
||||
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
|
||||
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
|
||||
#define AI_STATION_RANGE TileXY(MapMaxX(), MapMaxY())
|
||||
|
||||
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
|
||||
|
||||
// Flags used in user_data
|
||||
#define AI_PATHFINDER_FLAG_BRIDGE 1
|
||||
#define AI_PATHFINDER_FLAG_TUNNEL 2
|
||||
|
||||
typedef void AiNew_StateFunction(Player *p);
|
||||
|
||||
// ai_new.c
|
||||
void AiNewDoGameLoop(Player *p);
|
||||
|
||||
// ai_pathfinder.c
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
|
||||
|
||||
// ai_shared.c
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag);
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
|
||||
|
||||
// ai_build.c
|
||||
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
|
||||
EngineID AiNew_PickVehicle(Player *p);
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
|
||||
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
|
||||
|
||||
#endif /* AI_TROLLY_H */
|
26
aircraft.h
Normal file
26
aircraft.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRCRAFT_H
|
||||
#define AIRCRAFT_H
|
||||
|
||||
#include "station_map.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
|
||||
static inline bool IsAircraftInHangar(const Vehicle* v)
|
||||
{
|
||||
assert(v->type == VEH_Aircraft);
|
||||
return v->vehstatus & VS_HIDDEN && IsHangarTile(v->tile);
|
||||
}
|
||||
|
||||
static inline bool IsAircraftInHangarStopped(const Vehicle* v)
|
||||
{
|
||||
return IsAircraftInHangar(v) && v->vehstatus & VS_STOPPED;
|
||||
}
|
||||
|
||||
uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type);
|
||||
|
||||
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2);
|
||||
void HandleAircraftEnterHangar(Vehicle *v);
|
||||
|
||||
#endif /* AIRCRAFT_H */
|
2146
aircraft_cmd.c
Normal file
2146
aircraft_cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
350
aircraft_gui.c
Normal file
350
aircraft_gui.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "aircraft.h"
|
||||
#include "debug.h"
|
||||
#include "functions.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "vehicle.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
#include "engine.h"
|
||||
#include "viewport.h"
|
||||
#include "player.h"
|
||||
#include "depot.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "newgrf_engine.h"
|
||||
|
||||
|
||||
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) ShowAircraftViewWindow(GetVehicle(_new_vehicle_id));
|
||||
}
|
||||
|
||||
static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
const Vehicle *v = GetVehicle(w->window_number);
|
||||
|
||||
SetWindowWidgetDisabledState(w, 2, v->owner != _local_player);
|
||||
|
||||
/* Disable service-scroller when interval is set to disabled */
|
||||
SetWindowWidgetDisabledState(w, 5, !_patches.servint_aircraft);
|
||||
SetWindowWidgetDisabledState(w, 6, !_patches.servint_aircraft);
|
||||
|
||||
SetDParam(0, v->string_id);
|
||||
SetDParam(1, v->unitnumber);
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
/* Draw running cost */
|
||||
{
|
||||
int year = v->age / 366;
|
||||
|
||||
SetDParam(1, year);
|
||||
|
||||
SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED);
|
||||
SetDParam(2, v->max_age / 366);
|
||||
SetDParam(3, _price.aircraft_running * AircraftVehInfo(v->engine_type)->running_cost >> 8);
|
||||
DrawString(2, 15, STR_A00D_AGE_RUNNING_COST_YR, 0);
|
||||
}
|
||||
|
||||
/* Draw max speed */
|
||||
{
|
||||
SetDParam(0, v->max_speed * 128 / 10);
|
||||
DrawString(2, 25, STR_A00E_MAX_SPEED, 0);
|
||||
}
|
||||
|
||||
/* Draw profit */
|
||||
{
|
||||
SetDParam(0, v->profit_this_year);
|
||||
SetDParam(1, v->profit_last_year);
|
||||
DrawString(2, 35, STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR, 0);
|
||||
}
|
||||
|
||||
/* Draw breakdown & reliability */
|
||||
{
|
||||
SetDParam(0, v->reliability * 100 >> 16);
|
||||
SetDParam(1, v->breakdowns_since_last_service);
|
||||
DrawString(2, 45, STR_A010_RELIABILITY_BREAKDOWNS, 0);
|
||||
}
|
||||
|
||||
/* Draw service interval text */
|
||||
{
|
||||
SetDParam(0, v->service_interval);
|
||||
SetDParam(1, v->date_of_last_service);
|
||||
DrawString(13, 103, _patches.servint_ispercent?STR_SERVICING_INTERVAL_PERCENT:STR_883C_SERVICING_INTERVAL_DAYS, 0);
|
||||
}
|
||||
|
||||
DrawAircraftImage(v, 3, 57, INVALID_VEHICLE);
|
||||
|
||||
{
|
||||
const Vehicle *u;
|
||||
int y = 57;
|
||||
|
||||
do {
|
||||
if (v->subtype <= 2) {
|
||||
SetDParam(0, GetCustomEngineName(v->engine_type));
|
||||
SetDParam(1, v->build_year);
|
||||
SetDParam(2, v->value);
|
||||
DrawString(60, y, STR_A011_BUILT_VALUE, 0);
|
||||
y += 10;
|
||||
|
||||
SetDParam(0, v->cargo_type);
|
||||
SetDParam(1, v->cargo_cap);
|
||||
u = v->next;
|
||||
SetDParam(2, u->cargo_type);
|
||||
SetDParam(3, u->cargo_cap);
|
||||
DrawString(60, y, (u->cargo_cap != 0) ? STR_A019_CAPACITY : STR_A01A_CAPACITY, 0);
|
||||
y += 14;
|
||||
}
|
||||
|
||||
if (v->cargo_count != 0) {
|
||||
|
||||
/* Cargo names (fix pluralness) */
|
||||
SetDParam(0, v->cargo_type);
|
||||
SetDParam(1, v->cargo_count);
|
||||
SetDParam(2, v->cargo_source);
|
||||
DrawString(60, y, STR_8813_FROM, 0);
|
||||
|
||||
y += 10;
|
||||
}
|
||||
} while ( (v=v->next) != NULL);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_CLICK: {
|
||||
int mod;
|
||||
const Vehicle *v;
|
||||
switch (e->we.click.widget) {
|
||||
case 2: /* rename */
|
||||
v = GetVehicle(w->window_number);
|
||||
SetDParam(0, v->unitnumber);
|
||||
ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
|
||||
break;
|
||||
case 5: /* increase int */
|
||||
mod = _ctrl_pressed? 5 : 10;
|
||||
goto do_change_service_int;
|
||||
case 6: /* decrease int */
|
||||
mod = _ctrl_pressed?- 5 : -10;
|
||||
do_change_service_int:
|
||||
v = GetVehicle(w->window_number);
|
||||
|
||||
mod = GetServiceIntervalClamped(mod + v->service_interval);
|
||||
if (mod == v->service_interval) return;
|
||||
|
||||
DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_ON_EDIT_TEXT:
|
||||
if (e->we.edittext.str[0] != '\0') {
|
||||
_cmd_text = e->we.edittext.str;
|
||||
DoCommandP(0, w->window_number, 0, NULL,
|
||||
CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const Widget _aircraft_details_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
|
||||
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 349, 0, 13, STR_A00C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS },
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 350, 389, 0, 13, STR_01AA_NAME, STR_A032_NAME_AIRCRAFT },
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 14, 55, 0x0, STR_NULL },
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 56, 101, 0x0, STR_NULL },
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 102, 107, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL },
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 108, 113, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL },
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 11, 389, 102, 113, 0x0, STR_NULL },
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _aircraft_details_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 390, 114,
|
||||
WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
_aircraft_details_widgets,
|
||||
AircraftDetailsWndProc
|
||||
};
|
||||
|
||||
|
||||
static void ShowAircraftDetailsWindow(const Vehicle *v)
|
||||
{
|
||||
Window *w;
|
||||
VehicleID veh = v->index;
|
||||
|
||||
DeleteWindowById(WC_VEHICLE_ORDERS, veh);
|
||||
DeleteWindowById(WC_VEHICLE_DETAILS, veh);
|
||||
|
||||
w = AllocateWindowDescFront(&_aircraft_details_desc, veh);
|
||||
w->caption_color = v->owner;
|
||||
// w->vscroll.cap = 6;
|
||||
// w->traindetails_d.tab = 0;
|
||||
}
|
||||
|
||||
|
||||
static const Widget _aircraft_view_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
|
||||
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 237, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS },
|
||||
{ WWT_STICKYBOX, RESIZE_LR, 14, 238, 249, 0, 13, 0x0, STR_STICKY_BUTTON },
|
||||
{ WWT_PANEL, RESIZE_RB, 14, 0, 231, 14, 103, 0x0, STR_NULL },
|
||||
{ WWT_INSET, RESIZE_RB, 14, 2, 229, 16, 101, 0x0, STR_NULL },
|
||||
{ WWT_PUSHBTN, RESIZE_RTB, 14, 0, 237, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 14, 31, SPR_CENTRE_VIEW_VEHICLE, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_SEND_AIRCRAFT_TODEPOT,STR_A02A_SEND_AIRCRAFT_TO_HANGAR },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 50, 67, SPR_REFIT_VEHICLE, STR_A03B_REFIT_AIRCRAFT_TO_CARRY },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 68, 85, SPR_SHOW_ORDERS, STR_A028_SHOW_AIRCRAFT_S_ORDERS },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 86, 103, SPR_SHOW_VEHICLE_DETAILS, STR_A02B_SHOW_AIRCRAFT_DETAILS },
|
||||
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_CLONE_AIRCRAFT, STR_CLONE_AIRCRAFT_INFO },
|
||||
{ WWT_PANEL, RESIZE_LRB, 14, 232, 249, 104, 103, 0x0, STR_NULL },
|
||||
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 238, 249, 104, 115, 0x0, STR_NULL },
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static void AircraftViewWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
const Vehicle *v = GetVehicle(w->window_number);
|
||||
StringID str;
|
||||
bool is_localplayer = v->owner == _local_player;
|
||||
|
||||
SetWindowWidgetDisabledState(w, 7, !is_localplayer);
|
||||
SetWindowWidgetDisabledState(w, 8, !IsAircraftInHangarStopped(v) || !is_localplayer);
|
||||
SetWindowWidgetDisabledState(w, 11, !is_localplayer);
|
||||
|
||||
|
||||
/* draw widgets & caption */
|
||||
SetDParam(0, v->string_id);
|
||||
SetDParam(1, v->unitnumber);
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
if (v->vehstatus & VS_CRASHED) {
|
||||
str = STR_8863_CRASHED;
|
||||
} else if (v->vehstatus & VS_STOPPED) {
|
||||
str = STR_8861_STOPPED;
|
||||
} else {
|
||||
switch (v->current_order.type) {
|
||||
case OT_GOTO_STATION: {
|
||||
SetDParam(0, v->current_order.dest);
|
||||
SetDParam(1, v->cur_speed * 128 / 10);
|
||||
str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
|
||||
} break;
|
||||
|
||||
case OT_GOTO_DEPOT: {
|
||||
/* Aircrafts always go to a station, even if you say depot */
|
||||
SetDParam(0, v->current_order.dest);
|
||||
SetDParam(1, v->cur_speed * 128 / 10);
|
||||
if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) {
|
||||
str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed;
|
||||
} else {
|
||||
str = STR_HEADING_FOR_HANGAR_SERVICE + _patches.vehicle_speed;
|
||||
}
|
||||
} break;
|
||||
|
||||
case OT_LOADING:
|
||||
str = STR_882F_LOADING_UNLOADING;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (v->num_orders == 0) {
|
||||
str = STR_NO_ORDERS + _patches.vehicle_speed;
|
||||
SetDParam(0, v->cur_speed * 128 / 10);
|
||||
} else {
|
||||
str = STR_EMPTY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the flag plus orders */
|
||||
DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, 2, w->widget[5].top + 1);
|
||||
DrawStringCenteredTruncated(w->widget[5].left + 8, w->widget[5].right, w->widget[5].top + 1, str, 0);
|
||||
DrawWindowViewport(w);
|
||||
} break;
|
||||
|
||||
case WE_CLICK: {
|
||||
const Vehicle *v = GetVehicle(w->window_number);
|
||||
|
||||
switch (e->we.click.widget) {
|
||||
case 5: /* start stop */
|
||||
DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT));
|
||||
break;
|
||||
case 6: /* center main view */
|
||||
ScrollMainWindowTo(v->x_pos, v->y_pos);
|
||||
break;
|
||||
case 7: /* goto hangar */
|
||||
DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_MSG(STR_A012_CAN_T_SEND_AIRCRAFT_TO));
|
||||
break;
|
||||
case 8: /* refit */
|
||||
ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
|
||||
break;
|
||||
case 9: /* show orders */
|
||||
ShowOrdersWindow(v);
|
||||
break;
|
||||
case 10: /* show details */
|
||||
ShowAircraftDetailsWindow(v);
|
||||
break;
|
||||
case 11:
|
||||
/* clone vehicle */
|
||||
DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneAircraft, CMD_CLONE_VEHICLE | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_RESIZE:
|
||||
w->viewport->width += e->we.sizing.diff.x;
|
||||
w->viewport->height += e->we.sizing.diff.y;
|
||||
w->viewport->virtual_width += e->we.sizing.diff.x;
|
||||
w->viewport->virtual_height += e->we.sizing.diff.y;
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
|
||||
DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
|
||||
DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number);
|
||||
break;
|
||||
|
||||
case WE_MOUSELOOP: {
|
||||
const Vehicle *v = GetVehicle(w->window_number);
|
||||
bool plane_stopped = IsAircraftInHangarStopped(v);
|
||||
|
||||
/* Widget 7 (send to hangar) must be hidden if the plane is already stopped in hangar.
|
||||
* Widget 11 (clone) should then be shown, since cloning is allowed only while in hangar and stopped.
|
||||
* This sytem allows to have two buttons, on top of each other*/
|
||||
if (plane_stopped != IsWindowWidgetHidden(w, 7) || plane_stopped == IsWindowWidgetHidden(w, 11)) {
|
||||
SetWindowWidgetHiddenState(w, 7, plane_stopped); // send to hangar
|
||||
SetWindowWidgetHiddenState(w, 11, !plane_stopped); // clone
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const WindowDesc _aircraft_view_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 250, 116,
|
||||
WC_VEHICLE_VIEW ,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
|
||||
_aircraft_view_widgets,
|
||||
AircraftViewWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowAircraftViewWindow(const Vehicle *v)
|
||||
{
|
||||
Window *w = AllocateWindowDescFront(&_aircraft_view_desc, v->index);
|
||||
|
||||
if (w != NULL) {
|
||||
w->caption_color = v->owner;
|
||||
AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
|
||||
}
|
||||
}
|
489
airport.c
Normal file
489
airport.c
Normal file
@@ -0,0 +1,489 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
#include "airport_movement.h"
|
||||
#include "date.h"
|
||||
|
||||
/* Uncomment this to print out a full report of the airport-structure
|
||||
* You should either use
|
||||
* - true: full-report, print out every state and choice with string-names
|
||||
* OR
|
||||
* - false: give a summarized report which only shows current and next position */
|
||||
//#define DEBUG_AIRPORT false
|
||||
|
||||
static AirportFTAClass *CountryAirport;
|
||||
static AirportFTAClass *CityAirport;
|
||||
static AirportFTAClass *Oilrig;
|
||||
static AirportFTAClass *Heliport;
|
||||
static AirportFTAClass *MetropolitanAirport;
|
||||
static AirportFTAClass *InternationalAirport;
|
||||
static AirportFTAClass *CommuterAirport;
|
||||
static AirportFTAClass *HeliDepot;
|
||||
static AirportFTAClass *IntercontinentalAirport;
|
||||
static AirportFTAClass *HeliStation;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *apFA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots,
|
||||
uint size_x, uint size_y
|
||||
);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *apc);
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
|
||||
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA);
|
||||
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
|
||||
static byte AirportTestFTA(const AirportFTAClass *apc);
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report);
|
||||
#endif /* DEBUG_AIRPORT */
|
||||
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
// 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),
|
||||
4, 3
|
||||
);
|
||||
|
||||
// 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),
|
||||
6, 6
|
||||
);
|
||||
|
||||
// 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),
|
||||
6, 6
|
||||
);
|
||||
|
||||
// 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),
|
||||
7, 7
|
||||
);
|
||||
|
||||
// intercontintental airport
|
||||
IntercontinentalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
IntercontinentalAirport,
|
||||
_airport_terminal_intercontinental,
|
||||
_airport_helipad_intercontinental,
|
||||
43,
|
||||
ALL,
|
||||
_airport_fta_intercontinental,
|
||||
_airport_depots_intercontinental,
|
||||
lengthof(_airport_depots_intercontinental),
|
||||
9,11
|
||||
);
|
||||
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0,
|
||||
1, 1
|
||||
);
|
||||
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
|
||||
// commuter airport
|
||||
CommuterAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CommuterAirport,
|
||||
_airport_terminal_commuter,
|
||||
_airport_helipad_commuter,
|
||||
22,
|
||||
ALL,
|
||||
_airport_fta_commuter,
|
||||
_airport_depots_commuter,
|
||||
lengthof(_airport_depots_commuter),
|
||||
5,4
|
||||
);
|
||||
|
||||
// helidepot airport
|
||||
HeliDepot = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
HeliDepot,
|
||||
NULL,
|
||||
_airport_helipad_helidepot,
|
||||
4,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_helidepot,
|
||||
_airport_depots_helidepot,
|
||||
lengthof(_airport_depots_helidepot),
|
||||
2,2
|
||||
);
|
||||
|
||||
// helistation airport
|
||||
HeliStation = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
HeliStation,
|
||||
NULL,
|
||||
_airport_helipad_helistation,
|
||||
25,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_helistation,
|
||||
_airport_depots_helistation,
|
||||
lengthof(_airport_depots_helistation),
|
||||
4,2
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
AirportFTAClass_Destructor(Heliport);
|
||||
AirportFTAClass_Destructor(MetropolitanAirport);
|
||||
AirportFTAClass_Destructor(InternationalAirport);
|
||||
AirportFTAClass_Destructor(CommuterAirport);
|
||||
AirportFTAClass_Destructor(HeliDepot);
|
||||
AirportFTAClass_Destructor(IntercontinentalAirport);
|
||||
AirportFTAClass_Destructor(HeliStation);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *apFA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots,
|
||||
uint size_x, uint size_y
|
||||
)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups, nofhelipadgroups;
|
||||
|
||||
apc->size_x = size_x;
|
||||
apc->size_y = size_y;
|
||||
|
||||
/* Set up the terminal and helipad count for an airport.
|
||||
* TODO: If there are more than 10 terminals or 4 helipads, internal variables
|
||||
* need to be changed, so don't allow that for now */
|
||||
nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
|
||||
if (nofterminals > MAX_TERMINALS) {
|
||||
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d terminals are supported (you wanted %d)", MAX_TERMINALS, nofterminals);
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
}
|
||||
apc->terminals = terminals;
|
||||
|
||||
nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
|
||||
if (nofhelipads > MAX_HELIPADS) {
|
||||
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d helipads are supported (you wanted %d)", MAX_HELIPADS, nofhelipads);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
}
|
||||
apc->helipads = helipads;
|
||||
|
||||
/* Get the number of elements from the source table. We also double check this
|
||||
* with the entry point which must be within bounds and use this information
|
||||
* later on to build and validate the state machine */
|
||||
apc->nofelements = AirportGetNofElements(apFA);
|
||||
if (entry_point >= apc->nofelements) {
|
||||
DEBUG(misc, 0) ("[Ap] Entry (%d) must be within the airport (maximum %d)", entry_point, apc->nofelements);
|
||||
assert(entry_point < apc->nofelements);
|
||||
}
|
||||
|
||||
apc->acc_planes = acc_planes;
|
||||
apc->entry_point = entry_point;
|
||||
apc->airport_depots = depots;
|
||||
apc->nof_depots = nof_depots;
|
||||
|
||||
/* Build the state machine itself */
|
||||
AirportBuildAutomata(apc, apFA);
|
||||
DEBUG(misc, 1) ("[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entry %3d",
|
||||
apc->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, apc->entry_point);
|
||||
|
||||
/* Test if everything went allright. This is only a rude static test checking
|
||||
* the symantic correctness. By no means does passing the test mean that the
|
||||
* airport is working correctly or will not deadlock for example */
|
||||
{ byte ret = AirportTestFTA(apc);
|
||||
if (ret != MAX_ELEMENTS) DEBUG(misc, 0) ("[Ap] ERROR with element: %d", ret - 1);
|
||||
assert(ret == MAX_ELEMENTS);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
AirportPrintOut(apc, DEBUG_AIRPORT);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *apc)
|
||||
{
|
||||
int i;
|
||||
AirportFTA *current, *next;
|
||||
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
current = apc->layout[i].next;
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
};
|
||||
}
|
||||
free(apc->layout);
|
||||
free(apc);
|
||||
}
|
||||
|
||||
/** Get the number of elements of a source Airport state automata
|
||||
* Since it is actually just a big array of AirportFTA types, we only
|
||||
* know one element from the other by differing 'position' identifiers */
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
|
||||
{
|
||||
int i;
|
||||
uint16 nofelements = 0;
|
||||
int temp = apFA[0].position;
|
||||
|
||||
for (i = 0; i < MAX_ELEMENTS; i++) {
|
||||
if (temp != apFA[i].position) {
|
||||
nofelements++;
|
||||
temp = apFA[i].position;
|
||||
}
|
||||
if (apFA[i].position == MAX_ELEMENTS) break;
|
||||
}
|
||||
return nofelements;
|
||||
}
|
||||
|
||||
/* We calculate the terminal/helipod count based on the data passed to us
|
||||
* This data (terminals) contains an index as a first element as to how many
|
||||
* groups there are, and then the number of terminals for each group */
|
||||
static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
|
||||
{
|
||||
byte i;
|
||||
byte nof_terminals = 0;
|
||||
*groups = 0;
|
||||
|
||||
if (terminals != NULL) {
|
||||
i = terminals[0];
|
||||
*groups = i;
|
||||
while (i-- > 0) {
|
||||
terminals++;
|
||||
assert(*terminals != 0); // no empty groups please
|
||||
nof_terminals += *terminals;
|
||||
}
|
||||
}
|
||||
return nof_terminals;
|
||||
}
|
||||
|
||||
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA)
|
||||
{
|
||||
AirportFTA *current;
|
||||
AirportFTA *FAutomata = malloc(sizeof(AirportFTA) * apc->nofelements);
|
||||
uint16 internalcounter = 0;
|
||||
uint16 i;
|
||||
|
||||
apc->layout = FAutomata;
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
current = &apc->layout[i];
|
||||
current->position = apFA[internalcounter].position;
|
||||
current->heading = apFA[internalcounter].heading;
|
||||
current->block = apFA[internalcounter].block;
|
||||
current->next_position = apFA[internalcounter].next;
|
||||
|
||||
// outgoing nodes from the same position, create linked list
|
||||
while (current->position == apFA[internalcounter + 1].position) {
|
||||
AirportFTA *newNode = malloc(sizeof(AirportFTA));
|
||||
|
||||
newNode->position = apFA[internalcounter + 1].position;
|
||||
newNode->heading = apFA[internalcounter + 1].heading;
|
||||
newNode->block = apFA[internalcounter + 1].block;
|
||||
newNode->next_position = apFA[internalcounter + 1].next;
|
||||
// create link
|
||||
current->next = newNode;
|
||||
current = current->next;
|
||||
internalcounter++;
|
||||
} // while
|
||||
current->next = NULL;
|
||||
internalcounter++;
|
||||
}
|
||||
}
|
||||
|
||||
static byte AirportTestFTA(const AirportFTAClass *apc)
|
||||
{
|
||||
byte position, i, next_position;
|
||||
AirportFTA *current, *first;
|
||||
next_position = 0;
|
||||
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
position = apc->layout[i].position;
|
||||
if (position != next_position) return i;
|
||||
current = first = &apc->layout[i];
|
||||
|
||||
for (; current != NULL; current = current->next) {
|
||||
/* A heading must always be valid. The only exceptions are
|
||||
* - multiple choices as start, identified by a special value of 255
|
||||
* - terminal group which is identified by a special value of 255 */
|
||||
if (current->heading > MAX_HEADINGS) {
|
||||
if (current->heading != 255) return i;
|
||||
if (current == first && current->next == NULL) return i;
|
||||
if (current != first && current->next_position > apc->terminals[0]) return i;
|
||||
}
|
||||
|
||||
/* If there is only one choice, it must be at the end */
|
||||
if (current->heading == 0 && current->next != NULL) return i;
|
||||
/* Obviously the elements of the linked list must have the same identifier */
|
||||
if (position != current->position) return i;
|
||||
/* A next position must be within bounds */
|
||||
if (current->next_position >= apc->nofelements) return i;
|
||||
}
|
||||
next_position++;
|
||||
}
|
||||
return MAX_ELEMENTS;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
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",
|
||||
"TERM7",
|
||||
"TERM8",
|
||||
"HELIPAD3",
|
||||
"HELIPAD4",
|
||||
"DUMMY" // extra heading for 255
|
||||
};
|
||||
|
||||
static uint AirportBlockToString(uint32 block)
|
||||
{
|
||||
uint i = 0;
|
||||
if (block & 0xffff0000) { block >>= 16; i += 16; }
|
||||
if (block & 0x0000ff00) { block >>= 8; i += 8; }
|
||||
if (block & 0x000000f0) { block >>= 4; i += 4; }
|
||||
if (block & 0x0000000c) { block >>= 2; i += 2; }
|
||||
if (block & 0x00000002) { i += 1; }
|
||||
return i;
|
||||
}
|
||||
|
||||
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report)
|
||||
{
|
||||
uint16 i;
|
||||
|
||||
if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
|
||||
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
AirportFTA *current = &apc->layout[i];
|
||||
|
||||
for (; current != NULL; current = current->next) {
|
||||
if (full_report) {
|
||||
byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
|
||||
printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
|
||||
current->next_position, _airport_heading_strings[heading],
|
||||
AirportBlockToString(current->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", current->position, current->next_position);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const AirportFTAClass *GetAirport(const byte airport_type)
|
||||
{
|
||||
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
// needs constant change if more airports are added
|
||||
switch (airport_type) {
|
||||
default: NOT_REACHED();
|
||||
case AT_SMALL: return CountryAirport;
|
||||
case AT_LARGE: return CityAirport;
|
||||
case AT_METROPOLITAN: return MetropolitanAirport;
|
||||
case AT_HELIPORT: return Heliport;
|
||||
case AT_OILRIG: return Oilrig;
|
||||
case AT_INTERNATIONAL: return InternationalAirport;
|
||||
case AT_COMMUTER: return CommuterAirport;
|
||||
case AT_HELIDEPOT: return HeliDepot;
|
||||
case AT_INTERCON: return IntercontinentalAirport;
|
||||
case AT_HELISTATION: return HeliStation;
|
||||
}
|
||||
}
|
||||
|
||||
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position)
|
||||
{
|
||||
assert(airport_type < lengthof(_airport_moving_datas));
|
||||
assert(position < GetAirport(airport_type)->nofelements);
|
||||
return &_airport_moving_datas[airport_type][position];
|
||||
}
|
||||
|
||||
uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
if (_cur_year >= 1980) SETBIT(bytemask, 3); // metropolitan airport
|
||||
if (_cur_year >= 1990) SETBIT(bytemask, 4); // international airport
|
||||
if (_cur_year >= 1983) SETBIT(bytemask, 5); // commuter airport
|
||||
if (_cur_year >= 1976) SETBIT(bytemask, 6); // helidepot
|
||||
if (_cur_year >= 2002) SETBIT(bytemask, 7); // intercontinental airport
|
||||
if (_cur_year >= 1980) SETBIT(bytemask, 8); // helistation
|
||||
return bytemask;
|
||||
}
|
163
airport.h
Normal file
163
airport.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_H
|
||||
#define AIRPORT_H
|
||||
|
||||
enum {MAX_TERMINALS = 10};
|
||||
enum {MAX_HELIPADS = 4};
|
||||
enum {MAX_ELEMENTS = 255};
|
||||
enum {MAX_HEADINGS = 22};
|
||||
|
||||
// Airport types
|
||||
enum {
|
||||
AT_SMALL = 0,
|
||||
AT_LARGE = 1,
|
||||
AT_HELIPORT = 2,
|
||||
AT_METROPOLITAN = 3,
|
||||
AT_INTERNATIONAL = 4,
|
||||
AT_COMMUTER = 5,
|
||||
AT_HELIDEPOT = 6,
|
||||
AT_INTERCON = 7,
|
||||
AT_HELISTATION = 8,
|
||||
AT_OILRIG = 15
|
||||
};
|
||||
|
||||
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
|
||||
enum {
|
||||
AIRCRAFT_ONLY = 0,
|
||||
ALL = 1,
|
||||
HELICOPTERS_ONLY = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
AMED_NOSPDCLAMP = 1 << 0,
|
||||
AMED_TAKEOFF = 1 << 1,
|
||||
AMED_SLOWTURN = 1 << 2,
|
||||
AMED_LAND = 1 << 3,
|
||||
AMED_EXACTPOS = 1 << 4,
|
||||
AMED_BRAKE = 1 << 5,
|
||||
AMED_HELI_RAISE = 1 << 6,
|
||||
AMED_HELI_LOWER = 1 << 7,
|
||||
};
|
||||
|
||||
/* Movement States on Airports (headings target) */
|
||||
enum {
|
||||
TO_ALL = 0,
|
||||
HANGAR = 1,
|
||||
TERM1 = 2,
|
||||
TERM2 = 3,
|
||||
TERM3 = 4,
|
||||
TERM4 = 5,
|
||||
TERM5 = 6,
|
||||
TERM6 = 7,
|
||||
HELIPAD1 = 8,
|
||||
HELIPAD2 = 9,
|
||||
TAKEOFF = 10,
|
||||
STARTTAKEOFF = 11,
|
||||
ENDTAKEOFF = 12,
|
||||
HELITAKEOFF = 13,
|
||||
FLYING = 14,
|
||||
LANDING = 15,
|
||||
ENDLANDING = 16,
|
||||
HELILANDING = 17,
|
||||
HELIENDLANDING = 18,
|
||||
TERM7 = 19,
|
||||
TERM8 = 20,
|
||||
HELIPAD3 = 21,
|
||||
HELIPAD4 = 22
|
||||
};
|
||||
|
||||
// this maps the terminal to its corresponding state and block flag
|
||||
// currently set for 10 terms, 4 helipads
|
||||
static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
|
||||
static const byte _airport_terminal_flag[] = {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25};
|
||||
|
||||
/* Movement Blocks on Airports */
|
||||
// blocks (eg_airport_flags)
|
||||
enum {
|
||||
TERM1_block = 1 << 0,
|
||||
TERM2_block = 1 << 1,
|
||||
TERM3_block = 1 << 2,
|
||||
TERM4_block = 1 << 3,
|
||||
TERM5_block = 1 << 4,
|
||||
TERM6_block = 1 << 5,
|
||||
HELIPAD1_block = 1 << 6,
|
||||
HELIPAD2_block = 1 << 7,
|
||||
RUNWAY_IN_OUT_block = 1 << 8,
|
||||
RUNWAY_IN_block = 1 << 8,
|
||||
AIRPORT_BUSY_block = 1 << 8,
|
||||
RUNWAY_OUT_block = 1 << 9,
|
||||
TAXIWAY_BUSY_block = 1 << 10,
|
||||
OUT_WAY_block = 1 << 11,
|
||||
IN_WAY_block = 1 << 12,
|
||||
AIRPORT_ENTRANCE_block = 1 << 13,
|
||||
TERM_GROUP1_block = 1 << 14,
|
||||
TERM_GROUP2_block = 1 << 15,
|
||||
HANGAR2_AREA_block = 1 << 16,
|
||||
TERM_GROUP2_ENTER1_block = 1 << 17,
|
||||
TERM_GROUP2_ENTER2_block = 1 << 18,
|
||||
TERM_GROUP2_EXIT1_block = 1 << 19,
|
||||
TERM_GROUP2_EXIT2_block = 1 << 20,
|
||||
PRE_HELIPAD_block = 1 << 21,
|
||||
|
||||
// blocks for new airports
|
||||
TERM7_block = 1 << 22,
|
||||
TERM8_block = 1 << 23,
|
||||
TERM9_block = 1 << 24,
|
||||
HELIPAD3_block = 1 << 24,
|
||||
TERM10_block = 1 << 25,
|
||||
HELIPAD4_block = 1 << 25,
|
||||
HANGAR1_AREA_block = 1 << 26,
|
||||
OUT_WAY2_block = 1 << 27,
|
||||
IN_WAY2_block = 1 << 28,
|
||||
RUNWAY_IN2_block = 1 << 29,
|
||||
RUNWAY_OUT2_block = 1 << 10, // note re-uses TAXIWAY_BUSY
|
||||
HELIPAD_GROUP_block = 1 << 13, // note re-uses AIRPORT_ENTRANCE
|
||||
OUT_WAY_block2 = 1 << 31,
|
||||
// end of new blocks
|
||||
|
||||
NOTHING_block = 1 << 30
|
||||
};
|
||||
|
||||
typedef struct AirportMovingData {
|
||||
int x,y;
|
||||
byte flag;
|
||||
byte direction;
|
||||
} AirportMovingData;
|
||||
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAClass {
|
||||
byte nofelements; // number of positions the airport consists of
|
||||
const byte *terminals;
|
||||
const byte *helipads;
|
||||
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
|
||||
byte acc_planes; // accept airplanes or helicopters or both
|
||||
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
|
||||
byte nof_depots; // number of depots this airport has
|
||||
struct AirportFTA *layout; // state machine for airport
|
||||
byte size_x;
|
||||
byte size_y;
|
||||
} AirportFTAClass;
|
||||
|
||||
// internal structure used in openttd - Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTA {
|
||||
byte position; // the position that an airplane is at
|
||||
byte next_position; // next position from this position
|
||||
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
|
||||
byte heading; // heading (current orders), guiding an airplane to its target on an airport
|
||||
struct AirportFTA *next; // possible extra movement choices from this position
|
||||
} AirportFTA;
|
||||
|
||||
void InitializeAirports(void);
|
||||
void UnInitializeAirports(void);
|
||||
const AirportFTAClass *GetAirport(const byte airport_type);
|
||||
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position);
|
||||
|
||||
/** Get buildable airport bitmask.
|
||||
* @return get all buildable airports at this given time, bitmasked.
|
||||
* Bit 0 means the small airport is buildable, etc.
|
||||
* @todo set availability of airports by year, instead of airplane
|
||||
*/
|
||||
uint32 GetValidAirports(void);
|
||||
|
||||
#endif /* AIRPORT_H */
|
286
airport_gui.c
Normal file
286
airport_gui.c
Normal file
@@ -0,0 +1,286 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
#include "station.h"
|
||||
#include "airport.h"
|
||||
#include "depot.h"
|
||||
|
||||
static byte _selected_airport_type;
|
||||
|
||||
static void ShowBuildAirportPicker(void);
|
||||
|
||||
|
||||
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceAirport(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
|
||||
}
|
||||
|
||||
static void PlaceAir_DemolishArea(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, 4);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
ATW_AIRPORT = 3,
|
||||
ATW_DEMOLISH = 4
|
||||
};
|
||||
|
||||
|
||||
static void BuildAirClick_Airport(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
}
|
||||
|
||||
static void BuildAirClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_air_button_proc[] = {
|
||||
BuildAirClick_Airport,
|
||||
BuildAirClick_Demolish,
|
||||
BuildAirClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->we.click.widget - 3 >= 0)
|
||||
_build_air_button_proc[e->we.click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch (e->we.keypress.keycode) {
|
||||
case '1': BuildAirClick_Airport(w); break;
|
||||
case '2': BuildAirClick_Demolish(w); break;
|
||||
case 'l': BuildAirClick_Landscaping(w); break;
|
||||
default: return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->we.place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG:
|
||||
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
|
||||
break;
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->we.place.pt.x != -1) {
|
||||
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
RaiseWindowButtons(w);
|
||||
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != 0)
|
||||
WP(w,def_d).close = true;
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _air_toolbar_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS },
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON },
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 41, 14, 35, SPR_IMG_AIRPORT, STR_A01E_BUILD_AIRPORT },
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 42, 63, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC },
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP },
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static const WindowDesc _air_toolbar_desc = {
|
||||
WDP_ALIGN_TBR, 22, 86, 36,
|
||||
WC_BUILD_TOOLBAR, 0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_air_toolbar_widgets,
|
||||
BuildAirToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildAirToolbar(void)
|
||||
{
|
||||
if (!IsValidPlayer(_current_player)) return;
|
||||
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDescFront(&_air_toolbar_desc, 0);
|
||||
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_CREATE:
|
||||
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
|
||||
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
|
||||
LowerWindowWidget(w, _selected_airport_type + 7);
|
||||
break;
|
||||
|
||||
case WE_PAINT: {
|
||||
int i; // airport enabling loop
|
||||
int rad = 4; // default catchment radious
|
||||
uint32 avail_airports;
|
||||
const AirportFTAClass *airport;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
|
||||
avail_airports = GetValidAirports();
|
||||
|
||||
RaiseWindowWidget(w, _selected_airport_type + 7);
|
||||
if (!HASBIT(avail_airports, 0) && _selected_airport_type == AT_SMALL) _selected_airport_type = AT_LARGE;
|
||||
if (!HASBIT(avail_airports, 1) && _selected_airport_type == AT_LARGE) _selected_airport_type = AT_SMALL;
|
||||
LowerWindowWidget(w, _selected_airport_type + 7);
|
||||
|
||||
/* 'Country Airport' starts at widget 7, and if its bit is set, it is
|
||||
* available, so take its opposite value to set the disabled state.
|
||||
* There are 9 buildable airports
|
||||
* XXX TODO : all airports should be held in arrays, with all relevant data.
|
||||
* This should be part of newgrf-airports, i suppose
|
||||
*/
|
||||
for (i = 0; i < 9; i++) SetWindowWidgetDisabledState(w, i + 7, !HASBIT(avail_airports, i));
|
||||
|
||||
// select default the coverage area to 'Off' (16)
|
||||
airport = GetAirport(_selected_airport_type);
|
||||
SetTileSelectSize(airport->size_x, airport->size_y);
|
||||
|
||||
if (_patches.modified_catchment) {
|
||||
switch (_selected_airport_type) {
|
||||
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
|
||||
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
|
||||
case AT_SMALL: rad = CA_AIR_SMALL; break;
|
||||
case AT_LARGE: rad = CA_AIR_LARGE; break;
|
||||
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
|
||||
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
|
||||
case AT_COMMUTER: rad = CA_AIR_COMMUTER; break;
|
||||
case AT_HELIDEPOT: rad = CA_AIR_HELIDEPOT; break;
|
||||
case AT_INTERCON: rad = CA_AIR_INTERCON; break;
|
||||
case AT_HELISTATION: rad = CA_AIR_HELISTATION; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
// strings such as 'Size' and 'Coverage Area'
|
||||
// 'Coverage Area'
|
||||
DrawStationCoverageAreaText(2, 206, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK: {
|
||||
switch (e->we.click.widget) {
|
||||
case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
|
||||
RaiseWindowWidget(w, _selected_airport_type + 7);
|
||||
_selected_airport_type = e->we.click.widget - 7;
|
||||
LowerWindowWidget(w, _selected_airport_type + 7);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 16: case 17:
|
||||
_station_show_coverage = e->we.click.widget - 16;
|
||||
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
|
||||
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_MOUSELOOP: {
|
||||
if (WP(w,def_d).close) {
|
||||
DeleteWindow(w);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close) ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_airport_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 52, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 53, 89, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 90, 127, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 128, 177, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 178, 239, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 27, 38, STR_SMALL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 65, 76, STR_CITY_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 141, 152, STR_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 77, 88, STR_METRO_AIRPORT , STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 103, 114, STR_INTERNATIONAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_COMMUTER_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 165, 176, STR_HELIDEPOT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 115, 126, STR_INTERCONTINENTAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 153, 164, STR_HELISTATION, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 191, 202, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 191, 202, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 14, 27, STR_SMALL_AIRPORTS, STR_NULL},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 52, 65, STR_LARGE_AIRPORTS, STR_NULL},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 90, 103, STR_HUB_AIRPORTS, STR_NULL},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 128, 141, STR_HELIPORTS, STR_NULL},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 178, 191, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_airport_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 148, 240,
|
||||
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_airport_picker_widgets,
|
||||
BuildAirportPickerWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildAirportPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_airport_desc);
|
||||
}
|
||||
|
||||
void InitializeAirportGui(void)
|
||||
{
|
||||
_selected_airport_type = AT_SMALL;
|
||||
}
|
794
airport_movement.h
Normal file
794
airport_movement.h
Normal file
@@ -0,0 +1,794 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_MOVEMENT_H
|
||||
#define AIRPORT_MOVEMENT_H
|
||||
|
||||
|
||||
// state machine input struct (from external file, etc.)
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAbuildup {
|
||||
byte position; // the position that an airplane is at
|
||||
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
|
||||
uint32 block; // the block this position is on on the airport (st->airport_flags)
|
||||
byte next; // next position from this position
|
||||
} AirportFTAbuildup;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////*********Movement Positions on Airports********************///////
|
||||
// Country Airfield (small) 4x3
|
||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||
{ 53, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 53, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 32, 23, AMED_EXACTPOS, 7 }, // 02 Terminal 1
|
||||
{ 10, 23, AMED_EXACTPOS, 7 }, // 03 Terminal 2
|
||||
{ 43, 37, 0, 0 }, // 04 Going towards terminal 2
|
||||
{ 24, 37, 0, 0 }, // 05 Going towards terminal 2
|
||||
{ 53, 37, 0, 0 }, // 06 Going for takeoff
|
||||
{ 61, 40, AMED_EXACTPOS, 1 }, // 07 Taxi to start of runway (takeoff)
|
||||
{ 3, 40, AMED_NOSPDCLAMP, 0 }, // 08 Accelerate to end of runway
|
||||
{ -79, 40, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 09 Take off
|
||||
{ 177, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 10 Fly to landing position in air
|
||||
{ 56, 40, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 11 Going down for land
|
||||
{ 3, 40, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 12 Just landed, brake until end of runway
|
||||
{ 7, 40, 0, 0 }, // 13 Just landed, turn around and taxi 1 square
|
||||
{ 53, 40, 0, 0 }, // 14 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (south)
|
||||
{ 44, 37, AMED_HELI_RAISE, 0 }, // 19 Helicopter takeoff
|
||||
{ 44, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 In position above landing spot helicopter
|
||||
{ 44, 40, AMED_HELI_LOWER, 0 }, // 21 Helicopter landing
|
||||
};
|
||||
|
||||
// Commuter Airfield (small) 5x4
|
||||
static const AirportMovingData _airport_moving_data_commuter[37] = {
|
||||
{ 69, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 72, 22, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 8, 22, AMED_EXACTPOS, 5 }, // 01 Taxi to right outside depot
|
||||
{ 24, 36, AMED_EXACTPOS, 3 }, // 03 Terminal 1
|
||||
{ 40, 36, AMED_EXACTPOS, 3 }, // 04 Terminal 2
|
||||
{ 56, 36, AMED_EXACTPOS, 3 }, // 05 Terminal 3
|
||||
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
|
||||
{ 24, 22, 0, 5 }, // 08 Taxiing
|
||||
{ 40, 22, 0, 5 }, // 09 Taxiing
|
||||
{ 56, 22, 0, 5 }, // 10 Taxiing
|
||||
{ 72, 40, 0, 3 }, // 11 Airport OUTWAY
|
||||
{ 72, 54, AMED_EXACTPOS, 1 }, // 12 Accelerate to end of runway
|
||||
{ 7, 54, AMED_NOSPDCLAMP, 0 }, // 13 Release control of runway, for smoother movement
|
||||
{ 5, 54, AMED_NOSPDCLAMP, 0 }, // 14 End of runway
|
||||
{ -79, 54, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 15 Take off
|
||||
{ 145, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly to landing position in air
|
||||
{ 73, 54, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 17 Going down for land
|
||||
{ 3, 54, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 18 Just landed, brake until end of runway
|
||||
{ 12, 54, 0, 7 }, // 19 Just landed, turn around and taxi
|
||||
{ 8, 32, 0, 7 }, // 20 Taxi from runway to crossing
|
||||
{ -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (north-west)
|
||||
{ 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Fly around waiting for a landing spot (south-west)
|
||||
{ 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 24 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Bufferspace before helipad
|
||||
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Bufferspace before helipad
|
||||
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Get in position for Helipad1
|
||||
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Get in position for Helipad2
|
||||
{ 32, 8, AMED_HELI_LOWER, 0 }, // 29 Land at Helipad1
|
||||
{ 48, 8, AMED_HELI_LOWER, 0 }, // 30 Land at Helipad2
|
||||
{ 32, 8, AMED_HELI_RAISE, 0 }, // 31 Takeoff Helipad1
|
||||
{ 48, 8, AMED_HELI_RAISE, 0 }, // 32 Takeoff Helipad2
|
||||
{ 64, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 33 Go to position for Hangarentrance in air
|
||||
{ 64, 22, AMED_HELI_LOWER, 0 }, // 34 Land in front of hangar
|
||||
{ 40, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 2
|
||||
};
|
||||
|
||||
// City Airport (large) 6x6
|
||||
static const AirportMovingData _airport_moving_data_town[25] = {
|
||||
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
|
||||
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
|
||||
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
|
||||
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 80, 27, 0, 0 }, // 06 Taxiway terminals 2-3
|
||||
{ 44, 63, 0, 0 }, // 07 Taxi to Airport center
|
||||
{ 58, 71, 0, 0 }, // 08 Towards takeoff
|
||||
{ 72, 85, 0, 0 }, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 85, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 85, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
|
||||
{ -79, 85, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
|
||||
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
|
||||
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
|
||||
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
|
||||
{ 20, 87, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 36, 71, 0, 0 }, // 17 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south)
|
||||
{ 44, 63, AMED_HELI_RAISE, 0 }, // 22 Helicopter takeoff
|
||||
{ 28, 74, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 In position above landing spot helicopter
|
||||
{ 28, 74, AMED_HELI_LOWER, 0 }, // 24 Helicopter landing
|
||||
};
|
||||
|
||||
// Metropolitan Airport (metropolitan) - 2 runways
|
||||
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
|
||||
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
|
||||
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
|
||||
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
|
||||
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 70, 33, 0, 0 }, // 06 Taxiway terminals 2-3
|
||||
{ 44, 58, 0, 0 }, // 07 Taxi to Airport center
|
||||
{ 72, 58, 0, 0 }, // 08 Towards takeoff
|
||||
{ 72, 69, 0, 0 }, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 69, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 69, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
|
||||
{ -79, 69, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
|
||||
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
|
||||
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
|
||||
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
|
||||
{ 21, 85, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 21, 69, 0, 0 }, // 17 On Runway-out taxiing to In-Way
|
||||
{ 21, 54, AMED_EXACTPOS, 5 }, // 18 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (south)
|
||||
{ 44, 58, 0, 0 }, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
|
||||
{ 44, 63, AMED_HELI_RAISE, 0 }, // 24 Helicopter takeoff
|
||||
{ 15, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Get in position above landing spot helicopter
|
||||
{ 15, 54, AMED_HELI_LOWER, 0 }, // 26 Helicopter landing
|
||||
};
|
||||
|
||||
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
|
||||
static const AirportMovingData _airport_moving_data_international[51] = {
|
||||
{ 7, 55, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
|
||||
{ 100, 21, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
|
||||
{ 7, 70, 0, 0 }, // 02 Taxi to right outside depot
|
||||
{ 100, 36, 0, 0 }, // 03 Taxi to right outside depot
|
||||
{ 38, 70, AMED_EXACTPOS, 5 }, // 04 Terminal 1
|
||||
{ 38, 54, AMED_EXACTPOS, 5 }, // 05 Terminal 2
|
||||
{ 38, 38, AMED_EXACTPOS, 5 }, // 06 Terminal 3
|
||||
{ 70, 70, AMED_EXACTPOS, 1 }, // 07 Terminal 4
|
||||
{ 70, 54, AMED_EXACTPOS, 1 }, // 08 Terminal 5
|
||||
{ 70, 38, AMED_EXACTPOS, 1 }, // 09 Terminal 6
|
||||
{ 104, 71, AMED_EXACTPOS, 1 }, // 10 Helipad 1
|
||||
{ 104, 55, AMED_EXACTPOS, 1 }, // 11 Helipad 2
|
||||
{ 22, 87, 0, 0 }, // 12 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 60, 87, 0, 0 }, // 13 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 66, 87, 0, 0 }, // 14 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 87, AMED_EXACTPOS, 7 }, // 15 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 70, 0, 0 }, // 16 In Front of Terminal 4 / Helipad 1
|
||||
{ 86, 54, 0, 0 }, // 17 In Front of Terminal 5 / Helipad 2
|
||||
{ 86, 38, 0, 0 }, // 18 In Front of Terminal 6
|
||||
{ 86, 22, 0, 0 }, // 19 Towards Terminals Takeoff (Taxiway)
|
||||
{ 66, 22, 0, 0 }, // 20 Towards Terminals Takeoff (Taxiway)
|
||||
{ 60, 22, 0, 0 }, // 21 Towards Terminals Takeoff (Taxiway)
|
||||
{ 38, 22, 0, 0 }, // 22 Towards Terminals Takeoff (Taxiway)
|
||||
{ 22, 70, 0, 0 }, // 23 In Front of Terminal 1
|
||||
{ 22, 58, 0, 0 }, // 24 In Front of Terminal 2
|
||||
{ 22, 38, 0, 0 }, // 25 In Front of Terminal 3
|
||||
{ 22, 22, AMED_EXACTPOS, 7 }, // 26 Going for Takeoff
|
||||
{ 22, 6, 0, 0 }, // 27 On Runway-out, prepare for takeoff
|
||||
{ 3, 6, AMED_EXACTPOS, 5 }, // 28 Accelerate to end of runway
|
||||
{ 60, 6, AMED_NOSPDCLAMP, 0 }, // 29 Release control of runway, for smoother movement
|
||||
{ 105, 6, AMED_NOSPDCLAMP, 0 }, // 30 End of runway
|
||||
{ 190, 6, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 31 Take off
|
||||
{ 193, 104, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly to landing position in air
|
||||
{ 105, 104, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 33 Going down for land
|
||||
{ 3, 104, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 34 Just landed, brake until end of runway
|
||||
{ 12, 104, AMED_SLOWTURN, 0 }, // 35 Just landed, turn around and taxi 1 square
|
||||
{ 7, 84, 0, 0 }, // 36 Taxi from runway to crossing
|
||||
{ -31, 209, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 37 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 38 Fly around waiting for a landing spot (north-west)
|
||||
{ 273, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 39 Fly around waiting for a landing spot (south-west)
|
||||
{ 305, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 40 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 41 Bufferspace before helipad
|
||||
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 42 Bufferspace before helipad
|
||||
{ 96, 71, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Get in position for Helipad1
|
||||
{ 96, 55, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Get in position for Helipad2
|
||||
{ 96, 71, AMED_HELI_LOWER, 0 }, // 45 Land at Helipad1
|
||||
{ 96, 55, AMED_HELI_LOWER, 0 }, // 46 Land at Helipad2
|
||||
{ 104, 71, AMED_HELI_RAISE, 0 }, // 47 Takeoff Helipad1
|
||||
{ 104, 55, AMED_HELI_RAISE, 0 }, // 48 Takeoff Helipad2
|
||||
{ 104, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Go to position for Hangarentrance in air
|
||||
{ 104, 32, AMED_HELI_LOWER, 0} // 50 Land in HANGAR2_AREA to go to hangar
|
||||
};
|
||||
|
||||
// Intercontinental Airport - 4 runways, 8 terminals, 2 dedicated helipads
|
||||
static const AirportMovingData _airport_moving_data_intercontinental[77] = {
|
||||
{ 7, 87, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
|
||||
{ 135, 72, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
|
||||
{ 7, 104, 0, 0 }, // 02 Taxi to right outside depot 1
|
||||
{ 135, 88, 0, 0 }, // 03 Taxi to right outside depot 2
|
||||
{ 56, 120, AMED_EXACTPOS, 6 }, // 04 Terminal 1
|
||||
{ 56, 104, AMED_EXACTPOS, 5 }, // 05 Terminal 2
|
||||
{ 56, 88, AMED_EXACTPOS, 5 }, // 06 Terminal 3
|
||||
{ 56, 72, AMED_EXACTPOS, 5 }, // 07 Terminal 4
|
||||
{ 88, 120, AMED_EXACTPOS, 0 }, // 08 Terminal 5
|
||||
{ 88, 104, AMED_EXACTPOS, 1 }, // 09 Terminal 6
|
||||
{ 88, 88, AMED_EXACTPOS, 1 }, // 10 Terminal 7
|
||||
{ 88, 72, AMED_EXACTPOS, 1 }, // 11 Terminal 8
|
||||
{ 88, 56, AMED_EXACTPOS, 3 }, // 12 Helipad 1
|
||||
{ 72, 56, AMED_EXACTPOS, 1 }, // 13 Helipad 2
|
||||
{ 40, 136, 0, 0 }, // 14 Term group 2 enter 1 a
|
||||
{ 56, 136, 0, 0 }, // 15 Term group 2 enter 1 b
|
||||
{ 88, 136, 0, 0 }, // 16 Term group 2 enter 2 a
|
||||
{ 104, 136, 0, 0 }, // 17 Term group 2 enter 2 b
|
||||
{ 104, 120, 0, 0 }, // 18 Term group 2 - opp term 5
|
||||
{ 104, 104, 0, 0 }, // 19 Term group 2 - opp term 6 & exit2
|
||||
{ 104, 88, 0, 0 }, // 20 Term group 2 - opp term 7 & hangar area 2
|
||||
{ 104, 72, 0, 0 }, // 21 Term group 2 - opp term 8
|
||||
{ 104, 56, 0, 0 }, // 22 Taxi Term group 2 exit a
|
||||
{ 104, 40, 0, 0 }, // 23 Taxi Term group 2 exit b
|
||||
{ 56, 40, 0, 0 }, // 24 Term group 2 exit 2a
|
||||
{ 40, 40, 0, 0 }, // 25 Term group 2 exit 2b
|
||||
{ 40, 120, 0, 0 }, // 26 Term group 1 - opp term 1
|
||||
{ 40, 104, 0, 0 }, // 27 Term group 1 - opp term 2 & hangar area 1
|
||||
{ 40, 88, 0, 0 }, // 28 Term group 1 - opp term 3
|
||||
{ 40, 72, 0, 0 }, // 29 Term group 1 - opp term 4
|
||||
{ 18, 72, 0, 7 }, // 30 Outway 1
|
||||
{ 8, 40, 0, 7 }, // 31 Airport OUTWAY
|
||||
{ 8, 24, AMED_EXACTPOS, 5 }, // 32 Accelerate to end of runway
|
||||
{ 119, 24, AMED_NOSPDCLAMP, 0 }, // 33 Release control of runway, for smoother movement
|
||||
{ 117, 24, AMED_NOSPDCLAMP, 0 }, // 34 End of runway
|
||||
{ 197, 24, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 35 Take off
|
||||
{ 254, 84, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 36 Flying to landing position in air
|
||||
{ 117, 168, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 37 Going down for land
|
||||
{ 3, 168, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 38 Just landed, brake until end of runway
|
||||
{ 8, 168, 0, 0 }, // 39 Just landed, turn around and taxi
|
||||
{ 8, 144, 0, 7 }, // 40 Taxi from runway
|
||||
{ 8, 128, 0, 7 }, // 41 Taxi from runway
|
||||
{ 8, 120, AMED_EXACTPOS, 5 }, // 42 Airport entrance
|
||||
{ 56, 344, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Fly around waiting for a landing spot (north-east)
|
||||
{ -200, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Fly around waiting for a landing spot (north-west)
|
||||
{ 56, -168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 45 Fly around waiting for a landing spot (south-west)
|
||||
{ 312, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 46 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 47 Bufferspace before helipad
|
||||
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 48 Bufferspace before helipad
|
||||
{ 82, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Get in position for Helipad1
|
||||
{ 64, 56, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 50 Get in position for Helipad2
|
||||
{ 81, 55, AMED_HELI_LOWER, 0 }, // 51 Land at Helipad1
|
||||
{ 64, 56, AMED_HELI_LOWER, 0 }, // 52 Land at Helipad2
|
||||
{ 80, 56, AMED_HELI_RAISE, 0 }, // 53 Takeoff Helipad1
|
||||
{ 64, 56, AMED_HELI_RAISE, 0 }, // 54 Takeoff Helipad2
|
||||
{ 136, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 55 Go to position for Hangarentrance in air
|
||||
{ 136, 96, AMED_HELI_LOWER, 0 }, // 56 Land in front of hangar2
|
||||
{ 126, 104, 0, 3 }, // 57 Outway 2
|
||||
{ 136, 136, 0, 1 }, // 58 Airport OUTWAY 2
|
||||
{ 136, 152, AMED_EXACTPOS, 1 }, // 59 Accelerate to end of runway2
|
||||
{ 16, 152, AMED_NOSPDCLAMP, 0 }, // 60 Release control of runway2, for smoother movement
|
||||
{ 20, 152, AMED_NOSPDCLAMP, 0 }, // 61 End of runway2
|
||||
{ -56, 152, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 62 Take off2
|
||||
{ 24, 8, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 63 Going down for land2
|
||||
{ 136, 8, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 64 Just landed, brake until end of runway2in
|
||||
{ 136, 8, 0, 0 }, // 65 Just landed, turn around and taxi
|
||||
{ 136, 24, 0, 3 }, // 66 Taxi from runway 2in
|
||||
{ 136, 40, 0, 3 }, // 67 Taxi from runway 2in
|
||||
{ 136, 56, AMED_EXACTPOS, 1 }, // 68 Airport entrance2
|
||||
{ -56, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 69 Fly to landing position in air2
|
||||
{ 88, 40, 0, 0 }, // 70 Taxi Term group 2 exit - opp heli1
|
||||
{ 72, 40, 0, 0 }, // 71 Taxi Term group 2 exit - opp heli2
|
||||
{ 88, 57, AMED_EXACTPOS, 3 }, // 72 pre-helitakeoff helipad 1
|
||||
{ 71, 56, AMED_EXACTPOS, 1 }, // 73 pre-helitakeoff helipad 2
|
||||
{ 8, 120, AMED_HELI_RAISE, 0 }, // 74 Helitakeoff outside depot 1
|
||||
{ 136, 104, AMED_HELI_RAISE, 0 }, // 75 Helitakeoff outside depot 2
|
||||
{ 197, 168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0} // 76 Fly to landing position in air1
|
||||
};
|
||||
|
||||
|
||||
// Heliport (heliport)
|
||||
static const AirportMovingData _airport_moving_data_heliport[9] = {
|
||||
{ 5, 9, AMED_EXACTPOS, 1 }, // 0 - At heliport terminal
|
||||
{ 2, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
|
||||
{ -3, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
|
||||
{ -3, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
|
||||
{ 2, 9, 0, 0 }, // 4 - Goto terminal on ground
|
||||
{ -31, 59, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #1 (north-east)
|
||||
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #2 (north-west)
|
||||
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - Circle #3 (south-west)
|
||||
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - Circle #4 (south)
|
||||
};
|
||||
|
||||
// HeliDepot 2x2 (heliport)
|
||||
static const AirportMovingData _airport_moving_data_helidepot[18] = {
|
||||
{ 24, 4, AMED_EXACTPOS, 1 }, // 0 - At depot
|
||||
{ 24, 28, 0, 0 }, // 1 Taxi to right outside depot
|
||||
{ 5, 38, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 Flying
|
||||
{ -15, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 3 - Circle #1 (north-east)
|
||||
{ -15, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 4 - Circle #2 (north-west)
|
||||
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #3 (south-west)
|
||||
{ 49, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #4 (south-east)
|
||||
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 7 - PreHelipad
|
||||
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 8 - Helipad
|
||||
{ 8, 16, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 9 - Land
|
||||
{ 8, 16, AMED_HELI_LOWER, 7 }, // 10 - Land
|
||||
{ 8, 24, AMED_HELI_RAISE, 0 }, // 11 - Take off (play sound)
|
||||
{ 32, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 12 Air to above hangar area
|
||||
{ 32, 24, AMED_HELI_LOWER, 7 }, // 13 Taxi to right outside depot
|
||||
{ 8, 24, AMED_EXACTPOS, 7 }, // 14 - on helipad1
|
||||
{ 24, 28, AMED_HELI_RAISE, 0 }, // 15 Takeoff right outside depot
|
||||
{ 8, 24, AMED_HELI_RAISE, 5 }, // 16 - Take off (play sound)
|
||||
{ 8, 24, AMED_SLOWTURN | AMED_EXACTPOS, 2 }, // 17 - turn on helipad1 for takeoff
|
||||
};
|
||||
|
||||
// HeliDepot 2x2 (heliport)
|
||||
static const AirportMovingData _airport_moving_data_helistation[33] = {
|
||||
{ 8, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar2
|
||||
{ 8, 22, 0, 0 }, // 01 outside hangar 2
|
||||
{ 116, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 02 Fly to landing position in air
|
||||
{ 14, 22, AMED_HELI_RAISE, 0 }, // 03 Helitakeoff outside hangar1(play sound)
|
||||
{ 24, 22, 0, 0 }, // 04 taxiing
|
||||
{ 40, 22, 0, 0 }, // 05 taxiing
|
||||
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
|
||||
{ 56, 24, AMED_EXACTPOS, 1 }, // 08 Helipad 3
|
||||
{ 40, 8, AMED_EXACTPOS, 0 }, // 09 pre-helitakeoff helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 0 }, // 10 pre-helitakeoff helipad 2
|
||||
{ 56, 24, AMED_EXACTPOS, 0 }, // 11 pre-helitakeoff helipad 3
|
||||
{ 32, 8, AMED_HELI_RAISE, 0 }, // 12 Takeoff Helipad1
|
||||
{ 48, 8, AMED_HELI_RAISE, 0 }, // 13 Takeoff Helipad2
|
||||
{ 48, 24, AMED_HELI_RAISE, 0 }, // 14 Takeoff Helipad3
|
||||
{ 84, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Bufferspace before helipad
|
||||
{ 68, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Bufferspace before helipad
|
||||
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Get in position for Helipad1
|
||||
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Get in position for Helipad2
|
||||
{ 48, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 1 }, // 19 Get in position for Helipad3
|
||||
{ 40, 8, AMED_HELI_LOWER, 0 }, // 20 Land at Helipad1
|
||||
{ 48, 8, AMED_HELI_LOWER, 0 }, // 21 Land at Helipad2
|
||||
{ 48, 24, AMED_HELI_LOWER, 0 }, // 22 Land at Helipad3
|
||||
{ 0, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Go to position for Hangarentrance in air
|
||||
{ 0, 22, AMED_HELI_LOWER, 0 }, // 24 Land in front of hangar
|
||||
{ 148, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Fly around waiting for a landing spot (south-east)
|
||||
{ 148, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Fly around waiting for a landing spot (south-west)
|
||||
{ 132, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Fly around waiting for a landing spot (south-west)
|
||||
{ 100, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Fly around waiting for a landing spot (north-east)
|
||||
{ 84, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 29 Fly around waiting for a landing spot (south-east)
|
||||
{ 84, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 30 Fly around waiting for a landing spot (south-west)
|
||||
{ 100, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 31 Fly around waiting for a landing spot (north-west)
|
||||
{ 132, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly around waiting for a landing spot (north-east)
|
||||
};
|
||||
|
||||
// Oilrig
|
||||
static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
{ 31, 9, AMED_EXACTPOS, 1 }, // 0 - At oilrig terminal
|
||||
{ 28, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
|
||||
{ 23, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
|
||||
{ 23, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
|
||||
{ 28, 9, 0, 0 }, // 4 - Goto terminal on ground
|
||||
{ -31, 69, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - circle #1 (north-east)
|
||||
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - circle #2 (north-west)
|
||||
{ 69, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - circle #3 (south-west)
|
||||
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - circle #4 (south)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
/* First element of terminals array tells us how many depots there are (to know size of array)
|
||||
* this may be changed later when airports are moved to external file */
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, AIRPORT_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM1, TERM1_block, 2 }, { 1, TERM2, 0, 4 }, { 1, HELITAKEOFF, 0, 19 }, { 1, 0, 0, 6 },
|
||||
{ 2, TERM1, TERM1_block, 1 },
|
||||
{ 3, TERM2, TERM2_block, 5 },
|
||||
{ 4, 255, AIRPORT_BUSY_block, 0 }, { 4, TERM2, 0, 5 }, { 4, HANGAR, 0, 1 }, { 4, TAKEOFF, 0, 6 }, { 4, HELITAKEOFF, 0, 1 },
|
||||
{ 5, 255, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, 0, 0, 4 },
|
||||
{ 6, 0, AIRPORT_BUSY_block, 7 },
|
||||
// takeoff
|
||||
{ 7, TAKEOFF, AIRPORT_BUSY_block, 8 },
|
||||
{ 8, STARTTAKEOFF, NOTHING_block, 9 },
|
||||
{ 9, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 10, FLYING, NOTHING_block, 15 }, { 10, LANDING, 0, 11 }, { 10, HELILANDING, 0, 20 },
|
||||
{ 11, LANDING, AIRPORT_BUSY_block, 12 },
|
||||
{ 12, 0, AIRPORT_BUSY_block, 13 },
|
||||
{ 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 },
|
||||
{ 14, 0, AIRPORT_BUSY_block, 1 },
|
||||
// In air
|
||||
{ 15, 0, NOTHING_block, 16 },
|
||||
{ 16, 0, NOTHING_block, 17 },
|
||||
{ 17, 0, NOTHING_block, 18 },
|
||||
{ 18, 0, NOTHING_block, 10 },
|
||||
{ 19, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 20, HELILANDING, AIRPORT_BUSY_block, 21 },
|
||||
{ 21, HELIENDLANDING, AIRPORT_BUSY_block, 1 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_commuter[] = { { 4, 0 } };
|
||||
static const byte _airport_terminal_commuter[] = { 1, 3 };
|
||||
static const byte _airport_helipad_commuter[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_commuter[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 }, { 0, HELITAKEOFF, HELIPAD2_block, 1 }, { 0, 0, 0, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TAKEOFF, 0, 11 }, { 1, TERM1, TAXIWAY_BUSY_block, 10 }, { 1, TERM2, TAXIWAY_BUSY_block, 10 }, { 1, TERM3, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD1, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD2, TAXIWAY_BUSY_block, 10 }, { 1, HELITAKEOFF, TAXIWAY_BUSY_block, 10 }, { 1, 0, 0, 0 },
|
||||
{ 2, 255, AIRPORT_ENTRANCE_block, 2 }, { 2, HANGAR, 0, 8 }, { 2, TERM1, 0, 8 }, { 2, TERM2, 0, 8 }, { 2, TERM3, 0, 8 }, { 2, HELIPAD1, 0, 8 }, { 2, HELIPAD2, 0, 8 }, { 2, HELITAKEOFF, 0, 8 }, { 2, 0, 0, 2 },
|
||||
{ 3, TERM1, TERM1_block, 8 }, { 3, HANGAR, 0, 8 }, { 3, TAKEOFF, 0, 8 }, { 3, 0, 0, 3 },
|
||||
{ 4, TERM2, TERM2_block, 9 }, { 4, HANGAR, 0, 9 }, { 4, TAKEOFF, 0, 9 }, { 4, 0, 0, 4 },
|
||||
{ 5, TERM3, TERM3_block, 10 }, { 5, HANGAR, 0, 10 }, { 5, TAKEOFF, 0, 10 }, { 5, 0, 0, 5 },
|
||||
{ 6, HELIPAD1, HELIPAD1_block, 6 }, { 6, HANGAR, TAXIWAY_BUSY_block, 9 }, { 6, HELITAKEOFF, 0, 35 },
|
||||
{ 7, HELIPAD2, HELIPAD2_block, 7 }, { 7, HANGAR, TAXIWAY_BUSY_block, 10 }, { 7, HELITAKEOFF, 0, 36 },
|
||||
{ 8, 255, TAXIWAY_BUSY_block, 8 }, { 8, TAKEOFF, TAXIWAY_BUSY_block, 9 }, { 8, HANGAR, TAXIWAY_BUSY_block, 9 }, { 8, TERM1, TERM1_block, 3 }, { 8, 0, TAXIWAY_BUSY_block, 9 },
|
||||
{ 9, 255, TAXIWAY_BUSY_block, 9 }, { 9, TAKEOFF, TAXIWAY_BUSY_block, 10 }, { 9, HANGAR, TAXIWAY_BUSY_block, 10 }, { 9, TERM2, TERM2_block, 4 }, { 9, HELIPAD1, HELIPAD1_block, 6 }, { 9, HELITAKEOFF, HELIPAD1_block, 6 }, { 9, TERM1, TAXIWAY_BUSY_block, 8 }, { 9, 0, TAXIWAY_BUSY_block, 10 },
|
||||
{ 10, 255, TAXIWAY_BUSY_block, 10 }, { 10, TERM3, TERM3_block, 5 }, { 10, HELIPAD1, 0, 9 }, { 10, HELIPAD2, HELIPAD2_block, 7 }, { 10, HELITAKEOFF, HELIPAD2_block, 7 }, { 10, TAKEOFF, TAXIWAY_BUSY_block, 1 }, { 10, HANGAR, TAXIWAY_BUSY_block, 1 }, { 10, 0, TAXIWAY_BUSY_block, 9 },
|
||||
{ 11, 0, OUT_WAY_block, 12 },
|
||||
// takeoff
|
||||
{ 12, TAKEOFF, RUNWAY_IN_OUT_block, 13 },
|
||||
{ 13, 0, RUNWAY_IN_OUT_block, 14 },
|
||||
{ 14, STARTTAKEOFF, RUNWAY_IN_OUT_block, 15 },
|
||||
{ 15, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 16, FLYING, NOTHING_block, 21 }, { 16, LANDING, IN_WAY_block, 17 }, { 16, HELILANDING, 0, 25 },
|
||||
{ 17, LANDING, RUNWAY_IN_OUT_block, 18 },
|
||||
{ 18, 0, RUNWAY_IN_OUT_block, 19 },
|
||||
{ 19, 0, RUNWAY_IN_OUT_block, 20 },
|
||||
{ 20, ENDLANDING, IN_WAY_block, 2 },
|
||||
// In Air
|
||||
{ 21, 0, NOTHING_block, 22 },
|
||||
{ 22, 0, NOTHING_block, 23 },
|
||||
{ 23, 0, NOTHING_block, 24 },
|
||||
{ 24, 0, NOTHING_block, 16 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 25, HELILANDING, PRE_HELIPAD_block, 26 },
|
||||
{ 26, HELIENDLANDING, PRE_HELIPAD_block, 26 }, { 26, HELIPAD1, 0, 27 }, { 26, HELIPAD2, 0, 28 }, { 26, HANGAR, 0, 33 },
|
||||
{ 27, 0, NOTHING_block, 29 }, //helipad1 approach
|
||||
{ 28, 0, NOTHING_block, 30 },
|
||||
// landing
|
||||
{ 29, 255, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
|
||||
{ 30, 255, NOTHING_block, 0 }, { 30, HELIPAD2, HELIPAD2_block, 7 },
|
||||
// Helicopter -- takeoff
|
||||
{ 31, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 32, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 33, 0, TAXIWAY_BUSY_block, 34 }, // need to go to hangar when waiting in air
|
||||
{ 34, 0, TAXIWAY_BUSY_block, 1 },
|
||||
{ 35, 0, HELIPAD1_block, 31 },
|
||||
{ 36, 0, HELIPAD2_block, 32 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_city[] = { { 5, 0 } };
|
||||
static const byte _airport_terminal_city[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 }, { 0, TAKEOFF, OUT_WAY_block, 1 }, { 0, 0, 0, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
|
||||
{ 2, TERM1, TERM1_block, 7 }, { 2, TAKEOFF, OUT_WAY_block, 7 }, { 2, 0, 0, 7 },
|
||||
{ 3, TERM2, TERM2_block, 5 }, { 3, TAKEOFF, OUT_WAY_block, 5 }, { 3, 0, 0, 5 },
|
||||
{ 4, TERM3, TERM3_block, 5 }, { 4, TAKEOFF, OUT_WAY_block, 5 }, { 4, 0, 0, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
|
||||
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
|
||||
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, OUT_WAY_block, 8 }, { 7, HELITAKEOFF, 0, 22 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
|
||||
{ 8, 0, OUT_WAY_block, 9 },
|
||||
{ 9, 0, RUNWAY_IN_OUT_block, 10 },
|
||||
// takeoff
|
||||
{ 10, TAKEOFF, RUNWAY_IN_OUT_block, 11 },
|
||||
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
|
||||
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 13, FLYING, NOTHING_block, 18 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 23 },
|
||||
{ 14, LANDING, RUNWAY_IN_OUT_block, 15 },
|
||||
{ 15, 0, RUNWAY_IN_OUT_block, 16 },
|
||||
{ 16, 0, RUNWAY_IN_OUT_block, 17 },
|
||||
{ 17, ENDLANDING, IN_WAY_block, 7 },
|
||||
// In Air
|
||||
{ 18, 0, NOTHING_block, 19 },
|
||||
{ 19, 0, NOTHING_block, 20 },
|
||||
{ 20, 0, NOTHING_block, 21 },
|
||||
{ 21, 0, NOTHING_block, 13 },
|
||||
// helicopter
|
||||
{ 22, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 23, HELILANDING, IN_WAY_block, 24 },
|
||||
{ 24, HELIENDLANDING, IN_WAY_block, 17 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = { { 5, 0 } };
|
||||
static const byte _airport_terminal_metropolitan[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
|
||||
{ 2, TERM1, TERM1_block, 7 },
|
||||
{ 3, TERM2, TERM2_block, 5 },
|
||||
{ 4, TERM3, TERM3_block, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
|
||||
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
|
||||
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, 0, 8 }, { 7, HELITAKEOFF, 0, 23 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
|
||||
{ 8, 0, OUT_WAY_block, 9 },
|
||||
{ 9, 0, RUNWAY_OUT_block, 10 },
|
||||
// takeoff
|
||||
{ 10, TAKEOFF, RUNWAY_OUT_block, 11 },
|
||||
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
|
||||
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 13, FLYING, NOTHING_block, 19 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 25 },
|
||||
{ 14, LANDING, RUNWAY_IN_block, 15 },
|
||||
{ 15, 0, RUNWAY_IN_block, 16 },
|
||||
{ 16, 255, RUNWAY_IN_block, 0 }, { 16, ENDLANDING, IN_WAY_block, 17 },
|
||||
{ 17, 255, RUNWAY_OUT_block, 0 }, { 17, ENDLANDING, IN_WAY_block, 18 },
|
||||
{ 18, ENDLANDING, IN_WAY_block, 7 },
|
||||
// In Air
|
||||
{ 19, 0, NOTHING_block, 20 },
|
||||
{ 20, 0, NOTHING_block, 21 },
|
||||
{ 21, 0, NOTHING_block, 22 },
|
||||
{ 22, 0, NOTHING_block, 13 },
|
||||
// helicopter
|
||||
{ 23, 0, NOTHING_block, 24 },
|
||||
{ 24, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 25, HELILANDING, IN_WAY_block, 26 },
|
||||
{ 26, HELIENDLANDING, IN_WAY_block, 18 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_international[] = { { 0, 3 }, { 6, 1 } };
|
||||
static const byte _airport_terminal_international[] = { 2, 3, 3 };
|
||||
static const byte _airport_helipad_international[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, TERM_GROUP1_block, 0 }, { 0, 255, TERM_GROUP2_ENTER1_block, 1 }, { 0, HELITAKEOFF, HELIPAD1_block, 2 }, { 0, 0, 0, 2 },
|
||||
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, HELITAKEOFF, HELIPAD2_block, 3 }, { 1, 0, 0, 3 },
|
||||
{ 2, 255, AIRPORT_ENTRANCE_block, 0 }, { 2, HANGAR, 0, 0 }, { 2, TERM4, 0, 12 }, { 2, TERM5, 0, 12 }, { 2, TERM6, 0, 12 }, { 2, HELIPAD1, 0, 12 }, { 2, HELIPAD2, 0, 12 }, { 2, HELITAKEOFF, 0, 12 }, { 2, 0, 0, 23 },
|
||||
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, 0, 0, 18 },
|
||||
{ 4, TERM1, TERM1_block, 23 }, { 4, HANGAR, AIRPORT_ENTRANCE_block, 23 }, { 4, 0, 0, 23 },
|
||||
{ 5, TERM2, TERM2_block, 24 }, { 5, HANGAR, AIRPORT_ENTRANCE_block, 24 }, { 5, 0, 0, 24 },
|
||||
{ 6, TERM3, TERM3_block, 25 }, { 6, HANGAR, AIRPORT_ENTRANCE_block, 25 }, { 6, 0, 0, 25 },
|
||||
{ 7, TERM4, TERM4_block, 16 }, { 7, HANGAR, HANGAR2_AREA_block, 16 }, { 7, 0, 0, 16 },
|
||||
{ 8, TERM5, TERM5_block, 17 }, { 8, HANGAR, HANGAR2_AREA_block, 17 }, { 8, 0, 0, 17 },
|
||||
{ 9, TERM6, TERM6_block, 18 }, { 9, HANGAR, HANGAR2_AREA_block, 18 }, { 9, 0, 0, 18 },
|
||||
{ 10, HELIPAD1, HELIPAD1_block, 10 }, { 10, HANGAR, HANGAR2_AREA_block, 16 }, { 10, HELITAKEOFF, 0, 47 },
|
||||
{ 11, HELIPAD2, HELIPAD2_block, 11 }, { 11, HANGAR, HANGAR2_AREA_block, 17 }, { 11, HELITAKEOFF, 0, 48 },
|
||||
{ 12, 0, TERM_GROUP2_ENTER1_block, 13 },
|
||||
{ 13, 0, TERM_GROUP2_ENTER1_block, 14 },
|
||||
{ 14, 0, TERM_GROUP2_ENTER2_block, 15 },
|
||||
{ 15, 0, TERM_GROUP2_ENTER2_block, 16 },
|
||||
{ 16, 255, TERM_GROUP2_block, 0 }, { 16, TERM4, TERM4_block, 7 }, { 16, HELIPAD1, HELIPAD1_block, 10 }, { 16, HELITAKEOFF, HELIPAD1_block, 10 }, { 16, 0, 0, 17 },
|
||||
{ 17, 255, TERM_GROUP2_block, 0 }, { 17, TERM5, TERM5_block, 8 }, { 17, TERM4, 0, 16 }, { 17, HELIPAD1, 0, 16 }, { 17, HELIPAD2, HELIPAD2_block, 11 }, { 17, HELITAKEOFF, HELIPAD2_block, 11 }, { 17, 0, 0, 18 },
|
||||
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM6, TERM6_block, 9 }, { 18, TAKEOFF, 0, 19 }, { 18, HANGAR, HANGAR2_AREA_block, 3 }, { 18, 0, 0, 17 },
|
||||
{ 19, 0, TERM_GROUP2_EXIT1_block, 20 },
|
||||
{ 20, 0, TERM_GROUP2_EXIT1_block, 21 },
|
||||
{ 21, 0, TERM_GROUP2_EXIT2_block, 22 },
|
||||
{ 22, 0, TERM_GROUP2_EXIT2_block, 26 },
|
||||
{ 23, 255, TERM_GROUP1_block, 0 }, { 23, TERM1, TERM1_block, 4 }, { 23, HANGAR, AIRPORT_ENTRANCE_block, 2 }, { 23, 0, 0, 24 },
|
||||
{ 24, 255, TERM_GROUP1_block, 0 }, { 24, TERM2, TERM2_block, 5 }, { 24, TERM1, 0, 23 }, { 24, HANGAR, 0, 23 }, { 24, 0, 0, 25 },
|
||||
{ 25, 255, TERM_GROUP1_block, 0 }, { 25, TERM3, TERM3_block, 6 }, { 25, TAKEOFF, 0, 26 }, { 25, 0, 0, 24 },
|
||||
{ 26, 255, TAXIWAY_BUSY_block, 0 }, { 26, TAKEOFF, 0, 27 }, { 26, 0, 0, 25 },
|
||||
{ 27, 0, OUT_WAY_block, 28 },
|
||||
// takeoff
|
||||
{ 28, TAKEOFF, OUT_WAY_block, 29 },
|
||||
{ 29, 0, RUNWAY_OUT_block, 30 },
|
||||
{ 30, STARTTAKEOFF, NOTHING_block, 31 },
|
||||
{ 31, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 32, FLYING, NOTHING_block, 37 }, { 32, LANDING, 0, 33 }, { 32, HELILANDING, 0, 41 },
|
||||
{ 33, LANDING, RUNWAY_IN_block, 34 },
|
||||
{ 34, 0, RUNWAY_IN_block, 35 },
|
||||
{ 35, 0, RUNWAY_IN_block, 36 },
|
||||
{ 36, ENDLANDING, IN_WAY_block, 36 }, { 36, 255, TERM_GROUP1_block, 0 }, { 36, 255, TERM_GROUP2_ENTER1_block, 1 }, { 36, TERM4, 0, 12 }, { 36, TERM5, 0, 12 }, { 36, TERM6, 0, 12 }, { 36, 0, 0, 2 },
|
||||
// In Air
|
||||
{ 37, 0, NOTHING_block, 38 },
|
||||
{ 38, 0, NOTHING_block, 39 },
|
||||
{ 39, 0, NOTHING_block, 40 },
|
||||
{ 40, 0, NOTHING_block, 32 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 41, HELILANDING, PRE_HELIPAD_block, 42 },
|
||||
{ 42, HELIENDLANDING, PRE_HELIPAD_block, 42 }, { 42, HELIPAD1, 0, 43 }, { 42, HELIPAD2, 0, 44 }, { 42, HANGAR, 0, 49 },
|
||||
{ 43, 0, NOTHING_block, 45 },
|
||||
{ 44, 0, NOTHING_block, 46 },
|
||||
// landing
|
||||
{ 45, 255, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
|
||||
{ 46, 255, NOTHING_block, 0 }, { 46, HELIPAD2, HELIPAD2_block, 11 },
|
||||
// Helicopter -- takeoff
|
||||
{ 47, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 48, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 49, 0, HANGAR2_AREA_block, 50 }, // need to go to hangar when waiting in air
|
||||
{ 50, 0, HANGAR2_AREA_block, 3 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// intercontinental
|
||||
static const TileIndexDiffC _airport_depots_intercontinental[] = { { 0, 5 }, { 8, 4 } };
|
||||
static const byte _airport_terminal_intercontinental[] = { 2, 4, 4 };
|
||||
static const byte _airport_helipad_intercontinental[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_intercontinental[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 0 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 1 }, { 0, TAKEOFF, HANGAR1_AREA_block | TERM_GROUP1_block, 2 }, { 0, 0, 0, 2 },
|
||||
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, 255, HANGAR2_AREA_block, 0 }, { 1, 0, 0, 3 },
|
||||
{ 2, 255, HANGAR1_AREA_block, 0 }, { 2, 255, TERM_GROUP1_block, 0 }, { 2, 255, TERM_GROUP1_block, 1 }, { 2, HANGAR, 0, 0 }, { 2, TAKEOFF, TERM_GROUP1_block, 27 }, { 2, TERM5, 0, 26 }, { 2, TERM6, 0, 26 }, { 2, TERM7, 0, 26 }, { 2, TERM8, 0, 26 }, { 2, HELIPAD1, 0, 26 }, { 2, HELIPAD2, 0, 26 }, { 2, HELITAKEOFF, 0, 74 }, { 2, 0, 0, 27 },
|
||||
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 75 }, { 3, 0, 0, 20 },
|
||||
{ 4, TERM1, TERM1_block, 26 }, { 4, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 26 }, { 4, 0, 0, 26 },
|
||||
{ 5, TERM2, TERM2_block, 27 }, { 5, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 27 }, { 5, 0, 0, 27 },
|
||||
{ 6, TERM3, TERM3_block, 28 }, { 6, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 28 }, { 6, 0, 0, 28 },
|
||||
{ 7, TERM4, TERM4_block, 29 }, { 7, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 7, 0, 0, 29 },
|
||||
{ 8, TERM5, TERM5_block, 18 }, { 8, HANGAR, HANGAR2_AREA_block, 18 }, { 8, 0, 0, 18 },
|
||||
{ 9, TERM6, TERM6_block, 19 }, { 9, HANGAR, HANGAR2_AREA_block, 19 }, { 9, 0, 0, 19 },
|
||||
{ 10, TERM7, TERM7_block, 20 }, { 10, HANGAR, HANGAR2_AREA_block, 20 }, { 10, 0, 0, 20 },
|
||||
{ 11, TERM8, TERM8_block, 21 }, { 11, HANGAR, HANGAR2_AREA_block, 21 }, { 11, 0, 0, 21 },
|
||||
{ 12, HELIPAD1, HELIPAD1_block, 12 }, { 12, HANGAR, 0, 70 }, { 12, HELITAKEOFF, 0, 72 },
|
||||
{ 13, HELIPAD2, HELIPAD2_block, 13 }, { 13, HANGAR, 0, 71 }, { 13, HELITAKEOFF, 0, 73 },
|
||||
{ 14, 0, TERM_GROUP2_ENTER1_block, 15 },
|
||||
{ 15, 0, TERM_GROUP2_ENTER1_block, 16 },
|
||||
{ 16, 0, TERM_GROUP2_ENTER2_block, 17 },
|
||||
{ 17, 0, TERM_GROUP2_ENTER2_block, 18 },
|
||||
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM5, TERM5_block, 8 }, { 18, TAKEOFF, 0, 19 }, { 18, HELITAKEOFF, HELIPAD1_block, 19 }, { 18, 0, TERM_GROUP2_EXIT1_block, 19 },
|
||||
{ 19, 255, TERM_GROUP2_block, 0 }, { 19, TERM6, TERM6_block, 9 }, { 19, TERM5, 0, 18 }, { 19, TAKEOFF, 0, 57 }, { 19, HELITAKEOFF, HELIPAD1_block, 20 }, { 19, 0, TERM_GROUP2_EXIT1_block, 20 }, // add exit to runway out 2
|
||||
{ 20, 255, TERM_GROUP2_block, 0 }, { 20, TERM7, TERM7_block, 10 }, { 20, TERM5, 0, 19 }, { 20, TERM6, 0, 19 }, { 20, HANGAR, HANGAR2_AREA_block, 3 }, { 20, TAKEOFF, 0, 19 }, { 20, 0, TERM_GROUP2_EXIT1_block, 21 },
|
||||
{ 21, 255, TERM_GROUP2_block, 0 }, { 21, TERM8, TERM8_block, 11 }, { 21, HANGAR, HANGAR2_AREA_block, 20 }, { 21, TERM5, 0, 20 }, { 21, TERM6, 0, 20 }, { 21, TERM7, 0, 20 }, { 21, TAKEOFF, 0, 20 }, { 21, 0, TERM_GROUP2_EXIT1_block, 22 },
|
||||
{ 22, 255, TERM_GROUP2_block, 0 }, { 22, HANGAR, 0, 21 }, { 22, TERM5, 0, 21 }, { 22, TERM6, 0, 21 }, { 22, TERM7, 0, 21 }, { 22, TERM8, 0, 21 }, { 22, TAKEOFF, 0, 21 }, { 22, 0, 0, 23 },
|
||||
{ 23, 0, TERM_GROUP2_EXIT1_block, 70 },
|
||||
{ 24, 0, TERM_GROUP2_EXIT2_block, 25 },
|
||||
{ 25, 255, TERM_GROUP2_EXIT2_block, 0 }, { 25, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 25, 0, 0, 29 },
|
||||
{ 26, 255, TERM_GROUP1_block, 0 }, { 26, TERM1, TERM1_block, 4 }, { 26, HANGAR, HANGAR1_AREA_block, 27 }, { 26, TERM5, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM6, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM7, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM8, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD1, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD2, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELITAKEOFF, TERM_GROUP2_ENTER1_block, 14 }, { 26, 0, 0, 27 },
|
||||
{ 27, 255, TERM_GROUP1_block, 0 }, { 27, TERM2, TERM2_block, 5 }, { 27, HANGAR, HANGAR1_AREA_block, 2 }, { 27, TERM1, 0, 26 }, { 27, TERM5, 0, 26 }, { 27, TERM6, 0, 26 }, { 27, TERM7, 0, 26 }, { 27, TERM8, 0, 26 }, { 27, HELIPAD1, 0, 14 }, { 27, HELIPAD2, 0, 14 }, { 27, 0, 0, 28 },
|
||||
{ 28, 255, TERM_GROUP1_block, 0 }, { 28, TERM3, TERM3_block, 6 }, { 28, HANGAR, HANGAR1_AREA_block, 27 }, { 28, TERM1, 0, 27 }, { 28, TERM2, 0, 27 }, { 28, TERM4, 0, 29 }, { 28, TERM5, 0, 14 }, { 28, TERM6, 0, 14 }, { 28, TERM7, 0, 14 }, { 28, TERM8, 0, 14 }, { 28, HELIPAD1, 0, 14 }, { 28, HELIPAD2, 0, 14 }, { 28, 0, 0, 29 },
|
||||
{ 29, 255, TERM_GROUP1_block, 0 }, { 29, TERM4, TERM4_block, 7 }, { 29, HANGAR, HANGAR1_AREA_block, 27 }, { 29, TAKEOFF, 0, 30 }, { 29, 0, 0, 28 },
|
||||
{ 30, 0, OUT_WAY_block2, 31 },
|
||||
{ 31, 0, OUT_WAY_block, 32 },
|
||||
// takeoff
|
||||
{ 32, TAKEOFF, RUNWAY_OUT_block, 33 },
|
||||
{ 33, 0, RUNWAY_OUT_block, 34 },
|
||||
{ 34, STARTTAKEOFF, NOTHING_block, 35 },
|
||||
{ 35, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 36, 0, 0, 0 },
|
||||
{ 37, LANDING, RUNWAY_IN_block, 38 },
|
||||
{ 38, 0, RUNWAY_IN_block, 39 },
|
||||
{ 39, 0, RUNWAY_IN_block, 40 },
|
||||
{ 40, ENDLANDING, RUNWAY_IN_block, 41 },
|
||||
{ 41, 0, IN_WAY_block, 42 },
|
||||
{ 42, 255, IN_WAY_block, 0 }, { 42, 255, TERM_GROUP1_block, 0 }, { 42, 255, TERM_GROUP1_block, 1 }, { 42, HANGAR, 0, 2 }, { 42, 0, 0, 26 },
|
||||
// In Air
|
||||
{ 43, 0, 0, 44 },
|
||||
{ 44, FLYING, 0, 45 }, { 44, HELILANDING, 0, 47 }, { 44, LANDING, 0, 69 }, { 44, 0, 0, 45 },
|
||||
{ 45, 0, 0, 46 },
|
||||
{ 46, FLYING, 0, 43 }, { 46, LANDING, 0, 76 }, { 46, 0, 0, 43 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 47, HELILANDING, PRE_HELIPAD_block, 48 },
|
||||
{ 48, HELIENDLANDING, PRE_HELIPAD_block, 48 }, { 48, HELIPAD1, 0, 49 }, { 48, HELIPAD2, 0, 50 }, { 48, HANGAR, 0, 55 },
|
||||
{ 49, 0, NOTHING_block, 51 },
|
||||
{ 50, 0, NOTHING_block, 52 },
|
||||
// landing
|
||||
{ 51, 255, NOTHING_block, 0 }, { 51, HELIPAD1, HELIPAD1_block, 12 }, { 51, HANGAR, 0, 55 }, { 51, 0, 0, 12 },
|
||||
{ 52, 255, NOTHING_block, 0 }, { 52, HELIPAD2, HELIPAD2_block, 13 }, { 52, HANGAR, 0, 55 }, { 52, 0, 0, 13 },
|
||||
// Helicopter -- takeoff
|
||||
{ 53, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 54, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 55, 0, HANGAR2_AREA_block, 56 }, // need to go to hangar when waiting in air
|
||||
{ 56, 0, HANGAR2_AREA_block, 3 },
|
||||
// runway 2 out support
|
||||
{ 57, 255, OUT_WAY2_block, 0 }, { 57, TAKEOFF, 0, 58 }, { 57, 0, 0, 58 },
|
||||
{ 58, 0, OUT_WAY2_block, 59 },
|
||||
{ 59, TAKEOFF, RUNWAY_OUT2_block, 60 }, // takeoff
|
||||
{ 60, 0, RUNWAY_OUT2_block, 61 },
|
||||
{ 61, STARTTAKEOFF, NOTHING_block, 62 },
|
||||
{ 62, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// runway 2 in support
|
||||
{ 63, LANDING, RUNWAY_IN2_block, 64 },
|
||||
{ 64, 0, RUNWAY_IN2_block, 65 },
|
||||
{ 65, 0, RUNWAY_IN2_block, 66 },
|
||||
{ 66, ENDLANDING, RUNWAY_IN2_block, 0 }, { 66, 255, 0, 1 }, { 66, 255, 0, 0 }, { 66, 0, 0, 67 },
|
||||
{ 67, 0, IN_WAY2_block, 68 },
|
||||
{ 68, 255, IN_WAY2_block, 0 }, { 68, 255, TERM_GROUP2_block, 1 }, { 68, 255, TERM_GROUP1_block, 0 }, { 68, HANGAR, HANGAR2_AREA_block, 22 }, { 68, 0, 0, 22 },
|
||||
{ 69, 255, RUNWAY_IN2_block, 0 }, { 69, 0, RUNWAY_IN2_block, 63 },
|
||||
{ 70, 255, TERM_GROUP2_EXIT1_block, 0 }, { 70, HELIPAD1, HELIPAD1_block, 12 }, { 70, HELITAKEOFF, HELIPAD1_block, 12 }, { 70, 0, 0, 71 },
|
||||
{ 71, 255, TERM_GROUP2_EXIT1_block, 0 }, { 71, HELIPAD2, HELIPAD2_block, 13 }, { 71, HELITAKEOFF, HELIPAD1_block, 12 }, { 71, 0, 0, 24 },
|
||||
{ 72, 0, HELIPAD1_block, 53 },
|
||||
{ 73, 0, HELIPAD2_block, 54 },
|
||||
{ 74, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 75, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 76, 255, RUNWAY_IN_block, 0 }, { 76, 0, RUNWAY_IN_block, 37 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = { 1, 1 };
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{ 0, HELIPAD1, HELIPAD1_block, 1 },
|
||||
{ 1, HELITAKEOFF, NOTHING_block, 0 }, // takeoff
|
||||
{ 2, 255, AIRPORT_BUSY_block, 0 }, { 2, HELILANDING, 0, 3 }, { 2, HELITAKEOFF, 0, 1 },
|
||||
{ 3, HELILANDING, AIRPORT_BUSY_block, 4 },
|
||||
{ 4, HELIENDLANDING, AIRPORT_BUSY_block, 4 }, { 4, HELIPAD1, HELIPAD1_block, 0 }, { 4, HELITAKEOFF, 0, 2 },
|
||||
// In Air
|
||||
{ 5, 0, NOTHING_block, 6 },
|
||||
{ 6, 0, NOTHING_block, 7 },
|
||||
{ 7, 0, NOTHING_block, 8 },
|
||||
{ 8, FLYING, NOTHING_block, 5 }, { 8, HELILANDING, HELIPAD1_block, 2 }, // landing
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// helidepots
|
||||
static const TileIndexDiffC _airport_depots_helidepot[] = { { 1, 0 } };
|
||||
static const byte _airport_helipad_helidepot[] = { 1, 1 };
|
||||
static const AirportFTAbuildup _airport_fta_helidepot[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELIPAD1, HELIPAD1_block, 14 }, { 1, HELITAKEOFF, 0, 15 }, { 1, 0, 0, 0 },
|
||||
{ 2, FLYING, NOTHING_block, 3 }, { 2, HELILANDING, PRE_HELIPAD_block, 7 }, { 2, HANGAR, 0, 12 }, { 2, HELITAKEOFF, NOTHING_block, 16 },
|
||||
// In Air
|
||||
{ 3, 0, NOTHING_block, 4 },
|
||||
{ 4, 0, NOTHING_block, 5 },
|
||||
{ 5, 0, NOTHING_block, 6 },
|
||||
{ 6, 0, NOTHING_block, 2 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 7, HELILANDING, PRE_HELIPAD_block, 8 },
|
||||
{ 8, HELIENDLANDING, PRE_HELIPAD_block, 8 }, { 8, HELIPAD1, 0, 9 }, { 8, HANGAR, 0, 12 }, { 8, 0, 0, 2 },
|
||||
{ 9, 0, NOTHING_block, 10 },
|
||||
// landing
|
||||
{ 10, 255, NOTHING_block, 10 }, { 10, HELIPAD1, HELIPAD1_block, 14 }, { 10, HANGAR, 0, 1 }, { 10, 0, 0, 14 },
|
||||
// Helicopter -- takeoff
|
||||
{ 11, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 12, 0, HANGAR2_AREA_block, 13 }, // need to go to hangar when waiting in air
|
||||
{ 13, 0, HANGAR2_AREA_block, 1 },
|
||||
{ 14, HELIPAD1, HELIPAD1_block, 14 }, { 14, HANGAR, 0, 1 }, { 14, HELITAKEOFF, 0, 17 },
|
||||
{ 15, HELITAKEOFF, NOTHING_block, 0 }, // takeoff outside depot
|
||||
{ 16, HELITAKEOFF, 0, 14 },
|
||||
{ 17, 0, NOTHING_block, 11 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// helistation
|
||||
static const TileIndexDiffC _airport_depots_helistation[] = { { 0, 0 } };
|
||||
static const byte _airport_helipad_helistation[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_helistation[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 8 }, { 0, HELIPAD1, 0, 1 }, { 0, HELIPAD2, 0, 1 }, { 0, HELIPAD3, 0, 1 }, { 0, HELITAKEOFF, 0, 1 }, { 0, 0, 0, 0 },
|
||||
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELITAKEOFF, 0, 3 }, { 1, 0, 0, 4 },
|
||||
// landing
|
||||
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, 0, 0, 28 },
|
||||
// helicopter side
|
||||
{ 3, HELITAKEOFF, NOTHING_block, 0 }, // helitakeoff outside hangar2
|
||||
{ 4, 255, TAXIWAY_BUSY_block, 0 }, { 4, HANGAR, HANGAR2_AREA_block, 1 }, { 4, HELITAKEOFF, 0, 1 }, { 4, 0, 0, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, HELIPAD1, HELIPAD1_block, 6 }, { 5, HELIPAD2, HELIPAD2_block, 7 }, { 5, HELIPAD3, HELIPAD3_block, 8 }, { 5, 0, 0, 4 },
|
||||
{ 6, HELIPAD1, HELIPAD1_block, 5 }, { 6, HANGAR, HANGAR2_AREA_block, 5 }, { 6, HELITAKEOFF, 0, 9 }, { 6, 0, 0, 6 },
|
||||
{ 7, HELIPAD2, HELIPAD2_block, 5 }, { 7, HANGAR, HANGAR2_AREA_block, 5 }, { 7, HELITAKEOFF, 0, 10 }, { 7, 0, 0, 7 },
|
||||
{ 8, HELIPAD3, HELIPAD3_block, 5 }, { 8, HANGAR, HANGAR2_AREA_block, 5 }, { 8, HELITAKEOFF, 0, 11 }, { 8, 0, 0, 8 },
|
||||
{ 9, 0, HELIPAD1_block, 12 },
|
||||
{ 10, 0, HELIPAD2_block, 13 },
|
||||
{ 11, 0, HELIPAD3_block, 14 },
|
||||
{ 12, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 13, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 14, HELITAKEOFF, NOTHING_block, 0 },
|
||||
// heli - in flight moves
|
||||
{ 15, HELILANDING, PRE_HELIPAD_block, 16 },
|
||||
{ 16, HELIENDLANDING, PRE_HELIPAD_block, 16 }, { 16, HELIPAD1, 0, 17 }, { 16, HELIPAD2, 0, 18 }, { 16, HELIPAD3, 0, 19 }, { 16, HANGAR, 0, 23 },
|
||||
{ 17, 0, NOTHING_block, 20 },
|
||||
{ 18, 0, NOTHING_block, 21 },
|
||||
{ 19, 0, NOTHING_block, 22 },
|
||||
// heli landing
|
||||
{ 20, 255, NOTHING_block, 0 }, { 20, HELIPAD1, HELIPAD1_block, 6 }, { 20, HANGAR, 0, 23 }, { 20, 0, 0, 6 },
|
||||
{ 21, 255, NOTHING_block, 0 }, { 21, HELIPAD2, HELIPAD2_block, 7 }, { 21, HANGAR, 0, 23 }, { 21, 0, 0, 7 },
|
||||
{ 22, 255, NOTHING_block, 0 }, { 22, HELIPAD3, HELIPAD3_block, 8 }, { 22, HANGAR, 0, 23 }, { 22, 0, 0, 8 },
|
||||
{ 23, 0, HANGAR2_AREA_block, 24 }, // need to go to helihangar when waiting in air
|
||||
{ 24, 0, HANGAR2_AREA_block, 1 },
|
||||
{ 25, 0, NOTHING_block, 26 },
|
||||
{ 26, 0, NOTHING_block, 27 },
|
||||
{ 27, 0, NOTHING_block, 2 },
|
||||
{ 28, 0, NOTHING_block, 29 },
|
||||
{ 29, 0, NOTHING_block, 30 },
|
||||
{ 30, 0, NOTHING_block, 31 },
|
||||
{ 31, 0, NOTHING_block, 32 },
|
||||
{ 32, 0, NOTHING_block, 25 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
_airport_moving_data_commuter, // Commuter Airfield (small) 5x4
|
||||
_airport_moving_data_helidepot, // Helidepot
|
||||
_airport_moving_data_intercontinental, // Intercontinental Airport (xxlarge) - 4 runways
|
||||
_airport_moving_data_helistation, // Helistation
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
#endif /* AIRPORT_MOVEMENT_H */
|
296
aystar.c
Normal file
296
aystar.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/* $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"
|
||||
|
||||
int _aystar_stats_open_size;
|
||||
int _aystar_stats_closed_size;
|
||||
|
||||
// This looks in the Hash if a node exists in ClosedList
|
||||
// If so, it returns the PathNode, else NULL
|
||||
static PathNode* AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
|
||||
{
|
||||
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, const PathNode *node)
|
||||
{
|
||||
// Add a node to the ClosedList
|
||||
PathNode *new_node = malloc(sizeof(*new_node));
|
||||
*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, const 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, const AyStarNode *node, int f, int g)
|
||||
{
|
||||
// Add a new Node to the OpenList
|
||||
OpenListNode *new_node = malloc(sizeof(*new_node));
|
||||
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
|
||||
check = AyStarMain_OpenList_IsInList(aystar, current);
|
||||
if (check != 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
|
||||
switch (r) {
|
||||
case AYSTAR_FOUND_END_NODE: printf("[AyStar] Found path!\n"); break;
|
||||
case AYSTAR_EMPTY_OPENLIST: printf("[AyStar] OpenList run dry, no path found\n"); break;
|
||||
case AYSTAR_LIMIT_REACHED: printf("[AyStar] Exceeded search_nodes, no path found\n"); break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
if (r != AYSTAR_STILL_BUSY) {
|
||||
/* We're done, clean up */
|
||||
_aystar_stats_open_size = aystar->OpenListHash.size;
|
||||
_aystar_stats_closed_size = aystar->ClosedListHash.size;
|
||||
aystar->clear(aystar);
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case AYSTAR_FOUND_END_NODE: return AYSTAR_FOUND_END_NODE;
|
||||
case AYSTAR_EMPTY_OPENLIST:
|
||||
case AYSTAR_LIMIT_REACHED: return AYSTAR_NO_PATH;
|
||||
default: 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,369 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,121 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,58 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,8 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,69 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $Id$
|
||||
|
||||
if ! [ -f ai/regression/completeness.sh ]; then
|
||||
echo "Make sure you are in the root of OpenTTD before starting this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat ai/regression/tst_*/main.nut | tr ';' '\n' | awk '
|
||||
/^function/ {
|
||||
for (local in locals) {
|
||||
delete locals[local]
|
||||
}
|
||||
if (match($0, "function Regression::Start") || match($0, "function Regression::Stop")) next
|
||||
locals["this"] = "AIControllerSquirrel"
|
||||
}
|
||||
|
||||
/local/ {
|
||||
gsub(".*local", "local")
|
||||
if (match($4, "^AI")) {
|
||||
sub("\\(.*", "", $4)
|
||||
locals[$2] = $4
|
||||
}
|
||||
}
|
||||
|
||||
/Valuate/ {
|
||||
gsub(".*Valuate\\(", "")
|
||||
gsub("\\).*", "")
|
||||
gsub(",.*", "")
|
||||
gsub("\\.", "::")
|
||||
print $0
|
||||
}
|
||||
|
||||
/\./ {
|
||||
for (local in locals) {
|
||||
if (match($0, local ".")) {
|
||||
fname = substr($0, index($0, local "."))
|
||||
sub("\\(.*", "", fname)
|
||||
sub("\\.", "::", fname)
|
||||
sub(local, locals[local], fname)
|
||||
print fname
|
||||
if (match(locals[local], "List")) {
|
||||
sub(locals[local], "AIAbstractList", fname)
|
||||
print fname
|
||||
}
|
||||
}
|
||||
}
|
||||
# We want to remove everything before the FIRST occurence of AI.
|
||||
# If we do not remove any other occurences of AI from the string
|
||||
# we will remove everything before the LAST occurence of AI, so
|
||||
# do some little magic to make it work the way we want.
|
||||
sub("AI", "AXXXXY")
|
||||
gsub("AI", "AXXXXX")
|
||||
sub(".*AXXXXY", "AI")
|
||||
if (match($0, "^AI") && match($0, ".")) {
|
||||
sub("\\(.*", "", $0)
|
||||
sub("\\.", "::", $0)
|
||||
print $0
|
||||
}
|
||||
}
|
||||
' | sed 's/ //g' | sort | uniq > tmp.in_regression
|
||||
|
||||
grep 'DefSQ.*Method' ../src/script/api/ai/*.hpp.sq | grep -v 'AIError::' | grep -v 'AIAbstractList::Valuate' | grep -v '::GetClassName' | sed 's/^[^,]*, &//g;s/,[^,]*//g' | sort > tmp.in_api
|
||||
|
||||
diff -u tmp.in_regression tmp.in_api | grep -v '^+++' | grep '^+' | sed 's/^+//'
|
||||
|
||||
rm -f tmp.in_regression tmp.in_api
|
||||
|
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
[misc]
|
||||
display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|WAYPOINTS
|
||||
language = english.lng
|
||||
|
||||
[gui]
|
||||
autosave = off
|
||||
|
||||
[game_creation]
|
||||
town_name = english
|
||||
|
||||
[ai_players]
|
||||
none =
|
||||
regression =
|
||||
|
||||
[vehicle]
|
||||
road_side = right
|
||||
plane_speed = 2
|
||||
|
||||
[construction]
|
||||
max_bridge_length = 100
|
@@ -1,15 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
class Regression extends AIInfo {
|
||||
function GetAuthor() { return "OpenTTD NoAI Developers Team"; }
|
||||
function GetName() { return "Regression"; }
|
||||
function GetShortName() { return "REGR"; }
|
||||
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
|
||||
function GetVersion() { return 1; }
|
||||
function GetAPIVersion() { return "1.7"; }
|
||||
function GetDate() { return "2007-03-18"; }
|
||||
function CreateInstance() { return "Regression"; }
|
||||
}
|
||||
|
||||
RegisterAI(Regression());
|
||||
|
@@ -1,71 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $Id$
|
||||
|
||||
if ! [ -f ai/regression/run.sh ]; then
|
||||
echo "Make sure you are in the root of OpenTTD before starting this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f scripts/game_start.scr ]; then
|
||||
mv scripts/game_start.scr scripts/game_start.scr.regression
|
||||
fi
|
||||
|
||||
params=""
|
||||
gdb=""
|
||||
if [ "$1" != "-r" ]; then
|
||||
params="-snull -mnull -vnull:ticks=30000"
|
||||
fi
|
||||
if [ "$1" = "-g" ]; then
|
||||
gdb="gdb --ex run --args "
|
||||
fi
|
||||
|
||||
if [ -d "ai/regression/tst_$1" ]; then
|
||||
tests="ai/regression/tst_$1"
|
||||
elif [ -d "ai/regression/tst_$2" ]; then
|
||||
tests="ai/regression/tst_$2"
|
||||
else
|
||||
tests=ai/regression/tst_*
|
||||
fi
|
||||
|
||||
ret=0
|
||||
for tst in $tests; do
|
||||
echo -n "Running $tst... "
|
||||
|
||||
# Make sure that only one info.nut is present for each test run. Otherwise openttd gets confused.
|
||||
cp ai/regression/regression_info.nut $tst/info.nut
|
||||
|
||||
sav=$tst/test.sav
|
||||
if ! [ -f $sav ]; then
|
||||
sav=ai/regression/empty.sav
|
||||
fi
|
||||
|
||||
if [ -n "$gdb" ]; then
|
||||
$gdb ./openttd -x -c ai/regression/regression.cfg $params -g $sav
|
||||
else
|
||||
./openttd -x -c ai/regression/regression.cfg $params -g $sav -d script=2 -d misc=9 2>&1 | awk '{ gsub("0x(\\(nil\\)|0+)(x0)?", "0x00000000", $0); gsub("^dbg: \\[script\\]", "", $0); gsub("^ ", "ERROR: ", $0); gsub("ERROR: \\[1\\] ", "", $0); gsub("\\[P\\] ", "", $0); print $0; }' | grep -v '^dbg: \[.*\]' > tmp.regression
|
||||
fi
|
||||
|
||||
if [ -z "$gdb" ]; then
|
||||
res="`diff -ub $tst/result.txt tmp.regression`"
|
||||
if [ -z "$res" ]; then
|
||||
echo "passed!"
|
||||
else
|
||||
echo "failed! Difference:"
|
||||
echo "$res"
|
||||
ret=1
|
||||
fi
|
||||
fi
|
||||
|
||||
rm $tst/info.nut
|
||||
done
|
||||
|
||||
if [ -f scripts/game_start.scr.regression ]; then
|
||||
mv scripts/game_start.scr.regression scripts/game_start.scr
|
||||
fi
|
||||
|
||||
if [ "$1" != "-k" ]; then
|
||||
rm -f tmp.regression
|
||||
fi
|
||||
|
||||
exit $ret
|
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
print(" Required this file");
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,216 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
class Regression extends AIController {
|
||||
function Start();
|
||||
};
|
||||
|
||||
|
||||
function Regression::StationList()
|
||||
{
|
||||
local list = AIStationList(AIStation.STATION_BUS_STOP + AIStation.STATION_TRUCK_STOP);
|
||||
|
||||
print("");
|
||||
print("--StationList--");
|
||||
print(" Count(): " + list.Count());
|
||||
list.Valuate(AIStation.GetLocation);
|
||||
print(" Location ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetCargoWaiting, 0);
|
||||
print(" CargoWaiting(0) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetCargoWaiting, 1);
|
||||
print(" CargoWaiting(1) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_Cargo()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_Cargo--");
|
||||
|
||||
for (local mode = AIStationList_Cargo.CM_WAITING; mode <= AIStationList_Cargo.CM_PLANNED; ++mode) {
|
||||
print(" " + mode);
|
||||
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA ; ++selector) {
|
||||
print(" " + selector);
|
||||
local list = AIStationList_Cargo(mode, selector, 6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoPlanned()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoPlanned--");
|
||||
|
||||
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
|
||||
print(" " + selector);
|
||||
local list = AIStationList_CargoPlanned(selector, 6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoPlannedByFrom()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoPlannedByFrom--");
|
||||
local list = AIStationList_CargoPlannedByFrom(2, 0);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoPlannedByVia()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoPlannedByVia--");
|
||||
local list = AIStationList_CargoPlannedByVia(2, 0);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoPlannedViaByFrom()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoPlannedViaByFrom--");
|
||||
local list = AIStationList_CargoPlannedViaByFrom(6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoPlannedFromByVia()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoPlannedFromByVia--");
|
||||
local list = AIStationList_CargoPlannedFromByVia(6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoWaiting()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoWaiting--");
|
||||
|
||||
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
|
||||
print(" " + selector);
|
||||
local list = AIStationList_CargoWaiting(selector, 6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoWaitingByFrom()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoWaitingByFrom--");
|
||||
local list = AIStationList_CargoWaitingByFrom(2, 0);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoWaitingByVia()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoWaitingByVia--");
|
||||
local list = AIStationList_CargoWaitingByVia(2, 0);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoWaitingViaByFrom()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoWaitingViaByFrom--");
|
||||
local list = AIStationList_CargoWaitingViaByFrom(6, 0, 7);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_CargoWaitingFromByVia()
|
||||
{
|
||||
print("");
|
||||
print("--StationList_CargoWaitingFromByVia--");
|
||||
local list = AIStationList_CargoWaitingFromByVia(2, 0, 2);
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
};
|
||||
|
||||
function Regression::StationList_Vehicle()
|
||||
{
|
||||
local list = AIStationList_Vehicle(12);
|
||||
|
||||
print("");
|
||||
print("--StationList_Vehicle--");
|
||||
print(" Count(): " + list.Count());
|
||||
list.Valuate(AIStation.GetLocation);
|
||||
print(" Location ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetCargoWaiting, 0);
|
||||
print(" CargoWaiting(0) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetCargoWaiting, 1);
|
||||
print(" CargoWaiting(1) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetCargoRating, 1);
|
||||
print(" CargoRating(1) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetDistanceManhattanToTile, 30000);
|
||||
print(" DistanceManhattanToTile(30000) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.GetDistanceSquareToTile, 30000);
|
||||
print(" DistanceSquareToTile(30000) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
list.Valuate(AIStation.IsWithinTownInfluence, 0);
|
||||
print(" IsWithinTownInfluence(0) ListDump:");
|
||||
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||
print(" " + i + " => " + list.GetValue(i));
|
||||
}
|
||||
}
|
||||
|
||||
function Regression::Start()
|
||||
{
|
||||
StationList();
|
||||
StationList_Cargo();
|
||||
StationList_CargoPlanned();
|
||||
StationList_CargoPlannedByFrom();
|
||||
StationList_CargoPlannedByVia();
|
||||
StationList_CargoPlannedViaByFrom();
|
||||
StationList_CargoPlannedFromByVia();
|
||||
StationList_CargoWaiting();
|
||||
StationList_CargoWaitingByFrom();
|
||||
StationList_CargoWaitingByVia();
|
||||
StationList_CargoWaitingViaByFrom();
|
||||
StationList_CargoWaitingFromByVia();
|
||||
StationList_Vehicle();
|
||||
}
|
@@ -1,127 +0,0 @@
|
||||
|
||||
--StationList--
|
||||
Count(): 5
|
||||
Location ListDump:
|
||||
6 => 42341
|
||||
2 => 41831
|
||||
7 => 41825
|
||||
5 => 33421
|
||||
4 => 33411
|
||||
CargoWaiting(0) ListDump:
|
||||
7 => 6
|
||||
6 => 6
|
||||
2 => 3
|
||||
5 => 0
|
||||
4 => 0
|
||||
CargoWaiting(1) ListDump:
|
||||
7 => 0
|
||||
6 => 0
|
||||
5 => 0
|
||||
4 => 0
|
||||
2 => 0
|
||||
|
||||
--StationList_Cargo--
|
||||
0
|
||||
0
|
||||
6 => 6
|
||||
1
|
||||
6 => 2
|
||||
2
|
||||
2 => 4
|
||||
7 => 2
|
||||
3
|
||||
1
|
||||
0
|
||||
7 => 18
|
||||
6 => 16
|
||||
2 => 7
|
||||
1
|
||||
6 => 8
|
||||
2 => 3
|
||||
2
|
||||
2 => 16
|
||||
6 => 14
|
||||
7 => 11
|
||||
3
|
||||
6 => 10
|
||||
2 => 8
|
||||
|
||||
--StationList_CargoPlanned--
|
||||
0
|
||||
7 => 18
|
||||
6 => 16
|
||||
2 => 7
|
||||
1
|
||||
6 => 8
|
||||
2 => 3
|
||||
2
|
||||
2 => 16
|
||||
6 => 14
|
||||
7 => 11
|
||||
3
|
||||
6 => 10
|
||||
2 => 8
|
||||
|
||||
--StationList_CargoPlannedByFrom--
|
||||
7 => 8
|
||||
6 => 8
|
||||
2 => 7
|
||||
|
||||
--StationList_CargoPlannedByVia--
|
||||
2 => 16
|
||||
6 => 7
|
||||
|
||||
--StationList_CargoPlannedViaByFrom--
|
||||
6 => 8
|
||||
2 => 3
|
||||
|
||||
--StationList_CargoPlannedFromByVia--
|
||||
6 => 10
|
||||
2 => 8
|
||||
|
||||
--StationList_CargoWaiting--
|
||||
0
|
||||
6 => 6
|
||||
1
|
||||
6 => 2
|
||||
2
|
||||
2 => 4
|
||||
7 => 2
|
||||
3
|
||||
|
||||
--StationList_CargoWaitingByFrom--
|
||||
2 => 3
|
||||
|
||||
--StationList_CargoWaitingByVia--
|
||||
6 => 3
|
||||
|
||||
--StationList_CargoWaitingViaByFrom--
|
||||
6 => 2
|
||||
|
||||
--StationList_CargoWaitingFromByVia--
|
||||
6 => 3
|
||||
|
||||
--StationList_Vehicle--
|
||||
Count(): 2
|
||||
Location ListDump:
|
||||
5 => 33421
|
||||
4 => 33411
|
||||
CargoWaiting(0) ListDump:
|
||||
5 => 0
|
||||
4 => 0
|
||||
CargoWaiting(1) ListDump:
|
||||
5 => 0
|
||||
4 => 0
|
||||
CargoRating(1) ListDump:
|
||||
5 => -1
|
||||
4 => -1
|
||||
DistanceManhattanToTile(30000) ListDump:
|
||||
5 => 106
|
||||
4 => 96
|
||||
DistanceSquareToTile(30000) ListDump:
|
||||
5 => 8818
|
||||
4 => 7058
|
||||
IsWithinTownInfluence(0) ListDump:
|
||||
5 => 0
|
||||
4 => 0
|
||||
ERROR: The script died unexpectedly.
|
Binary file not shown.
@@ -1,103 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents more or less nothingness
|
||||
;
|
||||
[metadata]
|
||||
name = NoMusic
|
||||
shortname = NULL
|
||||
version = 0
|
||||
fallback = true
|
||||
description = A music pack without actual music.
|
||||
description.af_ZA = 'n Musiek stel sonder enige musiek.
|
||||
description.ar_EG = مجموعة موسيقى بدون موسيقى
|
||||
description.be_BY = "Пусты" набор музычнага афармлення, які не зьмяшчае ніякай музыкі.
|
||||
description.bg_BG = Празен музикален пакет.
|
||||
description.ca_ES = Una llista de música sense cap peça.
|
||||
description.cs_CZ = Prázná hudební sada.
|
||||
description.cy_GB = Pecyn cerddoriaeth heb unrhyw gerddoriaeth ynddo.
|
||||
description.da_DK = En musikpakke uden musik.
|
||||
description.de_DE = Ein Musikset ohne Musik.
|
||||
description.el_GR = Ένα πάκετο μουσικής χωρίς πραγματική μουσική.
|
||||
description.en_AU = A music pack without actual music.
|
||||
description.en_US = A music pack without actual music.
|
||||
description.es_ES = Un conjunto de música vacío.
|
||||
description.es_MX = Paquete de música vacío
|
||||
description.et_EE = Muusikakogu ilma muusikata.
|
||||
description.eu_ES = Musika gabeko musika paketea.
|
||||
description.fi_FI = Musiikkipaketti, jossa ei ole musiikkia.
|
||||
description.fr_FR = Un pack de musiques sans musiques.
|
||||
description.ga_IE = Pacáiste ceoil gan aon cheol iarbhír ann.
|
||||
description.gd_GB = Pacaid ciùil anns nach eil fonn sam bith.
|
||||
description.gl_ES = Un conxunto de músicas sen ningunha música.
|
||||
description.he_IL = אוסף מנגינות ללא מנגינות.
|
||||
description.hr_HR = Glazbeni paket bez ikakve glazbe.
|
||||
description.hu_HU = Zenei alapcsomag zene nélkül.
|
||||
description.id_ID = Paket musik tanpa musik sungguhan.
|
||||
description.is_IS = Tónlistarpakki sem er í raun án tónlistar.
|
||||
description.it_IT = Un pacchetto musicale non contenente alcuna musica.
|
||||
description.ja_JP = 空の音楽パック
|
||||
description.ko_KR = 실제 음악이 없는 음악 목록입니다.
|
||||
description.la_VA = Sarcina musicae sine ulla musica.
|
||||
description.lb_LU = E Musikpack ouni aktuell Musik.
|
||||
description.lt_LT = Muzikos pakas be muzikos.
|
||||
description.lv_LV = Mūzikas kopa bez mūzikas
|
||||
description.ms_MY = Pek muzik tanpa muzik sebenar.
|
||||
description.nb_NO = En musikkpakke uten noe musikk.
|
||||
description.nl_NL = Een muziekset zonder muziek.
|
||||
description.nn_NO = Ei musikkpakke utan noko musikk.
|
||||
description.pl_PL = Zestaw utworów muzycznych nie zawierający żadnej muzyki.
|
||||
description.pt_BR = Um pacote de músicas sem músicas.
|
||||
description.pt_PT = Um conjunto de música vazio.
|
||||
description.ro_RO = Un set de muzică fără muzică inclusă.
|
||||
description.ru_RU = "Пустой" набор музыкального оформления, не содержащий никакой музыки.
|
||||
description.sk_SK = Sada hudby neobsahujúca hudbu.
|
||||
description.sl_SI = Glasbeni paket z vključeno glasbo.
|
||||
description.sr_RS = Prazan skup muzičkih numera.
|
||||
description.sv_SE = Ett musikpaket utan någon musik.
|
||||
description.ta_IN = இசை இல்லாத இசைத்தொகுப்பு.
|
||||
description.th_TH = ชุดเพลงประกอบแบบไม่มีเสียงเพลง
|
||||
description.tr_TR = Müzik içermeyen boş bir müzik paketi.
|
||||
description.uk_UA = Порожній набір музики.
|
||||
description.vi_VN = Gói âm nhạc này không có nhạc nào.
|
||||
description.zh_CN = 一个没有实际内容的音乐包.
|
||||
description.zh_TW = 不含任何音樂的音樂集。
|
||||
|
||||
[files]
|
||||
theme =
|
||||
old_0 =
|
||||
old_1 =
|
||||
old_2 =
|
||||
old_3 =
|
||||
old_4 =
|
||||
old_5 =
|
||||
old_6 =
|
||||
old_7 =
|
||||
old_8 =
|
||||
old_9 =
|
||||
new_0 =
|
||||
new_1 =
|
||||
new_2 =
|
||||
new_3 =
|
||||
new_4 =
|
||||
new_5 =
|
||||
new_6 =
|
||||
new_7 =
|
||||
new_8 =
|
||||
new_9 =
|
||||
ezy_0 =
|
||||
ezy_1 =
|
||||
ezy_2 =
|
||||
ezy_3 =
|
||||
ezy_4 =
|
||||
ezy_5 =
|
||||
ezy_6 =
|
||||
ezy_7 =
|
||||
ezy_8 =
|
||||
ezy_9 =
|
||||
|
||||
[md5s]
|
||||
|
||||
[names]
|
||||
|
||||
[origin]
|
||||
default = This file was part of your OpenTTD installation.
|
@@ -1,70 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents more or less nothingness
|
||||
;
|
||||
[metadata]
|
||||
name = NoSound
|
||||
shortname = NULL
|
||||
version = 2
|
||||
fallback = true
|
||||
description = A sound pack without any sounds.
|
||||
description.af_ZA = 'n Klank stel sonder enige klanke.
|
||||
description.ar_EG = مجموعة صوت بدوت اصوات مضافة
|
||||
description.be_BY = "Пусты" набор гукавога афармленьня, які не зьмяшчае ніякіх гукаў.
|
||||
description.bg_BG = Празен звуков пакет.
|
||||
description.ca_ES = Una llista de sons buida.
|
||||
description.cs_CZ = Prázdná sada zvuků.
|
||||
description.cy_GB = Pecyn sain heb unrhyw effeithiau sain ynddo.
|
||||
description.da_DK = En lydpakke uden lyde.
|
||||
description.de_DE = Basissounds ohne Sound.
|
||||
description.el_GR = Ένα πάκετο ήχων χώρις ήχους.
|
||||
description.en_AU = A sound pack without any sounds.
|
||||
description.en_US = A sound pack without any sounds.
|
||||
description.es_ES = Un conjunto de sonidos vacío.
|
||||
description.es_MX = Paquete de sonidos vacío
|
||||
description.et_EE = Helikogu ilma helideta.
|
||||
description.eu_ES = Soinurik gabeko soinu pakete bat
|
||||
description.fi_FI = Äänipaketti, jossa ei ole ääniä.
|
||||
description.fr_FR = Un pack de sons sans sons.
|
||||
description.ga_IE = Pacáiste fuaimeanna gan aon fhuaimeanna ann.
|
||||
description.gd_GB = Pacaid fhuaimean anns nach eil fuaim sam bith.
|
||||
description.gl_ES = Un conxunto de sons sen ningún son
|
||||
description.he_IL = אוסף צלילים ללא צלילים.
|
||||
description.hr_HR = Zvučni paket bez ikakvih zvukova.
|
||||
description.hu_HU = Hang alapcsomag hangok nélkül.
|
||||
description.id_ID = Paket efek suara tanpa suara apapun.
|
||||
description.is_IS = Hljóðpakki án hljóðs.
|
||||
description.it_IT = Un pacchetto sonoro non contenente alcun suono.
|
||||
description.ja_JP = 空の効果音パック
|
||||
description.ko_KR = 아무런 효과음도 없는 효과음 팩입니다.
|
||||
description.la_VA = Sarcina sonorum sine ullis sonis.
|
||||
description.lb_LU = E Soundpack ouni iergendee Sound.
|
||||
description.lt_LT = Garsų pakas be jokių garsų.
|
||||
description.lv_LV = Skaņu kopa bez skaņas.
|
||||
description.nb_NO = En lydpakke uten noen lyder.
|
||||
description.nl_NL = Een geluidset zonder geluid.
|
||||
description.nn_NO = Ei lydpakke utan nokon lydar.
|
||||
description.pl_PL = Zestaw dźwięków nie zawierający żadnych dźwięków.
|
||||
description.pt_BR = Um pacote de sons sem sons.
|
||||
description.pt_PT = Um conjunto de sons vazio.
|
||||
description.ro_RO = Un set de sunete fără nici un sunet inclus.
|
||||
description.ru_RU = "Пустой" набор звукового оформления, не содержащий никаких звуков.
|
||||
description.sk_SK = Zvuková sada neobsahujúca zvuky.
|
||||
description.sl_SI = Zvočni paket brez zvoka.
|
||||
description.sr_RS = Prazan skup zvukova.
|
||||
description.sv_SE = Ett ljudpaket utan några ljud.
|
||||
description.ta_IN = ஒலிகள் இல்லாத ஒலி தொகுப்பு.
|
||||
description.th_TH = ชุดเสียงแบบไร้เสียง
|
||||
description.tr_TR = Ses içermeyen boş bir ses kümesi.
|
||||
description.uk_UA = Порожній набір звуків.
|
||||
description.vi_VN = Gói âm thanh này không có âm thanh nào.
|
||||
description.zh_CN = 一个空的音效包.
|
||||
description.zh_TW = 不含任何音效的音效集。
|
||||
|
||||
[files]
|
||||
samples =
|
||||
|
||||
[md5s]
|
||||
|
||||
[origin]
|
||||
default = This file was part of your OpenTTD installation.
|
Binary file not shown.
Binary file not shown.
@@ -1,84 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the non-German Transport
|
||||
; Tycoon Deluxe DOS CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_dos
|
||||
shortname = TTDD
|
||||
version = 1
|
||||
palette = DOS
|
||||
description = Original Transport Tycoon Deluxe DOS edition graphics.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS uitgawe grafieke.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الرسومية نسخة الدوس
|
||||
description.be_BY = Арыґінальная ґрафіка з Transport Tycoon Deluxe для DOS.
|
||||
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за DOS.
|
||||
description.ca_ES = Gràfics originals del Transport Tycoon Deluxe pel DOS.
|
||||
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (verze pro DOS).
|
||||
description.cy_GB = Graffeg gwreiddiol fersiwn DOS o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe DOS-version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe DOS Basisgrafiken.
|
||||
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση DOS.
|
||||
description.en_AU = Original Transport Tycoon Deluxe DOS edition graphics.
|
||||
description.en_US = Original Transport Tycoon Deluxe DOS edition graphics.
|
||||
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión DOS.
|
||||
description.es_MX = Gráficos originales de Transport Tycoon Deluxe para DOS.
|
||||
description.et_EE = Algse Transport Tycoon Deluxe DOSi versiooni graafika.
|
||||
description.eu_ES = Transport Tycoon Deluxe originaleko DOS edizioko grafikoak.
|
||||
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen DOS-version grafiikat.
|
||||
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version DOS).
|
||||
description.ga_IE = Grafaicí bunaidhTransport Tycoon Deluxe, eagrán DOS.
|
||||
description.gd_GB = Grafaigeachd aig an deasachadh DOS tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Graficos da edición orixinal de Transport Tycoon Deluxe para DOS.
|
||||
description.he_IL = גרפיקות Transport Tycoon Deluxe המקורי בגרסת DOS.
|
||||
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe DOS izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának grafikája.
|
||||
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS.
|
||||
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS útgáfunni.
|
||||
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione DOS.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (DOS)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션의 그래픽입니다.
|
||||
description.la_VA = Graphica ex editione originale Transport Tycoon Deluxe DOS.
|
||||
description.lb_LU = Original Transport Tycoon Deluxe DOS Editioun Grafik.
|
||||
description.lt_LT = Originali Transport Tycoon Deluxe DOS leidimo grafika.
|
||||
description.lv_LV = Oriģinālā Transport Tycoon Deluxe DOS izdevuma grafika.
|
||||
description.ms_MY = Grafik asal Transport Tycoon Deluxe DOS edition.
|
||||
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS.
|
||||
description.nl_NL = Originele graphics van de Transport Tycoon Deluxe DOS-versie.
|
||||
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for DOS.
|
||||
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe DOS.
|
||||
description.pt_BR = Gráficos Originais do Transport Tycoon Deluxe, Edição DOS.
|
||||
description.pt_PT = Gráficos originais da edição DOS de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru DOS.
|
||||
description.ru_RU = Оригинальная графика из Transport Tycoon Deluxe для DOS.
|
||||
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (DOS).
|
||||
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za različico DOS.
|
||||
description.sr_RS = Originalni skup grafika Transport Tycoon Deluxe DOS izdanja.
|
||||
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, DOS-utgåvan.
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS பதிப்பு அசைவூட்டங்கள்.
|
||||
description.th_TH = กราฟฟิกต้นตำหรับของ Transport Tycoon Deluxe DOS edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe DOS sürümü grafikleri.
|
||||
description.uk_UA = Оригінальна графіка з Transport Tycoon Deluxe DOS edition.
|
||||
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên DOS
|
||||
description.zh_CN = 运输大亨DOS豪华版原版图形包.
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版的圖形。
|
||||
|
||||
[files]
|
||||
base = TRG1.GRF
|
||||
logos = TRGI.GRF
|
||||
arctic = TRGC.GRF
|
||||
tropical = TRGH.GRF
|
||||
toyland = TRGT.GRF
|
||||
extra = ORIG_EXTRA.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
|
||||
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
|
||||
TRGC.GRF = ed446637e034104c5559b32c18afe78d
|
||||
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
|
||||
TRGT.GRF = e30e8a398ae86c03dc534a8ac7dfb3b6
|
||||
ORIG_EXTRA.GRF = 0b10a95c0adee710ecca9c3d676be4f3
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
ORIG_EXTRA.GRF = This file was part of your OpenTTD installation.
|
@@ -1,70 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original sounds as on the Transport
|
||||
; Tycoon Deluxe DOS CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_dos
|
||||
shortname = TTDO
|
||||
version = 0
|
||||
description = Original Transport Tycoon Deluxe DOS edition sounds.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS uitgawe klanke.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الصوتية نسخة الدوس
|
||||
description.be_BY = Арыґінальны набор гукавога афармленьня з гульні Transport Tycoon Deluxe для DOS.
|
||||
description.bg_BG = Оригинални звуци на Transport Tycoon Deluxe за DOS.
|
||||
description.ca_ES = Sons originals del Transport Tycoon Deluxe pel DOS.
|
||||
description.cs_CZ = Původní sada zvuků Transport Tycoon Deluxe (verze pro DOS).
|
||||
description.cy_GB = Effeithiau sain gwreiddiol fersiwn DOS o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originallyd fra Transport Tycoon Deluxe DOS-version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe DOS Basissounds.
|
||||
description.el_GR = Αρχικοί ήχοι από το Transport Tycoon Deluxe έκδοση DOS.
|
||||
description.en_AU = Original Transport Tycoon Deluxe DOS edition sounds.
|
||||
description.en_US = Original Transport Tycoon Deluxe DOS edition sounds.
|
||||
description.es_ES = Sonidos originales de Transport Tycoon Deluxe versión DOS.
|
||||
description.es_MX = Sonidos originales de Transport Tycoon Deluxe para DOS.
|
||||
description.et_EE = Algse Transport Tycoon Deluxe DOSi versiooni helid.
|
||||
description.eu_ES = Transport Tycoon Deluxe originaleko DOS edizioko soinuak.
|
||||
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen DOS-version äänet.
|
||||
description.fr_FR = Sons originaux de Transport Tycoon Deluxe (version DOS).
|
||||
description.ga_IE = Fuaimeanna bunaidh Transport Tycoon Deluxe, eagrán DOS.
|
||||
description.gd_GB = Fuaimean aig an deasachadh DOS tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Sons da edición orixinal de Transport Tycoon Deluxe para DOS.
|
||||
description.he_IL = צלילי Transport Tycoon Deluxe המקורי בגרסת DOS.
|
||||
description.hr_HR = Originalni zvukovi za Transport Tycoon Deluxe DOS izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának hangjai.
|
||||
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi DOS.
|
||||
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe DOS útgáfunni.
|
||||
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione DOS.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 効果音 (DOS)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 도스 에디션의 효과음입니다.
|
||||
description.la_VA = Soni ex editione originale Transport Tycoon Deluxe DOS.
|
||||
description.lb_LU = Original Transport Tycoon Deluxe DOS Editioun Sound.
|
||||
description.lt_LT = Originalūs Transport Tycoon Deluxe DOS leidimo garsai.
|
||||
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for DOS.
|
||||
description.nl_NL = Originele geluiden van de Transport Tycoon Deluxe DOS-versie.
|
||||
description.nn_NO = Originale lydar frå Transport Tycoon Deluxe for DOS.
|
||||
description.pl_PL = Oryginalna edycja dźwięków dla Transport Tycoon Deluxe DOS.
|
||||
description.pt_BR = Sons Originais do Transport Tycoon Deluxe, Edição DOS.
|
||||
description.pt_PT = Sons originais da edição DOS de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul de sunete original al Transport Tycoon Deluxe pentru DOS.
|
||||
description.ru_RU = Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для DOS.
|
||||
description.sk_SK = Pôvodné zvuky Transport Tycoon Deluxe (DOS).
|
||||
description.sl_SI = Originalni zvoki Transport Tycoon Deluxe različice DOS.
|
||||
description.sr_RS = Originalni skup zvukova Transport Tycoon Deluxe DOS izdanja.
|
||||
description.sv_SE = Originalljuden från Transport Tycoon Deluxe, DOS-utgåvan.
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS பதிப்பு ஒலிகள்.
|
||||
description.th_TH = เสียงต้นตำหรับของ Transport Tycoon Deluxe DOS edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe DOS sürümü sesleri.
|
||||
description.uk_UA = Оригінальний набір звуків з Transport Tycoon Deluxe DOS edition.
|
||||
description.vi_VN = Âm thanh gốc từ phiên bản Transport Tycoon Deluxe trên DOS
|
||||
description.zh_CN = 运输大亨DOS豪华版原版音效包.
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版的音效。
|
||||
|
||||
[files]
|
||||
samples = SAMPLE.CAT
|
||||
|
||||
[md5s]
|
||||
SAMPLE.CAT = 422ea3dd074d2859bb51639a6e0e85da
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
@@ -1,82 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the German Transport
|
||||
; Tycoon Deluxe DOS CD. It contains one broken sprite.
|
||||
;
|
||||
[metadata]
|
||||
name = original_dos_de
|
||||
shortname = TTDD
|
||||
version = 0
|
||||
palette = DOS
|
||||
description = Original Transport Tycoon Deluxe DOS (German) edition graphics.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS (German) uitgawe grafieke.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الالمانية نسخة الدوس
|
||||
description.be_BY = Арыґінальная ґрафіка зь нямецкай версіі Transport Tycoon Deluxe для DOS.
|
||||
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за DOS (немски) .
|
||||
description.ca_ES = Gràfics originals del Transport Tycoon Deluxe (alemany) pel DOS.
|
||||
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (německá verze pro DOS).
|
||||
description.cy_GB = Graffeg gwreiddiol fersiwn DOS (Almaenig) o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe DOS (Tysk) version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe DOS (Deutsch) Basisgrafiken.
|
||||
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση DOS (Γερμανικό).
|
||||
description.en_AU = Original Transport Tycoon Deluxe DOS (German) edition graphics.
|
||||
description.en_US = Original Transport Tycoon Deluxe DOS (German) edition graphics.
|
||||
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión DOS (Alemán).
|
||||
description.es_MX = Gráficos originales de Transport Tycoon Deluxe para DOS (en alemán).
|
||||
description.et_EE = Algse Transport Tycoon Deluxe DOSi (Saksa) versiooni graafika.
|
||||
description.fi_FI = Alkuperäiset Saksassa julkaistun Transport Tycoon Deluxen DOS-version grafiikat.
|
||||
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version DOS allemande).
|
||||
description.ga_IE = Grafaicí bunaidhTransport Tycoon Deluxe, eagrán DOS (Gearmánach).
|
||||
description.gd_GB = Grafaigeachd aig an deasachadh DOS (Gearmailteach) tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Graficos da edición orixinal (alemá) de Transport Tycoon Deluxe para DOS.
|
||||
description.he_IL = גרפיקות Transport Tycoon Deluxe המקורי בגרסת DOS (גרמנית).
|
||||
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe DOS (Njemački) izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS (német) verziójának grafikája.
|
||||
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS (Jerman).
|
||||
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS (þýsku) útgáfunni.
|
||||
description.it_IT = Grafica originale di Transport Tycoon Deluxe (tedesco), edizione DOS.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (DOS・ドイツ版)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션(독일)의 그래픽입니다.
|
||||
description.la_VA = Graphica ex editione originale Transport Tycoon Deluxe DOS (Germanica).
|
||||
description.lb_LU = Original Transport Tycoon Deluxe DOS (Däitsch) Editioun Grafik.
|
||||
description.lt_LT = Originali Transport Tycoon Deluxe DOS (Vokiečių) leidimo grafika.
|
||||
description.lv_LV = Oriģinālā Transport Tycoon Deluxe DOS (vācu) izdevuma grafika.
|
||||
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS (tysk).
|
||||
description.nl_NL = Originele graphics van de Duitse Transport Tycoon Deluxe DOS-versie.
|
||||
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for DOS (tysk).
|
||||
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe DOS (German).
|
||||
description.pt_BR = Gráficos Originais do Transport Tycoon Deluxe, Edição DOS alemã.
|
||||
description.pt_PT = Gráficos originais da edição DOS (Alemã) de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru DOS (ediţia germană).
|
||||
description.ru_RU = Оригинальная графика из немецкой версии Transport Tycoon Deluxe для DOS.
|
||||
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (DOS) (v jazyku nemčina).
|
||||
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za nemško različico DOS.
|
||||
description.sr_RS = Originalni skup grafika nemačkog Transport Tycoon Deluxe DOS izdanja.
|
||||
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, DOS-utgåvan (tyska).
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS (செருமன்) பதிப்பு அசைவூட்டங்கள்.
|
||||
description.th_TH = กราฟฟิกต้นตำหรับของ Transport Tycoon Deluxe DOS (German) edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe DOS (Almanca) sürümü grafikleri.
|
||||
description.uk_UA = Оригінальна графіка з Transport Tycoon Deluxe DOS edition (німецького).
|
||||
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên DOS (tiếng Đức)
|
||||
description.zh_CN = 运输大亨DOS豪华德语版原版图形包.
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版 (德國版) 的圖形。
|
||||
|
||||
[files]
|
||||
base = TRG1.GRF
|
||||
logos = TRGI.GRF
|
||||
arctic = TRGC.GRF
|
||||
tropical = TRGH.GRF
|
||||
toyland = TRGT.GRF
|
||||
extra = ORIG_EXTRA.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
|
||||
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
|
||||
TRGC.GRF = ed446637e034104c5559b32c18afe78d
|
||||
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
|
||||
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
|
||||
ORIG_EXTRA.GRF = 0b10a95c0adee710ecca9c3d676be4f3
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
ORIG_EXTRA.GRF = This file was part of your OpenTTD installation.
|
Binary file not shown.
@@ -1,83 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the Transport
|
||||
; Tycoon Deluxe for Windows CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_windows
|
||||
shortname = TTDW
|
||||
version = 0
|
||||
palette = Windows
|
||||
description = Original Transport Tycoon Deluxe Windows edition graphics.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe grafieke.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الرسومية نسخة وندوز
|
||||
description.be_BY = Арыґінальная ґрафіка з Transport Tycoon Deluxe для Windows.
|
||||
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за Windows.
|
||||
description.ca_ES = Gràfics originals del Transport Tycoon Deluxe pel Windows.
|
||||
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (verze pro Windows).
|
||||
description.cy_GB = Graffeg gwreiddiol fersiwn Windows o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe Windows-version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe Windows Basisgrafiken.
|
||||
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση Windows.
|
||||
description.en_AU = Original Transport Tycoon Deluxe Windows edition graphics.
|
||||
description.en_US = Original Transport Tycoon Deluxe Windows edition graphics.
|
||||
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión Windows.
|
||||
description.es_MX = Gráficos originales de Transport Tycoon Deluxe para Windows.
|
||||
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni graafika.
|
||||
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen Windows-version grafiikat.
|
||||
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version Windows).
|
||||
description.ga_IE = Grafaicí bunaidhTransport Tycoon Deluxe, eagrán Windows.
|
||||
description.gd_GB = Grafaigeachd aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Graficos da edición orixinal de Transport Tycoon Deluxe para Windows.
|
||||
description.he_IL = גרפיקות Transport Tycoon Deluxe המקורי בגרסת Windows.
|
||||
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe Windows izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának grafikája.
|
||||
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi Windows.
|
||||
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe Windows útgáfunni.
|
||||
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione Windows.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (Windows)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 그래픽입니다.
|
||||
description.la_VA = Graphica ex editione originale Transport Tycoon Deluxe Windows.
|
||||
description.lb_LU = Original Transport Tycoon Deluxe Windows Editioun Grafik.
|
||||
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo grafika.
|
||||
description.lv_LV = Oriģinālā Transport Tycoon Deluxe Windows izdevuma grafika.
|
||||
description.ms_MY = Grafik asal Transport Tycoon Deluxe edisi Windows.
|
||||
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for Windows.
|
||||
description.nl_NL = Originele graphics van de Transport Tycoon Deluxe Windows-versie.
|
||||
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for Windows.
|
||||
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe Windows.
|
||||
description.pt_BR = Gráficos Originais do Transport Tycoon, Edição Windows.
|
||||
description.pt_PT = Gráficos originais da edição Windows de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru Windows.
|
||||
description.ru_RU = Оригинальная графика из Transport Tycoon Deluxe для Windows.
|
||||
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (Windows).
|
||||
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za različico oken(windows).
|
||||
description.sr_RS = Originalni skup grafika Transport Tycoon Deluxe Windows izdanja.
|
||||
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, Windows-utgåvan.
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு அசைவூட்டங்கள்.
|
||||
description.th_TH = กราฟฟิกต้ำตำหรับของ Transport Tycoon Deluxe Windows edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe Windows sürümü grafikleri.
|
||||
description.uk_UA = Оригінальна графіка з Transport Tycoon Deluxe Windows edition.
|
||||
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên Windows
|
||||
description.zh_CN = 运输大亨Windows豪华版原版图形包.
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的圖形。
|
||||
|
||||
[files]
|
||||
base = TRG1R.GRF
|
||||
logos = TRGIR.GRF
|
||||
arctic = TRGCR.GRF
|
||||
tropical = TRGHR.GRF
|
||||
toyland = TRGTR.GRF
|
||||
extra = ORIG_EXTRA.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1R.GRF = b04ce593d8c5016e07473a743d7d3358
|
||||
TRGIR.GRF = 0c2484ff6be49fc63a83be6ab5c38f32
|
||||
TRGCR.GRF = 3668f410c761a050b5e7095a2b14879b
|
||||
TRGHR.GRF = 06bf2b7a31766f048baac2ebe43457b1
|
||||
TRGTR.GRF = de53650517fe661ceaa3138c6edb0eb8
|
||||
ORIG_EXTRA.GRF = 0b10a95c0adee710ecca9c3d676be4f3
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
ORIG_EXTRA.GRF = This file was part of your OpenTTD installation.
|
@@ -1,146 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original music as on the Transport
|
||||
; Tycoon Deluxe for Windows CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_windows
|
||||
shortname = TTDW
|
||||
version = 1
|
||||
description = Original Transport Tycoon Deluxe Windows edition music.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe musiek.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الموسيقية نسخة وندوز
|
||||
description.be_BY = Арыґінальны набор музычнага афармленьня з гульні Transport Tycoon Deluxe для Windows.
|
||||
description.bg_BG = Оригинална музика на Transport Tycoon Deluxe за Windows.
|
||||
description.ca_ES = Música original del Transport Tycoon Deluxe pel Windows.
|
||||
description.cs_CZ = Původní hudba Transport Tycoon Deluxe (verze pro Windows).
|
||||
description.cy_GB = Cerddoriaeth gwreiddiol fersion Windows o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originalmusik fra Transport Tycoon Deluxe Windows-version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe Windows Musikset.
|
||||
description.el_GR = Αρχική μουσική από το Transport Tycoon Deluxe έκδοση Windows.
|
||||
description.en_AU = Original Transport Tycoon Deluxe Windows edition music.
|
||||
description.en_US = Original Transport Tycoon Deluxe Windows edition music.
|
||||
description.es_ES = Música original de Transport Tycoon Deluxe versión Windows.
|
||||
description.es_MX = Música original de Transport Tycoon Deluxe para Windows.
|
||||
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni muusika.
|
||||
description.fi_FI = Alkuperäinen Transport Tycoon Deluxen Windows-version musiikki.
|
||||
description.fr_FR = Musiques originales de Transport Tycoon Deluxe (version Windows).
|
||||
description.ga_IE = Ceol bunaidh Transport Tycoon Deluxe, eagrán Windows.
|
||||
description.gd_GB = Ceòl aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Música da edición orixinal de Transport Tycoon Deluxe para Windows.
|
||||
description.he_IL = מנגינות Transport Tycoon Deluxe המקורי בגרסת Windows.
|
||||
description.hr_HR = Originalna glazba za Transport Tycoon Deluxe Windows izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának zenéje.
|
||||
description.id_ID = Musik pengiring orisinil Transport Tycoon Deluxe versi Windows.
|
||||
description.is_IS = Upprunalega tónlistin úr Transport Tycoon Deluxe Windows útgáfunni.
|
||||
description.it_IT = Musica originale di Transport Tycoon Deluxe, edizione Windows.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 音楽 (Windows)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 음악입니다.
|
||||
description.la_VA = Musica ex editione originale Transport Tycoon Deluxe Windows.
|
||||
description.lb_LU = Original Transport Tycoon Deluxe Windows Editioun Musik.
|
||||
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo muzika.
|
||||
description.lv_LV = Oriģinālā Transport Tycoon Deluxe Windows izdevuma mūzika.
|
||||
description.ms_MY = Muzik asal Transport Tycoon Deluxe edisi Windows.
|
||||
description.nb_NO = Original musikk fra Transport Tycoon Deluxe for Windows.
|
||||
description.nl_NL = Originele muziek van de Transport Tycoon Deluxe Windows-versie.
|
||||
description.nn_NO = Original musikk frå Transport Tycoon Deluxe for Windows.
|
||||
description.pl_PL = Oryginalna edycja utworów muzycznych w Transport Tycoon Deluxe Windows.
|
||||
description.pt_BR = Música Original do Transport Tycoon Deluxe, Edição Windows
|
||||
description.pt_PT = Música original da edição Windows de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul de muzică original al Transport Tycoon Deluxe pentru Windows.
|
||||
description.ru_RU = Оригинальный набор музыкального оформления из игры Transport Tycoon Deluxe для Windows.
|
||||
description.sk_SK = Pôvodná hudba z Transport Tycoon Deluxe (Windows).
|
||||
description.sl_SI = Originalna glasba Transport Tycoon Deluxe različice oken(windows).
|
||||
description.sr_RS = Originalni skup muzičkih numera Transport Tycoon Deluxe Windows izdanja.
|
||||
description.sv_SE = Originalmusiken från Transport Tycoon Deluxe, Windows-utgåvan.
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு இசை.
|
||||
description.th_TH = เพลงต้นตำหรับชอง Transport Tycoon Deluxe Windows edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe Windows sürümü müzikleri.
|
||||
description.uk_UA = Оригінальна музика з Transport Tycoon Deluxe Windows edition.
|
||||
description.vi_VN = Nhạc gốc từ phiên bản Transport Tycoon Deluxe trên Windows
|
||||
description.zh_CN = Transport Tycoon Deluxe(运输大亨Windows豪华版)的原版音乐包
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的音樂。
|
||||
|
||||
[files]
|
||||
theme = GM_TT00.GM
|
||||
old_0 = GM_TT02.GM
|
||||
old_1 = GM_TT06.GM
|
||||
old_2 = GM_TT03.GM
|
||||
old_3 = GM_TT12.GM
|
||||
old_4 = GM_TT08.GM
|
||||
old_5 = GM_TT13.GM
|
||||
old_6 = GM_TT14.GM
|
||||
old_7 = GM_TT10.GM
|
||||
old_8 =
|
||||
old_9 =
|
||||
new_0 = GM_TT04.GM
|
||||
new_1 = GM_TT01.GM
|
||||
new_2 = GM_TT05.GM
|
||||
new_3 = GM_TT15.GM
|
||||
new_4 = GM_TT11.GM
|
||||
new_5 = GM_TT16.GM
|
||||
new_6 = GM_TT09.GM
|
||||
new_7 =
|
||||
new_8 =
|
||||
new_9 =
|
||||
ezy_0 = GM_TT18.GM
|
||||
ezy_1 = GM_TT19.GM
|
||||
ezy_2 = GM_TT21.GM
|
||||
ezy_3 = GM_TT17.GM
|
||||
ezy_4 = GM_TT20.GM
|
||||
ezy_5 = GM_TT07.GM
|
||||
ezy_6 =
|
||||
ezy_7 =
|
||||
ezy_8 =
|
||||
ezy_9 =
|
||||
|
||||
[md5s]
|
||||
GM_TT00.GM = 45cfec1b9d8c7a0ad45e755833cbf221
|
||||
GM_TT01.GM = ab14ed3392d848abd2a2e90a9d75d121
|
||||
GM_TT02.GM = dd4f696e4be5987ce738257b08b50171
|
||||
GM_TT03.GM = a1bfde23343df9e4063419bf29c166b8
|
||||
GM_TT04.GM = 4e6943aa0c455203d76c79389054747d
|
||||
GM_TT05.GM = cee281cb85a2e2343552d97640545a47
|
||||
GM_TT06.GM = 26d1de5efa8675f94065784e9d539e49
|
||||
GM_TT07.GM = 6f2691e17558f552ec4c565e4ab7139c
|
||||
GM_TT08.GM = a42bf2cb3340a822f1a69646fc7a487d
|
||||
GM_TT09.GM = eb35761a58a8df3c59ed8929cce13916
|
||||
GM_TT10.GM = 42fecd686720a785d20a78590c466a82
|
||||
GM_TT11.GM = 50ef1ef02e49d2112786dd45e69dc3ee
|
||||
GM_TT12.GM = 4ce707a0e0e72419f0681dd9bd95271b
|
||||
GM_TT13.GM = e765753be29d889ec818f38009103619
|
||||
GM_TT14.GM = 270e2d63bd32b95a4d007ce15a6ce45f
|
||||
GM_TT15.GM = 89e116a1c0c69f1845cc903a9bfbe460
|
||||
GM_TT16.GM = f824e2371b3bedfe61aad4b9c62dd6be
|
||||
GM_TT17.GM = 1b23eebb0796c1ab99cd97fa7082cf7b
|
||||
GM_TT18.GM = 15650de3bad645d0e88c4f5c7a2df92a
|
||||
GM_TT19.GM = 7aec079e15bd09588660b85545ac4dfc
|
||||
GM_TT20.GM = 1509097889dee617aa1e9a1738a5a930
|
||||
GM_TT21.GM = a8d0aaad02e1a762d8d54cf81da56bab
|
||||
|
||||
[names]
|
||||
GM_TT00.GM = Tycoon DELUXE Theme
|
||||
GM_TT01.GM = Snarl Up
|
||||
GM_TT02.GM = Easy Driver
|
||||
GM_TT03.GM = Little Red Diesel
|
||||
GM_TT04.GM = City Groove
|
||||
GM_TT05.GM = Aliens Ate My Railway
|
||||
GM_TT06.GM = Stoke It
|
||||
GM_TT07.GM = Don't Walk!
|
||||
GM_TT08.GM = Sawyer's Tune
|
||||
GM_TT09.GM = Fell Apart On Me
|
||||
GM_TT10.GM = Can't Get There From Here
|
||||
GM_TT11.GM = Hard Drivin'
|
||||
GM_TT12.GM = Road Hog
|
||||
GM_TT13.GM = Hold That Train!
|
||||
GM_TT14.GM = Broomer's Oil Rag
|
||||
GM_TT15.GM = Goss Groove
|
||||
GM_TT16.GM = Small Town
|
||||
GM_TT17.GM = Cruise Control
|
||||
GM_TT18.GM = Stroll On
|
||||
GM_TT19.GM = Funk Central
|
||||
GM_TT20.GM = Jammit
|
||||
GM_TT21.GM = Movin' On
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
@@ -1,70 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original sounds as on the Transport
|
||||
; Tycoon Deluxe for Windows CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_windows
|
||||
shortname = TTDO
|
||||
version = 0
|
||||
description = Original Transport Tycoon Deluxe Windows edition sounds.
|
||||
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe klanke.
|
||||
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الصوتية نسخة وندوز
|
||||
description.be_BY = Арыґінальны набор гукавога афармленьня з гульні Transport Tycoon Deluxe для Windows.
|
||||
description.bg_BG = Оригинални звуци на Transport Tycoon Deluxe за Windows.
|
||||
description.ca_ES = Sons originals del Transport Tycoon Deluxe pel Windows.
|
||||
description.cs_CZ = Původní sada zvuků Transport Tycoon Deluxe (verze pro Windows).
|
||||
description.cy_GB = Effeithiau sain gwreiddiol fersiwn Windows o Transport Tycoon Deluxe.
|
||||
description.da_DK = Originallyd fra Transport Tycoon Deluxe Windows-version.
|
||||
description.de_DE = Original Transport Tycoon Deluxe Windows Basissounds.
|
||||
description.el_GR = Αρχικοί ήχοι από το Transport Tycoon Deluxe έκδοση Windows.
|
||||
description.en_AU = Original Transport Tycoon Deluxe Windows edition sounds.
|
||||
description.en_US = Original Transport Tycoon Deluxe Windows edition sounds.
|
||||
description.es_ES = Sonidos originales de Transport Tycoon Deluxe versión Windows.
|
||||
description.es_MX = Sonidos originales de Transport Tycoon Deluxe para Windows.
|
||||
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni helid.
|
||||
description.eu_ES = Transport Tycoon Deluxe originaleko Windows edizioko grafikoak.
|
||||
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen Windows-version äänet.
|
||||
description.fr_FR = Sons originaux de Transport Tycoon Deluxe (version Windows).
|
||||
description.ga_IE = Fuaimeanna bunaidh Transport Tycoon Deluxe, eagrán Windows.
|
||||
description.gd_GB = Fuaimean aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
|
||||
description.gl_ES = Sons da edición orixinal de Transport Tycoon Deluxe para Windows.
|
||||
description.he_IL = צלילי Transport Tycoon Deluxe המקורי בגרסת Windows.
|
||||
description.hr_HR = Originalni zvukovi za Transport Tycoon Deluxe Windows izdanje.
|
||||
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának hangjai.
|
||||
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi Windows.
|
||||
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe Windows útgáfunni.
|
||||
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione Windows.
|
||||
description.ja_JP = Transport Tycoon Deluxe オリジナル版 効果音 (Windows)
|
||||
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도 에디션의 효과음입니다.
|
||||
description.la_VA = Soni ex editione originale Transport Tycoon Deluxe Windows.
|
||||
description.lb_LU = Original Transport Tycoon Deluxe Windows Editioun Sound.
|
||||
description.lt_LT = Originalūs Transport Tycoon Deluxe Windows leidimo garsai.
|
||||
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for Windows.
|
||||
description.nl_NL = Originele geluiden van de Transport Tycoon Deluxe Windows-versie.
|
||||
description.nn_NO = Originale lydar frå Transport Tycoon Deluxe for Windows.
|
||||
description.pl_PL = Oryginalna edycja dźwięków dla Transport Tycoon Deluxe Windows.
|
||||
description.pt_BR = Sons Originais do Transport Tycoon Deluxe, Edição Windows.
|
||||
description.pt_PT = Sons originais da edição Windows de Transport Tycoon Deluxe.
|
||||
description.ro_RO = Setul de sunete original al Transport Tycoon Deluxe pentru Windows.
|
||||
description.ru_RU = Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для Windows.
|
||||
description.sk_SK = Pôvodné zvuky Transport Tycoon Deluxe (Windows).
|
||||
description.sl_SI = Originalni zvoki Transport Tycoon Deluxe različice oken(windows).
|
||||
description.sr_RS = Originalni skup zvukova Transport Tycoon Deluxe Windows izdanja.
|
||||
description.sv_SE = Originalljuden från Transport Tycoon Deluxe, Windows-utgåvan.
|
||||
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு ஒலிகள்.
|
||||
description.th_TH = เสียงต้นตำหรับของ Transport Tycoon Deluxe Windows edition
|
||||
description.tr_TR = Özgün Transport Tycoon Deluxe Windows sürümü sesleri.
|
||||
description.uk_UA = Оригінальний набір звуків з Transport Tycoon Deluxe Windows edition.
|
||||
description.vi_VN = Âm thanh gốc từ phiên bản Transport Tycoon Deluxe trên Windows
|
||||
description.zh_CN = Transport Tycoon Deluxe Windows (运输大亨Windows豪华版)的原版音效包.
|
||||
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的音效。
|
||||
|
||||
[files]
|
||||
samples = SAMPLE.CAT
|
||||
|
||||
[md5s]
|
||||
SAMPLE.CAT = 9212e81e72badd4bbe1eaeae66458e10
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
@@ -1,25 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,25 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,17 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,10 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,8 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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,2 +0,0 @@
|
||||
start_ai MyAI
|
||||
|
@@ -1,2 +0,0 @@
|
||||
# Show a MOTD
|
||||
say "Welcome..."
|
@@ -1,24 +1,12 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file bmp.cpp Read and write support for bmps. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "gfx.h"
|
||||
#include "bmp.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "core/mem_func.hpp"
|
||||
#include "macros.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
|
||||
{
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file) {
|
||||
buffer->pos = -1;
|
||||
buffer->file = file;
|
||||
buffer->read = 0;
|
||||
@@ -27,24 +15,18 @@ void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
|
||||
|
||||
static inline void AdvanceBuffer(BmpBuffer *buffer)
|
||||
{
|
||||
if (buffer->read < 0) return;
|
||||
|
||||
buffer->read = (int)fread(buffer->data, 1, BMP_BUFFER_SIZE, buffer->file);
|
||||
buffer->pos = 0;
|
||||
}
|
||||
|
||||
static inline bool EndOfBuffer(BmpBuffer *buffer)
|
||||
{
|
||||
if (buffer->read < 0) return false;
|
||||
|
||||
if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
|
||||
return buffer->pos == buffer->read;
|
||||
}
|
||||
|
||||
static inline byte ReadByte(BmpBuffer *buffer)
|
||||
{
|
||||
if (buffer->read < 0) return 0;
|
||||
|
||||
if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
|
||||
buffer->real_pos++;
|
||||
return buffer->data[buffer->pos++];
|
||||
@@ -70,9 +52,7 @@ static inline void SkipBytes(BmpBuffer *buffer, int bytes)
|
||||
|
||||
static inline void SetStreamOffset(BmpBuffer *buffer, int offset)
|
||||
{
|
||||
if (fseek(buffer->file, offset, SEEK_SET) < 0) {
|
||||
buffer->read = -1;
|
||||
}
|
||||
fseek(buffer->file, offset, SEEK_SET);
|
||||
buffer->pos = -1;
|
||||
buffer->real_pos = offset;
|
||||
AdvanceBuffer(buffer);
|
||||
@@ -140,63 +120,53 @@ static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
*/
|
||||
static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
{
|
||||
uint i;
|
||||
uint x = 0;
|
||||
uint y = info->height - 1;
|
||||
byte n, c, b;
|
||||
byte *pixel = &data->bitmap[y * info->width];
|
||||
while (y != 0 || x < info->width) {
|
||||
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
|
||||
|
||||
byte n = ReadByte(buffer);
|
||||
byte c = ReadByte(buffer);
|
||||
n = ReadByte(buffer);
|
||||
c = ReadByte(buffer);
|
||||
if (n == 0) {
|
||||
switch (c) {
|
||||
case 0: // end of line
|
||||
x = 0;
|
||||
if (y == 0) return false;
|
||||
pixel = &data->bitmap[--y * info->width];
|
||||
break;
|
||||
|
||||
case 1: // end of bitmap
|
||||
return true;
|
||||
|
||||
case 2: { // delta
|
||||
if (EndOfBuffer(buffer)) return false;
|
||||
byte dx = ReadByte(buffer);
|
||||
byte dy = ReadByte(buffer);
|
||||
|
||||
/* Check for over- and underflow. */
|
||||
if (x + dx >= info->width || x + dx < x || dy > y) return false;
|
||||
|
||||
x += dx;
|
||||
y -= dy;
|
||||
pixel = &data->bitmap[y * info->width + x];
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // uncompressed
|
||||
uint i = 0;
|
||||
while (i++ < c) {
|
||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
||||
byte b = ReadByte(buffer);
|
||||
*pixel++ = GB(b, 4, 4);
|
||||
case 0: // end of line
|
||||
x = 0;
|
||||
pixel = &data->bitmap[--y * info->width];
|
||||
break;
|
||||
case 1: // end of bitmap
|
||||
x = info->width;
|
||||
y = 0;
|
||||
pixel = NULL;
|
||||
break;
|
||||
case 2: // delta
|
||||
x += ReadByte(buffer);
|
||||
i = ReadByte(buffer);
|
||||
if (x >= info->width || (y == 0 && i > 0)) return false;
|
||||
y -= i;
|
||||
pixel = &data->bitmap[y * info->width + x];
|
||||
break;
|
||||
default: // uncompressed
|
||||
i = 0;
|
||||
while (i++ < c) {
|
||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
||||
b = ReadByte(buffer);
|
||||
*pixel++ = GB(b, 4, 4);
|
||||
x++;
|
||||
if (x < info->width && i++ < c) {
|
||||
*pixel++ = GB(b, 0, 4);
|
||||
x++;
|
||||
if (i++ < c) {
|
||||
if (x >= info->width) return false;
|
||||
*pixel++ = GB(b, 0, 4);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
/* Padding for 16 bit align */
|
||||
SkipBytes(buffer, ((c + 1) / 2) % 2);
|
||||
break;
|
||||
}
|
||||
/* Padding for 16 bit align */
|
||||
SkipBytes(buffer, ((c + 1) / 2) % 2);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Apparently it is common to encounter BMPs where the count of
|
||||
* pixels to be written is higher than the remaining line width.
|
||||
* Ignore the superfluous pixels instead of reporting an error. */
|
||||
uint i = 0;
|
||||
while (x < info->width && i++ < n) {
|
||||
i = 0;
|
||||
while (i++ < n) {
|
||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
||||
*pixel++ = GB(c, 4, 4);
|
||||
x++;
|
||||
if (x < info->width && i++ < n) {
|
||||
@@ -233,55 +203,43 @@ static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
*/
|
||||
static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
{
|
||||
uint i;
|
||||
uint x = 0;
|
||||
uint y = info->height - 1;
|
||||
byte n, c;
|
||||
byte *pixel = &data->bitmap[y * info->width];
|
||||
while (y != 0 || x < info->width) {
|
||||
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
|
||||
|
||||
byte n = ReadByte(buffer);
|
||||
byte c = ReadByte(buffer);
|
||||
n = ReadByte(buffer);
|
||||
c = ReadByte(buffer);
|
||||
if (n == 0) {
|
||||
switch (c) {
|
||||
case 0: // end of line
|
||||
x = 0;
|
||||
if (y == 0) return false;
|
||||
pixel = &data->bitmap[--y * info->width];
|
||||
break;
|
||||
|
||||
case 1: // end of bitmap
|
||||
return true;
|
||||
|
||||
case 2: { // delta
|
||||
if (EndOfBuffer(buffer)) return false;
|
||||
byte dx = ReadByte(buffer);
|
||||
byte dy = ReadByte(buffer);
|
||||
|
||||
/* Check for over- and underflow. */
|
||||
if (x + dx >= info->width || x + dx < x || dy > y) return false;
|
||||
|
||||
x += dx;
|
||||
y -= dy;
|
||||
pixel = &data->bitmap[y * info->width + x];
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // uncompressed
|
||||
for (uint i = 0; i < c; i++) {
|
||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
||||
*pixel++ = ReadByte(buffer);
|
||||
x++;
|
||||
}
|
||||
/* Padding for 16 bit align */
|
||||
SkipBytes(buffer, c % 2);
|
||||
break;
|
||||
}
|
||||
case 0: // end of line
|
||||
x = 0;
|
||||
pixel = &data->bitmap[--y * info->width];
|
||||
break;
|
||||
case 1: // end of bitmap
|
||||
x = info->width;
|
||||
y = 0;
|
||||
pixel = NULL;
|
||||
break;
|
||||
case 2: // delta
|
||||
x += ReadByte(buffer);
|
||||
i = ReadByte(buffer);
|
||||
if (x >= info->width || (y == 0 && i > 0)) return false;
|
||||
y -= i;
|
||||
pixel = &data->bitmap[y * info->width + x];
|
||||
break;
|
||||
default: // uncompressed
|
||||
if ((x += c) > info->width) return false;
|
||||
for (i = 0; i < c; i++) *pixel++ = ReadByte(buffer);
|
||||
/* Padding for 16 bit align */
|
||||
SkipBytes(buffer, c % 2);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Apparently it is common to encounter BMPs where the count of
|
||||
* pixels to be written is higher than the remaining line width.
|
||||
* Ignore the superfluous pixels instead of reporting an error. */
|
||||
for (uint i = 0; x < info->width && i < n; i++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
if (x >= info->width) return false;
|
||||
*pixel++ = c;
|
||||
x++;
|
||||
}
|
||||
@@ -320,7 +278,6 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
{
|
||||
uint32 header_size;
|
||||
assert(info != NULL);
|
||||
MemSetT(info, 0);
|
||||
|
||||
/* Reading BMP header */
|
||||
if (ReadWord(buffer) != 0x4D42) return false; // signature should be 'BM'
|
||||
@@ -363,15 +320,16 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
if (info->bpp <= 8) {
|
||||
uint i;
|
||||
|
||||
/* Reads number of colours if available in info header */
|
||||
/* Reads number of colors if available in info header */
|
||||
if (header_size >= 16) {
|
||||
SkipBytes(buffer, 12); // skip image size and resolution
|
||||
info->palette_size = ReadDword(buffer); // number of colours in palette
|
||||
info->palette_size = ReadDword(buffer); // number of colors in palette
|
||||
SkipBytes(buffer, header_size - 16); // skip the end of info header
|
||||
}
|
||||
if (info->palette_size == 0) info->palette_size = 1 << info->bpp;
|
||||
|
||||
data->palette = CallocT<Colour>(info->palette_size);
|
||||
data->palette = calloc(info->palette_size, sizeof(*(data->palette)));
|
||||
if (data->palette == NULL) return false;
|
||||
|
||||
for (i = 0; i < info->palette_size; i++) {
|
||||
data->palette[i].b = ReadByte(buffer);
|
||||
@@ -392,7 +350,8 @@ bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
{
|
||||
assert(info != NULL && data != NULL);
|
||||
|
||||
data->bitmap = CallocT<byte>(info->width * info->height * ((info->bpp == 24) ? 3 : 1));
|
||||
data->bitmap = calloc(info->width * info->height, ((info->bpp == 24) ? 3 : 1) * sizeof(byte));
|
||||
if (data->bitmap == NULL) return false;
|
||||
|
||||
/* Load image */
|
||||
SetStreamOffset(buffer, info->offset);
|
||||
@@ -403,11 +362,11 @@ bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||
case 4: return BmpRead4(buffer, info, data);
|
||||
case 8: return BmpRead8(buffer, info, data);
|
||||
case 24: return BmpRead24(buffer, info, data);
|
||||
default: NOT_REACHED();
|
||||
default: NOT_REACHED(); return false;
|
||||
}
|
||||
case 1: return BmpRead8Rle(buffer, info, data); // 8-bit RLE compression
|
||||
case 2: return BmpRead4Rle(buffer, info, data); // 4-bit RLE compression
|
||||
default: NOT_REACHED();
|
||||
default: NOT_REACHED(); return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,43 +1,32 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file bmp.h Read and write support for bmps. */
|
||||
|
||||
#ifndef BMP_H
|
||||
#define BMP_H
|
||||
|
||||
#include "gfx_type.h"
|
||||
|
||||
struct BmpInfo {
|
||||
typedef struct {
|
||||
uint32 offset; ///< offset of bitmap data from .bmp file begining
|
||||
uint32 width; ///< bitmap width
|
||||
uint32 height; ///< bitmap height
|
||||
bool os2_bmp; ///< true if OS/2 1.x or windows 2.x bitmap
|
||||
uint16 bpp; ///< bits per pixel
|
||||
uint32 compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
|
||||
uint32 palette_size; ///< number of colours in palette
|
||||
};
|
||||
uint32 palette_size; ///< number of colors in palette
|
||||
} BmpInfo;
|
||||
|
||||
struct BmpData {
|
||||
typedef struct {
|
||||
Colour *palette;
|
||||
byte *bitmap;
|
||||
};
|
||||
} BmpData;
|
||||
|
||||
#define BMP_BUFFER_SIZE 1024
|
||||
|
||||
struct BmpBuffer {
|
||||
typedef struct {
|
||||
byte data[BMP_BUFFER_SIZE];
|
||||
int pos;
|
||||
int read;
|
||||
FILE *file;
|
||||
uint real_pos;
|
||||
};
|
||||
} BmpBuffer;
|
||||
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file);
|
||||
bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data);
|
32
bridge.h
Normal file
32
bridge.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bridge.h Header file for bridges */
|
||||
|
||||
#ifndef BRIDGE_H
|
||||
#define BRIDGE_H
|
||||
|
||||
enum {
|
||||
MAX_BRIDGES = 13
|
||||
};
|
||||
|
||||
/** Struct containing information about a single bridge type
|
||||
*/
|
||||
typedef struct Bridge {
|
||||
Year avail_year; ///< the year in which the bridge becomes available
|
||||
byte min_length; ///< the minimum length of the bridge (not counting start and end tile)
|
||||
byte max_length; ///< the maximum length of the bridge (not counting start and end tile)
|
||||
uint16 price; ///< the relative price of the bridge
|
||||
uint16 speed; ///< maximum travel speed
|
||||
PalSpriteID sprite; ///< the sprite which is used in the GUI (possibly with a recolor sprite)
|
||||
StringID material; ///< the string that contains the bridge description
|
||||
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
|
||||
byte flags; ///< bit 0 set: disable drawing of far pillars.
|
||||
} Bridge;
|
||||
|
||||
extern const Bridge orig_bridge[MAX_BRIDGES];
|
||||
extern Bridge _bridge[MAX_BRIDGES];
|
||||
|
||||
uint GetBridgeFoundation(Slope tileh, Axis axis);
|
||||
uint GetBridgeHeightRamp(TileIndex t);
|
||||
|
||||
#endif /* BRIDGE_H */
|
167
bridge_gui.c
Normal file
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);
|
||||
SetDParam(0, b->material);
|
||||
DrawSprite(b->sprite, 3, 15 + i * 22);
|
||||
|
||||
DrawString(44, 15 + i * 22 , STR_500D, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
uint i = e->we.keypress.keycode - '1';
|
||||
if (i < 9 && i < _bridgedata.count) {
|
||||
e->we.keypress.cont = false;
|
||||
BuildBridge(w, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->we.click.widget == 2) {
|
||||
uint ind = ((int)e->we.click.pt.y - 14) / 22;
|
||||
if (ind < 4 && (ind += w->vscroll.pos) < _bridgedata.count)
|
||||
BuildBridge(w, ind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_bridge_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 200, 102,
|
||||
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
static const Widget _build_road_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_road_bridge_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 200, 102,
|
||||
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_road_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, byte bridge_type)
|
||||
{
|
||||
uint j = 0;
|
||||
int32 ret;
|
||||
StringID errmsg;
|
||||
|
||||
DeleteWindowById(WC_BUILD_BRIDGE, 0);
|
||||
|
||||
_bridgedata.type = bridge_type;
|
||||
_bridgedata.start_tile = start;
|
||||
_bridgedata.end_tile = end;
|
||||
|
||||
errmsg = INVALID_STRING_ID;
|
||||
|
||||
// only query bridge building possibility once, result is the same for all bridges!
|
||||
// returns CMD_ERROR on failure, and price on success
|
||||
ret = DoCommand(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
errmsg = _error_message;
|
||||
} else {
|
||||
// check which bridges can be built
|
||||
int bridge_len; // length of the middle parts of the bridge
|
||||
int tot_bridgedata_len; // total length of bridge
|
||||
|
||||
// get absolute bridge length
|
||||
bridge_len = GetBridgeLength(start, end);
|
||||
tot_bridgedata_len = bridge_len + 2;
|
||||
|
||||
tot_bridgedata_len = CalcBridgeLenCostFactor(tot_bridgedata_len);
|
||||
|
||||
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
const Bridge *b = &_bridge[bridge_type];
|
||||
// bridge is accepted, add to list
|
||||
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
|
||||
_bridgedata.costs[j] = ret + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
|
||||
_bridgedata.indexes[j] = bridge_type;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bridgedata.count = j;
|
||||
|
||||
if (j != 0) {
|
||||
Window *w = AllocateWindowDesc((_bridgedata.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
|
||||
w->vscroll.cap = 4;
|
||||
w->vscroll.count = (byte)j;
|
||||
} else {
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
|
||||
}
|
||||
}
|
37
bridge_map.c
Normal file
37
bridge_map.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "bridge_map.h"
|
||||
|
||||
|
||||
TileIndex GetBridgeEnd(TileIndex tile, DiagDirection dir)
|
||||
{
|
||||
TileIndexDiff delta = TileOffsByDiagDir(dir);
|
||||
|
||||
assert(DiagDirToAxis(dir) == GetBridgeAxis(tile));
|
||||
|
||||
do {
|
||||
tile += delta;
|
||||
} while (!IsBridgeRamp(tile));
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
|
||||
TileIndex GetSouthernBridgeEnd(TileIndex t)
|
||||
{
|
||||
return GetBridgeEnd(t, AxisToDiagDir(GetBridgeAxis(t)));
|
||||
}
|
||||
|
||||
|
||||
TileIndex GetOtherBridgeEnd(TileIndex tile)
|
||||
{
|
||||
TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
|
||||
|
||||
do {
|
||||
tile += delta;
|
||||
} while (!IsBridgeRamp(tile));
|
||||
|
||||
return tile;
|
||||
}
|
235
bridge_map.h
Normal file
235
bridge_map.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef BRIDGE_MAP_H
|
||||
#define BRIDGE_MAP_H
|
||||
|
||||
#include "direction.h"
|
||||
#include "macros.h"
|
||||
#include "map.h"
|
||||
#include "rail.h"
|
||||
#include "road_map.h"
|
||||
#include "tile.h"
|
||||
|
||||
|
||||
static inline bool IsBridge(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_TUNNELBRIDGE));
|
||||
return HASBIT(_m[t].m5, 7);
|
||||
}
|
||||
|
||||
static inline bool IsBridgeTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_TUNNELBRIDGE) && IsBridge(t);
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsBridgeRamp(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return !HASBIT(_m[t].m5, 6);
|
||||
}
|
||||
|
||||
static inline bool IsBridgeMiddle(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return HASBIT(_m[t].m5, 6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines which piece of a bridge is contained in the current tile
|
||||
* @param tile The tile to analyze
|
||||
* @return the piece
|
||||
*/
|
||||
static inline uint GetBridgePiece(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return GB(_m[t].m2, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the type of bridge on a tile
|
||||
* @param tile The tile to analyze
|
||||
* @return The bridge type
|
||||
*/
|
||||
static inline uint GetBridgeType(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return GB(_m[t].m2, 4, 4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the direction pointing onto the bridge
|
||||
*/
|
||||
static inline DiagDirection GetBridgeRampDirection(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeRamp(t));
|
||||
return ReverseDiagDir(XYNSToDiagDir((Axis)GB(_m[t].m5, 0, 1), GB(_m[t].m5, 5, 1)));
|
||||
}
|
||||
|
||||
|
||||
static inline Axis GetBridgeAxis(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return (Axis)GB(_m[t].m5, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
static inline TransportType GetBridgeTransportType(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return (TransportType)GB(_m[t].m5, 1, 2);
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsClearUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return GB(_m[t].m5, 3, 3) == 0;
|
||||
}
|
||||
|
||||
static inline bool IsWaterUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return GB(_m[t].m5, 3, 3) == 1;
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsTransportUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return HASBIT(_m[t].m5, 5);
|
||||
}
|
||||
|
||||
static inline TransportType GetTransportTypeUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsTransportUnderBridge(t));
|
||||
return (TransportType)GB(_m[t].m5, 3, 2);
|
||||
}
|
||||
|
||||
static inline RoadBits GetRoadBitsUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(GetTransportTypeUnderBridge(t) == TRANSPORT_ROAD);
|
||||
return GetBridgeAxis(t) == AXIS_X ? ROAD_Y : ROAD_X;
|
||||
}
|
||||
|
||||
static inline Track GetRailUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL);
|
||||
return AxisToTrack(OtherAxis(GetBridgeAxis(t)));
|
||||
}
|
||||
|
||||
static inline TrackBits GetRailBitsUnderBridge(TileIndex t)
|
||||
{
|
||||
return TrackToTrackBits(GetRailUnderBridge(t));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the end of a bridge in the specified direction starting at a middle tile
|
||||
*/
|
||||
TileIndex GetBridgeEnd(TileIndex, DiagDirection);
|
||||
|
||||
/**
|
||||
* Finds the southern end of a bridge starting at a middle tile
|
||||
*/
|
||||
TileIndex GetSouthernBridgeEnd(TileIndex t);
|
||||
|
||||
|
||||
/**
|
||||
* Starting at one bridge end finds the other bridge end
|
||||
*/
|
||||
TileIndex GetOtherBridgeEnd(TileIndex);
|
||||
|
||||
uint GetBridgeHeight(TileIndex t);
|
||||
|
||||
static inline void SetClearUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
SetTileOwner(t, OWNER_NONE);
|
||||
SB(_m[t].m5, 3, 3, 0 << 2 | 0);
|
||||
SB(_m[t].m3, 0, 4, 0);
|
||||
}
|
||||
|
||||
static inline void SetWaterUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
SetTileOwner(t, OWNER_WATER);
|
||||
SB(_m[t].m5, 3, 3, 0 << 2 | 1);
|
||||
SB(_m[t].m3, 0, 4, 0);
|
||||
}
|
||||
|
||||
static inline void SetCanalUnderBridge(TileIndex t, Owner o)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
SetTileOwner(t, o);
|
||||
SB(_m[t].m5, 3, 3, 0 << 2 | 1);
|
||||
SB(_m[t].m3, 0, 4, 0);
|
||||
}
|
||||
|
||||
static inline void SetRailUnderBridge(TileIndex t, Owner o, RailType r)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
SetTileOwner(t, o);
|
||||
SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_RAIL);
|
||||
SB(_m[t].m3, 0, 4, r);
|
||||
}
|
||||
|
||||
static inline void SetRoadUnderBridge(TileIndex t, Owner o)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
SetTileOwner(t, o);
|
||||
SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_ROAD);
|
||||
SB(_m[t].m3, 0, 4, 0);
|
||||
}
|
||||
|
||||
|
||||
static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt)
|
||||
{
|
||||
uint northsouth = (d == DIAGDIR_NE || d == DIAGDIR_NW);
|
||||
|
||||
SetTileType(t, MP_TUNNELBRIDGE);
|
||||
SetTileOwner(t, o);
|
||||
_m[t].m2 = bridgetype << 4;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m5 = 1 << 7 | 0 << 6 | northsouth << 5 | tt << 1 | DiagDirToAxis(d);
|
||||
}
|
||||
|
||||
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d)
|
||||
{
|
||||
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD);
|
||||
_m[t].m3 = 0;
|
||||
}
|
||||
|
||||
static inline void MakeRailBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RailType r)
|
||||
{
|
||||
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL);
|
||||
_m[t].m3 = r;
|
||||
}
|
||||
|
||||
|
||||
static inline void MakeBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, TransportType tt)
|
||||
{
|
||||
SetTileType(t, MP_TUNNELBRIDGE);
|
||||
SetTileOwner(t, OWNER_NONE);
|
||||
_m[t].m2 = bridgetype << 4 | piece;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m5 = 1 << 7 | 1 << 6 | 0 << 5 | 0 << 3 | tt << 1 | a;
|
||||
}
|
||||
|
||||
static inline void MakeRoadBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a)
|
||||
{
|
||||
MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_ROAD);
|
||||
}
|
||||
|
||||
static inline void MakeRailBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, RailType r)
|
||||
{
|
||||
MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_RAIL);
|
||||
SB(_m[t].m3, 4, 4, r);
|
||||
}
|
||||
|
||||
|
||||
#endif /* BRIDGE_MAP_H */
|
492
build_vehicle_gui.c
Normal file
492
build_vehicle_gui.c
Normal file
@@ -0,0 +1,492 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "aircraft.h"
|
||||
#include "debug.h"
|
||||
#include "functions.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "vehicle.h"
|
||||
#include "gfx.h"
|
||||
#include "station.h"
|
||||
#include "command.h"
|
||||
#include "engine.h"
|
||||
#include "player.h"
|
||||
#include "depot.h"
|
||||
#include "airport.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "date.h"
|
||||
#include "strings.h"
|
||||
|
||||
|
||||
enum BuildVehicleWidgets {
|
||||
BUILD_VEHICLE_WIDGET_CLOSEBOX = 0,
|
||||
BUILD_VEHICLE_WIDGET_CAPTION,
|
||||
BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING,
|
||||
BUILD_VEHICLE_WIDGET_SORT_TEXT,
|
||||
BUILD_VEHICLE_WIDGET_SORT_DROPDOWN,
|
||||
BUILD_VEHICLE_WIDGET_LIST,
|
||||
BUILD_VEHICLE_WIDGET_SCROLLBAR,
|
||||
BUILD_VEHICLE_WIDGET_PANEL,
|
||||
BUILD_VEHICLE_WIDGET_BUILD,
|
||||
BUILD_VEHICLE_WIDGET_RENAME,
|
||||
BUILD_VEHICLE_WIDGET_RESIZE,
|
||||
};
|
||||
|
||||
static const Widget _build_vehicle_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
|
||||
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 239, 0, 13, STR_A005_NEW_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS },
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 81, 227, 14, 25, 0x0, STR_SORT_CRITERIA_TIP},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 228, 239, 14, 25, STR_0225, STR_SORT_CRITERIA_TIP},
|
||||
{ WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 227, 26, 121, 0x401, STR_A025_AIRCRAFT_SELECTION_LIST },
|
||||
{ WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 228, 239, 26, 121, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST },
|
||||
{ WWT_PANEL, RESIZE_TB, 14, 0, 239, 122, 213, 0x0, STR_NULL },
|
||||
|
||||
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 114, 214, 225, STR_A006_BUILD_AIRCRAFT, STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT },
|
||||
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 115, 227, 214, 225, STR_A037_RENAME, STR_A038_RENAME_AIRCRAFT_TYPE },
|
||||
{ WWT_RESIZEBOX, RESIZE_TB, 14, 228, 239, 214, 225, 0x0, STR_RESIZE_BUTTON },
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static bool _internal_sort_order; // descending/ascending
|
||||
static byte _last_sort_criteria = 0;
|
||||
static bool _last_sort_order = false;
|
||||
|
||||
static int CDECL EngineNumberSorter(const void *a, const void *b)
|
||||
{
|
||||
const EngineID va = *(const EngineID*)a;
|
||||
const EngineID vb = *(const EngineID*)b;
|
||||
int r = va - vb;
|
||||
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL EngineIntroDateSorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = GetEngine(*(const EngineID*)a)->intro_date;
|
||||
const int vb = GetEngine(*(const EngineID*)b)->intro_date;
|
||||
const int r = va - vb;
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL EngineNameSorter(const void *a, const void *b)
|
||||
{
|
||||
static EngineID last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE };
|
||||
static char last_name[2][64] = { "\0", "\0" };
|
||||
|
||||
const EngineID va = *(const EngineID*)a;
|
||||
const EngineID vb = *(const EngineID*)b;
|
||||
int r;
|
||||
|
||||
if (va != last_engine[0]) {
|
||||
last_engine[0] = va;
|
||||
GetString(last_name[0], GetCustomEngineName(va), lastof(last_name[0]));
|
||||
}
|
||||
|
||||
if (vb != last_engine[1]) {
|
||||
last_engine[1] = vb;
|
||||
GetString(last_name[1], GetCustomEngineName(vb), lastof(last_name[1]));
|
||||
}
|
||||
|
||||
r = strcmp(last_name[0], last_name[1]); // sort by name
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL EngineReliabilitySorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = GetEngine(*(const EngineID*)a)->reliability;
|
||||
const int vb = GetEngine(*(const EngineID*)b)->reliability;
|
||||
const int r = va - vb;
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
/* Aircraft sorting functions */
|
||||
|
||||
static int CDECL AircraftEngineCostSorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost;
|
||||
const int vb = AircraftVehInfo(*(const EngineID*)b)->base_cost;
|
||||
int r = va - vb;
|
||||
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL AircraftEngineSpeedSorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = AircraftVehInfo(*(const EngineID*)a)->max_speed;
|
||||
const int vb = AircraftVehInfo(*(const EngineID*)b)->max_speed;
|
||||
const int r = va - vb;
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL AircraftEngineRunningCostSorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = AircraftVehInfo(*(const EngineID*)a)->running_cost;
|
||||
const int vb = AircraftVehInfo(*(const EngineID*)b)->running_cost;
|
||||
const int r = va - vb;
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static int CDECL AircraftEngineCargoSorter(const void *a, const void *b)
|
||||
{
|
||||
const int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity;
|
||||
const int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity;
|
||||
const int r = va - vb;
|
||||
|
||||
if (r == 0) {
|
||||
/* Use EngineID to sort instead since we want consistent sorting */
|
||||
return EngineNumberSorter(a, b);
|
||||
}
|
||||
return _internal_sort_order ? -r : r;
|
||||
}
|
||||
|
||||
static EngList_SortTypeFunction * const _aircraft_sorter[] = {
|
||||
&EngineNumberSorter,
|
||||
&AircraftEngineCostSorter,
|
||||
&AircraftEngineSpeedSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&AircraftEngineRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&AircraftEngineCargoSorter,
|
||||
};
|
||||
|
||||
static const StringID _aircraft_sort_listing[] = {
|
||||
STR_ENGINE_SORT_ENGINE_ID,
|
||||
STR_ENGINE_SORT_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_ENGINE_SORT_INTRO_DATE,
|
||||
STR_SORT_BY_DROPDOWN_NAME,
|
||||
STR_ENGINE_SORT_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_ENGINE_SORT_CARGO_CAPACITY,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Draw the purchase info details of an aircraft at a given location.
|
||||
* @param x,y location where to draw the info
|
||||
* @param engine_number the engine of which to draw the info of
|
||||
*/
|
||||
void DrawAircraftPurchaseInfo(int x, int y, uint w, EngineID engine_number)
|
||||
{
|
||||
const AircraftVehicleInfo *avi = AircraftVehInfo(engine_number);
|
||||
const Engine *e = GetEngine(engine_number);
|
||||
CargoID cargo;
|
||||
YearMonthDay ymd;
|
||||
ConvertDateToYMD(e->intro_date, &ymd);
|
||||
|
||||
/* Purchase cost - Max speed */
|
||||
SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
|
||||
SetDParam(1, avi->max_speed * 128 / 10);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
|
||||
y += 10;
|
||||
|
||||
/* Cargo capacity */
|
||||
cargo = FindFirstRefittableCargo(engine_number);
|
||||
if (cargo == CT_INVALID || cargo == CT_PASSENGERS) {
|
||||
SetDParam(0, avi->passenger_capacity);
|
||||
SetDParam(1, avi->mail_capacity);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY, 0);
|
||||
} else {
|
||||
/* Note, if the default capacity is selected by the refit capacity
|
||||
* callback, then the capacity shown is likely to be incorrect. */
|
||||
SetDParam(0, cargo);
|
||||
SetDParam(1, AircraftDefaultCargoCapacity(cargo, engine_number));
|
||||
SetDParam(2, STR_9842_REFITTABLE);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
|
||||
}
|
||||
y += 10;
|
||||
|
||||
/* Running cost */
|
||||
SetDParam(0, avi->running_cost * _price.aircraft_running >> 8);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
|
||||
y += 10;
|
||||
|
||||
/* Design date - Life length */
|
||||
SetDParam(0, ymd.year);
|
||||
SetDParam(1, e->lifelength);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_DESIGNED_LIFE, 0);
|
||||
y += 10;
|
||||
|
||||
/* Reliability */
|
||||
SetDParam(0, e->reliability * 100 >> 16);
|
||||
DrawString(x, y, STR_PURCHASE_INFO_RELIABILITY, 0);
|
||||
y += 10;
|
||||
|
||||
/* Additional text from NewGRF */
|
||||
y += ShowAdditionalText(x, y, w, engine_number);
|
||||
y += ShowRefitOptionsList(x, y, w, engine_number);
|
||||
}
|
||||
|
||||
void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection)
|
||||
{
|
||||
PalSpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
|
||||
DrawSprite(GetAircraftImage(v, DIR_W) | pal, x + 25, y + 10);
|
||||
if (v->subtype == 0) {
|
||||
SpriteID rotor_sprite = GetCustomRotorSprite(v, true);
|
||||
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
|
||||
DrawSprite(rotor_sprite, x + 25, y + 5);
|
||||
}
|
||||
if (v->index == selection) {
|
||||
DrawFrameRect(x - 1, y - 1, x + 58, y + 21, 0xF, FR_BORDERONLY);
|
||||
}
|
||||
}
|
||||
|
||||
void CcBuildAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
const Vehicle *v = GetVehicle(_new_vehicle_id);
|
||||
|
||||
if (v->tile == _backup_orders_tile) {
|
||||
_backup_orders_tile = 0;
|
||||
RestoreVehicleOrders(v, _backup_orders_data);
|
||||
}
|
||||
ShowAircraftViewWindow(v);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBuildAircraftList(Window *w)
|
||||
{
|
||||
EngineID eid, sel_id;
|
||||
buildvehicle_d *bv = &WP(w, buildvehicle_d);
|
||||
|
||||
EngList_RemoveAll(&bv->eng_list);
|
||||
|
||||
/* Make list of all available planes.
|
||||
* Also check to see if the previously selected plane is still available,
|
||||
* and if not, reset selection to INVALID_ENGINE. This could be the case
|
||||
* when planes become obsolete and are removed */
|
||||
sel_id = INVALID_ENGINE;
|
||||
for (eid = AIRCRAFT_ENGINES_INDEX; eid < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; eid++) {
|
||||
if (IsEngineBuildable(eid, VEH_Aircraft, _local_player)) {
|
||||
const AircraftVehicleInfo *avi = AircraftVehInfo(eid);
|
||||
switch (bv->filter.acc_planes) {
|
||||
case HELICOPTERS_ONLY:
|
||||
if (avi->subtype != 0) continue; // if not helicopter
|
||||
break;
|
||||
|
||||
case AIRCRAFT_ONLY:
|
||||
if (avi->subtype == 0) continue; // if helicopter
|
||||
break;
|
||||
|
||||
case ALL: break;
|
||||
}
|
||||
EngList_Add(&bv->eng_list, eid);
|
||||
|
||||
if (eid == bv->sel_engine) sel_id = eid;
|
||||
}
|
||||
}
|
||||
|
||||
bv->sel_engine = sel_id;
|
||||
}
|
||||
|
||||
static void GenerateBuildList(Window *w)
|
||||
{
|
||||
buildvehicle_d *bv = &WP(w, buildvehicle_d);
|
||||
|
||||
switch (bv->vehicle_type) {
|
||||
case VEH_Aircraft:
|
||||
GenerateBuildAircraftList(w);
|
||||
_internal_sort_order = bv->descending_sort_order;
|
||||
EngList_Sort(&bv->eng_list, _aircraft_sorter[bv->sort_criteria]);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawBuildAircraftWindow(Window *w)
|
||||
{
|
||||
const buildvehicle_d *bv = &WP(w, buildvehicle_d);
|
||||
|
||||
SetWindowWidgetDisabledState(w, BUILD_VEHICLE_WIDGET_BUILD, w->window_number == 0);
|
||||
|
||||
SetVScrollCount(w, EngList_Count(&bv->eng_list));
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
{
|
||||
int x = 2;
|
||||
int y = 27;
|
||||
EngineID selected_id = bv->sel_engine;
|
||||
EngineID eid = w->vscroll.pos;
|
||||
uint16 max = min(w->vscroll.pos + w->vscroll.cap, EngList_Count(&bv->eng_list));
|
||||
|
||||
for (; eid < max; eid++) {
|
||||
const EngineID engine = bv->eng_list[eid];
|
||||
|
||||
DrawString(x + 62, y + 7, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10);
|
||||
DrawAircraftEngine(x + 29, y + 10, engine, GetEnginePalette(engine, _local_player));
|
||||
y += 24;
|
||||
}
|
||||
|
||||
if (selected_id != INVALID_ENGINE) {
|
||||
const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
|
||||
DrawAircraftPurchaseInfo(x, wi->top + 1, wi->right - wi->left - 2, selected_id);
|
||||
}
|
||||
}
|
||||
DrawString(85, 15, _aircraft_sort_listing[bv->sort_criteria], 0x10);
|
||||
DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10);
|
||||
}
|
||||
|
||||
static void BuildAircraftClickEvent(Window *w, WindowEvent *e)
|
||||
{
|
||||
buildvehicle_d *bv = &WP(w, buildvehicle_d);
|
||||
|
||||
switch (e->we.click.widget) {
|
||||
case BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING:
|
||||
bv->descending_sort_order ^= true;
|
||||
_last_sort_order = bv->descending_sort_order;
|
||||
GenerateBuildList(w);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
|
||||
case BUILD_VEHICLE_WIDGET_LIST: {
|
||||
uint i = (e->we.click.pt.y - 26) / 24 + w->vscroll.pos;
|
||||
uint num_items = EngList_Count(&bv->eng_list);
|
||||
bv->sel_engine = (i < num_items) ? bv->eng_list[i] : INVALID_ENGINE;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
|
||||
case BUILD_VEHICLE_WIDGET_SORT_TEXT: case BUILD_VEHICLE_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */
|
||||
ShowDropDownMenu(w, _aircraft_sort_listing, bv->sort_criteria, BUILD_VEHICLE_WIDGET_SORT_DROPDOWN, 0, 0);
|
||||
return;
|
||||
|
||||
case BUILD_VEHICLE_WIDGET_BUILD: {
|
||||
EngineID sel_eng = bv->sel_engine;
|
||||
if (sel_eng != INVALID_ENGINE) {
|
||||
DoCommandP(w->window_number, sel_eng, 0, CcBuildAircraft, CMD_BUILD_AIRCRAFT | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BUILD_VEHICLE_WIDGET_RENAME: {
|
||||
EngineID sel_eng = bv->sel_engine;
|
||||
if (sel_eng != INVALID_ENGINE) {
|
||||
bv->rename_engine = sel_eng;
|
||||
ShowQueryString(GetCustomEngineName(sel_eng), STR_A039_RENAME_AIRCRAFT_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void NewAircraftWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
buildvehicle_d *bv = &WP(w, buildvehicle_d);
|
||||
|
||||
switch (e->event) {
|
||||
case WE_INVALIDATE_DATA:
|
||||
GenerateBuildList(w);
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
EngList_Destroy(&bv->eng_list);
|
||||
break;
|
||||
|
||||
case WE_PAINT:
|
||||
DrawBuildAircraftWindow(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
BuildAircraftClickEvent(w, e);
|
||||
break;
|
||||
|
||||
case WE_ON_EDIT_TEXT: {
|
||||
if (e->we.edittext.str[0] != '\0') {
|
||||
_cmd_text = e->we.edittext.str;
|
||||
DoCommandP(0, bv->rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
|
||||
if (bv->sort_criteria != e->we.dropdown.index) {
|
||||
bv->sort_criteria = _last_sort_criteria = e->we.dropdown.index;
|
||||
GenerateBuildList(w);
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
|
||||
case WE_RESIZE:
|
||||
w->vscroll.cap += e->we.sizing.diff.y / 24;
|
||||
w->widget[BUILD_VEHICLE_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const WindowDesc _build_vehicle_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 240, 226,
|
||||
WC_BUILD_VEHICLE,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
|
||||
_build_vehicle_widgets,
|
||||
NewAircraftWndProc
|
||||
};
|
||||
|
||||
void ShowBuildVehicleWindow(TileIndex tile, byte type)
|
||||
{
|
||||
buildvehicle_d *bv;
|
||||
Window *w;
|
||||
|
||||
DeleteWindowById(WC_BUILD_VEHICLE, tile);
|
||||
w = AllocateWindowDescFront(&_build_vehicle_desc, tile);
|
||||
if (w == NULL) return;
|
||||
|
||||
w->caption_color = (tile != 0) ? GetTileOwner(tile) : _local_player;
|
||||
w->resize.step_height = GetVehicleListHeight(type);
|
||||
w->vscroll.cap = 4;
|
||||
w->widget[BUILD_VEHICLE_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
|
||||
|
||||
bv = &WP(w, buildvehicle_d);
|
||||
EngList_Create(&bv->eng_list);
|
||||
bv->sel_engine = INVALID_ENGINE;
|
||||
bv->sort_criteria = _last_sort_criteria;
|
||||
bv->descending_sort_order = _last_sort_order;
|
||||
|
||||
bv->vehicle_type = type;
|
||||
|
||||
switch (type) {
|
||||
case VEH_Aircraft: {
|
||||
byte acc_planes = (tile == 0) ? ALL : GetAirport(GetStationByTile(tile)->airport_type)->acc_planes;
|
||||
bv->filter.acc_planes = acc_planes;
|
||||
break;
|
||||
}
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
GenerateBuildList(w);
|
||||
/* Select the first plane in the list as default when opening the window */
|
||||
if (EngList_Count(&bv->eng_list) > 0) bv->sel_engine = bv->eng_list[0];
|
||||
}
|
93
callback_table.c
Normal file
93
callback_table.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* $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;
|
||||
|
||||
/* depot_gui.c */
|
||||
CommandCallback CcCloneVehicle;
|
||||
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
CommandCallback CcBuildTown;
|
||||
CommandCallback CcGiveMoney;
|
||||
|
||||
/* 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 CcAI;
|
||||
|
||||
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,
|
||||
/* 0x19 */ CcAI,
|
||||
/* 0x1A */ CcCloneVehicle,
|
||||
/* 0x1B */ CcGiveMoney,
|
||||
};
|
||||
|
||||
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 "command.h"
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
|
||||
#endif /* CALLBACK_TABLE_H */
|
6007
changelog.txt
6007
changelog.txt
File diff suppressed because it is too large
Load Diff
802
clear_cmd.c
Normal file
802
clear_cmd.c
Normal file
@@ -0,0 +1,802 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "clear_map.h"
|
||||
#include "rail_map.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "tunnel_map.h"
|
||||
#include "variables.h"
|
||||
#include "table/sprites.h"
|
||||
#include "unmovable_map.h"
|
||||
#include "genworld.h"
|
||||
#include "industry.h"
|
||||
#include "water_map.h"
|
||||
|
||||
typedef struct TerraformerHeightMod {
|
||||
TileIndex tile;
|
||||
byte height;
|
||||
} TerraformerHeightMod;
|
||||
|
||||
typedef struct TerraformerState {
|
||||
int height[4];
|
||||
uint32 flags;
|
||||
|
||||
int direction;
|
||||
int modheight_count;
|
||||
int tile_table_count;
|
||||
|
||||
int32 cost;
|
||||
|
||||
TileIndex *tile_table;
|
||||
TerraformerHeightMod *modheight;
|
||||
|
||||
} TerraformerState;
|
||||
|
||||
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TileIndex *t;
|
||||
int count;
|
||||
|
||||
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) return -1;
|
||||
|
||||
t = ts->tile_table;
|
||||
for (count = ts->tile_table_count; count != 0; count--, t++) {
|
||||
if (*t == tile) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformerHeightMod *mod = ts->modheight;
|
||||
int count;
|
||||
|
||||
for (count = ts->modheight_count; count != 0; count--, mod++) {
|
||||
if (mod->tile == tile) return mod->height;
|
||||
}
|
||||
|
||||
return TileHeight(tile);
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
int count;
|
||||
TileIndex *t;
|
||||
|
||||
count = ts->tile_table_count;
|
||||
|
||||
if (count >= 625) return;
|
||||
|
||||
for (t = ts->tile_table; count != 0; count--,t++) {
|
||||
if (*t == tile) return;
|
||||
}
|
||||
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, 0));
|
||||
TerraformAddDirtyTile(ts, tile);
|
||||
}
|
||||
|
||||
static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
|
||||
{
|
||||
int r;
|
||||
int32 ret;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
r = TerraformAllowTileProcess(ts, tile);
|
||||
if (r <= 0) return r;
|
||||
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
static const TrackBits safe_track[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
|
||||
static const Slope unsafe_slope[] = { SLOPE_S, SLOPE_W, SLOPE_N, SLOPE_E };
|
||||
|
||||
Slope tileh;
|
||||
uint z;
|
||||
|
||||
// Nothing could be built at the steep slope - this avoids a bug
|
||||
// when you have a single diagonal track in one corner on a
|
||||
// basement and then you raise/lower the other corner.
|
||||
tileh = GetTileSlope(tile, &z);
|
||||
if (tileh == unsafe_slope[mode] ||
|
||||
tileh == (SLOPE_STEEP | ComplementSlope(unsafe_slope[mode]))) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If we have a single diagonal track there, the other side of
|
||||
// tile can be terraformed.
|
||||
if (IsPlainRailTile(tile) && GetTrackBits(tile) == safe_track[mode]) {
|
||||
/* If terraforming downwards prevent damaging a potential tunnel below.
|
||||
* This check is only necessary for flat tiles, because if the tile is
|
||||
* non-flat, then the corner opposing the rail is raised. Only this corner
|
||||
* can be lowered and this is a safe action
|
||||
*/
|
||||
if (tileh == SLOPE_FLAT &&
|
||||
ts->direction == -1 &&
|
||||
IsTunnelInWay(tile, z - TILE_HEIGHT)) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1002_EXCAVATION_WOULD_DAMAGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Canals can't be terraformed */
|
||||
if (IsClearWaterTile(tile) && IsCanal(tile)) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_MUST_DEMOLISH_CANAL_FIRST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
_terraform_err_tile = tile;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ts->cost += ret;
|
||||
|
||||
if (ts->tile_table_count >= 625) return -1;
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height)
|
||||
{
|
||||
int nh;
|
||||
TerraformerHeightMod *mod;
|
||||
int count;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if (height < 0) {
|
||||
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
|
||||
return false;
|
||||
}
|
||||
|
||||
_error_message = STR_1004_TOO_HIGH;
|
||||
|
||||
if (height > 15) return false;
|
||||
|
||||
nh = TerraformGetHeightOfTile(ts, tile);
|
||||
if (nh < 0 || height == nh) return false;
|
||||
|
||||
if (TerraformProc(ts, tile, 0) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
|
||||
|
||||
mod = ts->modheight;
|
||||
count = ts->modheight_count;
|
||||
|
||||
for (;;) {
|
||||
if (count == 0) {
|
||||
if (ts->modheight_count >= 576) return false;
|
||||
ts->modheight_count++;
|
||||
break;
|
||||
}
|
||||
if (mod->tile == tile) break;
|
||||
mod++;
|
||||
count--;
|
||||
}
|
||||
|
||||
mod->tile = tile;
|
||||
mod->height = (byte)height;
|
||||
|
||||
ts->cost += _price.terraform;
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for (ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
if (!TerraformTileHeight(ts, tile, r+direction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Terraform land
|
||||
* @param tile tile to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
int32 CmdTerraformLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
TileIndex t;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
TileIndex tile_table_data[625];
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_terraform_err_tile = 0;
|
||||
|
||||
ts.direction = direction = p2 ? 1 : -1;
|
||||
ts.flags = flags;
|
||||
ts.modheight_count = ts.tile_table_count = 0;
|
||||
ts.cost = 0;
|
||||
ts.modheight = modheight_data;
|
||||
ts.tile_table = tile_table_data;
|
||||
|
||||
/* Make an extra check for map-bounds cause we add tiles to the originating tile */
|
||||
if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
|
||||
|
||||
if (p1 & 1) {
|
||||
t = tile + TileDiffXY(1, 0);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
t = tile + TileDiffXY(1, 1);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
t = tile + TileDiffXY(0, 1);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
t = tile + TileDiffXY(0, 0);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (direction == -1) {
|
||||
/* Check if tunnel would take damage */
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
uint z, t;
|
||||
TileIndex tile = *ti;
|
||||
|
||||
z = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
|
||||
if (t <= z) z = t;
|
||||
|
||||
if (IsTunnelInWay(tile, z * TILE_HEIGHT)) {
|
||||
return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Clear the landscape at the tiles */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
DoCommand(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* change the height */
|
||||
{
|
||||
int count;
|
||||
TerraformerHeightMod *mod;
|
||||
|
||||
mod = ts.modheight;
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
TileIndex til = mod->tile;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally mark the dirty tiles dirty */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ts.cost;
|
||||
}
|
||||
|
||||
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param tile end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdLevelLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int ex;
|
||||
int ey;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 >= MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = TileHeight(p1);
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
ex = TileX(tile);
|
||||
ey = TileY(tile);
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TileXY(sx, sy);
|
||||
|
||||
size_x = ex-sx+1;
|
||||
size_y = ey-sy+1;
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param tile the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdPurchaseLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IsOwnedLandTile(tile) && IsTileOwner(tile, _current_player)) {
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
}
|
||||
|
||||
cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
MakeOwnedLand(tile, _current_player);
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
return cost + _price.purchase_land * 10;
|
||||
}
|
||||
|
||||
|
||||
static int32 ClearTile_Clear(TileIndex tile, byte flags)
|
||||
{
|
||||
static const int32* clear_price_table[] = {
|
||||
&_price.clear_1,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_3,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2, // XXX unused?
|
||||
};
|
||||
int32 price;
|
||||
|
||||
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
|
||||
price = 0;
|
||||
} else {
|
||||
price = *clear_price_table[GetClearGround(tile)];
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param tile the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
if (!IsOwnedLandTile(tile)) return CMD_ERROR;
|
||||
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
|
||||
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return - _price.purchase_land * 2;
|
||||
}
|
||||
|
||||
|
||||
#include "table/clear_land.h"
|
||||
|
||||
|
||||
void DrawClearLandTile(const TileInfo *ti, byte set)
|
||||
{
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19);
|
||||
}
|
||||
|
||||
void DrawHillyLandTile(const TileInfo *ti)
|
||||
{
|
||||
if (ti->tileh != SLOPE_FLAT) {
|
||||
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh]);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawClearLandFence(const TileInfo *ti)
|
||||
{
|
||||
byte z = ti->z;
|
||||
|
||||
if (ti->tileh & SLOPE_S) {
|
||||
z += TILE_HEIGHT;
|
||||
if (ti->tileh == SLOPE_STEEP_S) z += TILE_HEIGHT;
|
||||
}
|
||||
|
||||
if (GetFenceSW(ti->tile) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
|
||||
if (GetFenceSE(ti->tile) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawTile_Clear(TileInfo *ti)
|
||||
{
|
||||
switch (GetClearGround(ti->tile)) {
|
||||
case CLEAR_GRASS:
|
||||
DrawClearLandTile(ti, GetClearDensity(ti->tile));
|
||||
break;
|
||||
|
||||
case CLEAR_ROUGH:
|
||||
DrawHillyLandTile(ti);
|
||||
break;
|
||||
|
||||
case CLEAR_ROCKS:
|
||||
DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_FIELDS:
|
||||
DrawGroundSprite(_clear_land_sprites_1[GetFieldType(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_SNOW:
|
||||
DrawGroundSprite(_clear_land_sprites_2[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_DESERT:
|
||||
DrawGroundSprite(_clear_land_sprites_3[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawClearLandFence(ti);
|
||||
}
|
||||
|
||||
static uint GetSlopeZ_Clear(TileIndex tile, uint x, uint y)
|
||||
{
|
||||
uint z;
|
||||
uint tileh = GetTileSlope(tile, &z);
|
||||
|
||||
return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
|
||||
}
|
||||
|
||||
static Slope GetSlopeTileh_Clear(TileIndex tile, Slope tileh)
|
||||
{
|
||||
return tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static void AnimateTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte self;
|
||||
byte neighbour;
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
|
||||
|
||||
neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
|
||||
if (GetFenceSW(tile) == 0) {
|
||||
if (self != neighbour) {
|
||||
SetFenceSW(tile, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SetFenceSW(tile, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
|
||||
if (GetFenceSE(tile) == 0) {
|
||||
if (self != neighbour) {
|
||||
SetFenceSE(tile, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SetFenceSE(tile, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
|
||||
/* convert into snowy tiles */
|
||||
static void TileLoopClearAlps(TileIndex tile)
|
||||
{
|
||||
int k = GetTileZ(tile) - _opt.snow_line + TILE_HEIGHT;
|
||||
|
||||
if (k < 0) { // well below the snow line
|
||||
if (!IsClearGround(tile, CLEAR_SNOW)) return;
|
||||
if (GetClearDensity(tile) == 0) SetClearGroundDensity(tile, CLEAR_GRASS, 3);
|
||||
} else {
|
||||
if (!IsClearGround(tile, CLEAR_SNOW)) {
|
||||
SetClearGroundDensity(tile, CLEAR_SNOW, 0);
|
||||
} else {
|
||||
uint density = min((uint)k / TILE_HEIGHT, 3);
|
||||
|
||||
if (GetClearDensity(tile) < density) {
|
||||
AddClearDensity(tile, 1);
|
||||
} else if (GetClearDensity(tile) > density) {
|
||||
AddClearDensity(tile, -1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoopClearDesert(TileIndex tile)
|
||||
{
|
||||
if (IsClearGround(tile, CLEAR_DESERT)) return;
|
||||
|
||||
if (GetTropicZone(tile) == TROPICZONE_DESERT) {
|
||||
SetClearGroundDensity(tile, CLEAR_DESERT, 3);
|
||||
} else {
|
||||
if (GetTropicZone(tile + TileDiffXY( 1, 0)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY(-1, 0)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY( 0, 1)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
|
||||
return;
|
||||
SetClearGroundDensity(tile, CLEAR_DESERT, 1);
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoop_Clear(TileIndex tile)
|
||||
{
|
||||
TileLoopClearHelper(tile);
|
||||
|
||||
switch (_opt.landscape) {
|
||||
case LT_DESERT: TileLoopClearDesert(tile); break;
|
||||
case LT_HILLY: TileLoopClearAlps(tile); break;
|
||||
}
|
||||
|
||||
switch (GetClearGround(tile)) {
|
||||
case CLEAR_GRASS:
|
||||
if (GetClearDensity(tile) == 3) return;
|
||||
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
if (GetClearCounter(tile) < 7) {
|
||||
AddClearCounter(tile, 1);
|
||||
return;
|
||||
} else {
|
||||
SetClearCounter(tile, 0);
|
||||
AddClearDensity(tile, 1);
|
||||
}
|
||||
} else {
|
||||
SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLEAR_FIELDS: {
|
||||
uint field_type;
|
||||
|
||||
if (_game_mode == GM_EDITOR) return;
|
||||
|
||||
if (GetClearCounter(tile) < 7) {
|
||||
AddClearCounter(tile, 1);
|
||||
return;
|
||||
} else {
|
||||
SetClearCounter(tile, 0);
|
||||
}
|
||||
|
||||
if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
|
||||
/* This farmfield is no longer farmfield, so make it grass again */
|
||||
MakeClear(tile, CLEAR_GRASS, 2);
|
||||
} else {
|
||||
field_type = GetFieldType(tile);
|
||||
field_type = (field_type < 8) ? field_type + 1 : 0;
|
||||
SetFieldType(tile, field_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
uint i, gi;
|
||||
TileIndex tile;
|
||||
|
||||
/* add rough tiles */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
|
||||
gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
|
||||
|
||||
SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
|
||||
do {
|
||||
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
|
||||
tile = RandomTile();
|
||||
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
|
||||
} while (--i);
|
||||
|
||||
/* add rocky tiles */
|
||||
i = gi;
|
||||
do {
|
||||
uint32 r = Random();
|
||||
tile = RandomTileSeed(r);
|
||||
|
||||
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
|
||||
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
|
||||
uint j = GB(r, 16, 4) + 5;
|
||||
for (;;) {
|
||||
TileIndex tile_new;
|
||||
|
||||
SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + TileOffsByDiagDir(GB(Random(), 0, 2));
|
||||
} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
static void ClickTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const StringID _clear_land_str[] = {
|
||||
STR_080D_GRASS,
|
||||
STR_080B_ROUGH_LAND,
|
||||
STR_080A_ROCKS,
|
||||
STR_080E_FIELDS,
|
||||
STR_080F_SNOW_COVERED_LAND,
|
||||
STR_0810_DESERT
|
||||
};
|
||||
|
||||
static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
|
||||
td->str = STR_080C_BARE_LAND;
|
||||
} else {
|
||||
td->str = _clear_land_str[GetClearGround(tile)];
|
||||
}
|
||||
td->owner = GetTileOwner(tile);
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, /* draw_tile_proc */
|
||||
GetSlopeZ_Clear, /* get_slope_z_proc */
|
||||
ClearTile_Clear, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Clear, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
|
||||
ClickTile_Clear, /* click_tile_proc */
|
||||
AnimateTile_Clear, /* animate_tile_proc */
|
||||
TileLoop_Clear, /* tile_loop_clear */
|
||||
ChangeTileOwner_Clear, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
|
||||
};
|
145
clear_map.h
Normal file
145
clear_map.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef CLEAR_MAP_H
|
||||
#define CLEAR_MAP_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "tile.h"
|
||||
|
||||
/* ground type, m5 bits 2...4
|
||||
* valid densities (bits 0...1) in comments after the enum
|
||||
*/
|
||||
typedef enum ClearGround {
|
||||
CLEAR_GRASS = 0, // 0-3
|
||||
CLEAR_ROUGH = 1, // 3
|
||||
CLEAR_ROCKS = 2, // 3
|
||||
CLEAR_FIELDS = 3, // 3
|
||||
CLEAR_SNOW = 4, // 0-3
|
||||
CLEAR_DESERT = 5 // 1,3
|
||||
} ClearGround;
|
||||
|
||||
|
||||
static inline ClearGround GetClearGround(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR));
|
||||
return GB(_m[t].m5, 2, 3);
|
||||
}
|
||||
|
||||
static inline bool IsClearGround(TileIndex t, ClearGround ct)
|
||||
{
|
||||
return GetClearGround(t) == ct;
|
||||
}
|
||||
|
||||
|
||||
static inline uint GetClearDensity(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR));
|
||||
return GB(_m[t].m5, 0, 2);
|
||||
}
|
||||
|
||||
static inline void AddClearDensity(TileIndex t, int d)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
|
||||
_m[t].m5 += d;
|
||||
}
|
||||
|
||||
|
||||
static inline uint GetClearCounter(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR));
|
||||
return GB(_m[t].m5, 5, 3);
|
||||
}
|
||||
|
||||
static inline void AddClearCounter(TileIndex t, int c)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
|
||||
_m[t].m5 += c << 5;
|
||||
}
|
||||
|
||||
static inline void SetClearCounter(TileIndex t, uint c)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
|
||||
SB(_m[t].m5, 5, 3, c);
|
||||
}
|
||||
|
||||
|
||||
/* Sets type and density in one go, also sets the counter to 0 */
|
||||
static inline void SetClearGroundDensity(TileIndex t, ClearGround type, uint density)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR)); // XXX incomplete
|
||||
_m[t].m5 = 0 << 5 | type << 2 | density;
|
||||
}
|
||||
|
||||
|
||||
static inline uint GetFieldType(TileIndex t)
|
||||
{
|
||||
assert(GetClearGround(t) == CLEAR_FIELDS);
|
||||
return GB(_m[t].m3, 0, 4);
|
||||
}
|
||||
|
||||
static inline void SetFieldType(TileIndex t, uint f)
|
||||
{
|
||||
assert(GetClearGround(t) == CLEAR_FIELDS); // XXX incomplete
|
||||
SB(_m[t].m3, 0, 4, f);
|
||||
}
|
||||
|
||||
static inline uint16 GetIndustryIndexOfField(TileIndex t)
|
||||
{
|
||||
assert(GetClearGround(t) == CLEAR_FIELDS);
|
||||
return _m[t].m2;
|
||||
}
|
||||
|
||||
static inline void SetIndustryIndexOfField(TileIndex t, uint16 i)
|
||||
{
|
||||
assert(GetClearGround(t) == CLEAR_FIELDS);
|
||||
_m[t].m2 = i;
|
||||
}
|
||||
|
||||
/* Is used by tree tiles, too */
|
||||
static inline uint GetFenceSE(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
|
||||
return GB(_m[t].m4, 2, 3);
|
||||
}
|
||||
|
||||
static inline void SetFenceSE(TileIndex t, uint h)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
|
||||
SB(_m[t].m4, 2, 3, h);
|
||||
}
|
||||
|
||||
static inline uint GetFenceSW(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
|
||||
return GB(_m[t].m4, 5, 3);
|
||||
}
|
||||
|
||||
static inline void SetFenceSW(TileIndex t, uint h)
|
||||
{
|
||||
assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
|
||||
SB(_m[t].m4, 5, 3, h);
|
||||
}
|
||||
|
||||
|
||||
static inline void MakeClear(TileIndex t, ClearGround g, uint density)
|
||||
{
|
||||
SetTileType(t, MP_CLEAR);
|
||||
SetTileOwner(t, OWNER_NONE);
|
||||
_m[t].m2 = 0;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0 << 5 | 0 << 2;
|
||||
SetClearGroundDensity(t, g, density);
|
||||
}
|
||||
|
||||
|
||||
static inline void MakeField(TileIndex t, uint field_type, uint16 industry)
|
||||
{
|
||||
SetTileType(t, MP_CLEAR);
|
||||
SetTileOwner(t, OWNER_NONE);
|
||||
_m[t].m2 = industry;
|
||||
_m[t].m3 = field_type;
|
||||
_m[t].m4 = 0 << 5 | 0 << 2;
|
||||
SetClearGroundDensity(t, CLEAR_FIELDS, 3);
|
||||
}
|
||||
|
||||
#endif /* CLEAR_MAP_H */
|
566
command.c
Normal file
566
command.c
Normal file
@@ -0,0 +1,566 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "gui.h"
|
||||
#include "command.h"
|
||||
#include "player.h"
|
||||
#include "network.h"
|
||||
#include "variables.h"
|
||||
#include "genworld.h"
|
||||
|
||||
const char* _cmd_text = NULL;
|
||||
|
||||
#define DEF_COMMAND(yyyy) int32 yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
DEF_COMMAND(CmdBuildRailroadTrack);
|
||||
DEF_COMMAND(CmdRemoveRailroadTrack);
|
||||
DEF_COMMAND(CmdBuildSingleRail);
|
||||
DEF_COMMAND(CmdRemoveSingleRail);
|
||||
|
||||
DEF_COMMAND(CmdLandscapeClear);
|
||||
|
||||
DEF_COMMAND(CmdBuildBridge);
|
||||
|
||||
DEF_COMMAND(CmdBuildRailroadStation);
|
||||
DEF_COMMAND(CmdRemoveFromRailroadStation);
|
||||
DEF_COMMAND(CmdConvertRail);
|
||||
|
||||
DEF_COMMAND(CmdBuildSingleSignal);
|
||||
DEF_COMMAND(CmdRemoveSingleSignal);
|
||||
|
||||
DEF_COMMAND(CmdTerraformLand);
|
||||
|
||||
DEF_COMMAND(CmdPurchaseLandArea);
|
||||
DEF_COMMAND(CmdSellLandArea);
|
||||
|
||||
DEF_COMMAND(CmdBuildTunnel);
|
||||
|
||||
DEF_COMMAND(CmdBuildTrainDepot);
|
||||
DEF_COMMAND(CmdBuildTrainWaypoint);
|
||||
DEF_COMMAND(CmdRenameWaypoint);
|
||||
DEF_COMMAND(CmdRemoveTrainWaypoint);
|
||||
|
||||
DEF_COMMAND(CmdBuildRoadStop);
|
||||
|
||||
DEF_COMMAND(CmdBuildLongRoad);
|
||||
DEF_COMMAND(CmdRemoveLongRoad);
|
||||
DEF_COMMAND(CmdBuildRoad);
|
||||
DEF_COMMAND(CmdRemoveRoad);
|
||||
|
||||
DEF_COMMAND(CmdBuildRoadDepot);
|
||||
|
||||
DEF_COMMAND(CmdBuildAirport);
|
||||
|
||||
DEF_COMMAND(CmdBuildDock);
|
||||
|
||||
DEF_COMMAND(CmdBuildShipDepot);
|
||||
|
||||
DEF_COMMAND(CmdBuildBuoy);
|
||||
|
||||
DEF_COMMAND(CmdPlantTree);
|
||||
|
||||
DEF_COMMAND(CmdBuildRailVehicle);
|
||||
DEF_COMMAND(CmdMoveRailVehicle);
|
||||
|
||||
DEF_COMMAND(CmdStartStopTrain);
|
||||
|
||||
DEF_COMMAND(CmdSellRailWagon);
|
||||
|
||||
DEF_COMMAND(CmdSendTrainToDepot);
|
||||
DEF_COMMAND(CmdForceTrainProceed);
|
||||
DEF_COMMAND(CmdReverseTrainDirection);
|
||||
|
||||
DEF_COMMAND(CmdModifyOrder);
|
||||
DEF_COMMAND(CmdSkipOrder);
|
||||
DEF_COMMAND(CmdDeleteOrder);
|
||||
DEF_COMMAND(CmdInsertOrder);
|
||||
DEF_COMMAND(CmdChangeServiceInt);
|
||||
DEF_COMMAND(CmdRestoreOrderIndex);
|
||||
|
||||
DEF_COMMAND(CmdBuildIndustry);
|
||||
|
||||
DEF_COMMAND(CmdBuildCompanyHQ);
|
||||
DEF_COMMAND(CmdSetPlayerFace);
|
||||
DEF_COMMAND(CmdSetPlayerColor);
|
||||
|
||||
DEF_COMMAND(CmdIncreaseLoan);
|
||||
DEF_COMMAND(CmdDecreaseLoan);
|
||||
|
||||
DEF_COMMAND(CmdWantEnginePreview);
|
||||
|
||||
DEF_COMMAND(CmdNameVehicle);
|
||||
DEF_COMMAND(CmdRenameEngine);
|
||||
|
||||
DEF_COMMAND(CmdChangeCompanyName);
|
||||
DEF_COMMAND(CmdChangePresidentName);
|
||||
|
||||
DEF_COMMAND(CmdRenameStation);
|
||||
|
||||
DEF_COMMAND(CmdSellAircraft);
|
||||
DEF_COMMAND(CmdStartStopAircraft);
|
||||
DEF_COMMAND(CmdBuildAircraft);
|
||||
DEF_COMMAND(CmdSendAircraftToHangar);
|
||||
DEF_COMMAND(CmdRefitAircraft);
|
||||
|
||||
DEF_COMMAND(CmdPlaceSign);
|
||||
DEF_COMMAND(CmdRenameSign);
|
||||
|
||||
DEF_COMMAND(CmdBuildRoadVeh);
|
||||
DEF_COMMAND(CmdStartStopRoadVeh);
|
||||
DEF_COMMAND(CmdSellRoadVeh);
|
||||
DEF_COMMAND(CmdSendRoadVehToDepot);
|
||||
DEF_COMMAND(CmdTurnRoadVeh);
|
||||
DEF_COMMAND(CmdRefitRoadVeh);
|
||||
|
||||
DEF_COMMAND(CmdPause);
|
||||
|
||||
DEF_COMMAND(CmdBuyShareInCompany);
|
||||
DEF_COMMAND(CmdSellShareInCompany);
|
||||
DEF_COMMAND(CmdBuyCompany);
|
||||
|
||||
DEF_COMMAND(CmdBuildTown);
|
||||
|
||||
DEF_COMMAND(CmdRenameTown);
|
||||
DEF_COMMAND(CmdDoTownAction);
|
||||
|
||||
DEF_COMMAND(CmdSetRoadDriveSide);
|
||||
|
||||
DEF_COMMAND(CmdChangeDifficultyLevel);
|
||||
DEF_COMMAND(CmdChangePatchSetting);
|
||||
|
||||
DEF_COMMAND(CmdStartStopShip);
|
||||
DEF_COMMAND(CmdSellShip);
|
||||
DEF_COMMAND(CmdBuildShip);
|
||||
DEF_COMMAND(CmdSendShipToDepot);
|
||||
DEF_COMMAND(CmdRefitShip);
|
||||
|
||||
DEF_COMMAND(CmdOrderRefit);
|
||||
DEF_COMMAND(CmdCloneOrder);
|
||||
|
||||
DEF_COMMAND(CmdClearArea);
|
||||
|
||||
DEF_COMMAND(CmdGiveMoney);
|
||||
DEF_COMMAND(CmdMoneyCheat);
|
||||
DEF_COMMAND(CmdBuildCanal);
|
||||
DEF_COMMAND(CmdBuildLock);
|
||||
|
||||
DEF_COMMAND(CmdPlayerCtrl);
|
||||
|
||||
DEF_COMMAND(CmdLevelLand);
|
||||
|
||||
DEF_COMMAND(CmdRefitRailVehicle);
|
||||
|
||||
DEF_COMMAND(CmdBuildSignalTrack);
|
||||
DEF_COMMAND(CmdRemoveSignalTrack);
|
||||
|
||||
DEF_COMMAND(CmdSetAutoReplace);
|
||||
|
||||
DEF_COMMAND(CmdCloneVehicle);
|
||||
DEF_COMMAND(CmdMassStartStopVehicle);
|
||||
DEF_COMMAND(CmdDepotSellAllVehicles);
|
||||
DEF_COMMAND(CmdDepotMassAutoReplace);
|
||||
|
||||
/* The master command table */
|
||||
static const Command _command_proc_table[] = {
|
||||
{CmdBuildRailroadTrack, 0}, /* 0 */
|
||||
{CmdRemoveRailroadTrack, 0}, /* 1 */
|
||||
{CmdBuildSingleRail, 0}, /* 2 */
|
||||
{CmdRemoveSingleRail, 0}, /* 3 */
|
||||
{CmdLandscapeClear, 0}, /* 4 */
|
||||
{CmdBuildBridge, 0}, /* 5 */
|
||||
{CmdBuildRailroadStation, 0}, /* 6 */
|
||||
{CmdBuildTrainDepot, 0}, /* 7 */
|
||||
{CmdBuildSingleSignal, 0}, /* 8 */
|
||||
{CmdRemoveSingleSignal, 0}, /* 9 */
|
||||
{CmdTerraformLand, 0}, /* 10 */
|
||||
{CmdPurchaseLandArea, 0}, /* 11 */
|
||||
{CmdSellLandArea, 0}, /* 12 */
|
||||
{CmdBuildTunnel, 0}, /* 13 */
|
||||
{CmdRemoveFromRailroadStation, 0}, /* 14 */
|
||||
{CmdConvertRail, 0}, /* 15 */
|
||||
{CmdBuildTrainWaypoint, 0}, /* 16 */
|
||||
{CmdRenameWaypoint, 0}, /* 17 */
|
||||
{CmdRemoveTrainWaypoint, 0}, /* 18 */
|
||||
{NULL, 0}, /* 19 */
|
||||
{NULL, 0}, /* 20 */
|
||||
{CmdBuildRoadStop, 0}, /* 21 */
|
||||
{NULL, 0}, /* 22 */
|
||||
{CmdBuildLongRoad, 0}, /* 23 */
|
||||
{CmdRemoveLongRoad, 0}, /* 24 */
|
||||
{CmdBuildRoad, 0}, /* 25 */
|
||||
{CmdRemoveRoad, 0}, /* 26 */
|
||||
{CmdBuildRoadDepot, 0}, /* 27 */
|
||||
{NULL, 0}, /* 28 */
|
||||
{CmdBuildAirport, 0}, /* 29 */
|
||||
{CmdBuildDock, 0}, /* 30 */
|
||||
{CmdBuildShipDepot, 0}, /* 31 */
|
||||
{CmdBuildBuoy, 0}, /* 32 */
|
||||
{CmdPlantTree, 0}, /* 33 */
|
||||
{CmdBuildRailVehicle, 0}, /* 34 */
|
||||
{CmdMoveRailVehicle, 0}, /* 35 */
|
||||
{CmdStartStopTrain, 0}, /* 36 */
|
||||
{NULL, 0}, /* 37 */
|
||||
{CmdSellRailWagon, 0}, /* 38 */
|
||||
{CmdSendTrainToDepot, 0}, /* 39 */
|
||||
{CmdForceTrainProceed, 0}, /* 40 */
|
||||
{CmdReverseTrainDirection, 0}, /* 41 */
|
||||
|
||||
{CmdModifyOrder, 0}, /* 42 */
|
||||
{CmdSkipOrder, 0}, /* 43 */
|
||||
{CmdDeleteOrder, 0}, /* 44 */
|
||||
{CmdInsertOrder, 0}, /* 45 */
|
||||
|
||||
{CmdChangeServiceInt, 0}, /* 46 */
|
||||
|
||||
{CmdBuildIndustry, 0}, /* 47 */
|
||||
{CmdBuildCompanyHQ, 0}, /* 48 */
|
||||
{CmdSetPlayerFace, 0}, /* 49 */
|
||||
{CmdSetPlayerColor, 0}, /* 50 */
|
||||
|
||||
{CmdIncreaseLoan, 0}, /* 51 */
|
||||
{CmdDecreaseLoan, 0}, /* 52 */
|
||||
|
||||
{CmdWantEnginePreview, 0}, /* 53 */
|
||||
|
||||
{CmdNameVehicle, 0}, /* 54 */
|
||||
{CmdRenameEngine, 0}, /* 55 */
|
||||
|
||||
{CmdChangeCompanyName, 0}, /* 56 */
|
||||
{CmdChangePresidentName, 0}, /* 57 */
|
||||
|
||||
{CmdRenameStation, 0}, /* 58 */
|
||||
|
||||
{CmdSellAircraft, 0}, /* 59 */
|
||||
{CmdStartStopAircraft, 0}, /* 60 */
|
||||
|
||||
{CmdBuildAircraft, 0}, /* 61 */
|
||||
{CmdSendAircraftToHangar, 0}, /* 62 */
|
||||
{NULL, 0}, /* 63 */
|
||||
{CmdRefitAircraft, 0}, /* 64 */
|
||||
|
||||
{CmdPlaceSign, 0}, /* 65 */
|
||||
{CmdRenameSign, 0}, /* 66 */
|
||||
|
||||
{CmdBuildRoadVeh, 0}, /* 67 */
|
||||
{CmdStartStopRoadVeh, 0}, /* 68 */
|
||||
{CmdSellRoadVeh, 0}, /* 69 */
|
||||
{CmdSendRoadVehToDepot, 0}, /* 70 */
|
||||
{CmdTurnRoadVeh, 0}, /* 71 */
|
||||
{CmdRefitRoadVeh, 0}, /* 72 */
|
||||
|
||||
{CmdPause, CMD_SERVER}, /* 73 */
|
||||
|
||||
{CmdBuyShareInCompany, 0}, /* 74 */
|
||||
{CmdSellShareInCompany, 0}, /* 75 */
|
||||
{CmdBuyCompany, 0}, /* 76 */
|
||||
|
||||
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
|
||||
{NULL, 0}, /* 78 */
|
||||
{NULL, 0}, /* 79 */
|
||||
{CmdRenameTown, CMD_SERVER}, /* 80 */
|
||||
{CmdDoTownAction, 0}, /* 81 */
|
||||
|
||||
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
|
||||
{NULL, 0}, /* 83 */
|
||||
{NULL, 0}, /* 84 */
|
||||
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
|
||||
|
||||
{CmdStartStopShip, 0}, /* 86 */
|
||||
{CmdSellShip, 0}, /* 87 */
|
||||
{CmdBuildShip, 0}, /* 88 */
|
||||
{CmdSendShipToDepot, 0}, /* 89 */
|
||||
{NULL, 0}, /* 90 */
|
||||
{CmdRefitShip, 0}, /* 91 */
|
||||
|
||||
{NULL, 0}, /* 92 */
|
||||
{NULL, 0}, /* 93 */
|
||||
{NULL, 0}, /* 94 */
|
||||
{NULL, 0}, /* 95 */
|
||||
{NULL, 0}, /* 96 */
|
||||
{NULL, 0}, /* 97 */
|
||||
|
||||
{CmdOrderRefit, 0}, /* 98 */
|
||||
{CmdCloneOrder, 0}, /* 99 */
|
||||
|
||||
{CmdClearArea, 0}, /* 100 */
|
||||
{NULL, 0}, /* 101 */
|
||||
|
||||
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
|
||||
{CmdBuildCanal, 0}, /* 103 */
|
||||
{CmdPlayerCtrl, 0}, /* 104 */
|
||||
|
||||
{CmdLevelLand, 0}, /* 105 */
|
||||
|
||||
{CmdRefitRailVehicle, 0}, /* 106 */
|
||||
{CmdRestoreOrderIndex, 0}, /* 107 */
|
||||
{CmdBuildLock, 0}, /* 108 */
|
||||
{NULL, 0}, /* 109 */
|
||||
{CmdBuildSignalTrack, 0}, /* 110 */
|
||||
{CmdRemoveSignalTrack, 0}, /* 111 */
|
||||
{NULL, 0}, /* 112 */
|
||||
{CmdGiveMoney, 0}, /* 113 */
|
||||
{CmdChangePatchSetting, CMD_SERVER}, /* 114 */
|
||||
{CmdSetAutoReplace, 0}, /* 115 */
|
||||
{CmdCloneVehicle, 0}, /* 116 */
|
||||
{CmdMassStartStopVehicle, 0}, /* 117 */
|
||||
{CmdDepotSellAllVehicles, 0}, /* 118 */
|
||||
{CmdDepotMassAutoReplace, 0}, /* 119 */
|
||||
};
|
||||
|
||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||
bool IsValidCommand(uint cmd)
|
||||
{
|
||||
cmd &= 0xFF;
|
||||
|
||||
return
|
||||
cmd < lengthof(_command_proc_table) &&
|
||||
_command_proc_table[cmd].proc != NULL;
|
||||
}
|
||||
|
||||
byte GetCommandFlags(uint cmd)
|
||||
{
|
||||
return _command_proc_table[cmd & 0xFF].flags;
|
||||
}
|
||||
|
||||
|
||||
static int _docommand_recursive;
|
||||
|
||||
int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
int32 res;
|
||||
CommandProc *proc;
|
||||
|
||||
/* Do not even think about executing out-of-bounds tile-commands */
|
||||
if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
proc = _command_proc_table[procc].proc;
|
||||
|
||||
if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
|
||||
|
||||
_docommand_recursive++;
|
||||
|
||||
// only execute the test call if it's toplevel, or we're not execing.
|
||||
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
|
||||
res = proc(tile, flags & ~DC_EXEC, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_docommand_recursive == 1 &&
|
||||
!(flags & DC_QUERY_COST) &&
|
||||
res != 0 &&
|
||||
!CheckPlayerHasMoney(res)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(flags & DC_EXEC)) {
|
||||
_docommand_recursive--;
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute the command here. All cost-relevant functions set the expenses type
|
||||
* themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
|
||||
res = proc(tile, flags, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
error:
|
||||
_docommand_recursive--;
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
// if toplevel, subtract the money.
|
||||
if (--_docommand_recursive == 0) {
|
||||
SubtractMoneyFromPlayer(res);
|
||||
// XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player
|
||||
if (tile != 0 && IsValidPlayer(_current_player)) {
|
||||
GetPlayer(_current_player)->last_build_coordinate = tile;
|
||||
}
|
||||
}
|
||||
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32 GetAvailableMoneyForCommand(void)
|
||||
{
|
||||
PlayerID pid = _current_player;
|
||||
if (!IsValidPlayer(pid)) return 0x7FFFFFFF; // max int
|
||||
return GetPlayer(pid)->player_money;
|
||||
}
|
||||
|
||||
// toplevel network safe docommand function for the current player. must not be called recursively.
|
||||
// the callback is called when the command succeeded or failed.
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
|
||||
{
|
||||
int32 res = 0,res2;
|
||||
CommandProc *proc;
|
||||
uint32 flags;
|
||||
bool notest;
|
||||
StringID error_part1;
|
||||
|
||||
int x = TileX(tile) * TILE_SIZE;
|
||||
int y = TileY(tile) * TILE_SIZE;
|
||||
|
||||
/* Do not even think about executing out-of-bounds tile-commands */
|
||||
if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(_docommand_recursive == 0);
|
||||
|
||||
_error_message = INVALID_STRING_ID;
|
||||
error_part1 = GB(cmd, 16, 16);
|
||||
_additional_cash_required = 0;
|
||||
|
||||
/** Spectator has no rights except for the (dedicated) server which
|
||||
* is/can be a spectator but as the server it can do anything */
|
||||
if (_current_player == PLAYER_SPECTATOR && !_network_server) {
|
||||
ShowErrorMessage(_error_message, error_part1, x, y);
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
if (cmd & CMD_AUTO) flags |= DC_AUTO;
|
||||
if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
|
||||
|
||||
// get pointer to command handler
|
||||
assert((cmd & 0xFF) < lengthof(_command_proc_table));
|
||||
proc = _command_proc_table[cmd & 0xFF].proc;
|
||||
if (proc == NULL) {
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some commands have a different output in dryrun than the realrun
|
||||
// e.g.: if you demolish a whole town, the dryrun would say okay.
|
||||
// but by really destroying, your rating drops and at a certain point
|
||||
// it will fail. so res and res2 are different
|
||||
// CMD_REMOVE_ROAD: This command has special local authority
|
||||
// restrictions which may cause the test run to fail (the previous
|
||||
// road fragments still stay there and the town won't let you
|
||||
// disconnect the road system), but the exec will succeed and this
|
||||
// fact will trigger an assertion failure. --pasky
|
||||
notest =
|
||||
(cmd & 0xFF) == CMD_CLEAR_AREA ||
|
||||
(cmd & 0xFF) == CMD_CONVERT_RAIL ||
|
||||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
|
||||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
|
||||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
|
||||
|
||||
_docommand_recursive = 1;
|
||||
|
||||
// cost estimation only?
|
||||
if (!IsGeneratingWorld() &&
|
||||
_shift_pressed &&
|
||||
IsLocalPlayer() &&
|
||||
!(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) &&
|
||||
(cmd & 0xFF) != CMD_PAUSE) {
|
||||
// estimate the cost.
|
||||
res = proc(tile, flags, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
ShowErrorMessage(_error_message, error_part1, x, y);
|
||||
} else {
|
||||
ShowEstimatedCostOrIncome(res, x, y);
|
||||
}
|
||||
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
|
||||
// first test if the command can be executed.
|
||||
res = proc(tile, flags, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
goto show_error;
|
||||
}
|
||||
// no money? Only check if notest is off
|
||||
if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/** If we are in network, and the command is not from the network
|
||||
* send it to the command-queue and abort execution
|
||||
* If we are a dedicated server temporarily switch local player, otherwise
|
||||
* the other parties won't be able to execute our command and will desync.
|
||||
* We also need to do this if the server's company has gone bankrupt
|
||||
* @todo Rewrite (dedicated) server to something more than a dirty hack!
|
||||
*/
|
||||
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
|
||||
PlayerID pbck = _local_player;
|
||||
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = 0;
|
||||
NetworkSend_Command(tile, p1, p2, cmd, callback);
|
||||
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
// update last build coordinate of player.
|
||||
if (tile != 0 && IsValidPlayer(_current_player)) {
|
||||
GetPlayer(_current_player)->last_build_coordinate = tile;
|
||||
}
|
||||
|
||||
/* Actually try and execute the command. If no cost-type is given
|
||||
* use the construction one */
|
||||
_yearly_expenses_type = EXPENSES_CONSTRUCTION;
|
||||
res2 = proc(tile, flags | DC_EXEC, p1, p2);
|
||||
|
||||
// If notest is on, it means the result of the test can be different than
|
||||
// the real command.. so ignore the test
|
||||
if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
|
||||
assert(res == res2); // sanity check
|
||||
} else {
|
||||
if (CmdFailed(res2)) {
|
||||
if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
|
||||
goto show_error;
|
||||
}
|
||||
}
|
||||
|
||||
SubtractMoneyFromPlayer(res2);
|
||||
|
||||
if (IsLocalPlayer() && _game_mode != GM_EDITOR) {
|
||||
if (res2 != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
|
||||
if (_additional_cash_required) {
|
||||
SetDParam(0, _additional_cash_required);
|
||||
ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y);
|
||||
if (res2 == 0) goto callb_err;
|
||||
}
|
||||
}
|
||||
|
||||
_docommand_recursive = 0;
|
||||
|
||||
if (callback) callback(true, tile, p1, p2);
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
|
||||
show_error:
|
||||
// show error message if the command fails?
|
||||
if (IsLocalPlayer() && error_part1 != 0) {
|
||||
ShowErrorMessage(_error_message, error_part1, x,y);
|
||||
}
|
||||
|
||||
callb_err:
|
||||
_docommand_recursive = 0;
|
||||
|
||||
if (callback) callback(false, tile, p1, p2);
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
213
command.h
Normal file
213
command.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
enum {
|
||||
CMD_BUILD_RAILROAD_TRACK = 0,
|
||||
CMD_REMOVE_RAILROAD_TRACK = 1,
|
||||
CMD_BUILD_SINGLE_RAIL = 2,
|
||||
CMD_REMOVE_SINGLE_RAIL = 3,
|
||||
CMD_LANDSCAPE_CLEAR = 4,
|
||||
CMD_BUILD_BRIDGE = 5,
|
||||
CMD_BUILD_RAILROAD_STATION = 6,
|
||||
CMD_BUILD_TRAIN_DEPOT = 7,
|
||||
CMD_BUILD_SIGNALS = 8,
|
||||
CMD_REMOVE_SIGNALS = 9,
|
||||
CMD_TERRAFORM_LAND = 10,
|
||||
CMD_PURCHASE_LAND_AREA = 11,
|
||||
CMD_SELL_LAND_AREA = 12,
|
||||
CMD_BUILD_TUNNEL = 13,
|
||||
|
||||
CMD_REMOVE_FROM_RAILROAD_STATION = 14,
|
||||
CMD_CONVERT_RAIL = 15,
|
||||
|
||||
CMD_BUILD_TRAIN_WAYPOINT = 16,
|
||||
CMD_RENAME_WAYPOINT = 17,
|
||||
CMD_REMOVE_TRAIN_WAYPOINT = 18,
|
||||
|
||||
CMD_BUILD_ROAD_STOP = 21,
|
||||
CMD_BUILD_LONG_ROAD = 23,
|
||||
CMD_REMOVE_LONG_ROAD = 24,
|
||||
CMD_BUILD_ROAD = 25,
|
||||
CMD_REMOVE_ROAD = 26,
|
||||
CMD_BUILD_ROAD_DEPOT = 27,
|
||||
|
||||
CMD_BUILD_AIRPORT = 29,
|
||||
|
||||
CMD_BUILD_DOCK = 30,
|
||||
|
||||
CMD_BUILD_SHIP_DEPOT = 31,
|
||||
CMD_BUILD_BUOY = 32,
|
||||
|
||||
CMD_PLANT_TREE = 33,
|
||||
|
||||
CMD_BUILD_RAIL_VEHICLE = 34,
|
||||
CMD_MOVE_RAIL_VEHICLE = 35,
|
||||
|
||||
CMD_START_STOP_TRAIN = 36,
|
||||
|
||||
CMD_SELL_RAIL_WAGON = 38,
|
||||
|
||||
CMD_SEND_TRAIN_TO_DEPOT = 39,
|
||||
CMD_FORCE_TRAIN_PROCEED = 40,
|
||||
CMD_REVERSE_TRAIN_DIRECTION = 41,
|
||||
|
||||
CMD_MODIFY_ORDER = 42,
|
||||
CMD_SKIP_ORDER = 43,
|
||||
CMD_DELETE_ORDER = 44,
|
||||
CMD_INSERT_ORDER = 45,
|
||||
|
||||
CMD_CHANGE_SERVICE_INT = 46,
|
||||
|
||||
CMD_BUILD_INDUSTRY = 47,
|
||||
|
||||
CMD_BUILD_COMPANY_HQ = 48,
|
||||
CMD_SET_PLAYER_FACE = 49,
|
||||
CMD_SET_PLAYER_COLOR = 50,
|
||||
|
||||
CMD_INCREASE_LOAN = 51,
|
||||
CMD_DECREASE_LOAN = 52,
|
||||
|
||||
CMD_WANT_ENGINE_PREVIEW = 53,
|
||||
|
||||
CMD_NAME_VEHICLE = 54,
|
||||
CMD_RENAME_ENGINE = 55,
|
||||
CMD_CHANGE_COMPANY_NAME = 56,
|
||||
CMD_CHANGE_PRESIDENT_NAME = 57,
|
||||
CMD_RENAME_STATION = 58,
|
||||
|
||||
CMD_SELL_AIRCRAFT = 59,
|
||||
CMD_START_STOP_AIRCRAFT = 60,
|
||||
CMD_BUILD_AIRCRAFT = 61,
|
||||
CMD_SEND_AIRCRAFT_TO_HANGAR = 62,
|
||||
CMD_REFIT_AIRCRAFT = 64,
|
||||
|
||||
CMD_PLACE_SIGN = 65,
|
||||
CMD_RENAME_SIGN = 66,
|
||||
|
||||
CMD_BUILD_ROAD_VEH = 67,
|
||||
CMD_START_STOP_ROADVEH = 68,
|
||||
CMD_SELL_ROAD_VEH = 69,
|
||||
CMD_SEND_ROADVEH_TO_DEPOT = 70,
|
||||
CMD_TURN_ROADVEH = 71,
|
||||
CMD_REFIT_ROAD_VEH = 72,
|
||||
|
||||
CMD_PAUSE = 73,
|
||||
|
||||
CMD_BUY_SHARE_IN_COMPANY = 74,
|
||||
CMD_SELL_SHARE_IN_COMPANY = 75,
|
||||
CMD_BUY_COMPANY = 76,
|
||||
|
||||
CMD_BUILD_TOWN = 77,
|
||||
|
||||
CMD_RENAME_TOWN = 80,
|
||||
CMD_DO_TOWN_ACTION = 81,
|
||||
|
||||
CMD_SET_ROAD_DRIVE_SIDE = 82,
|
||||
|
||||
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
|
||||
|
||||
CMD_START_STOP_SHIP = 86,
|
||||
CMD_SELL_SHIP = 87,
|
||||
CMD_BUILD_SHIP = 88,
|
||||
CMD_SEND_SHIP_TO_DEPOT = 89,
|
||||
CMD_REFIT_SHIP = 91,
|
||||
|
||||
CMD_ORDER_REFIT = 98,
|
||||
CMD_CLONE_ORDER = 99,
|
||||
CMD_CLEAR_AREA = 100,
|
||||
|
||||
CMD_MONEY_CHEAT = 102,
|
||||
CMD_BUILD_CANAL = 103,
|
||||
|
||||
CMD_PLAYER_CTRL = 104, // used in multiplayer to create a new player etc.
|
||||
CMD_LEVEL_LAND = 105, // level land
|
||||
|
||||
CMD_REFIT_RAIL_VEHICLE = 106,
|
||||
CMD_RESTORE_ORDER_INDEX = 107,
|
||||
CMD_BUILD_LOCK = 108,
|
||||
|
||||
CMD_BUILD_SIGNAL_TRACK = 110,
|
||||
CMD_REMOVE_SIGNAL_TRACK = 111,
|
||||
|
||||
CMD_GIVE_MONEY = 113,
|
||||
CMD_CHANGE_PATCH_SETTING = 114,
|
||||
|
||||
CMD_SET_AUTOREPLACE = 115,
|
||||
|
||||
CMD_CLONE_VEHICLE = 116,
|
||||
CMD_MASS_START_STOP = 117,
|
||||
CMD_DEPOT_SELL_ALL_VEHICLES = 118,
|
||||
CMD_DEPOT_MASS_AUTOREPLACE = 119,
|
||||
};
|
||||
|
||||
enum {
|
||||
DC_EXEC = 0x01,
|
||||
DC_AUTO = 0x02, // don't allow building on structures
|
||||
DC_QUERY_COST = 0x04, // query cost only, don't build.
|
||||
DC_NO_WATER = 0x08, // don't allow building on water
|
||||
DC_NO_RAIL_OVERLAP = 0x10, // don't allow overlap of rails (used in buildrail)
|
||||
DC_AI_BUILDING = 0x20, // special building rules for AI
|
||||
DC_NO_TOWN_RATING = 0x40, // town rating does not disallow you from building
|
||||
DC_FORCETEST = 0x80, // force test too.
|
||||
|
||||
CMD_ERROR = ((int32)0x80000000),
|
||||
};
|
||||
|
||||
#define CMD_MSG(x) ((x)<<16)
|
||||
|
||||
enum {
|
||||
CMD_AUTO = 0x0200,
|
||||
CMD_NO_WATER = 0x0400,
|
||||
CMD_NETWORK_COMMAND = 0x0800, // execute the command without sending it on the network
|
||||
CMD_NO_TEST_IF_IN_NETWORK = 0x1000, // When enabled, the command will bypass the no-DC_EXEC round if in network
|
||||
CMD_SHOW_NO_ERROR = 0x2000,
|
||||
};
|
||||
|
||||
/** Command flags for the command table
|
||||
* @see _command_proc_table
|
||||
*/
|
||||
enum {
|
||||
CMD_SERVER = 0x1, /// the command can only be initiated by the server
|
||||
CMD_OFFLINE = 0x2, /// the command cannot be executed in a multiplayer game; single-player only
|
||||
};
|
||||
|
||||
typedef int32 CommandProc(TileIndex tile, uint32 flags, uint32 p1, uint32 p2);
|
||||
|
||||
typedef struct Command {
|
||||
CommandProc *proc;
|
||||
byte flags;
|
||||
} Command;
|
||||
|
||||
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
|
||||
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
|
||||
|
||||
/**
|
||||
* Check the return value of a DoCommand*() function
|
||||
* @param res the resulting value from the command to be checked
|
||||
* @return Return true if the command failed, false otherwise
|
||||
*/
|
||||
static inline bool CmdFailed(int32 res)
|
||||
{
|
||||
// lower 16bits are the StringID of the possible error
|
||||
return res <= (CMD_ERROR | INVALID_STRING_ID);
|
||||
}
|
||||
|
||||
/* command.c */
|
||||
typedef void CommandCallback(bool success, TileIndex tile, uint32 p1, uint32 p2);
|
||||
int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd);
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
||||
void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
extern const char* _cmd_text; // Text, which gets sent with a command
|
||||
|
||||
bool IsValidCommand(uint cmd);
|
||||
byte GetCommandFlags(uint cmd);
|
||||
int32 GetAvailableMoneyForCommand(void);
|
||||
|
||||
#endif /* COMMAND_H */
|
3568
config.lib
3568
config.lib
File diff suppressed because it is too large
Load Diff
472
configure
vendored
472
configure
vendored
@@ -1,175 +1,323 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $Id$
|
||||
# This 'configure' script is a very easy wrapper around 'make updateconf'
|
||||
# It allows cross-compilers to do their job much more easy.
|
||||
|
||||
# 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/>.
|
||||
|
||||
check_path_characters() {
|
||||
if [ -n "`echo $ROOT_DIR | grep '[^-_A-Za-z0-9\/\\\.:]'`" ]; then
|
||||
echo "WARNING: The path contains a non-alphanumeric character that might cause"
|
||||
echo " failures in subsequent build stages. Any failures with the build"
|
||||
echo " will most likely be caused by this."
|
||||
fi
|
||||
showhelp() {
|
||||
echo "Configure for OpenTTD"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $0 --your_options"
|
||||
echo ""
|
||||
echo "Params:"
|
||||
echo " --debug Create debug-release [no]"
|
||||
echo " --profile Create profile-release [no]"
|
||||
echo " --dedicated Make a dedicated build [no]"
|
||||
echo " --revision Set the revision of the compilation [detected]"
|
||||
echo " --target-cc Sets the target-compiler [\$CC]"
|
||||
echo " --target-cxx Sets the C++ target-compiler []"
|
||||
echo " --host-cc Sets the host-compiler [\$CC]"
|
||||
echo " --host-cxx Sets the C++ host-compiler []"
|
||||
echo " --os Sets the OS. Listens to: [detected]"
|
||||
echo " UNIX, OSX, FREEBSD, MORPHOS"
|
||||
echo " BEOS, SUNOS, CYGWIN, MINGW, OS2"
|
||||
echo " --windres Sets the windres (Windows) [windres]"
|
||||
echo " --force-le Force LE platform [no]"
|
||||
echo " --force-be Force BE platform [no]"
|
||||
echo ""
|
||||
echo "Params that can be used with --with or --without"
|
||||
echo " (e.g.: --without-static disables static (default))"
|
||||
echo " static Do you want a static build? [no]"
|
||||
echo " directmusic Do you want direct-music? [no]"
|
||||
echo " zlib Do you want zlib-support? [yes]"
|
||||
echo " sdl Do you want SDL-support? [yes]"
|
||||
echo " png Do you want PNG-support? [yes]"
|
||||
echo " iconv Do you want iconv-support? [no]"
|
||||
echo " network Do you want network-support? [yes]"
|
||||
echo " cocoa Do you want cocoa-support? (MacOSX) [no]"
|
||||
echo " freetype Do you want freetype-support? [yes]"
|
||||
echo " fontconfig Do you want fontconfig-support? [yes]"
|
||||
echo ""
|
||||
echo "Params used to configure external libs:"
|
||||
echo " --static-zlib-path Set the path to your static zlib []"
|
||||
echo " --sdl-config Where is your sdl-config [sdl-config]"
|
||||
echo " --libpng-config Where is your libpng-config [libpng-config]"
|
||||
echo " --freetype-config Where is your freetype-config [freetype-config]"
|
||||
echo " --fontconfig-config Where is your fontconfig-config [pkg-config fontconfig]"
|
||||
echo " --with-iconv Set the path to your iconv headers []"
|
||||
echo " "
|
||||
}
|
||||
|
||||
CONFIGURE_EXECUTABLE="$_"
|
||||
# On *nix systems those two are equal when ./configure is done
|
||||
if [ "$0" != "$CONFIGURE_EXECUTABLE" ]; then
|
||||
# On some systems, when ./configure is triggered from 'make'
|
||||
# the $_ is filled with 'make'. So if that is true, skip 'make'
|
||||
# and use $0 (and hope that is correct ;))
|
||||
if [ -n "`echo $CONFIGURE_EXECUTABLE | grep make`" ]; then
|
||||
CONFIGURE_EXECUTABLE="$0"
|
||||
else
|
||||
CONFIGURE_EXECUTABLE="$CONFIGURE_EXECUTABLE $0"
|
||||
handle() {
|
||||
PARAM="$PARAM \"$1=`awk 'BEGIN { FS="="; $0="'"$2"'"; print $2;}'`\""
|
||||
}
|
||||
|
||||
# The things you can use inside this case:
|
||||
# handle NAME VALUE - Sets the value to give the 'make upgradeconf'
|
||||
# Value is in form: tag=REAL_VALUE
|
||||
# ITEM="NAME" - Will set the value as above, only with the next param
|
||||
# SITEM="NAME" - Will set the var $NAME to the next param
|
||||
for n in "$@"
|
||||
do
|
||||
case "$n" in
|
||||
--help | -h)
|
||||
showhelp
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--debug)
|
||||
DEBUG_SET=1
|
||||
ITEM="DEBUG"
|
||||
;;
|
||||
--debug=*)
|
||||
handle "DEBUG" "$n"
|
||||
;;
|
||||
--profile)
|
||||
PARAM="$PARAM PROFILE=1"
|
||||
;;
|
||||
--dedicated)
|
||||
PARAM="$PARAM DEDICATED=1"
|
||||
;;
|
||||
--revision=*)
|
||||
RELEASE=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--revision)
|
||||
SITEM="RELEASE"
|
||||
;;
|
||||
--target-cc=*)
|
||||
handle "CC_TARGET" "$n"
|
||||
;;
|
||||
--target-cc)
|
||||
ITEM="CC_TARGET"
|
||||
;;
|
||||
--target-cxx=*)
|
||||
handle "CXX_TARGET" "$n"
|
||||
;;
|
||||
--target-cxx)
|
||||
SITEM="CXX_TARGET"
|
||||
;;
|
||||
--host-cc=*)
|
||||
handle "CC_HOST" "$n"
|
||||
;;
|
||||
--host-cc)
|
||||
ITEM="CC_HOST"
|
||||
;;
|
||||
--host-cxx=*)
|
||||
handle "CXX_HOST" "$n"
|
||||
;;
|
||||
--host-cxx)
|
||||
ITEM="CXX_HOST"
|
||||
;;
|
||||
--host-cflags=*)
|
||||
handle CFLAGS_HOST "$n"
|
||||
;;
|
||||
--host-cflags)
|
||||
ITEM="CFLAGS_HOST"
|
||||
;;
|
||||
--os=*)
|
||||
TARGET_OS=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--os)
|
||||
SITEM="TARGET_OS"
|
||||
;;
|
||||
--windres=*)
|
||||
handle WINDRES "$n"
|
||||
;;
|
||||
--windres)
|
||||
ITEM="WINDRES"
|
||||
;;
|
||||
--force-le)
|
||||
PARAM="$PARAM ENDIAN_FORCE=LE"
|
||||
;;
|
||||
--force-be)
|
||||
PARAM="$PARAM ENDIAN_FORCE=BE"
|
||||
;;
|
||||
|
||||
--with-static)
|
||||
PARAM="$PARAM STATIC=1"
|
||||
;;
|
||||
--without-static)
|
||||
PARAM="$PARAM STATIC="
|
||||
;;
|
||||
--with-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC=1"
|
||||
;;
|
||||
--without-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC="
|
||||
;;
|
||||
--with-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB=1"
|
||||
;;
|
||||
--without-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB="
|
||||
;;
|
||||
--with-sdl)
|
||||
PARAM="$PARAM WITH_SDL=1"
|
||||
;;
|
||||
--without-sdl)
|
||||
PARAM="$PARAM WITH_SDL="
|
||||
;;
|
||||
--with-png)
|
||||
PARAM="$PARAM WITH_PNG=1"
|
||||
;;
|
||||
--without-png)
|
||||
PARAM="$PARAM WITH_PNG="
|
||||
;;
|
||||
--with-iconv)
|
||||
PARAM="$PARAM WITH_ICONV=1"
|
||||
;;
|
||||
--with-iconv=*)
|
||||
PARAM="$PARAM WITH_ICONV=1"
|
||||
handle WITH_ICONV_PATH "$n"
|
||||
;;
|
||||
--without-iconv)
|
||||
PARAM="$PARAM WITH_ICONV="
|
||||
;;
|
||||
--with-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA=1"
|
||||
;;
|
||||
--with-network)
|
||||
PARAM="$PARAM WITH_NETWORK=1"
|
||||
;;
|
||||
--without-network)
|
||||
PARAM="$PARAM WITH_NETWORK="
|
||||
;;
|
||||
--without-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA="
|
||||
;;
|
||||
--with-freetype)
|
||||
PARAM="$PARAM WITH_FREETYPE=1"
|
||||
;;
|
||||
--without-freetype)
|
||||
PARAM="$PARAM WITH_FREETYPE="
|
||||
;;
|
||||
--with-fontconfig)
|
||||
PARAM="$PARAM WITH_FONTCONFIG=1"
|
||||
;;
|
||||
--without-fontconfig)
|
||||
PARAM="$PARAM WITH_FONTCONFIG="
|
||||
;;
|
||||
--static-zlib-path=*)
|
||||
handle STATIC_ZLIB_PATH "$n"
|
||||
;;
|
||||
--static-zlib-path)
|
||||
ITEM="STATIC_ZLIB_PATH"
|
||||
;;
|
||||
--sdl-config=*)
|
||||
handle SDL_CONFIG "$n"
|
||||
;;
|
||||
--sdl-config)
|
||||
ITEM="SDL_CONFIG"
|
||||
;;
|
||||
--libpng-config=*)
|
||||
handle LIBPNG_CONFIG "$n"
|
||||
;;
|
||||
--libpng-config)
|
||||
ITEM="LIBPNG_CONFIG"
|
||||
;;
|
||||
--freetype-config=*)
|
||||
handle FREETYPE_CONFIG "$n"
|
||||
;;
|
||||
--freetype-config)
|
||||
ITEM="FREETYPE_CONFIG"
|
||||
;;
|
||||
--fontconfig-config=*)
|
||||
handle FONTCONFIG_CONFIG "$n"
|
||||
;;
|
||||
--fontconfig-config)
|
||||
ITEM="FONTCONFIG_CONFIG"
|
||||
;;
|
||||
|
||||
--*=*)
|
||||
echo -n "Unknown switch "
|
||||
echo `awk 'BEGIN { FS="="; $0="'"$n"'"; print $1;}'`
|
||||
exit 1
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
if ! test -z "$ITEM"
|
||||
then
|
||||
PARAM="$PARAM $ITEM=\"$n\""
|
||||
ITEM="";
|
||||
elif ! test -z "$SITEM"
|
||||
then
|
||||
export $SITEM="$n"
|
||||
SITEM=""
|
||||
else
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! test -z "$TARGET_OS"
|
||||
then
|
||||
TARGET_OS=`echo $TARGET_OS | tr '[:lower:]' '[:upper:]'`
|
||||
case "$TARGET_OS" in
|
||||
WIN32)
|
||||
PARAM="$PARAM WIN32=1"
|
||||
;;
|
||||
UNIX)
|
||||
PARAM="$PARAM UNIX=1"
|
||||
;;
|
||||
OSX)
|
||||
PARAM="$PARAM OSX=1 UNIX=1"
|
||||
;;
|
||||
FREEBSD)
|
||||
PARAM="$PARAM FREEBSD=1"
|
||||
;;
|
||||
MORPHOS)
|
||||
PARAM="$PARAM MORPHOS=1 UNIX=1"
|
||||
;;
|
||||
BEOS)
|
||||
PARAM="$PARAM BEOS=1 UNIX=1"
|
||||
;;
|
||||
OS2)
|
||||
PARAM="$PARAM OS2=1 UNIX=1"
|
||||
;;
|
||||
SUNOS)
|
||||
PARAM="$PARAM SUNOS=1 UNIX=1"
|
||||
;;
|
||||
CYGWIN)
|
||||
PARAM="$PARAM CYGWIN=1 WIN32=1"
|
||||
;;
|
||||
MINGW)
|
||||
PARAM="$PARAM MINGW=1 WIN32=1"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OS: $TARGET_OS"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
PARAM="$PARAM BYPASS_OS_DETECT=1"
|
||||
fi
|
||||
|
||||
if ! test -z "$DEBUG_SET"
|
||||
then
|
||||
if test -z "`echo $PARAM | grep "DEBUG="`"
|
||||
then
|
||||
# Someone did --debug, without assigning a value, assume 1
|
||||
PARAM="$PARAM DEBUG=1"
|
||||
fi
|
||||
fi
|
||||
# Find out where configure is (in what dir)
|
||||
ROOT_DIR="`dirname $0`"
|
||||
# For MSYS/MinGW we want to know the FULL path. This as that path is generated
|
||||
# once you call an outside binary. Having the same path for the rest is needed
|
||||
# for dependency checking.
|
||||
# pwd -W returns said FULL path, but doesn't exist on others so fall back.
|
||||
ROOT_DIR="`cd $ROOT_DIR && (pwd -W 2>/dev/null || pwd 2>/dev/null)`"
|
||||
|
||||
check_path_characters
|
||||
# First remove the Makefile.config, else you can have double entries
|
||||
rm -f Makefile.config
|
||||
|
||||
# Same here as for the ROOT_DIR above
|
||||
PWD="`pwd -W 2>/dev/null || pwd 2>/dev/null`"
|
||||
PREFIX="$PWD/bin"
|
||||
echo "make upgradeconf $PARAM" > ./Makefile.run
|
||||
. ./Makefile.run
|
||||
rm -f ./Makefile.run
|
||||
|
||||
. $ROOT_DIR/config.lib
|
||||
# Makefile.config currently doesn't support custom RELEASE (revision), so, we add the line
|
||||
# yourself!
|
||||
|
||||
# Set default dirs
|
||||
OBJS_DIR="$PWD/objs"
|
||||
BASE_SRC_OBJS_DIR="$OBJS_DIR"
|
||||
LANG_OBJS_DIR="$OBJS_DIR/lang"
|
||||
GRF_OBJS_DIR="$OBJS_DIR/extra_grf"
|
||||
SETTING_OBJS_DIR="$OBJS_DIR/setting"
|
||||
BIN_DIR="$PREFIX"
|
||||
SRC_DIR="$ROOT_DIR/src"
|
||||
LANG_DIR="$SRC_DIR/lang"
|
||||
MEDIA_DIR="$ROOT_DIR/media"
|
||||
SOURCE_LIST="$ROOT_DIR/source.list"
|
||||
|
||||
if [ "$1" = "--reconfig" ] || [ "$1" = "--reconfigure" ]; then
|
||||
if [ ! -f "config.cache" ]; then
|
||||
echo "can't reconfigure, because never configured before"
|
||||
exit 1
|
||||
fi
|
||||
# Make sure we don't lock config.cache
|
||||
cat config.cache | sed 's@\\ @\\\\ @g' > cache.tmp
|
||||
sh cache.tmp
|
||||
RET=$?
|
||||
rm -f cache.tmp
|
||||
exit $RET
|
||||
if ! test -z "$RELEASE"
|
||||
then
|
||||
echo "RELEASE=$RELEASE" >> Makefile.config
|
||||
fi
|
||||
|
||||
set_default
|
||||
detect_params "$@"
|
||||
check_params
|
||||
save_params
|
||||
make_cflags_and_ldflags
|
||||
|
||||
EXE=""
|
||||
if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ] || [ "$os" = "WINCE" ]; then
|
||||
EXE=".exe"
|
||||
fi
|
||||
|
||||
TTD="openttd$EXE"
|
||||
STRGEN="strgen$EXE"
|
||||
ENDIAN_CHECK="endian_check$EXE"
|
||||
DEPEND="depend$EXE"
|
||||
SETTINGSGEN="settings_gen$EXE"
|
||||
|
||||
if [ -z "$sort" ]; then
|
||||
PIPE_SORT="sed s@a@a@"
|
||||
else
|
||||
PIPE_SORT="$sort"
|
||||
fi
|
||||
|
||||
if [ ! -f "$LANG_DIR/english.txt" ]; then
|
||||
echo "Languages not found in $LANG_DIR. Can't continue without it."
|
||||
echo "Please make sure the dir exists and contains at least english.txt"
|
||||
fi
|
||||
|
||||
# Read the source.list and process it
|
||||
AWKCOMMAND='
|
||||
{ }
|
||||
/^( *)#end/ { if (deep == skip) { skip -= 1; } deep -= 1; next; }
|
||||
/^( *)#else/ { if (deep == skip) { skip -= 1; } else if (deep - 1 == skip) { skip += 1; } next; }
|
||||
/^( *)#if/ {
|
||||
gsub(" ", "", $0);
|
||||
gsub("^#if ", "", $0);
|
||||
|
||||
if (deep != skip) { deep += 1; next; }
|
||||
|
||||
deep += 1;
|
||||
|
||||
if ($0 == "ALLEGRO" && "'$allegro_config'" == "") { next; }
|
||||
if ($0 == "SDL" && "'$sdl_config'" == "") { next; }
|
||||
if ($0 == "PNG" && "'$png_config'" == "") { next; }
|
||||
if ($0 == "OSX" && "'$os'" != "OSX") { next; }
|
||||
if ($0 == "OS2" && "'$os'" != "OS2") { next; }
|
||||
if ($0 == "PSP" && "'$os'" != "PSP") { next; }
|
||||
if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; }
|
||||
if ($0 == "AI" && "'$enable_ai'" == "0") { next; }
|
||||
if ($0 == "COCOA" && "'$with_cocoa'" == "0") { next; }
|
||||
if ($0 == "DOS" && "'$os'" != "DOS") { next; }
|
||||
if ($0 == "BEOS" && "'$os'" != "BEOS" &&
|
||||
"'$os'" != "HAIKU") { next; }
|
||||
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
|
||||
"'$os'" != "CYGWIN" && "'$os'" != "MSVC") { next; }
|
||||
if ($0 == "MORPHOS" && "'$os'" != "MORPHOS") { next; }
|
||||
if ($0 == "WINCE" && "'$os'" != "WINCE") { next; }
|
||||
if ($0 == "MSVC" && "'$os'" != "MSVC") { next; }
|
||||
if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; }
|
||||
if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; }
|
||||
if ($0 == "HAVE_THREAD" && "'$with_threads'" == "0") { next; }
|
||||
if ($0 == "SSE" && "'$with_sse'" != "1") { next; }
|
||||
|
||||
skip += 1;
|
||||
|
||||
next;
|
||||
}
|
||||
/^( *)#/ { next }
|
||||
/^$/ { next }
|
||||
/\.h$/ { next }
|
||||
/\.hpp$/ { next }
|
||||
{
|
||||
if (deep == skip) {
|
||||
gsub(" ", "", $0);
|
||||
print $0;
|
||||
}
|
||||
}
|
||||
'
|
||||
|
||||
# Read the source.list and process it
|
||||
# Please escape ALL " within ` because e.g. "" terminates the string in some sh implementations
|
||||
SRCS="`< $ROOT_DIR/source.list tr '\r' '\n' | $awk \"$AWKCOMMAND\" | LC_ALL=C $PIPE_SORT`"
|
||||
|
||||
OBJS_C="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.c$/ { gsub(\".c$\", \".o\", $0); print $0; }'`"
|
||||
OBJS_CPP="`echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.cpp$/ { gsub(\".cpp$\", \".o\", $0); print $0; }'`"
|
||||
OBJS_MM="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.mm$/ { gsub(\".mm$\", \".o\", $0); print $0; }'`"
|
||||
OBJS_RC="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.rc$/ { gsub(\".rc$\", \".o\", $0); print $0; }'`"
|
||||
SRCS="` echo \"$SRCS\" | $awk ' { ORS = \" \" } { print $0; }'`"
|
||||
|
||||
# In makefiles, we always use -u for sort
|
||||
if [ -z "$sort" ]; then
|
||||
sort="sed s@a@a@"
|
||||
else
|
||||
sort="$sort -u"
|
||||
fi
|
||||
|
||||
CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.grf.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in $ROOT_DIR/Makefile.setting.in"
|
||||
|
||||
generate_main
|
||||
generate_lang
|
||||
generate_settings
|
||||
generate_grf
|
||||
generate_src
|
||||
|
||||
check_path_characters
|
||||
|
160
console.h
Normal file
160
console.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
// maximum length of a typed in command
|
||||
#define ICON_CMDLN_SIZE 255
|
||||
// maximum length of a totally expanded command
|
||||
#define ICON_MAX_STREAMSIZE 1024
|
||||
|
||||
typedef enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_BOOLEAN,
|
||||
ICONSOLE_VAR_BYTE,
|
||||
ICONSOLE_VAR_UINT16,
|
||||
ICONSOLE_VAR_UINT32,
|
||||
ICONSOLE_VAR_INT16,
|
||||
ICONSOLE_VAR_INT32,
|
||||
ICONSOLE_VAR_STRING
|
||||
} IConsoleVarTypes;
|
||||
|
||||
typedef enum IConsoleModes {
|
||||
ICONSOLE_FULL,
|
||||
ICONSOLE_OPENED,
|
||||
ICONSOLE_CLOSED
|
||||
} IConsoleModes;
|
||||
|
||||
typedef enum IConsoleHookTypes {
|
||||
ICONSOLE_HOOK_ACCESS,
|
||||
ICONSOLE_HOOK_PRE_ACTION,
|
||||
ICONSOLE_HOOK_POST_ACTION
|
||||
} IConsoleHookTypes;
|
||||
|
||||
/** --Hooks--
|
||||
* Hooks are certain triggers get get accessed/executed on either
|
||||
* access, before execution/change or after execution/change. This allows
|
||||
* for general flow of permissions or special action needed in some cases
|
||||
*/
|
||||
typedef bool IConsoleHook(void);
|
||||
typedef struct IConsoleHooks{
|
||||
IConsoleHook *access; // trigger when accessing the variable/command
|
||||
IConsoleHook *pre; // trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; // trigger after the variable/command is changed/executed
|
||||
} IConsoleHooks;
|
||||
|
||||
/** --Commands--
|
||||
* Commands are commands, or functions. They get executed once and any
|
||||
* effect they produce are carried out. The arguments to the commands
|
||||
* are given to them, each input word seperated by a double-quote (") is an argument
|
||||
* If you want to handle multiple words as one, enclose them in double-quotes
|
||||
* eg. 'say "hello sexy boy"'
|
||||
*/
|
||||
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
|
||||
|
||||
struct IConsoleCmd;
|
||||
typedef struct IConsoleCmd {
|
||||
char *name; // name of command
|
||||
struct IConsoleCmd *next; // next command in list
|
||||
|
||||
IConsoleCmdProc *proc; // process executed when command is typed
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleCmd;
|
||||
|
||||
/** --Variables--
|
||||
* Variables are pointers to real ingame variables which allow for
|
||||
* changing while ingame. After changing they keep their new value
|
||||
* and can be used for debugging, gameplay, etc. It accepts:
|
||||
* - no arguments; just print out current value
|
||||
* - '= <new value>' to assign a new value to the variable
|
||||
* - '++' to increase value by one
|
||||
* - '--' to decrease value by one
|
||||
*/
|
||||
struct IConsoleVar;
|
||||
typedef struct IConsoleVar {
|
||||
char *name; // name of the variable
|
||||
struct IConsoleVar *next; // next variable in list
|
||||
|
||||
void *addr; // the address where the variable is pointing at
|
||||
uint32 size; // size of the variable, used for strings
|
||||
char *help; // the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; // type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleVar;
|
||||
|
||||
/** --Aliases--
|
||||
* Aliases are like shortcuts for complex functions, variable assignments,
|
||||
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
|
||||
* 'list_vars' for example), or concatenate more commands into one
|
||||
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
|
||||
* given to them in the command line.
|
||||
* - "%A - %Z" substitute arguments 1 t/m 26
|
||||
* - "%+" lists all parameters keeping them seperated
|
||||
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
|
||||
* - ";" allows for combining commands (see example 'ng')
|
||||
*/
|
||||
struct IConsoleAlias;
|
||||
typedef struct IConsoleAlias {
|
||||
char *name; // name of the alias
|
||||
struct IConsoleAlias *next; // next alias in list
|
||||
|
||||
char *cmdline; // command(s) that is/are being aliased
|
||||
} IConsoleAlias;
|
||||
|
||||
/* console parser */
|
||||
VARDEF IConsoleCmd *_iconsole_cmds; // list of registred commands
|
||||
VARDEF IConsoleVar *_iconsole_vars; // list of registred vars
|
||||
VARDEF IConsoleAlias *_iconsole_aliases; // list of registred aliases
|
||||
|
||||
/* console colors/modes */
|
||||
VARDEF byte _icolour_def;
|
||||
VARDEF byte _icolour_err;
|
||||
VARDEF byte _icolour_warn;
|
||||
VARDEF byte _icolour_dbg;
|
||||
VARDEF byte _icolour_cmd;
|
||||
VARDEF IConsoleModes _iconsole_mode;
|
||||
|
||||
/* console functions */
|
||||
void IConsoleInit(void);
|
||||
void IConsoleFree(void);
|
||||
void IConsoleClearBuffer(void);
|
||||
void IConsoleResize(Window *w);
|
||||
void IConsoleSwitch(void);
|
||||
void IConsoleClose(void);
|
||||
void IConsoleOpen(void);
|
||||
|
||||
/* console output */
|
||||
void IConsolePrint(uint16 color_code, const char *string);
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
|
||||
void IConsoleDebug(const char *string);
|
||||
void IConsoleWarning(const char *string);
|
||||
void IConsoleError(const char *string);
|
||||
|
||||
/* Commands */
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
|
||||
void IConsoleAliasRegister(const char *name, const char *cmd);
|
||||
IConsoleCmd *IConsoleCmdGet(const char *name);
|
||||
IConsoleAlias *IConsoleAliasGet(const char *name);
|
||||
|
||||
/* Variables */
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
|
||||
IConsoleVar* IConsoleVarGet(const char *name);
|
||||
void IConsoleVarPrintGetValue(const IConsoleVar *var);
|
||||
void IConsoleVarPrintSetValue(const IConsoleVar *var);
|
||||
|
||||
/* Parser */
|
||||
void IConsoleCmdExec(const char *cmdstr);
|
||||
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
|
||||
|
||||
/* console std lib (register ingame commands/aliases/variables) */
|
||||
void IConsoleStdLibRegister(void);
|
||||
|
||||
/* Hooking code */
|
||||
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
|
||||
|
||||
/* Supporting functions */
|
||||
bool GetArgumentInteger(uint32 *value, const char *arg);
|
||||
#endif /* CONSOLE_H */
|
1643
console_cmds.c
Normal file
1643
console_cmds.c
Normal file
File diff suppressed because it is too large
Load Diff
187
currency.c
Normal file
187
currency.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "currency.h"
|
||||
#include "news.h"
|
||||
#include "variables.h"
|
||||
#include "table/strings.h"
|
||||
#include "date.h"
|
||||
|
||||
// exchange rate prefix symbol_pos
|
||||
// | separator | postfix |
|
||||
// | | Euro year | | | name
|
||||
// | | | | | | |
|
||||
static const CurrencySpec origin_currency_specs[NUM_CURRENCY] = {
|
||||
{ 1, ',', CF_NOEURO, "£", "", 0, STR_CURR_GBP }, // british pounds
|
||||
{ 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, // us dollars
|
||||
{ 2, ',', CF_ISEURO, "€", "", 0, STR_CURR_EUR }, // Euro
|
||||
{ 220, ',', CF_NOEURO, "¥", "", 0, STR_CURR_YEN }, // yen
|
||||
{ 20, ',', 2002, "", " S.", 1, STR_CURR_ATS }, // austrian schilling
|
||||
{ 59, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, // belgian franc
|
||||
{ 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, // swiss franc
|
||||
{ 41, ',', CF_NOEURO, "", " Kč", 1, STR_CURR_CZK }, // czech koruna
|
||||
{ 3, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, // deutsche mark
|
||||
{ 11, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, // danish krone
|
||||
{ 245, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, // spanish pesetas
|
||||
{ 9, ',', 2002, "", " mk", 1, STR_CURR_FIM }, // finnish markka
|
||||
{ 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, // french francs
|
||||
{ 500, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, // greek drachma
|
||||
{ 378, ',', 2010, "", " Ft", 1, STR_CURR_HUF }, // hungarian forint
|
||||
{ 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, // icelandic krona
|
||||
{ 2850, ',', 2002, "", " L.", 1, STR_CURR_ITL }, // italian lira
|
||||
{ 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, // dutch gulden
|
||||
{ 12, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, // norwegian krone
|
||||
{ 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, // polish zloty
|
||||
{ 5, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, // romanian Lei
|
||||
{ 50, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, // russian rouble
|
||||
{ 352, '.', CF_NOEURO, "", " SIT", 1, STR_CURR_SIT }, // slovenian tolar
|
||||
{ 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, // swedish krona
|
||||
{ 3, '.', CF_NOEURO, "", " YTL", 1, STR_CURR_YTL }, // turkish lira
|
||||
{ 52, ',', CF_NOEURO, "", " Sk", 1, STR_CURR_SKK }, // slovak koruna
|
||||
{ 4, ',', CF_NOEURO, "R$ ", "", 0, STR_CURR_BRR }, // brazil real
|
||||
{ 1, ' ', CF_NOEURO, "", "", 2, STR_CURR_CUSTOM }, // custom currency
|
||||
};
|
||||
|
||||
/* Array of currencies used by the system */
|
||||
CurrencySpec _currency_specs[NUM_CURRENCY];
|
||||
|
||||
/**
|
||||
* These enums are only declared in order to make sens
|
||||
* out of the TTDPatch_To_OTTDIndex array that will follow
|
||||
* Every currency used by Ottd is there, just in case TTDPatch will
|
||||
* add those missing in its code
|
||||
**/
|
||||
enum {
|
||||
CURR_GBP,
|
||||
CURR_USD,
|
||||
CURR_EUR,
|
||||
CURR_YEN,
|
||||
CURR_ATS,
|
||||
CURR_BEF,
|
||||
CURR_CHF,
|
||||
CURR_CZK,
|
||||
CURR_DEM,
|
||||
CURR_DKK,
|
||||
CURR_ESP,
|
||||
CURR_FIM,
|
||||
CURR_FRF,
|
||||
CURR_GRD,
|
||||
CURR_HUF,
|
||||
CURR_ISK,
|
||||
CURR_ITL,
|
||||
CURR_NLG,
|
||||
CURR_NOK,
|
||||
CURR_PLN,
|
||||
CURR_ROL,
|
||||
CURR_RUR,
|
||||
CURR_SIT,
|
||||
CURR_SEK,
|
||||
CURR_YTL,
|
||||
};
|
||||
|
||||
/**
|
||||
* This array represent the position of OpenTTD's currencies,
|
||||
* compared to TTDPatch's ones.
|
||||
* When a grf sends currencies, they are based on the order defined by TTDPatch.
|
||||
* So, we must reindex them to our own order.
|
||||
**/
|
||||
const byte TTDPatch_To_OTTDIndex[] =
|
||||
{
|
||||
CURR_GBP,
|
||||
CURR_USD,
|
||||
CURR_FRF,
|
||||
CURR_DEM,
|
||||
CURR_YEN,
|
||||
CURR_ESP,
|
||||
CURR_HUF,
|
||||
CURR_PLN,
|
||||
CURR_ATS,
|
||||
CURR_BEF,
|
||||
CURR_DKK,
|
||||
CURR_FIM,
|
||||
CURR_GRD,
|
||||
CURR_CHF,
|
||||
CURR_NLG,
|
||||
CURR_ITL,
|
||||
CURR_SEK,
|
||||
CURR_RUR,
|
||||
CURR_EUR,
|
||||
};
|
||||
|
||||
/**
|
||||
* Will return the ottd's index correspondance to
|
||||
* the ttdpatch's id. If the id is bigger then the array,
|
||||
* it is a grf written for ottd, thus returning the same id.
|
||||
* Only called from newgrf.c
|
||||
* @param grfcurr_id currency id coming from newgrf
|
||||
* @return the corrected index
|
||||
**/
|
||||
byte GetNewgrfCurrencyIdConverted(byte grfcurr_id)
|
||||
{
|
||||
return (grfcurr_id >= lengthof(TTDPatch_To_OTTDIndex)) ? grfcurr_id : TTDPatch_To_OTTDIndex[grfcurr_id];
|
||||
}
|
||||
|
||||
/* get a mask of the allowed currencies depending on the year */
|
||||
uint GetMaskOfAllowedCurrencies(void)
|
||||
{
|
||||
uint mask = 0;
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < NUM_CURRENCY; i++) {
|
||||
Year to_euro = _currency_specs[i].to_euro;
|
||||
|
||||
if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue;
|
||||
if (to_euro == CF_ISEURO && _cur_year < 2000) continue;
|
||||
mask |= (1 << i);
|
||||
}
|
||||
mask |= (1 << CUSTOM_CURRENCY_ID); // always allow custom currency
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the currency chosen by the user is about to be converted to Euro
|
||||
**/
|
||||
void CheckSwitchToEuro(void)
|
||||
{
|
||||
if (_currency_specs[_opt.currency].to_euro != CF_NOEURO &&
|
||||
_currency_specs[_opt.currency].to_euro != CF_ISEURO &&
|
||||
_cur_year >= _currency_specs[_opt.currency].to_euro) {
|
||||
_opt.currency = 2; // this is the index of euro above.
|
||||
AddNewsItem(STR_EURO_INTRODUCE, NEWS_FLAGS(NM_NORMAL, 0, NT_ECONOMY, 0), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will fill _currency_specs array with
|
||||
* default values from origin_currency_specs
|
||||
* Called only from newgrf.c and settings.c.
|
||||
* @param preserve_custom will not reset custom currency (the latest one on the list)
|
||||
* if ever it is flagged to true. In which case, the total size of the memory to move
|
||||
* will be one currency spec less, thus preserving the custom curreny from been
|
||||
* overwritten.void ResetCurrencies(bool preserve_custom)
|
||||
*/
|
||||
void ResetCurrencies(bool preserve_custom)
|
||||
{
|
||||
memcpy(&_currency_specs, &origin_currency_specs, sizeof(origin_currency_specs) - (preserve_custom ? sizeof(_custom_currency) : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of currency names StringIDs to use in a dropdown list
|
||||
* @return Pointer to a (static) array of StringIDs
|
||||
*/
|
||||
StringID* BuildCurrencyDropdown(void)
|
||||
{
|
||||
/* Allow room for all currencies, plus a terminator entry */
|
||||
static StringID names[NUM_CURRENCY + 1];
|
||||
uint i;
|
||||
|
||||
/* Add each name */
|
||||
for (i = 0; i < NUM_CURRENCY; i++) {
|
||||
names[i] = _currency_specs[i].name;
|
||||
}
|
||||
/* Terminate the list */
|
||||
names[i] = INVALID_STRING_ID;
|
||||
|
||||
return names;
|
||||
}
|
45
currency.h
Normal file
45
currency.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef CURRENCY_H
|
||||
#define CURRENCY_H
|
||||
|
||||
enum {
|
||||
CF_NOEURO = 0,
|
||||
CF_ISEURO = 1,
|
||||
NUM_CURRENCY = 28,
|
||||
CUSTOM_CURRENCY_ID = NUM_CURRENCY - 1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 rate;
|
||||
char separator;
|
||||
Year to_euro;
|
||||
char prefix[16];
|
||||
char suffix[16];
|
||||
/**
|
||||
* The currency symbol is represented by two possible values, prefix and suffix
|
||||
* Usage of one or the other is determined by symbol_pos.
|
||||
* 0 = prefix
|
||||
* 1 = suffix
|
||||
* 2 = both : Special case only for custom currency.
|
||||
* It is not a spec from Newgrf,
|
||||
* rather a way to let users do what they want with custom curency
|
||||
*/
|
||||
byte symbol_pos;
|
||||
StringID name;
|
||||
} CurrencySpec;
|
||||
|
||||
|
||||
extern CurrencySpec _currency_specs[NUM_CURRENCY];
|
||||
|
||||
// XXX small hack, but makes the rest of the code a bit nicer to read
|
||||
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
|
||||
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
|
||||
|
||||
uint GetMaskOfAllowedCurrencies(void);
|
||||
void CheckSwitchToEuro(void);
|
||||
void ResetCurrencies(bool preserve_custom);
|
||||
StringID* BuildCurrencyDropdown(void);
|
||||
byte GetNewgrfCurrencyIdConverted(byte grfcurr_id);
|
||||
|
||||
#endif /* CURRENCY_H */
|
BIN
data/2ccmap.grf
Normal file
BIN
data/2ccmap.grf
Normal file
Binary file not shown.
BIN
data/airports.grf
Normal file
BIN
data/airports.grf
Normal file
Binary file not shown.
BIN
data/autorail.grf
Normal file
BIN
data/autorail.grf
Normal file
Binary file not shown.
BIN
data/canalsw.grf
Normal file
BIN
data/canalsw.grf
Normal file
Binary file not shown.
BIN
data/dosdummy.grf
Normal file
BIN
data/dosdummy.grf
Normal file
Binary file not shown.
BIN
data/elrailsw.grf
Normal file
BIN
data/elrailsw.grf
Normal file
Binary file not shown.
BIN
data/nsignalsw.grf
Normal file
BIN
data/nsignalsw.grf
Normal file
Binary file not shown.
BIN
data/openttd.grf
Normal file
BIN
data/openttd.grf
Normal file
Binary file not shown.
BIN
data/opntitle.dat
Normal file
BIN
data/opntitle.dat
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user