mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-07-16 15:49:43 +00:00
Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9df8a3bd4c | |||
| 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 |
-12
@@ -1,12 +0,0 @@
|
||||
Makefile*
|
||||
bin/*
|
||||
bundle/*
|
||||
!bin/data/chars.grf
|
||||
!bin/data/openttdd.grf
|
||||
!bin/data/openttdw.grf
|
||||
!bin/data/opntitle.grf
|
||||
!bin/scenario/README
|
||||
!bin/scripts*
|
||||
config.*
|
||||
objs/*
|
||||
src/rev.cpp
|
||||
@@ -1,11 +0,0 @@
|
||||
bin/lang/*
|
||||
bin/opentd*
|
||||
bundle/*
|
||||
config.cache.*
|
||||
config.log
|
||||
config.pwd
|
||||
Makefile
|
||||
Makefile.am
|
||||
media/openttd.desktop*
|
||||
objs/*
|
||||
src/rev.cpp
|
||||
@@ -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)
|
||||
@@ -1,10 +1,11 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# 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" \
|
||||
@@ -76,14 +77,13 @@ WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./src/
|
||||
INPUT = ./
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
*.hpp \
|
||||
table/*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
@@ -158,7 +158,7 @@ RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_MAN = YES
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
@@ -185,13 +185,13 @@ PERLMOD_MAKEVAR_PREFIX =
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED = DEF_COMMAND
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
@@ -220,6 +220,8 @@ DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
#
|
||||
# Creation of bundles
|
||||
#
|
||||
|
||||
# The revision is needed for the bundle name and creating an OSX application bundle.
|
||||
ifdef REVISION
|
||||
REV := $(REVISION)
|
||||
else
|
||||
# Detect the revision
|
||||
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
|
||||
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
|
||||
endif
|
||||
|
||||
# Make sure we have something in REV
|
||||
ifeq ($(REV),)
|
||||
REV := norev000
|
||||
endif
|
||||
|
||||
ifndef BUNDLE_NAME
|
||||
BUNDLE_NAME = openttd-custom-$(REV)-$(OS)
|
||||
endif
|
||||
|
||||
# An OSX application bundle needs the data files, lang files and openttd executable in a different location.
|
||||
ifdef OSXAPP
|
||||
DATA_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/data
|
||||
LANG_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/lang
|
||||
TTD_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/MacOS
|
||||
else
|
||||
DATA_DIR = $(BUNDLE_DIR)/data
|
||||
LANG_DIR = $(BUNDLE_DIR)/lang
|
||||
TTD_DIR = $(BUNDLE_DIR)
|
||||
endif
|
||||
|
||||
bundle: all
|
||||
@echo '[BUNDLE] Constructing bundle'
|
||||
$(Q)rm -rf "$(BUNDLE_DIR)"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/docs"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/media"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/scripts"
|
||||
$(Q)mkdir -p "$(TTD_DIR)"
|
||||
$(Q)mkdir -p "$(DATA_DIR)"
|
||||
$(Q)mkdir -p "$(LANG_DIR)"
|
||||
ifdef OSXAPP
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources"
|
||||
$(Q)echo "APPL????" > "$(BUNDLE_DIR)/$(OSXAPP)/Contents/PkgInfo"
|
||||
$(Q)cp "$(ROOT_DIR)/os/macosx/openttd.icns" "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/openttd.icns"
|
||||
$(Q)$(ROOT_DIR)/os/macosx/plistgen.sh "$(BUNDLE_DIR)/$(OSXAPP)" "$(REV)"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/OSX_install_instructions.txt" "$(BUNDLE_DIR)/docs/"
|
||||
$(Q)cp "$(ROOT_DIR)/os/macosx/splash.png" "$(DATA_DIR)"
|
||||
endif
|
||||
$(Q)cp "$(BIN_DIR)/$(TTD)" "$(TTD_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/data/"*.grf "$(DATA_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/data/"*.obg "$(DATA_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/data/opntitle.dat" "$(DATA_DIR)/"
|
||||
$(Q)cp "$(BIN_DIR)/lang/"*.lng "$(LANG_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/readme.txt" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/COPYING" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/obg_format.txt" "$(BUNDLE_DIR)/docs/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.txt" "$(BUNDLE_DIR)/docs/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/32bpp.txt" "$(BUNDLE_DIR)/docs/"
|
||||
$(Q)cp "$(ROOT_DIR)/changelog.txt" "$(BUNDLE_DIR)/"
|
||||
ifdef MAN_DIR
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/man/"
|
||||
$(Q)cp "$(ROOT_DIR)/docs/openttd.6" "$(BUNDLE_DIR)/man/"
|
||||
$(Q)gzip -9 "$(BUNDLE_DIR)/man/openttd.6"
|
||||
endif
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/"
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd."*.png "$(BUNDLE_DIR)/media/"
|
||||
$(Q)cp "$(BIN_DIR)/scripts/"* "$(BUNDLE_DIR)/scripts/"
|
||||
ifdef MENU_DIR
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/"
|
||||
$(Q)cat "$(ROOT_DIR)/media/openttd.desktop" | sed s/=openttd/=$(BINARY_NAME)/g > "$(ROOT_DIR)/media/openttd.desktop.install"
|
||||
endif
|
||||
ifeq ($(TTD), openttd.exe)
|
||||
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/readme.txt" "$(BUNDLE_DIR)/COPYING" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt"
|
||||
ifeq ($(OS), DOS)
|
||||
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.txt" "$(BUNDLE_DIR)/docs/"
|
||||
ifndef STRIP
|
||||
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.exe" "$(TTD_DIR)/"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
### Packing the current bundle into several compressed file formats ###
|
||||
#
|
||||
# Zips & dmgs do not contain a root folder, i.e. they have files in the root of the zip/dmg.
|
||||
# gzip, bzip2 and lha archives have a root folder, with the same name as the bundle.
|
||||
#
|
||||
# One can supply a custom name by adding BUNDLE_NAME:=<name> to the make command.
|
||||
#
|
||||
bundle_zip: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).zip'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)cd "$(BUNDLE_DIR)" && zip -r $(shell if test -z "$(VERBOSE)"; then echo '-q'; fi) "$(BUNDLES_DIR)/$(BUNDLE_NAME).zip" .
|
||||
|
||||
bundle_gzip: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.gz'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.gzip" && tar -zc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.gz" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.gzip"
|
||||
|
||||
bundle_bzip2: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.bz2'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.bzip2" && tar -jc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.bz2" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.bzip2"
|
||||
|
||||
bundle_lha: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).lha'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)/"
|
||||
$(Q)cd "$(BUNDLES_DIR)/.lha" && lha ao6 "$(BUNDLES_DIR)/$(BUNDLE_NAME).lha" "$(BUNDLE_NAME)"
|
||||
$(Q)rm -rf "$(BUNDLES_DIR)/.lha"
|
||||
|
||||
bundle_dmg: bundle
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).dmg'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/" "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
$(Q)hdiutil create -ov -format UDZO -srcfolder "$(BUNDLES_DIR)/OpenTTD $(REV)" "$(BUNDLES_DIR)/$(BUNDLE_NAME).dmg"
|
||||
$(Q)rm -fr "$(BUNDLES_DIR)/OpenTTD $(REV)"
|
||||
|
||||
bundle_exe: all
|
||||
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
|
||||
$(Q)mkdir -p "$(BUNDLES_DIR)"
|
||||
$(Q)unix2dos "$(ROOT_DIR)/docs/"* "$(ROOT_DIR)/readme.txt" "$(ROOT_DIR)/COPYING" "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt"
|
||||
$(Q)cd $(ROOT_DIR)/os/win32/installer && makensis.exe //DVERSION_INCLUDE=version_$(PLATFORM).txt install.nsi
|
||||
$(Q)mv $(ROOT_DIR)/os/win32/installer/*$(PLATFORM).exe "$(BUNDLES_DIR)/$(BUNDLE_NAME).exe"
|
||||
|
||||
ifdef OSXAPP
|
||||
install:
|
||||
@echo '[INSTALL] Cannot install the OSX Application Bundle'
|
||||
else
|
||||
install: bundle
|
||||
@echo '[INSTALL] Installing OpenTTD'
|
||||
$(Q)install -d "$(INSTALL_BINARY_DIR)"
|
||||
$(Q)install -d "$(INSTALL_ICON_DIR)"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/gm"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/data"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/lang"
|
||||
$(Q)install -d "$(INSTALL_DATA_DIR)/scripts"
|
||||
$(Q)install -d "$(INSTALL_DOC_DIR)"
|
||||
ifeq ($(TTD), openttd.exe)
|
||||
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}.exe"
|
||||
else
|
||||
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}"
|
||||
endif
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/lang/"* "$(INSTALL_DATA_DIR)/lang"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/data/"* "$(INSTALL_DATA_DIR)/data"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/scripts/"* "$(INSTALL_DATA_DIR)/scripts"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/docs/"* "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/"*.txt "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING" "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)/${BINARY_NAME}.32.xpm"
|
||||
ifdef ICON_THEME_DIR
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/16x16/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.16.png" "$(INSTALL_ICON_THEME_DIR)/16x16/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/32x32/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.png" "$(INSTALL_ICON_THEME_DIR)/32x32/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/48x48/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.48.png" "$(INSTALL_ICON_THEME_DIR)/48x48/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/64x64/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.64.png" "$(INSTALL_ICON_THEME_DIR)/64x64/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/128x128/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.128.png" "$(INSTALL_ICON_THEME_DIR)/128x128/apps/${BINARY_NAME}.png"
|
||||
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/256x256/apps"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.256.png" "$(INSTALL_ICON_THEME_DIR)/256x256/apps/${BINARY_NAME}.png"
|
||||
else
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/"*.png "$(INSTALL_ICON_DIR)"
|
||||
endif
|
||||
ifdef MAN_DIR
|
||||
$(Q)install -d "$(INSTALL_MAN_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/man/openttd.6.gz" "$(INSTALL_MAN_DIR)/${BINARY_NAME}.6.gz"
|
||||
endif
|
||||
ifdef MENU_DIR
|
||||
$(Q)install -d "$(INSTALL_MENU_DIR)"
|
||||
$(Q)install -m 644 "$(ROOT_DIR)/media/openttd.desktop.install" "$(INSTALL_MENU_DIR)/${BINARY_NAME}.desktop"
|
||||
endif
|
||||
endif # OSXAPP
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
include Makefile.am
|
||||
|
||||
SOURCE_LIST = !!SOURCE_LIST!!
|
||||
CONFIG_CACHE_SOURCE_LIST = !!CONFIG_CACHE_SOURCE_LIST!!
|
||||
CONFIG_CACHE_PWD = !!CONFIG_CACHE_PWD!!
|
||||
CONFIGURE_FILES = !!CONFIGURE_FILES!!
|
||||
LIPO = !!LIPO!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
ICON_THEME_DIR = !!ICON_THEME_DIR!!
|
||||
MAN_DIR = !!MAN_DIR!!
|
||||
MENU_DIR = !!MENU_DIR!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
ROOT_DIR = !!ROOT_DIR!!
|
||||
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
|
||||
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
|
||||
INSTALL_DIR = !!INSTALL_DIR!!
|
||||
INSTALL_BINARY_DIR = "$(INSTALL_DIR)/"!!BINARY_DIR!!
|
||||
INSTALL_MAN_DIR = "$(INSTALL_DIR)/$(MAN_DIR)"
|
||||
INSTALL_MENU_DIR = "$(INSTALL_DIR)/$(MENU_DIR)"
|
||||
INSTALL_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!!
|
||||
INSTALL_ICON_THEME_DIR = "$(INSTALL_DIR)/$(ICON_THEME_DIR)"
|
||||
INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!!
|
||||
INSTALL_DOC_DIR = "$(INSTALL_DIR)/"!!DOC_DIR!!
|
||||
BINARY_NAME = !!BINARY_NAME!!
|
||||
STRIP = !!STRIP!!
|
||||
TTD = !!TTD!!
|
||||
TTDS = $(SRC_DIRS:%=%/$(TTD))
|
||||
OS = !!OS!!
|
||||
OSXAPP = !!OSXAPP!!
|
||||
REVISION = !!REVISION!!
|
||||
AWK = !!AWK!!
|
||||
DISTCC = !!DISTCC!!
|
||||
|
||||
RES := $(shell if [ ! -f $(CONFIG_CACHE_PWD) ] || [ "`pwd`" != "`cat $(CONFIG_CACHE_PWD)`" ]; then echo "`pwd`" > $(CONFIG_CACHE_PWD); fi )
|
||||
RES := $(shell if [ ! -f $(CONFIG_CACHE_SOURCE_LIST) ] || [ -n "`cmp $(CONFIG_CACHE_SOURCE_LIST) $(SOURCE_LIST) 2>/dev/null`" ]; then cp $(SOURCE_LIST) $(CONFIG_CACHE_SOURCE_LIST); fi )
|
||||
|
||||
all: config.pwd config.cache
|
||||
ifdef DISTCC
|
||||
@if [ -z "`echo '$(MFLAGS)' | grep '\-j'`" ]; then echo; echo "WARNING: you enabled distcc support, but you don't seem to be using the -jN paramter"; echo; fi
|
||||
endif
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir all; \
|
||||
done
|
||||
ifdef LIPO
|
||||
# Lipo is an OSX thing. If it is defined, it means we are building for universal,
|
||||
# and so we have have to combine the binaries into one big binary
|
||||
|
||||
# Remove the last binary made by the last compiled target
|
||||
$(Q)rm -f $(BIN_DIR)/$(TTD)
|
||||
# Make all the binaries into one
|
||||
$(Q)$(LIPO) -create -output $(BIN_DIR)/$(TTD) $(TTDS)
|
||||
endif
|
||||
|
||||
help:
|
||||
@echo "Available make commands:"
|
||||
@echo ""
|
||||
@echo "Compilation:"
|
||||
@echo " all compile the executable and the lang files"
|
||||
@echo " lang compile the lang files only"
|
||||
@echo "Clean up:"
|
||||
@echo " clean remove the files generated during compilation"
|
||||
@echo " mrproper remove the files generated during configuration and compilation"
|
||||
@echo "Run after compilation:"
|
||||
@echo " run execute openttd after the compilation"
|
||||
@echo " run-gdb execute openttd in debug mode after the compilation"
|
||||
@echo " run-prof execute openttd in profiling mode after the compilation"
|
||||
@echo "Installation:"
|
||||
@echo " install install the compiled files and the data-files after the compilation"
|
||||
@echo " bundle create the base for an installation bundle"
|
||||
@echo " bundle_zip create the zip installation bundle"
|
||||
@echo " bundle_gzip create the gzip installation bundle"
|
||||
@echo " bundle_bzip2 create the bzip2 installation bundle"
|
||||
@echo " bundle_lha create the lha installation bundle"
|
||||
@echo " bundle_dmg create the dmg installation bundle"
|
||||
|
||||
config.pwd: $(CONFIG_CACHE_PWD)
|
||||
$(MAKE) reconfigure
|
||||
|
||||
config.cache: $(CONFIG_CACHE_SOURCE_LIST) $(CONFIGURE_FILES)
|
||||
$(MAKE) reconfigure
|
||||
|
||||
reconfigure:
|
||||
ifeq ($(shell if test -f config.cache; then echo 1; fi), 1)
|
||||
@echo "----------------"
|
||||
@echo "The system detected that source.list or any configure file is altered."
|
||||
@echo " Going to reconfigure with last known settings..."
|
||||
@echo "----------------"
|
||||
# Make sure we don't lock config.cache
|
||||
@$(shell cat config.cache | sed 's@\\ @\\\\ @g') || exit 1
|
||||
@echo "----------------"
|
||||
@echo "Reconfig done. Please re-execute make."
|
||||
@echo "----------------"
|
||||
else
|
||||
@echo "----------------"
|
||||
@echo "Have not found a configuration, please run configure first."
|
||||
@echo "----------------"
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
clean:
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir clean; \
|
||||
done
|
||||
$(Q)rm -rf $(BUNDLE_TARGET)
|
||||
|
||||
lang:
|
||||
@for dir in $(LANG_DIRS); do \
|
||||
$(MAKE) -C $$dir all; \
|
||||
done
|
||||
|
||||
mrproper:
|
||||
@for dir in $(DIRS); do \
|
||||
$(MAKE) -C $$dir mrproper; \
|
||||
rm -f $$dir/Makefile; \
|
||||
done
|
||||
$(Q)rm -rf objs
|
||||
$(Q)rm -f Makefile Makefile.am Makefile.bundle
|
||||
$(Q)rm -f media/openttd.desktop
|
||||
$(Q)rm -f $(CONFIG_CACHE_SOURCE_LIST) config.cache config.pwd config.log $(CONFIG_CACHE_PWD)
|
||||
$(Q)rm -rf $(BUNDLE_DIR)
|
||||
$(Q)rm -rf $(BUNDLES_DIR)
|
||||
|
||||
depend:
|
||||
@for dir in $(SRC_DIRS); do \
|
||||
$(MAKE) -C $$dir depend; \
|
||||
done
|
||||
|
||||
run: all
|
||||
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS)
|
||||
|
||||
run-gdb: all
|
||||
$(Q)cd !!BIN_DIR!! && gdb --ex run --args ./!!TTD!! $(OPENTTD_ARGS)
|
||||
|
||||
run-prof: all
|
||||
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS) && gprof !!TTD!! | less
|
||||
|
||||
regression: all
|
||||
$(Q)cd !!BIN_DIR!! && sh ai/regression/run.sh
|
||||
|
||||
%.o:
|
||||
@for dir in $(SRC_DIRS); do \
|
||||
$(MAKE) -C $$dir $(@:src/%=%); \
|
||||
done
|
||||
|
||||
%.lng:
|
||||
@for dir in $(LANG_DIRS); do \
|
||||
$(MAKE) -C $$dir $@; \
|
||||
done
|
||||
|
||||
include Makefile.bundle
|
||||
@@ -1,87 +0,0 @@
|
||||
STRGEN = !!STRGEN!!
|
||||
ENDIAN_CHECK = !!ENDIAN_CHECK!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
LANG_DIR = !!LANG_DIR!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
LANGS_SRC = $(shell ls $(LANG_DIR)/*.txt)
|
||||
LANGS = $(LANGS_SRC:$(LANG_DIR)/%.txt=%.lng)
|
||||
CXX_BUILD = !!CXX_BUILD!!
|
||||
CFLAGS_BUILD = !!CFLAGS_BUILD!!
|
||||
STRGEN_FLAGS = !!STRGEN_FLAGS!!
|
||||
STAGE = !!STAGE!!
|
||||
LANG_SUPPRESS= !!LANG_SUPPRESS!!
|
||||
LANG_OBJS_DIR= !!LANG_OBJS_DIR!!
|
||||
|
||||
ifeq ($(LANG_SUPPRESS), yes)
|
||||
LANG_ERRORS = >/dev/null 2>&1
|
||||
endif
|
||||
|
||||
# Make sure endian_host.h is reasable as if it was in the src/ dir
|
||||
CFLAGS_BUILD += -I $(LANG_OBJS_DIR)
|
||||
|
||||
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
RES := $(shell mkdir -p $(BIN_DIR)/lang )
|
||||
|
||||
all: table/strings.h $(LANGS)
|
||||
|
||||
strgen.o: $(SRC_DIR)/strgen/strgen.cpp endian_host.h $(SRC_DIR)/table/control_codes.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
string.o: $(SRC_DIR)/string.cpp endian_host.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSTRGEN -c -o $@ $<
|
||||
|
||||
lang/english.txt: $(LANG_DIR)/english.txt
|
||||
$(Q)mkdir -p lang
|
||||
$(Q)cp $(LANG_DIR)/english.txt lang/english.txt
|
||||
|
||||
$(STRGEN): alloc_func.o string.o strgen.o
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $^ -o $@
|
||||
|
||||
table/strings.h: lang/english.txt $(STRGEN)
|
||||
$(E) '$(STAGE) Generating $@'
|
||||
@mkdir -p table
|
||||
$(Q)./$(STRGEN) -s $(LANG_DIR) -d table
|
||||
|
||||
$(LANGS): %.lng: $(LANG_DIR)/%.txt $(STRGEN) lang/english.txt
|
||||
$(E) '$(STAGE) Compiling language $(*F)'
|
||||
$(Q)./$(STRGEN) $(STRGEN_FLAGS) -s $(LANG_DIR) -d $(LANG_OBJS_DIR) $< $(LANG_ERRORS) && cp $@ $(BIN_DIR)/lang || true # Do not fail all languages when one fails
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_host.h: $(ENDIAN_CHECK)
|
||||
$(E) '$(STAGE) Testing endianness for host'
|
||||
$(Q)./$(ENDIAN_CHECK) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
|
||||
|
||||
depend:
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up language files'
|
||||
$(Q)rm -f strgen.o string.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* $(ENDIAN_TARGETS)
|
||||
|
||||
mrproper: clean
|
||||
|
||||
%.lng:
|
||||
@echo '$(STAGE) No such language: $(@:%.lng=%)'
|
||||
|
||||
.PHONY: all mrproper depend clean
|
||||
@@ -1,28 +0,0 @@
|
||||
#
|
||||
# Makefile for creating bundles of MSVC's binaries in the same way as we make
|
||||
# the zip bundles for ALL other OSes.
|
||||
#
|
||||
# Usage: make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=openttd-<version>-win[32|64]
|
||||
# or make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=OTTD-win[32|64]-nightly-<revision>
|
||||
#
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
AWK = "awk"
|
||||
ROOT_DIR := $(shell pwd)
|
||||
BIN_DIR = "$(ROOT_DIR)/bin"
|
||||
SRC_DIR = "$(ROOT_DIR)/src"
|
||||
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
|
||||
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
|
||||
TTD = "openttd.exe"
|
||||
TARGET := $(shell echo $(PLATFORM) | sed "s@win64@x64@;s@win32@Win32@")
|
||||
|
||||
all:
|
||||
$(Q)cp objs/$(TARGET)/Release/$(TTD) $(BIN_DIR)/$(TTD)
|
||||
|
||||
include Makefile.bundle.in
|
||||
-302
@@ -1,302 +0,0 @@
|
||||
CC_HOST = !!CC_HOST!!
|
||||
CXX_HOST = !!CXX_HOST!!
|
||||
CC_BUILD = !!CC_BUILD!!
|
||||
CXX_BUILD = !!CXX_BUILD!!
|
||||
WINDRES = !!WINDRES!!
|
||||
STRIP = !!STRIP!!
|
||||
CC_CFLAGS = !!CC_CFLAGS!!
|
||||
CFLAGS = !!CFLAGS!!
|
||||
CFLAGS_BUILD = !!CFLAGS_BUILD!!
|
||||
LIBS = !!LIBS!!
|
||||
LDFLAGS = !!LDFLAGS!!
|
||||
ROOT_DIR = !!ROOT_DIR!!
|
||||
BIN_DIR = !!BIN_DIR!!
|
||||
LANG_DIR = !!LANG_DIR!!
|
||||
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
|
||||
LANG_OBJS_DIR= !!LANG_OBJS_DIR!!
|
||||
SRC_DIR = !!SRC_DIR!!
|
||||
SCRIPT_SRC_DIR=!!SCRIPT_SRC_DIR!!
|
||||
MEDIA_DIR = !!MEDIA_DIR!!
|
||||
TTD = !!TTD!!
|
||||
STRGEN = !!STRGEN!!
|
||||
ENDIAN_CHECK = !!ENDIAN_CHECK!!
|
||||
ENDIAN_FORCE = !!ENDIAN_FORCE!!
|
||||
OS = !!OS!!
|
||||
STAGE = !!STAGE!!
|
||||
MAKEDEPEND = !!MAKEDEPEND!!
|
||||
CFLAGS_MAKEDEP= !!CFLAGS_MAKEDEP!!
|
||||
SORT = !!SORT!!
|
||||
REVISION = !!REVISION!!
|
||||
AWK = !!AWK!!
|
||||
GCC295 = !!GCC295!!
|
||||
CONFIG_CACHE_COMPILER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_COMPILER!!
|
||||
CONFIG_CACHE_LINKER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_LINKER!!
|
||||
CONFIG_CACHE_ENDIAN = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_ENDIAN!!
|
||||
CONFIG_CACHE_SOURCE = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_SOURCE!!
|
||||
CONFIG_CACHE_VERSION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_VERSION!!
|
||||
|
||||
OBJS_C := !!OBJS_C!!
|
||||
OBJS_CPP := !!OBJS_CPP!!
|
||||
OBJS_MM := !!OBJS_MM!!
|
||||
OBJS_RC := !!OBJS_RC!!
|
||||
OBJS := $(OBJS_C) $(OBJS_CPP) $(OBJS_MM) $(OBJS_RC)
|
||||
SRCS := !!SRCS!!
|
||||
|
||||
# All C-files depend on those 3 files
|
||||
FILE_DEP := $(CONFIG_CACHE_COMPILER) endian_target.h
|
||||
# Create all dirs and subdirs
|
||||
RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
|
||||
|
||||
# Make sure endian_target.h is reasable as if it was in the src/ dir
|
||||
CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR)
|
||||
CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SCRIPT_SRC_DIR)
|
||||
|
||||
ENDIAN_TARGETS := endian_target.h $(ENDIAN_CHECK)
|
||||
|
||||
# This 'sed' basicly just removes 'const' from the line if it is a 2+D array
|
||||
# For more information, please check:
|
||||
# http://maillist.openttd.org/pipermail/devs/2007-April/000284.html
|
||||
# http://maillist.openttd.org/pipermail/devs/2007-February/000248.html
|
||||
GCC295_FIX=sed -r 's@^(\t*)(.*)( const )([A-Za-z0-9_ ]+(\[.*\]){2,})(( = \{)|(;))(.*)$$@\1\2 \4\6\8\9@g'
|
||||
# This 'sed' removes the 3rd '4' in the # lines of the -E output of
|
||||
# gcc 2.95.3 and lower, as it should indicate that it is a C-linkage, but the
|
||||
# compiler can't handle that information (just don't ask). So we remove it
|
||||
# and then it compiles happily and without bitching :)
|
||||
# Furthermore gcc 2.95 has some trouble with protected and private when
|
||||
# accessing the protected/private stuff of the enclosing class (or the
|
||||
# super class of the enclosing class).
|
||||
GCC295_FIX_2=sed -e 's@\(^\# [0-9][0-9]* "[^"]*"[ 0-9]*\) 4$$@\1@g;s@private:@public:@g;s@protected:@public:@g'
|
||||
|
||||
# Check if we want to show what we are doing
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
E = @true
|
||||
else
|
||||
Q = @
|
||||
E = @echo
|
||||
endif
|
||||
|
||||
# Our default target
|
||||
all: $(BIN_DIR)/$(TTD)
|
||||
|
||||
# This are 2 rules that are pointing back to STRGEN stuff.
|
||||
# There is not really a need to have them here, but in case
|
||||
# some weirdo wants to run 'make' in the 'src' dir and expects
|
||||
# the languages to be recompiled, this catches that case and
|
||||
# takes care of it nicely.
|
||||
$(LANG_OBJS_DIR)/$(STRGEN):
|
||||
$(MAKE) -C $(LANG_OBJS_DIR) $(STRGEN)
|
||||
|
||||
$(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
|
||||
$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
|
||||
|
||||
# Always run version detection, so we always have an accurate modified
|
||||
# flag
|
||||
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
|
||||
MODIFIED := $(shell echo "$(VERSIONS)" | cut -f 3 -d' ')
|
||||
|
||||
ifdef REVISION
|
||||
# Use specified revision (which should be of the form "r000").
|
||||
REV := $(REVISION)
|
||||
REV_NR := $(shell echo $(REVISION) | sed "s@[^0-9]@@g")
|
||||
else
|
||||
# Use autodetected revisions
|
||||
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
|
||||
REV_NR := $(shell echo "$(VERSIONS)" | cut -f 2 -d' ')
|
||||
endif
|
||||
|
||||
# Make sure we have something in REV and REV_NR
|
||||
ifeq ($(REV),)
|
||||
REV := norev000
|
||||
endif
|
||||
ifeq ($(REV_NR),)
|
||||
REV_NR := 0
|
||||
endif
|
||||
|
||||
# This helps to recompile if flags change
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_COMPILER) 2>/dev/null`" != "$(CC_CFLAGS) $(CFLAGS)" ]; then echo "$(CC_CFLAGS) $(CFLAGS)" > $(CONFIG_CACHE_COMPILER); fi )
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_LINKER) 2>/dev/null`" != "$(LDFLAGS) $(LIBS)" ]; then echo "$(LDFLAGS) $(LIBS)" > $(CONFIG_CACHE_LINKER); fi )
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_ENDIAN) 2>/dev/null`" != "$(ENDIAN_FORCE)" ]; then echo "$(ENDIAN_FORCE)" > $(CONFIG_CACHE_ENDIAN); fi )
|
||||
|
||||
# If there is a change in the source-file-list, make sure we recheck the deps
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_SOURCE) 2>/dev/null`" != "$(SRCS)" ]; then echo "$(SRCS)" > $(CONFIG_CACHE_SOURCE); fi )
|
||||
# If there is a change in the revision, make sure we recompile rev.cpp
|
||||
RES := $(shell if [ "`cat $(CONFIG_CACHE_VERSION) 2>/dev/null`" != "$(REV) $(MODIFIED)" ]; then echo "$(REV) $(MODIFIED)" > $(CONFIG_CACHE_VERSION); fi )
|
||||
|
||||
ifndef MAKEDEPEND
|
||||
# The slow, but always correct, dep-check
|
||||
DEP_MASK := %.d
|
||||
DEPS := $(OBJS:%.o=%.d)
|
||||
|
||||
# Only include the deps if we are compiling everything
|
||||
ifeq ($(filter $(ENDIAN_TARGETS) %.o clean mrproper, $(MAKECMDGOALS)),)
|
||||
-include $(DEPS)
|
||||
else
|
||||
# In case we want to compile a single target, include the .d file for it
|
||||
ifneq ($(filter %.o, $(MAKECMDGOALS)),)
|
||||
SINGLE_DEP := $(filter %.o, $(MAKECMDGOALS))
|
||||
-include $(SINGLE_DEP:%.o=%.d)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Find the deps via GCC. Rarely wrong, but a bit slow
|
||||
|
||||
$(OBJS_C:%.o=%.d): %.d: $(SRC_DIR)/%.c $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.c=%.c)'
|
||||
$(Q)$(CC_HOST) $(CC_CFLAGS) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_CPP:%.o=%.d): %.d: $(SRC_DIR)/%.cpp $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_MM:%.o=%.d): %.d: $(SRC_DIR)/%.mm $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
|
||||
|
||||
$(OBJS_RC:%.o=%.d): %.d: $(SRC_DIR)/%.rc $(FILE_DEP)
|
||||
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
|
||||
$(Q)touch $@
|
||||
|
||||
else
|
||||
# The much faster, but can be wrong, dep-check
|
||||
DEP_MASK :=
|
||||
DEPS := Makefile.dep
|
||||
|
||||
# Only include the deps if we are not cleaning
|
||||
ifeq ($(filter $(ENDIAN_TARGETS) depend clean mrproper, $(MAKECMDGOALS)),)
|
||||
-include Makefile.dep
|
||||
endif
|
||||
|
||||
# Make sure that only 'make depend' ALWAYS triggers a recheck
|
||||
ifeq ($(filter depend, $(MAKECMDGOALS)),)
|
||||
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(CONFIG_CACHE_SOURCE)
|
||||
else
|
||||
Makefile.dep: FORCE
|
||||
endif
|
||||
$(E) '$(STAGE) DEP CHECK (all files)'
|
||||
$(Q)rm -f Makefile.dep.tmp
|
||||
$(Q)touch Makefile.dep.tmp
|
||||
|
||||
# Calculate the deps via makedepend
|
||||
$(Q)$(MAKEDEPEND) -f$(SRC_OBJS_DIR)/Makefile.dep.tmp -o.o -Y -v -- $(CFLAGS_MAKEDEP) -- $(SRCS:%=$(SRC_DIR)/%) 2>/dev/null
|
||||
|
||||
# Convert x:/... paths to /x/... for mingw
|
||||
ifeq ($(OS), MINGW)
|
||||
@cat Makefile.dep.tmp | sed 's@\([a-zA-Z]\):\/@\/\1\/@g' > Makefile.dep.tmp.mingw
|
||||
@cp Makefile.dep.tmp.mingw Makefile.dep.tmp
|
||||
@rm -f Makefile.dep.tmp.mingw
|
||||
endif
|
||||
|
||||
# Remove all comments and includes that don't start with $(SRC_DIR)
|
||||
# Remove $(SRC_DIR) from object-file-name
|
||||
@$(AWK) ' \
|
||||
/^# DO NOT/ { print $$0 ; next} \
|
||||
/^#/ {next} \
|
||||
/:/ { \
|
||||
left = NF - 1; \
|
||||
for (n = 2; n <= NF; n++) { \
|
||||
if (match($$n, "^$(ROOT_DIR)") == 0) { \
|
||||
$$n = ""; \
|
||||
left--; \
|
||||
} \
|
||||
} \
|
||||
gsub("$(SRC_DIR)/", "", $$1); \
|
||||
if (left > 0) { \
|
||||
print $$0; \
|
||||
$$1 = "Makefile.dep:"; \
|
||||
print $$0; \
|
||||
} \
|
||||
next \
|
||||
} \
|
||||
{ \
|
||||
print $$0 \
|
||||
} \
|
||||
' < Makefile.dep.tmp | sed 's@ *@ @g;s@ $$@@' | $(SORT) > Makefile.dep
|
||||
|
||||
$(Q)rm -f Makefile.dep.tmp Makefile.dep.tmp.bak
|
||||
|
||||
endif
|
||||
|
||||
# Avoid problems with deps if a .h/.hpp/.hpp.sq file is deleted without the deps
|
||||
# being updated. Now the Makefile continues, the deps are recreated
|
||||
# and all will be fine.
|
||||
%.h %.hpp %.hpp.sq:
|
||||
@true
|
||||
|
||||
|
||||
# Compile all the files according to the targets
|
||||
|
||||
$(OBJS_C): %.o: $(SRC_DIR)/%.c $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.c=%.c)'
|
||||
$(Q)$(CC_HOST) $(CC_CFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJS_CPP): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
|
||||
ifeq ($(GCC295), 1)
|
||||
$(Q)$(CXX_HOST) -E $(CFLAGS) $< | $(GCC295_FIX) | $(GCC295_FIX_2) | $(CXX_HOST) $(CFLAGS) -c -o $@ -x c++ -
|
||||
else
|
||||
$(Q)$(CXX_HOST) $(CFLAGS) -c -o $@ $<
|
||||
endif
|
||||
|
||||
$(OBJS_MM): %.o: $(SRC_DIR)/%.mm $(DEP_MASK) $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
|
||||
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJS_RC): %.o: $(SRC_DIR)/%.rc $(FILE_DEP)
|
||||
$(E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
|
||||
$(Q)$(WINDRES) -o $@ -I $(MEDIA_DIR) $<
|
||||
|
||||
$(BIN_DIR)/$(TTD): $(TTD)
|
||||
$(Q)cp $< $@
|
||||
|
||||
$(TTD): $(OBJS) $(CONFIG_CACHE_LINKER)
|
||||
$(E) '$(STAGE) Linking $@'
|
||||
ifeq ($(OS), PSP)
|
||||
# Because of a bug in the PSP GCC tools, linking via CXX results
|
||||
# in total chaos and more problems then you can handle. So we need
|
||||
# CC to link OpenTTD for PSP
|
||||
$(Q)$(CC_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
else
|
||||
$(Q)$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
endif
|
||||
ifdef STRIP
|
||||
$(Q)$(STRIP) $@
|
||||
ifeq ($(OS), DOS)
|
||||
$(E) '$(STAGE) Adding CWSDPMI stub to $@'
|
||||
$(Q)$(ROOT_DIR)/os/dos/make_dos_binary_selfcontained.sh $(SRC_OBJS_DIR)/$@
|
||||
endif
|
||||
endif
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN)
|
||||
$(E) '$(STAGE) Testing endianness for target'
|
||||
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
|
||||
|
||||
# Revision files
|
||||
|
||||
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
|
||||
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!MODIFIED!!@$(MODIFIED)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/rev.cpp
|
||||
|
||||
$(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in
|
||||
$(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/ottdres.rc
|
||||
|
||||
FORCE:
|
||||
|
||||
depend: $(DEPS)
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up object files'
|
||||
$(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(TTD:%=$(BIN_DIR)/%) $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS)
|
||||
|
||||
mrproper: clean
|
||||
$(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/ottdres.rc
|
||||
|
||||
%.o:
|
||||
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
|
||||
|
||||
.PHONY: all mrproper depend clean FORCE
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEFAULT_H
|
||||
#define DEFAULT_H
|
||||
|
||||
void AiDoGameLoop(Player*);
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+350
@@ -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);
|
||||
}
|
||||
}
|
||||
+213
-213
@@ -1,15 +1,14 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file airport.cpp Functions related to airports. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
#include "airport_movement.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "date_func.h"
|
||||
#include "settings_type.h"
|
||||
#include "date.h"
|
||||
|
||||
/* Uncomment this to print out a full report of the airport-structure
|
||||
* You should either use
|
||||
@@ -18,7 +17,6 @@
|
||||
* - false: give a summarized report which only shows current and next position */
|
||||
//#define DEBUG_AIRPORT false
|
||||
|
||||
static AirportFTAClass *DummyAirport;
|
||||
static AirportFTAClass *CountryAirport;
|
||||
static AirportFTAClass *CityAirport;
|
||||
static AirportFTAClass *Oilrig;
|
||||
@@ -30,275 +28,256 @@ static AirportFTAClass *HeliDepot;
|
||||
static AirportFTAClass *IntercontinentalAirport;
|
||||
static AirportFTAClass *HeliStation;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *apFA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots,
|
||||
uint size_x, uint size_y
|
||||
);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *apc);
|
||||
|
||||
void InitializeAirports()
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
|
||||
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA);
|
||||
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
|
||||
static byte AirportTestFTA(const AirportFTAClass *apc);
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report);
|
||||
#endif /* DEBUG_AIRPORT */
|
||||
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
DummyAirport = new AirportFTAClass(
|
||||
_airport_moving_data_dummy,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_entries_dummy,
|
||||
AirportFTAClass::ALL,
|
||||
_airport_fta_dummy,
|
||||
NULL,
|
||||
0,
|
||||
0, 0, 0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
// country airport
|
||||
CountryAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
CountryAirport = new AirportFTAClass(
|
||||
_airport_moving_data_country,
|
||||
AirportFTAClass_Constructor(
|
||||
CountryAirport,
|
||||
_airport_terminal_country,
|
||||
NULL,
|
||||
_airport_entries_country,
|
||||
AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
|
||||
16,
|
||||
ALL,
|
||||
_airport_fta_country,
|
||||
_airport_depots_country,
|
||||
lengthof(_airport_depots_country),
|
||||
4, 3, 3,
|
||||
0,
|
||||
4
|
||||
4, 3
|
||||
);
|
||||
|
||||
CityAirport = new AirportFTAClass(
|
||||
_airport_moving_data_town,
|
||||
// city airport
|
||||
CityAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CityAirport,
|
||||
_airport_terminal_city,
|
||||
NULL,
|
||||
_airport_entries_city,
|
||||
AirportFTAClass::ALL,
|
||||
19,
|
||||
ALL,
|
||||
_airport_fta_city,
|
||||
_airport_depots_city,
|
||||
lengthof(_airport_depots_city),
|
||||
6, 6, 5,
|
||||
0,
|
||||
5
|
||||
6, 6
|
||||
);
|
||||
|
||||
MetropolitanAirport = new AirportFTAClass(
|
||||
_airport_moving_data_metropolitan,
|
||||
// metropolitan airport
|
||||
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
MetropolitanAirport,
|
||||
_airport_terminal_metropolitan,
|
||||
NULL,
|
||||
_airport_entries_metropolitan,
|
||||
AirportFTAClass::ALL,
|
||||
20,
|
||||
ALL,
|
||||
_airport_fta_metropolitan,
|
||||
_airport_depots_metropolitan,
|
||||
lengthof(_airport_depots_metropolitan),
|
||||
6, 6, 8,
|
||||
0,
|
||||
6
|
||||
6, 6
|
||||
);
|
||||
|
||||
InternationalAirport = new AirportFTAClass(
|
||||
_airport_moving_data_international,
|
||||
// international airport
|
||||
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
InternationalAirport,
|
||||
_airport_terminal_international,
|
||||
_airport_helipad_international,
|
||||
_airport_entries_international,
|
||||
AirportFTAClass::ALL,
|
||||
37,
|
||||
ALL,
|
||||
_airport_fta_international,
|
||||
_airport_depots_international,
|
||||
lengthof(_airport_depots_international),
|
||||
7, 7, 17,
|
||||
0,
|
||||
8
|
||||
7, 7
|
||||
);
|
||||
|
||||
IntercontinentalAirport = new AirportFTAClass(
|
||||
_airport_moving_data_intercontinental,
|
||||
// intercontintental airport
|
||||
IntercontinentalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
IntercontinentalAirport,
|
||||
_airport_terminal_intercontinental,
|
||||
_airport_helipad_intercontinental,
|
||||
_airport_entries_intercontinental,
|
||||
AirportFTAClass::ALL,
|
||||
43,
|
||||
ALL,
|
||||
_airport_fta_intercontinental,
|
||||
_airport_depots_intercontinental,
|
||||
lengthof(_airport_depots_intercontinental),
|
||||
9, 11, 25,
|
||||
0,
|
||||
10
|
||||
9,11
|
||||
);
|
||||
|
||||
Heliport = new AirportFTAClass(
|
||||
_airport_moving_data_heliport,
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
_airport_entries_heliport_oilrig,
|
||||
AirportFTAClass::HELICOPTERS,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0,
|
||||
1, 1, 1,
|
||||
60,
|
||||
4
|
||||
1, 1
|
||||
);
|
||||
|
||||
Oilrig = new AirportFTAClass(
|
||||
_airport_moving_data_oilrig,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
_airport_entries_heliport_oilrig,
|
||||
AirportFTAClass::HELICOPTERS,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0,
|
||||
1, 1, 0,
|
||||
54,
|
||||
3
|
||||
);
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
|
||||
CommuterAirport = new AirportFTAClass(
|
||||
_airport_moving_data_commuter,
|
||||
// commuter airport
|
||||
CommuterAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CommuterAirport,
|
||||
_airport_terminal_commuter,
|
||||
_airport_helipad_commuter,
|
||||
_airport_entries_commuter,
|
||||
AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
|
||||
22,
|
||||
ALL,
|
||||
_airport_fta_commuter,
|
||||
_airport_depots_commuter,
|
||||
lengthof(_airport_depots_commuter),
|
||||
5, 4, 4,
|
||||
0,
|
||||
4
|
||||
5,4
|
||||
);
|
||||
|
||||
HeliDepot = new AirportFTAClass(
|
||||
_airport_moving_data_helidepot,
|
||||
// helidepot airport
|
||||
HeliDepot = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
HeliDepot,
|
||||
NULL,
|
||||
_airport_helipad_helidepot,
|
||||
_airport_entries_helidepot,
|
||||
AirportFTAClass::HELICOPTERS,
|
||||
4,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_helidepot,
|
||||
_airport_depots_helidepot,
|
||||
lengthof(_airport_depots_helidepot),
|
||||
2, 2, 2,
|
||||
0,
|
||||
4
|
||||
2,2
|
||||
);
|
||||
|
||||
HeliStation = new AirportFTAClass(
|
||||
_airport_moving_data_helistation,
|
||||
// helistation airport
|
||||
HeliStation = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
HeliStation,
|
||||
NULL,
|
||||
_airport_helipad_helistation,
|
||||
_airport_entries_helistation,
|
||||
AirportFTAClass::HELICOPTERS,
|
||||
25,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_helistation,
|
||||
_airport_depots_helistation,
|
||||
lengthof(_airport_depots_helistation),
|
||||
4, 2, 3,
|
||||
0,
|
||||
4
|
||||
4,2
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void UnInitializeAirports()
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
delete DummyAirport;
|
||||
delete CountryAirport;
|
||||
delete CityAirport;
|
||||
delete Heliport;
|
||||
delete MetropolitanAirport;
|
||||
delete InternationalAirport;
|
||||
delete CommuterAirport;
|
||||
delete HeliDepot;
|
||||
delete IntercontinentalAirport;
|
||||
delete HeliStation;
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
AirportFTAClass_Destructor(Heliport);
|
||||
AirportFTAClass_Destructor(MetropolitanAirport);
|
||||
AirportFTAClass_Destructor(InternationalAirport);
|
||||
AirportFTAClass_Destructor(CommuterAirport);
|
||||
AirportFTAClass_Destructor(HeliDepot);
|
||||
AirportFTAClass_Destructor(IntercontinentalAirport);
|
||||
AirportFTAClass_Destructor(HeliStation);
|
||||
}
|
||||
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
|
||||
static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
|
||||
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
|
||||
static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
|
||||
#endif
|
||||
|
||||
|
||||
AirportFTAClass::AirportFTAClass(
|
||||
const AirportMovingData *moving_data_,
|
||||
const byte *terminals_,
|
||||
const byte *helipads_,
|
||||
const byte *entry_points_,
|
||||
Flags flags_,
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *apFA,
|
||||
const TileIndexDiffC *depots_,
|
||||
const byte nof_depots_,
|
||||
uint size_x_,
|
||||
uint size_y_,
|
||||
byte noise_level_,
|
||||
byte delta_z_,
|
||||
byte catchment_
|
||||
) :
|
||||
moving_data(moving_data_),
|
||||
terminals(terminals_),
|
||||
helipads(helipads_),
|
||||
airport_depots(depots_),
|
||||
flags(flags_),
|
||||
nof_depots(nof_depots_),
|
||||
nofelements(AirportGetNofElements(apFA)),
|
||||
entry_points(entry_points_),
|
||||
size_x(size_x_),
|
||||
size_y(size_y_),
|
||||
noise_level(noise_level_),
|
||||
delta_z(delta_z_),
|
||||
catchment(catchment_)
|
||||
const TileIndexDiffC *depots, const byte nof_depots,
|
||||
uint size_x, uint size_y
|
||||
)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups, nofhelipadgroups;
|
||||
|
||||
apc->size_x = size_x;
|
||||
apc->size_y = size_y;
|
||||
|
||||
/* Set up the terminal and helipad count for an airport.
|
||||
* TODO: If there are more than 10 terminals or 4 helipads, internal variables
|
||||
* need to be changed, so don't allow that for now */
|
||||
uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
|
||||
nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
|
||||
if (nofterminals > MAX_TERMINALS) {
|
||||
DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
|
||||
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d terminals are supported (you wanted %d)", MAX_TERMINALS, nofterminals);
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
}
|
||||
apc->terminals = terminals;
|
||||
|
||||
uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
|
||||
nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
|
||||
if (nofhelipads > MAX_HELIPADS) {
|
||||
DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
|
||||
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d helipads are supported (you wanted %d)", MAX_HELIPADS, nofhelipads);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
}
|
||||
apc->helipads = helipads;
|
||||
|
||||
/* Get the number of elements from the source table. We also double check this
|
||||
* with the entry point which must be within bounds and use this information
|
||||
* later on to build and validate the state machine */
|
||||
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
|
||||
if (entry_points[i] >= nofelements) {
|
||||
DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
|
||||
assert(entry_points[i] < nofelements);
|
||||
}
|
||||
apc->nofelements = AirportGetNofElements(apFA);
|
||||
if (entry_point >= apc->nofelements) {
|
||||
DEBUG(misc, 0) ("[Ap] Entry (%d) must be within the airport (maximum %d)", entry_point, apc->nofelements);
|
||||
assert(entry_point < apc->nofelements);
|
||||
}
|
||||
|
||||
apc->acc_planes = acc_planes;
|
||||
apc->entry_point = entry_point;
|
||||
apc->airport_depots = depots;
|
||||
apc->nof_depots = nof_depots;
|
||||
|
||||
/* Build the state machine itself */
|
||||
layout = AirportBuildAutomata(nofelements, apFA);
|
||||
DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
|
||||
nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
|
||||
entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
|
||||
AirportBuildAutomata(apc, apFA);
|
||||
DEBUG(misc, 1) ("[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entry %3d",
|
||||
apc->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, apc->entry_point);
|
||||
|
||||
/* Test if everything went allright. This is only a rude static test checking
|
||||
* the symantic correctness. By no means does passing the test mean that the
|
||||
* airport is working correctly or will not deadlock for example */
|
||||
uint ret = AirportTestFTA(nofelements, layout, terminals);
|
||||
if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
|
||||
assert(ret == MAX_ELEMENTS);
|
||||
{ byte ret = AirportTestFTA(apc);
|
||||
if (ret != MAX_ELEMENTS) DEBUG(misc, 0) ("[Ap] ERROR with element: %d", ret - 1);
|
||||
assert(ret == MAX_ELEMENTS);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
|
||||
AirportPrintOut(apc, DEBUG_AIRPORT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
AirportFTAClass::~AirportFTAClass()
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *apc)
|
||||
{
|
||||
for (uint i = 0; i < nofelements; i++) {
|
||||
AirportFTA *current = layout[i].next;
|
||||
int i;
|
||||
AirportFTA *current, *next;
|
||||
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
current = apc->layout[i].next;
|
||||
while (current != NULL) {
|
||||
AirportFTA *next = current->next;
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
};
|
||||
}
|
||||
free(layout);
|
||||
free(apc->layout);
|
||||
free(apc);
|
||||
}
|
||||
|
||||
/** Get the number of elements of a source Airport state automata
|
||||
@@ -306,10 +285,11 @@ AirportFTAClass::~AirportFTAClass()
|
||||
* know one element from the other by differing 'position' identifiers */
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
|
||||
{
|
||||
int i;
|
||||
uint16 nofelements = 0;
|
||||
int temp = apFA[0].position;
|
||||
|
||||
for (uint i = 0; i < MAX_ELEMENTS; i++) {
|
||||
for (i = 0; i < MAX_ELEMENTS; i++) {
|
||||
if (temp != apFA[i].position) {
|
||||
nofelements++;
|
||||
temp = apFA[i].position;
|
||||
@@ -319,16 +299,17 @@ static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
|
||||
return nofelements;
|
||||
}
|
||||
|
||||
/** We calculate the terminal/helipod count based on the data passed to us
|
||||
/* We calculate the terminal/helipod count based on the data passed to us
|
||||
* This data (terminals) contains an index as a first element as to how many
|
||||
* groups there are, and then the number of terminals for each group */
|
||||
static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
|
||||
{
|
||||
byte i;
|
||||
byte nof_terminals = 0;
|
||||
*groups = 0;
|
||||
|
||||
if (terminals != NULL) {
|
||||
uint i = terminals[0];
|
||||
i = terminals[0];
|
||||
*groups = i;
|
||||
while (i-- > 0) {
|
||||
terminals++;
|
||||
@@ -339,56 +320,58 @@ static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
|
||||
return nof_terminals;
|
||||
}
|
||||
|
||||
|
||||
static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
|
||||
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA)
|
||||
{
|
||||
AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
|
||||
AirportFTA *current;
|
||||
AirportFTA *FAutomata = malloc(sizeof(AirportFTA) * apc->nofelements);
|
||||
uint16 internalcounter = 0;
|
||||
uint16 i;
|
||||
|
||||
for (uint i = 0; i < nofelements; i++) {
|
||||
AirportFTA *current = &FAutomata[i];
|
||||
apc->layout = FAutomata;
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
current = &apc->layout[i];
|
||||
current->position = apFA[internalcounter].position;
|
||||
current->heading = apFA[internalcounter].heading;
|
||||
current->block = apFA[internalcounter].block;
|
||||
current->next_position = apFA[internalcounter].next;
|
||||
|
||||
/* outgoing nodes from the same position, create linked list */
|
||||
// outgoing nodes from the same position, create linked list
|
||||
while (current->position == apFA[internalcounter + 1].position) {
|
||||
AirportFTA *newNode = MallocT<AirportFTA>(1);
|
||||
AirportFTA *newNode = malloc(sizeof(AirportFTA));
|
||||
|
||||
newNode->position = apFA[internalcounter + 1].position;
|
||||
newNode->heading = apFA[internalcounter + 1].heading;
|
||||
newNode->block = apFA[internalcounter + 1].block;
|
||||
newNode->next_position = apFA[internalcounter + 1].next;
|
||||
/* create link */
|
||||
// create link
|
||||
current->next = newNode;
|
||||
current = current->next;
|
||||
internalcounter++;
|
||||
}
|
||||
} // while
|
||||
current->next = NULL;
|
||||
internalcounter++;
|
||||
}
|
||||
return FAutomata;
|
||||
}
|
||||
|
||||
|
||||
static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
|
||||
static byte AirportTestFTA(const AirportFTAClass *apc)
|
||||
{
|
||||
uint next_position = 0;
|
||||
byte position, i, next_position;
|
||||
AirportFTA *current, *first;
|
||||
next_position = 0;
|
||||
|
||||
for (uint i = 0; i < nofelements; i++) {
|
||||
uint position = layout[i].position;
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
position = apc->layout[i].position;
|
||||
if (position != next_position) return i;
|
||||
const AirportFTA *first = &layout[i];
|
||||
current = first = &apc->layout[i];
|
||||
|
||||
for (const AirportFTA *current = first; current != NULL; current = current->next) {
|
||||
for (; current != NULL; current = current->next) {
|
||||
/* A heading must always be valid. The only exceptions are
|
||||
* - multiple choices as start, identified by a special value of 255
|
||||
* - terminal group which is identified by a special value of 255 */
|
||||
if (current->heading > MAX_HEADINGS) {
|
||||
if (current->heading != 255) return i;
|
||||
if (current == first && current->next == NULL) return i;
|
||||
if (current != first && current->next_position > terminals[0]) return i;
|
||||
if (current != first && current->next_position > apc->terminals[0]) return i;
|
||||
}
|
||||
|
||||
/* If there is only one choice, it must be at the end */
|
||||
@@ -396,7 +379,7 @@ static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byt
|
||||
/* Obviously the elements of the linked list must have the same identifier */
|
||||
if (position != current->position) return i;
|
||||
/* A next position must be within bounds */
|
||||
if (current->next_position >= nofelements) return i;
|
||||
if (current->next_position >= apc->nofelements) return i;
|
||||
}
|
||||
next_position++;
|
||||
}
|
||||
@@ -404,7 +387,7 @@ static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byt
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AIRPORT
|
||||
static const char * const _airport_heading_strings[] = {
|
||||
static const char* const _airport_heading_strings[] = {
|
||||
"TO_ALL",
|
||||
"HANGAR",
|
||||
"TERM1",
|
||||
@@ -431,17 +414,32 @@ static const char * const _airport_heading_strings[] = {
|
||||
"DUMMY" // extra heading for 255
|
||||
};
|
||||
|
||||
static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
|
||||
static uint AirportBlockToString(uint32 block)
|
||||
{
|
||||
uint i = 0;
|
||||
if (block & 0xffff0000) { block >>= 16; i += 16; }
|
||||
if (block & 0x0000ff00) { block >>= 8; i += 8; }
|
||||
if (block & 0x000000f0) { block >>= 4; i += 4; }
|
||||
if (block & 0x0000000c) { block >>= 2; i += 2; }
|
||||
if (block & 0x00000002) { i += 1; }
|
||||
return i;
|
||||
}
|
||||
|
||||
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report)
|
||||
{
|
||||
uint16 i;
|
||||
|
||||
if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
|
||||
|
||||
for (uint i = 0; i < nofelements; i++) {
|
||||
for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
|
||||
for (i = 0; i < apc->nofelements; i++) {
|
||||
AirportFTA *current = &apc->layout[i];
|
||||
|
||||
for (; current != NULL; current = current->next) {
|
||||
if (full_report) {
|
||||
byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
|
||||
printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
|
||||
current->next_position, _airport_heading_strings[heading],
|
||||
FindLastBit(current->block));
|
||||
AirportBlockToString(current->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", current->position, current->next_position);
|
||||
}
|
||||
@@ -453,8 +451,8 @@ static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool ful
|
||||
|
||||
const AirportFTAClass *GetAirport(const byte airport_type)
|
||||
{
|
||||
/* FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
* needs constant change if more airports are added */
|
||||
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
// needs constant change if more airports are added
|
||||
switch (airport_type) {
|
||||
default: NOT_REACHED();
|
||||
case AT_SMALL: return CountryAirport;
|
||||
@@ -467,23 +465,25 @@ const AirportFTAClass *GetAirport(const byte airport_type)
|
||||
case AT_HELIDEPOT: return HeliDepot;
|
||||
case AT_INTERCON: return IntercontinentalAirport;
|
||||
case AT_HELISTATION: return HeliStation;
|
||||
case AT_DUMMY: return DummyAirport;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32 GetValidAirports()
|
||||
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position)
|
||||
{
|
||||
uint32 mask = 0;
|
||||
|
||||
if (_cur_year < 1960 || _settings_game.station.always_small_airport) SetBit(mask, 0); // small airport
|
||||
if (_cur_year >= 1955) SetBit(mask, 1); // city airport
|
||||
if (_cur_year >= 1963) SetBit(mask, 2); // heliport
|
||||
if (_cur_year >= 1980) SetBit(mask, 3); // metropolitan airport
|
||||
if (_cur_year >= 1990) SetBit(mask, 4); // international airport
|
||||
if (_cur_year >= 1983) SetBit(mask, 5); // commuter airport
|
||||
if (_cur_year >= 1976) SetBit(mask, 6); // helidepot
|
||||
if (_cur_year >= 2002) SetBit(mask, 7); // intercontinental airport
|
||||
if (_cur_year >= 1980) SetBit(mask, 8); // helistation
|
||||
return mask;
|
||||
assert(airport_type < lengthof(_airport_moving_datas));
|
||||
assert(position < GetAirport(airport_type)->nofelements);
|
||||
return &_airport_moving_datas[airport_type][position];
|
||||
}
|
||||
|
||||
uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
if (_cur_year >= 1980) SETBIT(bytemask, 3); // metropolitan airport
|
||||
if (_cur_year >= 1990) SETBIT(bytemask, 4); // international airport
|
||||
if (_cur_year >= 1983) SETBIT(bytemask, 5); // commuter airport
|
||||
if (_cur_year >= 1976) SETBIT(bytemask, 6); // helidepot
|
||||
if (_cur_year >= 2002) SETBIT(bytemask, 7); // intercontinental airport
|
||||
if (_cur_year >= 1980) SETBIT(bytemask, 8); // helistation
|
||||
return bytemask;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,794 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_MOVEMENT_H
|
||||
#define AIRPORT_MOVEMENT_H
|
||||
|
||||
|
||||
// state machine input struct (from external file, etc.)
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAbuildup {
|
||||
byte position; // the position that an airplane is at
|
||||
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
|
||||
uint32 block; // the block this position is on on the airport (st->airport_flags)
|
||||
byte next; // next position from this position
|
||||
} AirportFTAbuildup;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////*********Movement Positions on Airports********************///////
|
||||
// Country Airfield (small) 4x3
|
||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||
{ 53, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 53, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 32, 23, AMED_EXACTPOS, 7 }, // 02 Terminal 1
|
||||
{ 10, 23, AMED_EXACTPOS, 7 }, // 03 Terminal 2
|
||||
{ 43, 37, 0, 0 }, // 04 Going towards terminal 2
|
||||
{ 24, 37, 0, 0 }, // 05 Going towards terminal 2
|
||||
{ 53, 37, 0, 0 }, // 06 Going for takeoff
|
||||
{ 61, 40, AMED_EXACTPOS, 1 }, // 07 Taxi to start of runway (takeoff)
|
||||
{ 3, 40, AMED_NOSPDCLAMP, 0 }, // 08 Accelerate to end of runway
|
||||
{ -79, 40, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 09 Take off
|
||||
{ 177, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 10 Fly to landing position in air
|
||||
{ 56, 40, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 11 Going down for land
|
||||
{ 3, 40, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 12 Just landed, brake until end of runway
|
||||
{ 7, 40, 0, 0 }, // 13 Just landed, turn around and taxi 1 square
|
||||
{ 53, 40, 0, 0 }, // 14 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (south)
|
||||
{ 44, 37, AMED_HELI_RAISE, 0 }, // 19 Helicopter takeoff
|
||||
{ 44, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 In position above landing spot helicopter
|
||||
{ 44, 40, AMED_HELI_LOWER, 0 }, // 21 Helicopter landing
|
||||
};
|
||||
|
||||
// Commuter Airfield (small) 5x4
|
||||
static const AirportMovingData _airport_moving_data_commuter[37] = {
|
||||
{ 69, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 72, 22, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 8, 22, AMED_EXACTPOS, 5 }, // 01 Taxi to right outside depot
|
||||
{ 24, 36, AMED_EXACTPOS, 3 }, // 03 Terminal 1
|
||||
{ 40, 36, AMED_EXACTPOS, 3 }, // 04 Terminal 2
|
||||
{ 56, 36, AMED_EXACTPOS, 3 }, // 05 Terminal 3
|
||||
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
|
||||
{ 24, 22, 0, 5 }, // 08 Taxiing
|
||||
{ 40, 22, 0, 5 }, // 09 Taxiing
|
||||
{ 56, 22, 0, 5 }, // 10 Taxiing
|
||||
{ 72, 40, 0, 3 }, // 11 Airport OUTWAY
|
||||
{ 72, 54, AMED_EXACTPOS, 1 }, // 12 Accelerate to end of runway
|
||||
{ 7, 54, AMED_NOSPDCLAMP, 0 }, // 13 Release control of runway, for smoother movement
|
||||
{ 5, 54, AMED_NOSPDCLAMP, 0 }, // 14 End of runway
|
||||
{ -79, 54, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 15 Take off
|
||||
{ 145, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly to landing position in air
|
||||
{ 73, 54, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 17 Going down for land
|
||||
{ 3, 54, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 18 Just landed, brake until end of runway
|
||||
{ 12, 54, 0, 7 }, // 19 Just landed, turn around and taxi
|
||||
{ 8, 32, 0, 7 }, // 20 Taxi from runway to crossing
|
||||
{ -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (north-west)
|
||||
{ 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Fly around waiting for a landing spot (south-west)
|
||||
{ 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 24 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Bufferspace before helipad
|
||||
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Bufferspace before helipad
|
||||
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Get in position for Helipad1
|
||||
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Get in position for Helipad2
|
||||
{ 32, 8, AMED_HELI_LOWER, 0 }, // 29 Land at Helipad1
|
||||
{ 48, 8, AMED_HELI_LOWER, 0 }, // 30 Land at Helipad2
|
||||
{ 32, 8, AMED_HELI_RAISE, 0 }, // 31 Takeoff Helipad1
|
||||
{ 48, 8, AMED_HELI_RAISE, 0 }, // 32 Takeoff Helipad2
|
||||
{ 64, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 33 Go to position for Hangarentrance in air
|
||||
{ 64, 22, AMED_HELI_LOWER, 0 }, // 34 Land in front of hangar
|
||||
{ 40, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 2
|
||||
};
|
||||
|
||||
// City Airport (large) 6x6
|
||||
static const AirportMovingData _airport_moving_data_town[25] = {
|
||||
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
|
||||
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
|
||||
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
|
||||
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 80, 27, 0, 0 }, // 06 Taxiway terminals 2-3
|
||||
{ 44, 63, 0, 0 }, // 07 Taxi to Airport center
|
||||
{ 58, 71, 0, 0 }, // 08 Towards takeoff
|
||||
{ 72, 85, 0, 0 }, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 85, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 85, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
|
||||
{ -79, 85, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
|
||||
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
|
||||
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
|
||||
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
|
||||
{ 20, 87, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 36, 71, 0, 0 }, // 17 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south)
|
||||
{ 44, 63, AMED_HELI_RAISE, 0 }, // 22 Helicopter takeoff
|
||||
{ 28, 74, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 In position above landing spot helicopter
|
||||
{ 28, 74, AMED_HELI_LOWER, 0 }, // 24 Helicopter landing
|
||||
};
|
||||
|
||||
// Metropolitan Airport (metropolitan) - 2 runways
|
||||
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
|
||||
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
|
||||
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
|
||||
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
|
||||
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
|
||||
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
|
||||
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 70, 33, 0, 0 }, // 06 Taxiway terminals 2-3
|
||||
{ 44, 58, 0, 0 }, // 07 Taxi to Airport center
|
||||
{ 72, 58, 0, 0 }, // 08 Towards takeoff
|
||||
{ 72, 69, 0, 0 }, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 69, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 69, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
|
||||
{ -79, 69, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
|
||||
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
|
||||
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
|
||||
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
|
||||
{ 21, 85, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 21, 69, 0, 0 }, // 17 On Runway-out taxiing to In-Way
|
||||
{ 21, 54, AMED_EXACTPOS, 5 }, // 18 Taxi from runway to crossing
|
||||
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (north-west)
|
||||
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south-west)
|
||||
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (south)
|
||||
{ 44, 58, 0, 0 }, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
|
||||
{ 44, 63, AMED_HELI_RAISE, 0 }, // 24 Helicopter takeoff
|
||||
{ 15, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Get in position above landing spot helicopter
|
||||
{ 15, 54, AMED_HELI_LOWER, 0 }, // 26 Helicopter landing
|
||||
};
|
||||
|
||||
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
|
||||
static const AirportMovingData _airport_moving_data_international[51] = {
|
||||
{ 7, 55, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
|
||||
{ 100, 21, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
|
||||
{ 7, 70, 0, 0 }, // 02 Taxi to right outside depot
|
||||
{ 100, 36, 0, 0 }, // 03 Taxi to right outside depot
|
||||
{ 38, 70, AMED_EXACTPOS, 5 }, // 04 Terminal 1
|
||||
{ 38, 54, AMED_EXACTPOS, 5 }, // 05 Terminal 2
|
||||
{ 38, 38, AMED_EXACTPOS, 5 }, // 06 Terminal 3
|
||||
{ 70, 70, AMED_EXACTPOS, 1 }, // 07 Terminal 4
|
||||
{ 70, 54, AMED_EXACTPOS, 1 }, // 08 Terminal 5
|
||||
{ 70, 38, AMED_EXACTPOS, 1 }, // 09 Terminal 6
|
||||
{ 104, 71, AMED_EXACTPOS, 1 }, // 10 Helipad 1
|
||||
{ 104, 55, AMED_EXACTPOS, 1 }, // 11 Helipad 2
|
||||
{ 22, 87, 0, 0 }, // 12 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 60, 87, 0, 0 }, // 13 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 66, 87, 0, 0 }, // 14 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 87, AMED_EXACTPOS, 7 }, // 15 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 70, 0, 0 }, // 16 In Front of Terminal 4 / Helipad 1
|
||||
{ 86, 54, 0, 0 }, // 17 In Front of Terminal 5 / Helipad 2
|
||||
{ 86, 38, 0, 0 }, // 18 In Front of Terminal 6
|
||||
{ 86, 22, 0, 0 }, // 19 Towards Terminals Takeoff (Taxiway)
|
||||
{ 66, 22, 0, 0 }, // 20 Towards Terminals Takeoff (Taxiway)
|
||||
{ 60, 22, 0, 0 }, // 21 Towards Terminals Takeoff (Taxiway)
|
||||
{ 38, 22, 0, 0 }, // 22 Towards Terminals Takeoff (Taxiway)
|
||||
{ 22, 70, 0, 0 }, // 23 In Front of Terminal 1
|
||||
{ 22, 58, 0, 0 }, // 24 In Front of Terminal 2
|
||||
{ 22, 38, 0, 0 }, // 25 In Front of Terminal 3
|
||||
{ 22, 22, AMED_EXACTPOS, 7 }, // 26 Going for Takeoff
|
||||
{ 22, 6, 0, 0 }, // 27 On Runway-out, prepare for takeoff
|
||||
{ 3, 6, AMED_EXACTPOS, 5 }, // 28 Accelerate to end of runway
|
||||
{ 60, 6, AMED_NOSPDCLAMP, 0 }, // 29 Release control of runway, for smoother movement
|
||||
{ 105, 6, AMED_NOSPDCLAMP, 0 }, // 30 End of runway
|
||||
{ 190, 6, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 31 Take off
|
||||
{ 193, 104, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly to landing position in air
|
||||
{ 105, 104, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 33 Going down for land
|
||||
{ 3, 104, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 34 Just landed, brake until end of runway
|
||||
{ 12, 104, 0, 0 }, // 35 Just landed, turn around and taxi 1 square
|
||||
{ 7, 84, 0, 0 }, // 36 Taxi from runway to crossing
|
||||
{ -31, 209, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 37 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 38 Fly around waiting for a landing spot (north-west)
|
||||
{ 273, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 39 Fly around waiting for a landing spot (south-west)
|
||||
{ 305, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 40 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 41 Bufferspace before helipad
|
||||
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 42 Bufferspace before helipad
|
||||
{ 96, 71, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Get in position for Helipad1
|
||||
{ 96, 55, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Get in position for Helipad2
|
||||
{ 96, 71, AMED_HELI_LOWER, 0 }, // 45 Land at Helipad1
|
||||
{ 96, 55, AMED_HELI_LOWER, 0 }, // 46 Land at Helipad2
|
||||
{ 104, 71, AMED_HELI_RAISE, 0 }, // 47 Takeoff Helipad1
|
||||
{ 104, 55, AMED_HELI_RAISE, 0 }, // 48 Takeoff Helipad2
|
||||
{ 104, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Go to position for Hangarentrance in air
|
||||
{ 104, 32, AMED_HELI_LOWER, 0} // 50 Land in HANGAR2_AREA to go to hangar
|
||||
};
|
||||
|
||||
// Intercontinental Airport - 4 runways, 8 terminals, 2 dedicated helipads
|
||||
static const AirportMovingData _airport_moving_data_intercontinental[77] = {
|
||||
{ 7, 87, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
|
||||
{ 135, 72, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
|
||||
{ 7, 104, 0, 0 }, // 02 Taxi to right outside depot 1
|
||||
{ 135, 88, 0, 0 }, // 03 Taxi to right outside depot 2
|
||||
{ 56, 120, AMED_EXACTPOS, 6 }, // 04 Terminal 1
|
||||
{ 56, 104, AMED_EXACTPOS, 5 }, // 05 Terminal 2
|
||||
{ 56, 88, AMED_EXACTPOS, 5 }, // 06 Terminal 3
|
||||
{ 56, 72, AMED_EXACTPOS, 5 }, // 07 Terminal 4
|
||||
{ 88, 120, AMED_EXACTPOS, 0 }, // 08 Terminal 5
|
||||
{ 88, 104, AMED_EXACTPOS, 1 }, // 09 Terminal 6
|
||||
{ 88, 88, AMED_EXACTPOS, 1 }, // 10 Terminal 7
|
||||
{ 88, 72, AMED_EXACTPOS, 1 }, // 11 Terminal 8
|
||||
{ 88, 56, AMED_EXACTPOS, 3 }, // 12 Helipad 1
|
||||
{ 72, 56, AMED_EXACTPOS, 1 }, // 13 Helipad 2
|
||||
{ 40, 136, 0, 0 }, // 14 Term group 2 enter 1 a
|
||||
{ 56, 136, 0, 0 }, // 15 Term group 2 enter 1 b
|
||||
{ 88, 136, 0, 0 }, // 16 Term group 2 enter 2 a
|
||||
{ 104, 136, 0, 0 }, // 17 Term group 2 enter 2 b
|
||||
{ 104, 120, 0, 0 }, // 18 Term group 2 - opp term 5
|
||||
{ 104, 104, 0, 0 }, // 19 Term group 2 - opp term 6 & exit2
|
||||
{ 104, 88, 0, 0 }, // 20 Term group 2 - opp term 7 & hangar area 2
|
||||
{ 104, 72, 0, 0 }, // 21 Term group 2 - opp term 8
|
||||
{ 104, 56, 0, 0 }, // 22 Taxi Term group 2 exit a
|
||||
{ 104, 40, 0, 0 }, // 23 Taxi Term group 2 exit b
|
||||
{ 56, 40, 0, 0 }, // 24 Term group 2 exit 2a
|
||||
{ 40, 40, 0, 0 }, // 25 Term group 2 exit 2b
|
||||
{ 40, 120, 0, 0 }, // 26 Term group 1 - opp term 1
|
||||
{ 40, 104, 0, 0 }, // 27 Term group 1 - opp term 2 & hangar area 1
|
||||
{ 40, 88, 0, 0 }, // 28 Term group 1 - opp term 3
|
||||
{ 40, 72, 0, 0 }, // 29 Term group 1 - opp term 4
|
||||
{ 18, 72, 0, 7 }, // 30 Outway 1
|
||||
{ 8, 40, 0, 7 }, // 31 Airport OUTWAY
|
||||
{ 8, 24, AMED_EXACTPOS, 5 }, // 32 Accelerate to end of runway
|
||||
{ 119, 24, AMED_NOSPDCLAMP, 0 }, // 33 Release control of runway, for smoother movement
|
||||
{ 117, 24, AMED_NOSPDCLAMP, 0 }, // 34 End of runway
|
||||
{ 197, 24, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 35 Take off
|
||||
{ 254, 84, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 36 Flying to landing position in air
|
||||
{ 117, 168, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 37 Going down for land
|
||||
{ 3, 168, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 38 Just landed, brake until end of runway
|
||||
{ 8, 168, 0, 0 }, // 39 Just landed, turn around and taxi
|
||||
{ 8, 144, 0, 7 }, // 40 Taxi from runway
|
||||
{ 8, 128, 0, 7 }, // 41 Taxi from runway
|
||||
{ 8, 120, AMED_EXACTPOS, 5 }, // 42 Airport entrance
|
||||
{ 56, 344, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Fly around waiting for a landing spot (north-east)
|
||||
{ -200, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Fly around waiting for a landing spot (north-west)
|
||||
{ 56, -168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 45 Fly around waiting for a landing spot (south-west)
|
||||
{ 312, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 46 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 47 Bufferspace before helipad
|
||||
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 48 Bufferspace before helipad
|
||||
{ 82, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Get in position for Helipad1
|
||||
{ 64, 56, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 50 Get in position for Helipad2
|
||||
{ 81, 55, AMED_HELI_LOWER, 0 }, // 51 Land at Helipad1
|
||||
{ 64, 56, AMED_HELI_LOWER, 0 }, // 52 Land at Helipad2
|
||||
{ 80, 56, AMED_HELI_RAISE, 0 }, // 53 Takeoff Helipad1
|
||||
{ 64, 56, AMED_HELI_RAISE, 0 }, // 54 Takeoff Helipad2
|
||||
{ 136, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 55 Go to position for Hangarentrance in air
|
||||
{ 136, 96, AMED_HELI_LOWER, 0 }, // 56 Land in front of hangar2
|
||||
{ 126, 104, 0, 3 }, // 57 Outway 2
|
||||
{ 136, 136, 0, 1 }, // 58 Airport OUTWAY 2
|
||||
{ 136, 152, AMED_EXACTPOS, 1 }, // 59 Accelerate to end of runway2
|
||||
{ 16, 152, AMED_NOSPDCLAMP, 0 }, // 60 Release control of runway2, for smoother movement
|
||||
{ 20, 152, AMED_NOSPDCLAMP, 0 }, // 61 End of runway2
|
||||
{ -56, 152, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 62 Take off2
|
||||
{ 24, 8, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 63 Going down for land2
|
||||
{ 136, 8, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 64 Just landed, brake until end of runway2in
|
||||
{ 136, 8, 0, 0 }, // 65 Just landed, turn around and taxi
|
||||
{ 136, 24, 0, 3 }, // 66 Taxi from runway 2in
|
||||
{ 136, 40, 0, 3 }, // 67 Taxi from runway 2in
|
||||
{ 136, 56, AMED_EXACTPOS, 1 }, // 68 Airport entrance2
|
||||
{ -56, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 69 Fly to landing position in air2
|
||||
{ 88, 40, 0, 0 }, // 70 Taxi Term group 2 exit - opp heli1
|
||||
{ 72, 40, 0, 0 }, // 71 Taxi Term group 2 exit - opp heli2
|
||||
{ 88, 57, AMED_EXACTPOS, 3 }, // 72 pre-helitakeoff helipad 1
|
||||
{ 71, 56, AMED_EXACTPOS, 1 }, // 73 pre-helitakeoff helipad 2
|
||||
{ 8, 120, AMED_HELI_RAISE, 0 }, // 74 Helitakeoff outside depot 1
|
||||
{ 136, 104, AMED_HELI_RAISE, 0 }, // 75 Helitakeoff outside depot 2
|
||||
{ 197, 168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0} // 76 Fly to landing position in air1
|
||||
};
|
||||
|
||||
|
||||
// Heliport (heliport)
|
||||
static const AirportMovingData _airport_moving_data_heliport[9] = {
|
||||
{ 5, 9, AMED_EXACTPOS, 1 }, // 0 - At heliport terminal
|
||||
{ 2, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
|
||||
{ -3, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
|
||||
{ -3, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
|
||||
{ 2, 9, 0, 0 }, // 4 - Goto terminal on ground
|
||||
{ -31, 59, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #1 (north-east)
|
||||
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #2 (north-west)
|
||||
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - Circle #3 (south-west)
|
||||
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - Circle #4 (south)
|
||||
};
|
||||
|
||||
// HeliDepot 2x2 (heliport)
|
||||
static const AirportMovingData _airport_moving_data_helidepot[18] = {
|
||||
{ 24, 4, AMED_EXACTPOS, 1 }, // 0 - At depot
|
||||
{ 24, 28, 0, 0 }, // 1 Taxi to right outside depot
|
||||
{ 5, 38, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 Flying
|
||||
{ -15, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 3 - Circle #1 (north-east)
|
||||
{ -15, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 4 - Circle #2 (north-west)
|
||||
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #3 (south-west)
|
||||
{ 49, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #4 (south-east)
|
||||
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 7 - PreHelipad
|
||||
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 8 - Helipad
|
||||
{ 8, 16, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 9 - Land
|
||||
{ 8, 16, AMED_HELI_LOWER, 7 }, // 10 - Land
|
||||
{ 8, 24, AMED_HELI_RAISE, 0 }, // 11 - Take off (play sound)
|
||||
{ 32, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 12 Air to above hangar area
|
||||
{ 32, 24, AMED_HELI_LOWER, 7 }, // 13 Taxi to right outside depot
|
||||
{ 8, 24, AMED_EXACTPOS, 7 }, // 14 - on helipad1
|
||||
{ 24, 28, AMED_HELI_RAISE, 0 }, // 15 Takeoff right outside depot
|
||||
{ 8, 24, AMED_HELI_RAISE, 5 }, // 16 - Take off (play sound)
|
||||
{ 8, 24, AMED_SLOWTURN | AMED_EXACTPOS, 2 }, // 17 - turn on helipad1 for takeoff
|
||||
};
|
||||
|
||||
// HeliDepot 2x2 (heliport)
|
||||
static const AirportMovingData _airport_moving_data_helistation[33] = {
|
||||
{ 8, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar2
|
||||
{ 8, 22, 0, 0 }, // 01 outside hangar 2
|
||||
{ 116, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 02 Fly to landing position in air
|
||||
{ 14, 22, AMED_HELI_RAISE, 0 }, // 03 Helitakeoff outside hangar1(play sound)
|
||||
{ 24, 22, 0, 0 }, // 04 taxiing
|
||||
{ 40, 22, 0, 0 }, // 05 taxiing
|
||||
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
|
||||
{ 56, 24, AMED_EXACTPOS, 1 }, // 08 Helipad 3
|
||||
{ 40, 8, AMED_EXACTPOS, 0 }, // 09 pre-helitakeoff helipad 1
|
||||
{ 56, 8, AMED_EXACTPOS, 0 }, // 10 pre-helitakeoff helipad 2
|
||||
{ 56, 24, AMED_EXACTPOS, 0 }, // 11 pre-helitakeoff helipad 3
|
||||
{ 32, 8, AMED_HELI_RAISE, 0 }, // 12 Takeoff Helipad1
|
||||
{ 48, 8, AMED_HELI_RAISE, 0 }, // 13 Takeoff Helipad2
|
||||
{ 48, 24, AMED_HELI_RAISE, 0 }, // 14 Takeoff Helipad3
|
||||
{ 84, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Bufferspace before helipad
|
||||
{ 68, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Bufferspace before helipad
|
||||
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Get in position for Helipad1
|
||||
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Get in position for Helipad2
|
||||
{ 48, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 1 }, // 19 Get in position for Helipad3
|
||||
{ 40, 8, AMED_HELI_LOWER, 0 }, // 20 Land at Helipad1
|
||||
{ 48, 8, AMED_HELI_LOWER, 0 }, // 21 Land at Helipad2
|
||||
{ 48, 24, AMED_HELI_LOWER, 0 }, // 22 Land at Helipad3
|
||||
{ 0, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Go to position for Hangarentrance in air
|
||||
{ 0, 22, AMED_HELI_LOWER, 0 }, // 24 Land in front of hangar
|
||||
{ 148, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Fly around waiting for a landing spot (south-east)
|
||||
{ 148, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Fly around waiting for a landing spot (south-west)
|
||||
{ 132, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Fly around waiting for a landing spot (south-west)
|
||||
{ 100, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Fly around waiting for a landing spot (north-east)
|
||||
{ 84, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 29 Fly around waiting for a landing spot (south-east)
|
||||
{ 84, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 30 Fly around waiting for a landing spot (south-west)
|
||||
{ 100, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 31 Fly around waiting for a landing spot (north-west)
|
||||
{ 132, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly around waiting for a landing spot (north-east)
|
||||
};
|
||||
|
||||
// Oilrig
|
||||
static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
{ 31, 9, AMED_EXACTPOS, 1 }, // 0 - At oilrig terminal
|
||||
{ 28, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
|
||||
{ 23, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
|
||||
{ 23, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
|
||||
{ 28, 9, 0, 0 }, // 4 - Goto terminal on ground
|
||||
{ -31, 69, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - circle #1 (north-east)
|
||||
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - circle #2 (north-west)
|
||||
{ 69, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - circle #3 (south-west)
|
||||
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - circle #4 (south)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
/* First element of terminals array tells us how many depots there are (to know size of array)
|
||||
* this may be changed later when airports are moved to external file */
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, AIRPORT_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM1, TERM1_block, 2 }, { 1, TERM2, 0, 4 }, { 1, HELITAKEOFF, 0, 19 }, { 1, 0, 0, 6 },
|
||||
{ 2, TERM1, TERM1_block, 1 },
|
||||
{ 3, TERM2, TERM2_block, 5 },
|
||||
{ 4, 255, AIRPORT_BUSY_block, 0 }, { 4, TERM2, 0, 5 }, { 4, HANGAR, 0, 1 }, { 4, TAKEOFF, 0, 6 }, { 4, HELITAKEOFF, 0, 1 },
|
||||
{ 5, 255, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, 0, 0, 4 },
|
||||
{ 6, 0, AIRPORT_BUSY_block, 7 },
|
||||
// takeoff
|
||||
{ 7, TAKEOFF, AIRPORT_BUSY_block, 8 },
|
||||
{ 8, STARTTAKEOFF, NOTHING_block, 9 },
|
||||
{ 9, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 10, FLYING, NOTHING_block, 15 }, { 10, LANDING, 0, 11 }, { 10, HELILANDING, 0, 20 },
|
||||
{ 11, LANDING, AIRPORT_BUSY_block, 12 },
|
||||
{ 12, 0, AIRPORT_BUSY_block, 13 },
|
||||
{ 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 },
|
||||
{ 14, 0, AIRPORT_BUSY_block, 1 },
|
||||
// In air
|
||||
{ 15, 0, NOTHING_block, 16 },
|
||||
{ 16, 0, NOTHING_block, 17 },
|
||||
{ 17, 0, NOTHING_block, 18 },
|
||||
{ 18, 0, NOTHING_block, 10 },
|
||||
{ 19, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 20, HELILANDING, AIRPORT_BUSY_block, 21 },
|
||||
{ 21, HELIENDLANDING, AIRPORT_BUSY_block, 1 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_commuter[] = { { 4, 0 } };
|
||||
static const byte _airport_terminal_commuter[] = { 1, 3 };
|
||||
static const byte _airport_helipad_commuter[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_commuter[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 }, { 0, HELITAKEOFF, HELIPAD2_block, 1 }, { 0, 0, 0, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TAKEOFF, 0, 11 }, { 1, TERM1, TAXIWAY_BUSY_block, 10 }, { 1, TERM2, TAXIWAY_BUSY_block, 10 }, { 1, TERM3, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD1, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD2, TAXIWAY_BUSY_block, 10 }, { 1, HELITAKEOFF, TAXIWAY_BUSY_block, 10 }, { 1, 0, 0, 0 },
|
||||
{ 2, 255, AIRPORT_ENTRANCE_block, 2 }, { 2, HANGAR, 0, 8 }, { 2, TERM1, 0, 8 }, { 2, TERM2, 0, 8 }, { 2, TERM3, 0, 8 }, { 2, HELIPAD1, 0, 8 }, { 2, HELIPAD2, 0, 8 }, { 2, HELITAKEOFF, 0, 8 }, { 2, 0, 0, 2 },
|
||||
{ 3, TERM1, TERM1_block, 8 }, { 3, HANGAR, 0, 8 }, { 3, TAKEOFF, 0, 8 }, { 3, 0, 0, 3 },
|
||||
{ 4, TERM2, TERM2_block, 9 }, { 4, HANGAR, 0, 9 }, { 4, TAKEOFF, 0, 9 }, { 4, 0, 0, 4 },
|
||||
{ 5, TERM3, TERM3_block, 10 }, { 5, HANGAR, 0, 10 }, { 5, TAKEOFF, 0, 10 }, { 5, 0, 0, 5 },
|
||||
{ 6, HELIPAD1, HELIPAD1_block, 6 }, { 6, HANGAR, TAXIWAY_BUSY_block, 9 }, { 6, HELITAKEOFF, 0, 35 },
|
||||
{ 7, HELIPAD2, HELIPAD2_block, 7 }, { 7, HANGAR, TAXIWAY_BUSY_block, 10 }, { 7, HELITAKEOFF, 0, 36 },
|
||||
{ 8, 255, TAXIWAY_BUSY_block, 8 }, { 8, TAKEOFF, TAXIWAY_BUSY_block, 9 }, { 8, HANGAR, TAXIWAY_BUSY_block, 9 }, { 8, TERM1, TERM1_block, 3 }, { 8, 0, TAXIWAY_BUSY_block, 9 },
|
||||
{ 9, 255, TAXIWAY_BUSY_block, 9 }, { 9, TAKEOFF, TAXIWAY_BUSY_block, 10 }, { 9, HANGAR, TAXIWAY_BUSY_block, 10 }, { 9, TERM2, TERM2_block, 4 }, { 9, HELIPAD1, HELIPAD1_block, 6 }, { 9, HELITAKEOFF, HELIPAD1_block, 6 }, { 9, TERM1, TAXIWAY_BUSY_block, 8 }, { 9, 0, TAXIWAY_BUSY_block, 10 },
|
||||
{ 10, 255, TAXIWAY_BUSY_block, 10 }, { 10, TERM3, TERM3_block, 5 }, { 10, HELIPAD1, 0, 9 }, { 10, HELIPAD2, HELIPAD2_block, 7 }, { 10, HELITAKEOFF, HELIPAD2_block, 7 }, { 10, TAKEOFF, TAXIWAY_BUSY_block, 1 }, { 10, HANGAR, TAXIWAY_BUSY_block, 1 }, { 10, 0, TAXIWAY_BUSY_block, 9 },
|
||||
{ 11, 0, OUT_WAY_block, 12 },
|
||||
// takeoff
|
||||
{ 12, TAKEOFF, RUNWAY_IN_OUT_block, 13 },
|
||||
{ 13, 0, RUNWAY_IN_OUT_block, 14 },
|
||||
{ 14, STARTTAKEOFF, RUNWAY_IN_OUT_block, 15 },
|
||||
{ 15, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 16, FLYING, NOTHING_block, 21 }, { 16, LANDING, IN_WAY_block, 17 }, { 16, HELILANDING, 0, 25 },
|
||||
{ 17, LANDING, RUNWAY_IN_OUT_block, 18 },
|
||||
{ 18, 0, RUNWAY_IN_OUT_block, 19 },
|
||||
{ 19, 0, RUNWAY_IN_OUT_block, 20 },
|
||||
{ 20, ENDLANDING, IN_WAY_block, 2 },
|
||||
// In Air
|
||||
{ 21, 0, NOTHING_block, 22 },
|
||||
{ 22, 0, NOTHING_block, 23 },
|
||||
{ 23, 0, NOTHING_block, 24 },
|
||||
{ 24, 0, NOTHING_block, 16 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 25, HELILANDING, PRE_HELIPAD_block, 26 },
|
||||
{ 26, HELIENDLANDING, PRE_HELIPAD_block, 26 }, { 26, HELIPAD1, 0, 27 }, { 26, HELIPAD2, 0, 28 }, { 26, HANGAR, 0, 33 },
|
||||
{ 27, 0, NOTHING_block, 29 }, //helipad1 approach
|
||||
{ 28, 0, NOTHING_block, 30 },
|
||||
// landing
|
||||
{ 29, 255, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
|
||||
{ 30, 255, NOTHING_block, 0 }, { 30, HELIPAD2, HELIPAD2_block, 7 },
|
||||
// Helicopter -- takeoff
|
||||
{ 31, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 32, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 33, 0, TAXIWAY_BUSY_block, 34 }, // need to go to hangar when waiting in air
|
||||
{ 34, 0, TAXIWAY_BUSY_block, 1 },
|
||||
{ 35, 0, HELIPAD1_block, 31 },
|
||||
{ 36, 0, HELIPAD2_block, 32 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_city[] = { { 5, 0 } };
|
||||
static const byte _airport_terminal_city[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 }, { 0, TAKEOFF, OUT_WAY_block, 1 }, { 0, 0, 0, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
|
||||
{ 2, TERM1, TERM1_block, 7 }, { 2, TAKEOFF, OUT_WAY_block, 7 }, { 2, 0, 0, 7 },
|
||||
{ 3, TERM2, TERM2_block, 5 }, { 3, TAKEOFF, OUT_WAY_block, 5 }, { 3, 0, 0, 5 },
|
||||
{ 4, TERM3, TERM3_block, 5 }, { 4, TAKEOFF, OUT_WAY_block, 5 }, { 4, 0, 0, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
|
||||
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
|
||||
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, OUT_WAY_block, 8 }, { 7, HELITAKEOFF, 0, 22 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
|
||||
{ 8, 0, OUT_WAY_block, 9 },
|
||||
{ 9, 0, RUNWAY_IN_OUT_block, 10 },
|
||||
// takeoff
|
||||
{ 10, TAKEOFF, RUNWAY_IN_OUT_block, 11 },
|
||||
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
|
||||
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 13, FLYING, NOTHING_block, 18 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 23 },
|
||||
{ 14, LANDING, RUNWAY_IN_OUT_block, 15 },
|
||||
{ 15, 0, RUNWAY_IN_OUT_block, 16 },
|
||||
{ 16, 0, RUNWAY_IN_OUT_block, 17 },
|
||||
{ 17, ENDLANDING, IN_WAY_block, 7 },
|
||||
// In Air
|
||||
{ 18, 0, NOTHING_block, 19 },
|
||||
{ 19, 0, NOTHING_block, 20 },
|
||||
{ 20, 0, NOTHING_block, 21 },
|
||||
{ 21, 0, NOTHING_block, 13 },
|
||||
// helicopter
|
||||
{ 22, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 23, HELILANDING, IN_WAY_block, 24 },
|
||||
{ 24, HELIENDLANDING, IN_WAY_block, 17 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = { { 5, 0 } };
|
||||
static const byte _airport_terminal_metropolitan[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
|
||||
{ 2, TERM1, TERM1_block, 7 },
|
||||
{ 3, TERM2, TERM2_block, 5 },
|
||||
{ 4, TERM3, TERM3_block, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
|
||||
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
|
||||
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, 0, 8 }, { 7, HELITAKEOFF, 0, 23 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
|
||||
{ 8, 0, OUT_WAY_block, 9 },
|
||||
{ 9, 0, RUNWAY_OUT_block, 10 },
|
||||
// takeoff
|
||||
{ 10, TAKEOFF, RUNWAY_OUT_block, 11 },
|
||||
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
|
||||
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 13, FLYING, NOTHING_block, 19 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 25 },
|
||||
{ 14, LANDING, RUNWAY_IN_block, 15 },
|
||||
{ 15, 0, RUNWAY_IN_block, 16 },
|
||||
{ 16, 255, RUNWAY_IN_block, 0 }, { 16, ENDLANDING, IN_WAY_block, 17 },
|
||||
{ 17, 255, RUNWAY_OUT_block, 0 }, { 17, ENDLANDING, IN_WAY_block, 18 },
|
||||
{ 18, ENDLANDING, IN_WAY_block, 7 },
|
||||
// In Air
|
||||
{ 19, 0, NOTHING_block, 20 },
|
||||
{ 20, 0, NOTHING_block, 21 },
|
||||
{ 21, 0, NOTHING_block, 22 },
|
||||
{ 22, 0, NOTHING_block, 13 },
|
||||
// helicopter
|
||||
{ 23, 0, NOTHING_block, 24 },
|
||||
{ 24, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 25, HELILANDING, IN_WAY_block, 26 },
|
||||
{ 26, HELIENDLANDING, IN_WAY_block, 18 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_international[] = { { 0, 3 }, { 6, 1 } };
|
||||
static const byte _airport_terminal_international[] = { 2, 3, 3 };
|
||||
static const byte _airport_helipad_international[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, TERM_GROUP1_block, 0 }, { 0, 255, TERM_GROUP2_ENTER1_block, 1 }, { 0, HELITAKEOFF, HELIPAD1_block, 2 }, { 0, 0, 0, 2 },
|
||||
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, HELITAKEOFF, HELIPAD2_block, 3 }, { 1, 0, 0, 3 },
|
||||
{ 2, 255, AIRPORT_ENTRANCE_block, 0 }, { 2, HANGAR, 0, 0 }, { 2, TERM4, 0, 12 }, { 2, TERM5, 0, 12 }, { 2, TERM6, 0, 12 }, { 2, HELIPAD1, 0, 12 }, { 2, HELIPAD2, 0, 12 }, { 2, HELITAKEOFF, 0, 12 }, { 2, 0, 0, 23 },
|
||||
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, 0, 0, 18 },
|
||||
{ 4, TERM1, TERM1_block, 23 }, { 4, HANGAR, AIRPORT_ENTRANCE_block, 23 }, { 4, 0, 0, 23 },
|
||||
{ 5, TERM2, TERM2_block, 24 }, { 5, HANGAR, AIRPORT_ENTRANCE_block, 24 }, { 5, 0, 0, 24 },
|
||||
{ 6, TERM3, TERM3_block, 25 }, { 6, HANGAR, AIRPORT_ENTRANCE_block, 25 }, { 6, 0, 0, 25 },
|
||||
{ 7, TERM4, TERM4_block, 16 }, { 7, HANGAR, HANGAR2_AREA_block, 16 }, { 7, 0, 0, 16 },
|
||||
{ 8, TERM5, TERM5_block, 17 }, { 8, HANGAR, HANGAR2_AREA_block, 17 }, { 8, 0, 0, 17 },
|
||||
{ 9, TERM6, TERM6_block, 18 }, { 9, HANGAR, HANGAR2_AREA_block, 18 }, { 9, 0, 0, 18 },
|
||||
{ 10, HELIPAD1, HELIPAD1_block, 10 }, { 10, HANGAR, HANGAR2_AREA_block, 16 }, { 10, HELITAKEOFF, 0, 47 },
|
||||
{ 11, HELIPAD2, HELIPAD2_block, 11 }, { 11, HANGAR, HANGAR2_AREA_block, 17 }, { 11, HELITAKEOFF, 0, 48 },
|
||||
{ 12, 0, TERM_GROUP2_ENTER1_block, 13 },
|
||||
{ 13, 0, TERM_GROUP2_ENTER1_block, 14 },
|
||||
{ 14, 0, TERM_GROUP2_ENTER2_block, 15 },
|
||||
{ 15, 0, TERM_GROUP2_ENTER2_block, 16 },
|
||||
{ 16, 255, TERM_GROUP2_block, 0 }, { 16, TERM4, TERM4_block, 7 }, { 16, HELIPAD1, HELIPAD1_block, 10 }, { 16, HELITAKEOFF, HELIPAD1_block, 10 }, { 16, 0, 0, 17 },
|
||||
{ 17, 255, TERM_GROUP2_block, 0 }, { 17, TERM5, TERM5_block, 8 }, { 17, TERM4, 0, 16 }, { 17, HELIPAD1, 0, 16 }, { 17, HELIPAD2, HELIPAD2_block, 11 }, { 17, HELITAKEOFF, HELIPAD2_block, 11 }, { 17, 0, 0, 18 },
|
||||
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM6, TERM6_block, 9 }, { 18, TAKEOFF, 0, 19 }, { 18, HANGAR, HANGAR2_AREA_block, 3 }, { 18, 0, 0, 17 },
|
||||
{ 19, 0, TERM_GROUP2_EXIT1_block, 20 },
|
||||
{ 20, 0, TERM_GROUP2_EXIT1_block, 21 },
|
||||
{ 21, 0, TERM_GROUP2_EXIT2_block, 22 },
|
||||
{ 22, 0, TERM_GROUP2_EXIT2_block, 26 },
|
||||
{ 23, 255, TERM_GROUP1_block, 0 }, { 23, TERM1, TERM1_block, 4 }, { 23, HANGAR, AIRPORT_ENTRANCE_block, 2 }, { 23, 0, 0, 24 },
|
||||
{ 24, 255, TERM_GROUP1_block, 0 }, { 24, TERM2, TERM2_block, 5 }, { 24, TERM1, 0, 23 }, { 24, HANGAR, 0, 23 }, { 24, 0, 0, 25 },
|
||||
{ 25, 255, TERM_GROUP1_block, 0 }, { 25, TERM3, TERM3_block, 6 }, { 25, TAKEOFF, 0, 26 }, { 25, 0, 0, 24 },
|
||||
{ 26, 255, TAXIWAY_BUSY_block, 0 }, { 26, TAKEOFF, 0, 27 }, { 26, 0, 0, 25 },
|
||||
{ 27, 0, OUT_WAY_block, 28 },
|
||||
// takeoff
|
||||
{ 28, TAKEOFF, OUT_WAY_block, 29 },
|
||||
{ 29, 0, RUNWAY_OUT_block, 30 },
|
||||
{ 30, STARTTAKEOFF, NOTHING_block, 31 },
|
||||
{ 31, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 32, FLYING, NOTHING_block, 37 }, { 32, LANDING, 0, 33 }, { 32, HELILANDING, 0, 41 },
|
||||
{ 33, LANDING, RUNWAY_IN_block, 34 },
|
||||
{ 34, 0, RUNWAY_IN_block, 35 },
|
||||
{ 35, 0, RUNWAY_IN_block, 36 },
|
||||
{ 36, ENDLANDING, IN_WAY_block, 36 }, { 36, 255, TERM_GROUP1_block, 0 }, { 36, 255, TERM_GROUP2_ENTER1_block, 1 }, { 36, TERM4, 0, 12 }, { 36, TERM5, 0, 12 }, { 36, TERM6, 0, 12 }, { 36, 0, 0, 2 },
|
||||
// In Air
|
||||
{ 37, 0, NOTHING_block, 38 },
|
||||
{ 38, 0, NOTHING_block, 39 },
|
||||
{ 39, 0, NOTHING_block, 40 },
|
||||
{ 40, 0, NOTHING_block, 32 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 41, HELILANDING, PRE_HELIPAD_block, 42 },
|
||||
{ 42, HELIENDLANDING, PRE_HELIPAD_block, 42 }, { 42, HELIPAD1, 0, 43 }, { 42, HELIPAD2, 0, 44 }, { 42, HANGAR, 0, 49 },
|
||||
{ 43, 0, NOTHING_block, 45 },
|
||||
{ 44, 0, NOTHING_block, 46 },
|
||||
// landing
|
||||
{ 45, 255, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
|
||||
{ 46, 255, NOTHING_block, 0 }, { 46, HELIPAD2, HELIPAD2_block, 11 },
|
||||
// Helicopter -- takeoff
|
||||
{ 47, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 48, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 49, 0, HANGAR2_AREA_block, 50 }, // need to go to hangar when waiting in air
|
||||
{ 50, 0, HANGAR2_AREA_block, 3 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// intercontinental
|
||||
static const TileIndexDiffC _airport_depots_intercontinental[] = { { 0, 5 }, { 8, 4 } };
|
||||
static const byte _airport_terminal_intercontinental[] = { 2, 4, 4 };
|
||||
static const byte _airport_helipad_intercontinental[] = { 1, 2 };
|
||||
static const AirportFTAbuildup _airport_fta_intercontinental[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 0 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 1 }, { 0, TAKEOFF, HANGAR1_AREA_block | TERM_GROUP1_block, 2 }, { 0, 0, 0, 2 },
|
||||
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, 255, HANGAR2_AREA_block, 0 }, { 1, 0, 0, 3 },
|
||||
{ 2, 255, HANGAR1_AREA_block, 0 }, { 2, 255, TERM_GROUP1_block, 0 }, { 2, 255, TERM_GROUP1_block, 1 }, { 2, HANGAR, 0, 0 }, { 2, TAKEOFF, TERM_GROUP1_block, 27 }, { 2, TERM5, 0, 26 }, { 2, TERM6, 0, 26 }, { 2, TERM7, 0, 26 }, { 2, TERM8, 0, 26 }, { 2, HELIPAD1, 0, 26 }, { 2, HELIPAD2, 0, 26 }, { 2, HELITAKEOFF, 0, 74 }, { 2, 0, 0, 27 },
|
||||
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 75 }, { 3, 0, 0, 20 },
|
||||
{ 4, TERM1, TERM1_block, 26 }, { 4, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 26 }, { 4, 0, 0, 26 },
|
||||
{ 5, TERM2, TERM2_block, 27 }, { 5, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 27 }, { 5, 0, 0, 27 },
|
||||
{ 6, TERM3, TERM3_block, 28 }, { 6, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 28 }, { 6, 0, 0, 28 },
|
||||
{ 7, TERM4, TERM4_block, 29 }, { 7, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 7, 0, 0, 29 },
|
||||
{ 8, TERM5, TERM5_block, 18 }, { 8, HANGAR, HANGAR2_AREA_block, 18 }, { 8, 0, 0, 18 },
|
||||
{ 9, TERM6, TERM6_block, 19 }, { 9, HANGAR, HANGAR2_AREA_block, 19 }, { 9, 0, 0, 19 },
|
||||
{ 10, TERM7, TERM7_block, 20 }, { 10, HANGAR, HANGAR2_AREA_block, 20 }, { 10, 0, 0, 20 },
|
||||
{ 11, TERM8, TERM8_block, 21 }, { 11, HANGAR, HANGAR2_AREA_block, 21 }, { 11, 0, 0, 21 },
|
||||
{ 12, HELIPAD1, HELIPAD1_block, 12 }, { 12, HANGAR, 0, 70 }, { 12, HELITAKEOFF, 0, 72 },
|
||||
{ 13, HELIPAD2, HELIPAD2_block, 13 }, { 13, HANGAR, 0, 71 }, { 13, HELITAKEOFF, 0, 73 },
|
||||
{ 14, 0, TERM_GROUP2_ENTER1_block, 15 },
|
||||
{ 15, 0, TERM_GROUP2_ENTER1_block, 16 },
|
||||
{ 16, 0, TERM_GROUP2_ENTER2_block, 17 },
|
||||
{ 17, 0, TERM_GROUP2_ENTER2_block, 18 },
|
||||
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM5, TERM5_block, 8 }, { 18, TAKEOFF, 0, 19 }, { 18, HELITAKEOFF, HELIPAD1_block, 19 }, { 18, 0, TERM_GROUP2_EXIT1_block, 19 },
|
||||
{ 19, 255, TERM_GROUP2_block, 0 }, { 19, TERM6, TERM6_block, 9 }, { 19, TERM5, 0, 18 }, { 19, TAKEOFF, 0, 57 }, { 19, HELITAKEOFF, HELIPAD1_block, 20 }, { 19, 0, TERM_GROUP2_EXIT1_block, 20 }, // add exit to runway out 2
|
||||
{ 20, 255, TERM_GROUP2_block, 0 }, { 20, TERM7, TERM7_block, 10 }, { 20, TERM5, 0, 19 }, { 20, TERM6, 0, 19 }, { 20, HANGAR, HANGAR2_AREA_block, 3 }, { 20, TAKEOFF, 0, 19 }, { 20, 0, TERM_GROUP2_EXIT1_block, 21 },
|
||||
{ 21, 255, TERM_GROUP2_block, 0 }, { 21, TERM8, TERM8_block, 11 }, { 21, HANGAR, HANGAR2_AREA_block, 20 }, { 21, TERM5, 0, 20 }, { 21, TERM6, 0, 20 }, { 21, TERM7, 0, 20 }, { 21, TAKEOFF, 0, 20 }, { 21, 0, TERM_GROUP2_EXIT1_block, 22 },
|
||||
{ 22, 255, TERM_GROUP2_block, 0 }, { 22, HANGAR, 0, 21 }, { 22, TERM5, 0, 21 }, { 22, TERM6, 0, 21 }, { 22, TERM7, 0, 21 }, { 22, TERM8, 0, 21 }, { 22, TAKEOFF, 0, 21 }, { 22, 0, 0, 23 },
|
||||
{ 23, 0, TERM_GROUP2_EXIT1_block, 70 },
|
||||
{ 24, 0, TERM_GROUP2_EXIT2_block, 25 },
|
||||
{ 25, 255, TERM_GROUP2_EXIT2_block, 0 }, { 25, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 25, 0, 0, 29 },
|
||||
{ 26, 255, TERM_GROUP1_block, 0 }, { 26, TERM1, TERM1_block, 4 }, { 26, HANGAR, HANGAR1_AREA_block, 27 }, { 26, TERM5, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM6, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM7, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM8, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD1, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD2, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELITAKEOFF, TERM_GROUP2_ENTER1_block, 14 }, { 26, 0, 0, 27 },
|
||||
{ 27, 255, TERM_GROUP1_block, 0 }, { 27, TERM2, TERM2_block, 5 }, { 27, HANGAR, HANGAR1_AREA_block, 2 }, { 27, TERM1, 0, 26 }, { 27, TERM5, 0, 26 }, { 27, TERM6, 0, 26 }, { 27, TERM7, 0, 26 }, { 27, TERM8, 0, 26 }, { 27, HELIPAD1, 0, 14 }, { 27, HELIPAD2, 0, 14 }, { 27, 0, 0, 28 },
|
||||
{ 28, 255, TERM_GROUP1_block, 0 }, { 28, TERM3, TERM3_block, 6 }, { 28, HANGAR, HANGAR1_AREA_block, 27 }, { 28, TERM1, 0, 27 }, { 28, TERM2, 0, 27 }, { 28, TERM4, 0, 29 }, { 28, TERM5, 0, 14 }, { 28, TERM6, 0, 14 }, { 28, TERM7, 0, 14 }, { 28, TERM8, 0, 14 }, { 28, HELIPAD1, 0, 14 }, { 28, HELIPAD2, 0, 14 }, { 28, 0, 0, 29 },
|
||||
{ 29, 255, TERM_GROUP1_block, 0 }, { 29, TERM4, TERM4_block, 7 }, { 29, HANGAR, HANGAR1_AREA_block, 27 }, { 29, TAKEOFF, 0, 30 }, { 29, 0, 0, 28 },
|
||||
{ 30, 0, OUT_WAY_block2, 31 },
|
||||
{ 31, 0, OUT_WAY_block, 32 },
|
||||
// takeoff
|
||||
{ 32, TAKEOFF, RUNWAY_OUT_block, 33 },
|
||||
{ 33, 0, RUNWAY_OUT_block, 34 },
|
||||
{ 34, STARTTAKEOFF, NOTHING_block, 35 },
|
||||
{ 35, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// landing
|
||||
{ 36, 0, 0, 0 },
|
||||
{ 37, LANDING, RUNWAY_IN_block, 38 },
|
||||
{ 38, 0, RUNWAY_IN_block, 39 },
|
||||
{ 39, 0, RUNWAY_IN_block, 40 },
|
||||
{ 40, ENDLANDING, RUNWAY_IN_block, 41 },
|
||||
{ 41, 0, IN_WAY_block, 42 },
|
||||
{ 42, 255, IN_WAY_block, 0 }, { 42, 255, TERM_GROUP1_block, 0 }, { 42, 255, TERM_GROUP1_block, 1 }, { 42, HANGAR, 0, 2 }, { 42, 0, 0, 26 },
|
||||
// In Air
|
||||
{ 43, 0, 0, 44 },
|
||||
{ 44, FLYING, 0, 45 }, { 44, HELILANDING, 0, 47 }, { 44, LANDING, 0, 69 }, { 44, 0, 0, 45 },
|
||||
{ 45, 0, 0, 46 },
|
||||
{ 46, FLYING, 0, 43 }, { 46, LANDING, 0, 76 }, { 46, 0, 0, 43 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 47, HELILANDING, PRE_HELIPAD_block, 48 },
|
||||
{ 48, HELIENDLANDING, PRE_HELIPAD_block, 48 }, { 48, HELIPAD1, 0, 49 }, { 48, HELIPAD2, 0, 50 }, { 48, HANGAR, 0, 55 },
|
||||
{ 49, 0, NOTHING_block, 51 },
|
||||
{ 50, 0, NOTHING_block, 52 },
|
||||
// landing
|
||||
{ 51, 255, NOTHING_block, 0 }, { 51, HELIPAD1, HELIPAD1_block, 12 }, { 51, HANGAR, 0, 55 }, { 51, 0, 0, 12 },
|
||||
{ 52, 255, NOTHING_block, 0 }, { 52, HELIPAD2, HELIPAD2_block, 13 }, { 52, HANGAR, 0, 55 }, { 52, 0, 0, 13 },
|
||||
// Helicopter -- takeoff
|
||||
{ 53, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 54, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 55, 0, HANGAR2_AREA_block, 56 }, // need to go to hangar when waiting in air
|
||||
{ 56, 0, HANGAR2_AREA_block, 3 },
|
||||
// runway 2 out support
|
||||
{ 57, 255, OUT_WAY2_block, 0 }, { 57, TAKEOFF, 0, 58 }, { 57, 0, 0, 58 },
|
||||
{ 58, 0, OUT_WAY2_block, 59 },
|
||||
{ 59, TAKEOFF, RUNWAY_OUT2_block, 60 }, // takeoff
|
||||
{ 60, 0, RUNWAY_OUT2_block, 61 },
|
||||
{ 61, STARTTAKEOFF, NOTHING_block, 62 },
|
||||
{ 62, ENDTAKEOFF, NOTHING_block, 0 },
|
||||
// runway 2 in support
|
||||
{ 63, LANDING, RUNWAY_IN2_block, 64 },
|
||||
{ 64, 0, RUNWAY_IN2_block, 65 },
|
||||
{ 65, 0, RUNWAY_IN2_block, 66 },
|
||||
{ 66, ENDLANDING, RUNWAY_IN2_block, 0 }, { 66, 255, 0, 1 }, { 66, 255, 0, 0 }, { 66, 0, 0, 67 },
|
||||
{ 67, 0, IN_WAY2_block, 68 },
|
||||
{ 68, 255, IN_WAY2_block, 0 }, { 68, 255, TERM_GROUP2_block, 1 }, { 68, 255, TERM_GROUP1_block, 0 }, { 68, HANGAR, HANGAR2_AREA_block, 22 }, { 68, 0, 0, 22 },
|
||||
{ 69, 255, RUNWAY_IN2_block, 0 }, { 69, 0, RUNWAY_IN2_block, 63 },
|
||||
{ 70, 255, TERM_GROUP2_EXIT1_block, 0 }, { 70, HELIPAD1, HELIPAD1_block, 12 }, { 70, HELITAKEOFF, HELIPAD1_block, 12 }, { 70, 0, 0, 71 },
|
||||
{ 71, 255, TERM_GROUP2_EXIT1_block, 0 }, { 71, HELIPAD2, HELIPAD2_block, 13 }, { 71, HELITAKEOFF, HELIPAD1_block, 12 }, { 71, 0, 0, 24 },
|
||||
{ 72, 0, HELIPAD1_block, 53 },
|
||||
{ 73, 0, HELIPAD2_block, 54 },
|
||||
{ 74, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 75, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 76, 255, RUNWAY_IN_block, 0 }, { 76, 0, RUNWAY_IN_block, 37 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = { 1, 1 };
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{ 0, HELIPAD1, HELIPAD1_block, 1 },
|
||||
{ 1, HELITAKEOFF, NOTHING_block, 0 }, // takeoff
|
||||
{ 2, 255, AIRPORT_BUSY_block, 0 }, { 2, HELILANDING, 0, 3 }, { 2, HELITAKEOFF, 0, 1 },
|
||||
{ 3, HELILANDING, AIRPORT_BUSY_block, 4 },
|
||||
{ 4, HELIENDLANDING, AIRPORT_BUSY_block, 4 }, { 4, HELIPAD1, HELIPAD1_block, 0 }, { 4, HELITAKEOFF, 0, 2 },
|
||||
// In Air
|
||||
{ 5, 0, NOTHING_block, 6 },
|
||||
{ 6, 0, NOTHING_block, 7 },
|
||||
{ 7, 0, NOTHING_block, 8 },
|
||||
{ 8, FLYING, NOTHING_block, 5 }, { 8, HELILANDING, HELIPAD1_block, 2 }, // landing
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// helidepots
|
||||
static const TileIndexDiffC _airport_depots_helidepot[] = { { 1, 0 } };
|
||||
static const byte _airport_helipad_helidepot[] = { 1, 1 };
|
||||
static const AirportFTAbuildup _airport_fta_helidepot[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 1 },
|
||||
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELIPAD1, HELIPAD1_block, 14 }, { 1, HELITAKEOFF, 0, 15 }, { 1, 0, 0, 0 },
|
||||
{ 2, FLYING, NOTHING_block, 3 }, { 2, HELILANDING, PRE_HELIPAD_block, 7 }, { 2, HANGAR, 0, 12 }, { 2, HELITAKEOFF, NOTHING_block, 16 },
|
||||
// In Air
|
||||
{ 3, 0, NOTHING_block, 4 },
|
||||
{ 4, 0, NOTHING_block, 5 },
|
||||
{ 5, 0, NOTHING_block, 6 },
|
||||
{ 6, 0, NOTHING_block, 2 },
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{ 7, HELILANDING, PRE_HELIPAD_block, 8 },
|
||||
{ 8, HELIENDLANDING, PRE_HELIPAD_block, 8 }, { 8, HELIPAD1, 0, 9 }, { 8, HANGAR, 0, 12 }, { 8, 0, 0, 2 },
|
||||
{ 9, 0, NOTHING_block, 10 },
|
||||
// landing
|
||||
{ 10, 255, NOTHING_block, 10 }, { 10, HELIPAD1, HELIPAD1_block, 14 }, { 10, HANGAR, 0, 1 }, { 10, 0, 0, 14 },
|
||||
// Helicopter -- takeoff
|
||||
{ 11, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 12, 0, HANGAR2_AREA_block, 13 }, // need to go to hangar when waiting in air
|
||||
{ 13, 0, HANGAR2_AREA_block, 1 },
|
||||
{ 14, HELIPAD1, HELIPAD1_block, 14 }, { 14, HANGAR, 0, 1 }, { 14, HELITAKEOFF, 0, 17 },
|
||||
{ 15, HELITAKEOFF, NOTHING_block, 0 }, // takeoff outside depot
|
||||
{ 16, HELITAKEOFF, 0, 14 },
|
||||
{ 17, 0, NOTHING_block, 11 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// helistation
|
||||
static const TileIndexDiffC _airport_depots_helistation[] = { { 0, 0 } };
|
||||
static const byte _airport_helipad_helistation[] = { 1, 3 };
|
||||
static const AirportFTAbuildup _airport_fta_helistation[] = {
|
||||
{ 0, HANGAR, NOTHING_block, 8 }, { 0, HELIPAD1, 0, 1 }, { 0, HELIPAD2, 0, 1 }, { 0, HELIPAD3, 0, 1 }, { 0, HELITAKEOFF, 0, 1 }, { 0, 0, 0, 0 },
|
||||
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELITAKEOFF, 0, 3 }, { 1, 0, 0, 4 },
|
||||
// landing
|
||||
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, 0, 0, 28 },
|
||||
// helicopter side
|
||||
{ 3, HELITAKEOFF, NOTHING_block, 0 }, // helitakeoff outside hangar2
|
||||
{ 4, 255, TAXIWAY_BUSY_block, 0 }, { 4, HANGAR, HANGAR2_AREA_block, 1 }, { 4, HELITAKEOFF, 0, 1 }, { 4, 0, 0, 5 },
|
||||
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, HELIPAD1, HELIPAD1_block, 6 }, { 5, HELIPAD2, HELIPAD2_block, 7 }, { 5, HELIPAD3, HELIPAD3_block, 8 }, { 5, 0, 0, 4 },
|
||||
{ 6, HELIPAD1, HELIPAD1_block, 5 }, { 6, HANGAR, HANGAR2_AREA_block, 5 }, { 6, HELITAKEOFF, 0, 9 }, { 6, 0, 0, 6 },
|
||||
{ 7, HELIPAD2, HELIPAD2_block, 5 }, { 7, HANGAR, HANGAR2_AREA_block, 5 }, { 7, HELITAKEOFF, 0, 10 }, { 7, 0, 0, 7 },
|
||||
{ 8, HELIPAD3, HELIPAD3_block, 5 }, { 8, HANGAR, HANGAR2_AREA_block, 5 }, { 8, HELITAKEOFF, 0, 11 }, { 8, 0, 0, 8 },
|
||||
{ 9, 0, HELIPAD1_block, 12 },
|
||||
{ 10, 0, HELIPAD2_block, 13 },
|
||||
{ 11, 0, HELIPAD3_block, 14 },
|
||||
{ 12, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 13, HELITAKEOFF, NOTHING_block, 0 },
|
||||
{ 14, HELITAKEOFF, NOTHING_block, 0 },
|
||||
// heli - in flight moves
|
||||
{ 15, HELILANDING, PRE_HELIPAD_block, 16 },
|
||||
{ 16, HELIENDLANDING, PRE_HELIPAD_block, 16 }, { 16, HELIPAD1, 0, 17 }, { 16, HELIPAD2, 0, 18 }, { 16, HELIPAD3, 0, 19 }, { 16, HANGAR, 0, 23 },
|
||||
{ 17, 0, NOTHING_block, 20 },
|
||||
{ 18, 0, NOTHING_block, 21 },
|
||||
{ 19, 0, NOTHING_block, 22 },
|
||||
// heli landing
|
||||
{ 20, 255, NOTHING_block, 0 }, { 20, HELIPAD1, HELIPAD1_block, 6 }, { 20, HANGAR, 0, 23 }, { 20, 0, 0, 6 },
|
||||
{ 21, 255, NOTHING_block, 0 }, { 21, HELIPAD2, HELIPAD2_block, 7 }, { 21, HANGAR, 0, 23 }, { 21, 0, 0, 7 },
|
||||
{ 22, 255, NOTHING_block, 0 }, { 22, HELIPAD3, HELIPAD3_block, 8 }, { 22, HANGAR, 0, 23 }, { 22, 0, 0, 8 },
|
||||
{ 23, 0, HANGAR2_AREA_block, 24 }, // need to go to helihangar when waiting in air
|
||||
{ 24, 0, HANGAR2_AREA_block, 1 },
|
||||
{ 25, 0, NOTHING_block, 26 },
|
||||
{ 26, 0, NOTHING_block, 27 },
|
||||
{ 27, 0, NOTHING_block, 2 },
|
||||
{ 28, 0, NOTHING_block, 29 },
|
||||
{ 29, 0, NOTHING_block, 30 },
|
||||
{ 30, 0, NOTHING_block, 31 },
|
||||
{ 31, 0, NOTHING_block, 32 },
|
||||
{ 32, 0, NOTHING_block, 25 },
|
||||
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
_airport_moving_data_commuter, // Commuter Airfield (small) 5x4
|
||||
_airport_moving_data_helidepot, // Helidepot
|
||||
_airport_moving_data_intercontinental, // Intercontinental Airport (xxlarge) - 4 runways
|
||||
_airport_moving_data_helistation, // Helistation
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
#endif /* AIRPORT_MOVEMENT_H */
|
||||
+52
-54
@@ -1,7 +1,5 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file aystar.cpp Implementation of A*. */
|
||||
|
||||
/*
|
||||
* This file has the core function for AyStar
|
||||
* AyStar is a fast pathfinding routine and is used for things like
|
||||
@@ -19,42 +17,42 @@
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "aystar.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
|
||||
int _aystar_stats_open_size;
|
||||
int _aystar_stats_closed_size;
|
||||
|
||||
/* This looks in the Hash if a node exists in ClosedList
|
||||
* If so, it returns the PathNode, else NULL */
|
||||
static PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
|
||||
// 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 */
|
||||
// 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 = MallocT<PathNode>(1);
|
||||
// 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 */
|
||||
// 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 */
|
||||
// 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. */
|
||||
// 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);
|
||||
@@ -63,18 +61,18 @@ static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Adds a node to the OpenList
|
||||
* It makes a copy of node, and puts the pointer of parent in the struct */
|
||||
// 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 = MallocT<OpenListNode>(1);
|
||||
// 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 */
|
||||
// Add it to the queue
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
|
||||
}
|
||||
|
||||
@@ -89,49 +87,49 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
PathNode *closedlist_parent;
|
||||
OpenListNode *check;
|
||||
|
||||
/* Check the new node against the ClosedList */
|
||||
// Check the new node against the ClosedList
|
||||
if (AyStarMain_ClosedList_IsInList(aystar, current) != NULL) return AYSTAR_DONE;
|
||||
|
||||
/* Calculate the G-value for this node */
|
||||
// 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 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.. */
|
||||
// There should not be given any other error-code..
|
||||
assert(new_g >= 0);
|
||||
/* Add the parent g-value to the new g-value */
|
||||
// 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 */
|
||||
// Calculate the h-value
|
||||
new_h = aystar->CalculateH(aystar, current, parent);
|
||||
/* There should not be given any error-code.. */
|
||||
// There should not be given any error-code..
|
||||
assert(new_h >= 0);
|
||||
|
||||
/* The f-value if g + h */
|
||||
// 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) */
|
||||
// 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 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.. */
|
||||
// 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 */
|
||||
// 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 */
|
||||
// Readd him in the OpenListQueue
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
|
||||
} else {
|
||||
/* A new node, add him to the OpenList */
|
||||
// A new node, add him to the OpenList
|
||||
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
|
||||
}
|
||||
|
||||
@@ -153,12 +151,12 @@ int AyStarMain_Loop(AyStar *aystar)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
/* Get the best node from OpenList */
|
||||
// Get the best node from OpenList
|
||||
OpenListNode *current = AyStarMain_OpenList_Pop(aystar);
|
||||
/* If empty, drop an error */
|
||||
// If empty, drop an error
|
||||
if (current == NULL) return AYSTAR_EMPTY_OPENLIST;
|
||||
|
||||
/* Check for end node and if found, return that code */
|
||||
// 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);
|
||||
@@ -166,26 +164,26 @@ int AyStarMain_Loop(AyStar *aystar)
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
}
|
||||
|
||||
/* Add the node to the ClosedList */
|
||||
// Add the node to the ClosedList
|
||||
AyStarMain_ClosedList_Add(aystar, ¤t->path);
|
||||
|
||||
/* Load the neighbours */
|
||||
// Load the neighbours
|
||||
aystar->GetNeighbours(aystar, current);
|
||||
|
||||
/* Go through all neighbours */
|
||||
// Go through all neighbours
|
||||
for (i = 0; i < aystar->num_neighbours; i++) {
|
||||
/* Check and add them to the OpenList if needed */
|
||||
// Check and add them to the OpenList if needed
|
||||
r = aystar->checktile(aystar, &aystar->neighbours[i], current);
|
||||
}
|
||||
|
||||
/* Free the node */
|
||||
// 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 that we are still busy
|
||||
return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
}
|
||||
@@ -211,10 +209,10 @@ void AyStarMain_Free(AyStar *aystar)
|
||||
*/
|
||||
void AyStarMain_Clear(AyStar *aystar)
|
||||
{
|
||||
/* Clean the Queue, but not the elements within. That will be done by
|
||||
* the hash. */
|
||||
// Clean the Queue, but not the elements within. That will be done by
|
||||
// the hash.
|
||||
aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
|
||||
/* Clean the hashes */
|
||||
// Clean the hashes
|
||||
clear_Hash(&aystar->OpenListHash, true);
|
||||
clear_Hash(&aystar->ClosedListHash, true);
|
||||
|
||||
@@ -235,8 +233,8 @@ void AyStarMain_Clear(AyStar *aystar)
|
||||
*/
|
||||
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 */
|
||||
// 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) {
|
||||
@@ -279,14 +277,14 @@ void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g)
|
||||
|
||||
void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets)
|
||||
{
|
||||
/* Allocated the Hash for the OpenList and ClosedList */
|
||||
// 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 */
|
||||
// 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;
|
||||
+12
-11
@@ -1,6 +1,6 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file aystar.h
|
||||
/*
|
||||
* This file has the header for AyStar
|
||||
* AyStar is a fast pathfinding routine and is used for things like
|
||||
* AI_pathfinding and Train_pathfinding.
|
||||
@@ -12,8 +12,6 @@
|
||||
#define AYSTAR_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "tile_type.h"
|
||||
#include "track_type.h"
|
||||
|
||||
//#define AYSTAR_DEBUG
|
||||
enum {
|
||||
@@ -29,28 +27,31 @@ enum{
|
||||
AYSTAR_INVALID_NODE = -1,
|
||||
};
|
||||
|
||||
typedef struct AyStarNode AyStarNode;
|
||||
struct AyStarNode {
|
||||
TileIndex tile;
|
||||
Trackdir direction;
|
||||
uint direction;
|
||||
uint user_data[2];
|
||||
};
|
||||
|
||||
/* The resulting path has nodes looking like this. */
|
||||
// The resulting path has nodes looking like this.
|
||||
typedef struct PathNode PathNode;
|
||||
struct PathNode {
|
||||
AyStarNode node;
|
||||
/* The parent of this item */
|
||||
// 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. */
|
||||
// For internal use only
|
||||
// We do not save the h-value, because it is only needed to calculate the f-value.
|
||||
// h-value should _always_ be the distance left to the end-tile.
|
||||
typedef struct OpenListNode OpenListNode;
|
||||
struct OpenListNode {
|
||||
int g;
|
||||
PathNode path;
|
||||
};
|
||||
|
||||
struct AyStar;
|
||||
typedef struct AyStar AyStar;
|
||||
/*
|
||||
* This function is called to check if the end-tile is found
|
||||
* return values can be:
|
||||
@@ -97,7 +98,7 @@ typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
*/
|
||||
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
/* For internal use, see aystar.cpp */
|
||||
// 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);
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $Id$
|
||||
|
||||
if ! [ -f ai/regression/regression.nut ]; then
|
||||
echo "Make sure you are in the root of OpenTTD before starting this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat ai/regression/regression.nut | tr ';' '\n' | awk '
|
||||
/^function/ {
|
||||
for (local in locals) {
|
||||
delete locals[local]
|
||||
}
|
||||
if (match($0, "function Regression::Start") || match($0, "function Regression::Stop")) next
|
||||
locals["this"] = "AIControllerSquirrel"
|
||||
}
|
||||
|
||||
/local/ {
|
||||
gsub(".*local", "local")
|
||||
if (match($4, "^AI")) {
|
||||
sub("\\(.*", "", $4)
|
||||
locals[$2] = $4
|
||||
}
|
||||
}
|
||||
|
||||
/Valuate/ {
|
||||
gsub(".*Valuate\\(", "")
|
||||
gsub("\\).*", "")
|
||||
gsub(",.*", "")
|
||||
gsub("\\.", "::")
|
||||
print $0
|
||||
}
|
||||
|
||||
/\./ {
|
||||
for (local in locals) {
|
||||
if (match($0, local ".")) {
|
||||
fname = substr($0, index($0, local "."))
|
||||
sub("\\(.*", "", fname)
|
||||
sub("\\.", "::", fname)
|
||||
sub(local, locals[local], fname)
|
||||
print fname
|
||||
if (match(locals[local], "List")) {
|
||||
sub(locals[local], "AIAbstractList", fname)
|
||||
print fname
|
||||
}
|
||||
}
|
||||
}
|
||||
# We want to remove everything before the FIRST occurence of AI.
|
||||
# If we do not remove any other occurences of AI from the string
|
||||
# we will remove everything before the LAST occurence of AI, so
|
||||
# do some little magic to make it work the way we want.
|
||||
sub("AI", "AXXXXY")
|
||||
gsub("AI", "AXXXXX")
|
||||
sub(".*AXXXXY", "AI")
|
||||
if (match($0, "^AI") && match($0, ".")) {
|
||||
sub("\\(.*", "", $0)
|
||||
sub("\\.", "::", $0)
|
||||
print $0
|
||||
}
|
||||
}
|
||||
' | sed 's/ //g' | sort | uniq > tmp.in_regression
|
||||
|
||||
grep 'DefSQ.*Method' ../src/ai/api/*.hpp.sq | grep -v 'AIError::' | grep -v 'AIAbstractList::Valuate' | grep -v '::GetClassName' | sed 's/^[^,]*, &//g;s/,[^,]*//g' | sort > tmp.in_api
|
||||
|
||||
diff -u tmp.in_regression tmp.in_api | grep -v '^+++' | grep '^+' | sed 's/^+//'
|
||||
|
||||
rm -f tmp.in_regression tmp.in_api
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[misc]
|
||||
display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|WAYPOINTS
|
||||
language = english.lng
|
||||
|
||||
[gui]
|
||||
autosave = off
|
||||
|
||||
[game_creation]
|
||||
town_name = english
|
||||
|
||||
[ai_players]
|
||||
none =
|
||||
regression =
|
||||
|
||||
[vehicle]
|
||||
road_side = right
|
||||
plane_speed = 2
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
class Regression extends AIInfo {
|
||||
function GetAuthor() { return "OpenTTD NoAI Developers Team"; }
|
||||
function GetName() { return "Regression"; }
|
||||
function GetShortName() { return "REGR"; }
|
||||
function GetDescription() { return "This runs regression-tests on all commands. On the same map the result should always be the same."; }
|
||||
function GetVersion() { return 1; }
|
||||
function GetDate() { return "2007-03-18"; }
|
||||
function CreateInstance() { return "Regression"; }
|
||||
}
|
||||
|
||||
RegisterAI(Regression());
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
print(" Required this file");
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $Id$
|
||||
|
||||
if ! [ -f ai/regression/regression.nut ]; then
|
||||
echo "Make sure you are in the root of OpenTTD before starting this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp ai/regression/regression.nut ai/regression/main.nut
|
||||
cp ai/regression/regression_info.nut ai/regression/info.nut
|
||||
|
||||
if [ -f scripts/game_start.scr ]; then
|
||||
mv scripts/game_start.scr scripts/game_start.scr.regression
|
||||
fi
|
||||
|
||||
params=""
|
||||
gdb=""
|
||||
if [ "$1" != "-r" ]; then
|
||||
params="-snull -mnull -vnull:ticks=30000"
|
||||
fi
|
||||
if [ "$1" = "-g" ]; then
|
||||
gdb="gdb --ex run --args "
|
||||
fi
|
||||
if [ -n "$gdb" ]; then
|
||||
$gdb ./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.sav
|
||||
else
|
||||
./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.sav -d ai=2 2>&1 | awk '{ gsub("0x(\\(nil\\)|0+)", "0x00000000", $0); gsub("^dbg: \\[ai\\]", "", $0); gsub("^ ", "ERROR: ", $0); gsub("ERROR: \\[1\\] ", "", $0); gsub("\\[P\\] ", "", $0); print $0; }' > tmp.regression
|
||||
fi
|
||||
|
||||
if [ -z "$gdb" ]; then
|
||||
res="`diff -ub ai/regression/regression.txt tmp.regression`"
|
||||
if [ -z "$res" ]; then
|
||||
echo "Regression test passed!"
|
||||
else
|
||||
echo "Regression test failed! Difference:"
|
||||
echo "$res"
|
||||
fi
|
||||
echo ""
|
||||
echo "Regression test done"
|
||||
fi
|
||||
|
||||
rm -f ai/regression/main.nut ai/regression/info.nut
|
||||
|
||||
if [ -f scripts/game_start.scr.regression ]; then
|
||||
mv scripts/game_start.scr.regression scripts/game_start.scr
|
||||
fi
|
||||
|
||||
if [ "$1" != "-k" ]; then
|
||||
rm -f tmp.regression
|
||||
fi
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,31 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the non-German Transport
|
||||
; Tycoon Deluxe DOS CD.
|
||||
;
|
||||
[metadata]
|
||||
name = original_dos
|
||||
shortname = TTDD
|
||||
version = 1
|
||||
description = Original Transport Tycoon Deluxe DOS edition graphics
|
||||
palette = DOS
|
||||
|
||||
[files]
|
||||
base = TRG1.GRF
|
||||
logos = TRGI.GRF
|
||||
arctic = TRGC.GRF
|
||||
tropical = TRGH.GRF
|
||||
toyland = TRGT.GRF
|
||||
extra = OPENTTDD.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
|
||||
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
|
||||
TRGC.GRF = ed446637e034104c5559b32c18afe78d
|
||||
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
|
||||
TRGT.GRF = e30e8a398ae86c03dc534a8ac7dfb3b6
|
||||
OPENTTDD.GRF = c886c7d5b38a93f2cb1cdc0d33472eb8
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
OPENTTDD.GRF = This file was part of your installation.
|
||||
@@ -1,31 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the German Transport
|
||||
; Tycoon Deluxe DOS CD. It contains one broken sprite.
|
||||
;
|
||||
[metadata]
|
||||
name = original_dos_de
|
||||
shortname = TTDD
|
||||
version = 0
|
||||
description = Original Transport Tycoon Deluxe DOS (German) edition graphics
|
||||
palette = DOS
|
||||
|
||||
[files]
|
||||
base = TRG1.GRF
|
||||
logos = TRGI.GRF
|
||||
arctic = TRGC.GRF
|
||||
tropical = TRGH.GRF
|
||||
toyland = TRGT.GRF
|
||||
extra = OPENTTDD.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
|
||||
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
|
||||
TRGC.GRF = ed446637e034104c5559b32c18afe78d
|
||||
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
|
||||
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
|
||||
OPENTTDD.GRF = c886c7d5b38a93f2cb1cdc0d33472eb8
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
OPENTTDD.GRF = This file was part of your installation.
|
||||
@@ -1,31 +0,0 @@
|
||||
; $Id$
|
||||
;
|
||||
; This represents the original graphics as on the Transport
|
||||
; Tycoon Deluxe for Windows.
|
||||
;
|
||||
[metadata]
|
||||
name = original_windows
|
||||
shortname = TTDW
|
||||
version = 0
|
||||
description = Original Transport Tycoon Deluxe Windows edition graphics
|
||||
palette = Windows
|
||||
|
||||
[files]
|
||||
base = TRG1R.GRF
|
||||
logos = TRGIR.GRF
|
||||
arctic = TRGCR.GRF
|
||||
tropical = TRGHR.GRF
|
||||
toyland = TRGTR.GRF
|
||||
extra = OPENTTDW.GRF
|
||||
|
||||
[md5s]
|
||||
TRG1R.GRF = b04ce593d8c5016e07473a743d7d3358
|
||||
TRGIR.GRF = 0c2484ff6be49fc63a83be6ab5c38f32
|
||||
TRGCR.GRF = 3668f410c761a050b5e7095a2b14879b
|
||||
TRGHR.GRF = 06bf2b7a31766f048baac2ebe43457b1
|
||||
TRGTR.GRF = de53650517fe661ceaa3138c6edb0eb8
|
||||
OPENTTDW.GRF = b6689105405fa3ea34cb8a5543633d29
|
||||
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
OPENTTDW.GRF = This file was part of your installation.
|
||||
@@ -1,2 +0,0 @@
|
||||
start_ai MyAI
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# Show a MOTD
|
||||
say "Welcome..."
|
||||
+10
-10
@@ -1,14 +1,12 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bmp.cpp Read and write support for bmps. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "gfx.h"
|
||||
#include "bmp.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "macros.h"
|
||||
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
|
||||
{
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file) {
|
||||
buffer->pos = -1;
|
||||
buffer->file = file;
|
||||
buffer->read = 0;
|
||||
@@ -322,15 +320,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);
|
||||
@@ -351,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);
|
||||
+7
-11
@@ -1,36 +1,32 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bmp.h Read and write support for bmps. */
|
||||
|
||||
#ifndef BMP_H
|
||||
#define BMP_H
|
||||
|
||||
#include "gfx_type.h"
|
||||
|
||||
struct BmpInfo {
|
||||
typedef struct {
|
||||
uint32 offset; ///< offset of bitmap data from .bmp file begining
|
||||
uint32 width; ///< bitmap width
|
||||
uint32 height; ///< bitmap height
|
||||
bool os2_bmp; ///< true if OS/2 1.x or windows 2.x bitmap
|
||||
uint16 bpp; ///< bits per pixel
|
||||
uint32 compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
|
||||
uint32 palette_size; ///< number of colours in palette
|
||||
};
|
||||
uint32 palette_size; ///< number of colors in palette
|
||||
} BmpInfo;
|
||||
|
||||
struct BmpData {
|
||||
typedef struct {
|
||||
Colour *palette;
|
||||
byte *bitmap;
|
||||
};
|
||||
} BmpData;
|
||||
|
||||
#define BMP_BUFFER_SIZE 1024
|
||||
|
||||
struct BmpBuffer {
|
||||
typedef struct {
|
||||
byte data[BMP_BUFFER_SIZE];
|
||||
int pos;
|
||||
int read;
|
||||
FILE *file;
|
||||
uint real_pos;
|
||||
};
|
||||
} BmpBuffer;
|
||||
|
||||
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file);
|
||||
bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data);
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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];
|
||||
}
|
||||
@@ -1,60 +1,61 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.cpp All command callbacks. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "callback_table.h"
|
||||
#include "command_type.h"
|
||||
#include "functions.h"
|
||||
|
||||
/* If you add a callback for DoCommandP, also add the callback in here
|
||||
* see below for the full list!
|
||||
* If you don't do it, it won't work across the network!! */
|
||||
// If you add a callback for DoCommandP, also add the callback in here
|
||||
// see below for the full list!
|
||||
// If you don't do it, it won't work across the network!!
|
||||
|
||||
/* aircraft_gui.cpp */
|
||||
/* aircraft_gui.c */
|
||||
CommandCallback CcBuildAircraft;
|
||||
CommandCallback CcCloneAircraft;
|
||||
|
||||
/* airport_gui.cpp */
|
||||
/* airport_gui.c */
|
||||
CommandCallback CcBuildAirport;
|
||||
|
||||
/* bridge_gui.cpp */
|
||||
/* bridge_gui.c */
|
||||
CommandCallback CcBuildBridge;
|
||||
|
||||
/* dock_gui.cpp */
|
||||
/* dock_gui.c */
|
||||
CommandCallback CcBuildDocks;
|
||||
CommandCallback CcBuildCanal;
|
||||
|
||||
/* depot_gui.cpp */
|
||||
/* depot_gui.c */
|
||||
CommandCallback CcCloneVehicle;
|
||||
|
||||
/* main_gui.cpp */
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
CommandCallback CcBuildTown;
|
||||
CommandCallback CcGiveMoney;
|
||||
|
||||
/* rail_gui.cpp */
|
||||
/* rail_gui.c */
|
||||
CommandCallback CcPlaySound1E;
|
||||
CommandCallback CcRailDepot;
|
||||
CommandCallback CcStation;
|
||||
CommandCallback CcBuildRailTunnel;
|
||||
|
||||
/* road_gui.cpp */
|
||||
/* road_gui.c */
|
||||
CommandCallback CcPlaySound1D;
|
||||
CommandCallback CcBuildRoadTunnel;
|
||||
CommandCallback CcRoadDepot;
|
||||
|
||||
/* roadveh_gui.cpp */
|
||||
/* roadveh_gui.c */
|
||||
CommandCallback CcBuildRoadVeh;
|
||||
CommandCallback CcCloneRoadVeh;
|
||||
|
||||
/* ship_gui.cpp */
|
||||
/* ship_gui.c */
|
||||
CommandCallback CcBuildShip;
|
||||
CommandCallback CcCloneShip;
|
||||
|
||||
/* train_gui.cpp */
|
||||
/* train_gui.c */
|
||||
CommandCallback CcBuildWagon;
|
||||
CommandCallback CcBuildLoco;
|
||||
CommandCallback CcCloneTrain;
|
||||
|
||||
/* ai/ai_core.cpp */
|
||||
CommandCallback CcAI;
|
||||
|
||||
CommandCallback *_callback_table[] = {
|
||||
@@ -79,9 +80,12 @@ CommandCallback *_callback_table[] = {
|
||||
/* 0x12 */ CcPlaySound1E,
|
||||
/* 0x13 */ CcStation,
|
||||
/* 0x14 */ CcTerraform,
|
||||
/* 0x15 */ CcAI,
|
||||
/* 0x16 */ CcCloneVehicle,
|
||||
/* 0x17 */ CcGiveMoney,
|
||||
/* 0x15 */ CcCloneAircraft,
|
||||
/* 0x16 */ CcCloneRoadVeh,
|
||||
/* 0x17 */ CcCloneShip,
|
||||
/* 0x18 */ CcCloneTrain,
|
||||
/* 0x19 */ CcAI,
|
||||
/* 0x1A */ CcCloneVehicle
|
||||
};
|
||||
|
||||
const int _callback_table_count = lengthof(_callback_table);
|
||||
@@ -1,11 +1,9 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.h Table with all command callbacks. */
|
||||
|
||||
#ifndef CALLBACK_TABLE_H
|
||||
#define CALLBACK_TABLE_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "command.h"
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
+907
-2016
File diff suppressed because it is too large
Load Diff
+794
@@ -0,0 +1,794 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "clear_map.h"
|
||||
#include "rail_map.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "tunnel_map.h"
|
||||
#include "variables.h"
|
||||
#include "table/sprites.h"
|
||||
#include "unmovable_map.h"
|
||||
#include "genworld.h"
|
||||
#include "industry.h"
|
||||
|
||||
typedef struct TerraformerHeightMod {
|
||||
TileIndex tile;
|
||||
byte height;
|
||||
} TerraformerHeightMod;
|
||||
|
||||
typedef struct TerraformerState {
|
||||
int height[4];
|
||||
uint32 flags;
|
||||
|
||||
int direction;
|
||||
int modheight_count;
|
||||
int tile_table_count;
|
||||
|
||||
int32 cost;
|
||||
|
||||
TileIndex *tile_table;
|
||||
TerraformerHeightMod *modheight;
|
||||
|
||||
} TerraformerState;
|
||||
|
||||
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TileIndex *t;
|
||||
int count;
|
||||
|
||||
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) return -1;
|
||||
|
||||
t = ts->tile_table;
|
||||
for (count = ts->tile_table_count; count != 0; count--, t++) {
|
||||
if (*t == tile) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformerHeightMod *mod = ts->modheight;
|
||||
int count;
|
||||
|
||||
for (count = ts->modheight_count; count != 0; count--, mod++) {
|
||||
if (mod->tile == tile) return mod->height;
|
||||
}
|
||||
|
||||
return TileHeight(tile);
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
int count;
|
||||
TileIndex *t;
|
||||
|
||||
count = ts->tile_table_count;
|
||||
|
||||
if (count >= 625) return;
|
||||
|
||||
for (t = ts->tile_table; count != 0; count--,t++) {
|
||||
if (*t == tile) return;
|
||||
}
|
||||
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, 0));
|
||||
TerraformAddDirtyTile(ts, tile);
|
||||
}
|
||||
|
||||
static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
|
||||
{
|
||||
int r;
|
||||
int32 ret;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
r = TerraformAllowTileProcess(ts, tile);
|
||||
if (r <= 0) return r;
|
||||
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
static const TrackBits safe_track[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
|
||||
static const Slope unsafe_slope[] = { SLOPE_S, SLOPE_W, SLOPE_N, SLOPE_E };
|
||||
|
||||
Slope tileh;
|
||||
uint z;
|
||||
|
||||
// Nothing could be built at the steep slope - this avoids a bug
|
||||
// when you have a single diagonal track in one corner on a
|
||||
// basement and then you raise/lower the other corner.
|
||||
tileh = GetTileSlope(tile, &z);
|
||||
if (tileh == unsafe_slope[mode] ||
|
||||
tileh == ComplementSlope(unsafe_slope[mode])) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If we have a single diagonal track there, the other side of
|
||||
// tile can be terraformed.
|
||||
if (IsPlainRailTile(tile) && GetTrackBits(tile) == safe_track[mode]) {
|
||||
/* If terraforming downwards prevent damaging a potential tunnel below.
|
||||
* This check is only necessary for flat tiles, because if the tile is
|
||||
* non-flat, then the corner opposing the rail is raised. Only this corner
|
||||
* can be lowered and this is a safe action
|
||||
*/
|
||||
if (tileh == SLOPE_FLAT &&
|
||||
ts->direction == -1 &&
|
||||
IsTunnelInWay(tile, z - TILE_HEIGHT)) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1002_EXCAVATION_WOULD_DAMAGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
_terraform_err_tile = tile;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ts->cost += ret;
|
||||
|
||||
if (ts->tile_table_count >= 625) return -1;
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height)
|
||||
{
|
||||
int nh;
|
||||
TerraformerHeightMod *mod;
|
||||
int count;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if (height < 0) {
|
||||
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
|
||||
return false;
|
||||
}
|
||||
|
||||
_error_message = STR_1004_TOO_HIGH;
|
||||
|
||||
if (height > 15) return false;
|
||||
|
||||
nh = TerraformGetHeightOfTile(ts, tile);
|
||||
if (nh < 0 || height == nh) return false;
|
||||
|
||||
if (TerraformProc(ts, tile, 0) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
|
||||
|
||||
mod = ts->modheight;
|
||||
count = ts->modheight_count;
|
||||
|
||||
for (;;) {
|
||||
if (count == 0) {
|
||||
if (ts->modheight_count >= 576) return false;
|
||||
ts->modheight_count++;
|
||||
break;
|
||||
}
|
||||
if (mod->tile == tile) break;
|
||||
mod++;
|
||||
count--;
|
||||
}
|
||||
|
||||
mod->tile = tile;
|
||||
mod->height = (byte)height;
|
||||
|
||||
ts->cost += _price.terraform;
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for (ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
if (!TerraformTileHeight(ts, tile, r+direction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Terraform land
|
||||
* @param tile tile to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
int32 CmdTerraformLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
TileIndex t;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
TileIndex tile_table_data[625];
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_terraform_err_tile = 0;
|
||||
|
||||
ts.direction = direction = p2 ? 1 : -1;
|
||||
ts.flags = flags;
|
||||
ts.modheight_count = ts.tile_table_count = 0;
|
||||
ts.cost = 0;
|
||||
ts.modheight = modheight_data;
|
||||
ts.tile_table = tile_table_data;
|
||||
|
||||
/* Make an extra check for map-bounds cause we add tiles to the originating tile */
|
||||
if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
|
||||
|
||||
if (p1 & 1) {
|
||||
t = tile + TileDiffXY(1, 0);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
t = tile + TileDiffXY(1, 1);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
t = tile + TileDiffXY(0, 1);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
t = tile + TileDiffXY(0, 0);
|
||||
if (!TerraformTileHeight(&ts, t, TileHeight(t) + direction)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (direction == -1) {
|
||||
/* Check if tunnel would take damage */
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
uint z, t;
|
||||
TileIndex tile = *ti;
|
||||
|
||||
z = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
|
||||
if (t <= z) z = t;
|
||||
|
||||
if (IsTunnelInWay(tile, z * TILE_HEIGHT)) {
|
||||
return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Clear the landscape at the tiles */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
DoCommand(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* change the height */
|
||||
{
|
||||
int count;
|
||||
TerraformerHeightMod *mod;
|
||||
|
||||
mod = ts.modheight;
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
TileIndex til = mod->tile;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally mark the dirty tiles dirty */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ts.cost;
|
||||
}
|
||||
|
||||
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param tile end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdLevelLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int ex;
|
||||
int ey;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 >= MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = TileHeight(p1);
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
ex = TileX(tile);
|
||||
ey = TileY(tile);
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TileXY(sx, sy);
|
||||
|
||||
size_x = ex-sx+1;
|
||||
size_y = ey-sy+1;
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommand(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param tile the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdPurchaseLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IsOwnedLandTile(tile) && IsTileOwner(tile, _current_player)) {
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
}
|
||||
|
||||
cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
MakeOwnedLand(tile, _current_player);
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
return cost + _price.purchase_land * 10;
|
||||
}
|
||||
|
||||
|
||||
static int32 ClearTile_Clear(TileIndex tile, byte flags)
|
||||
{
|
||||
static const int32* clear_price_table[] = {
|
||||
&_price.clear_1,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_3,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2, // XXX unused?
|
||||
};
|
||||
int32 price;
|
||||
|
||||
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
|
||||
price = 0;
|
||||
} else {
|
||||
price = *clear_price_table[GetClearGround(tile)];
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param tile the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
if (!IsOwnedLandTile(tile)) return CMD_ERROR;
|
||||
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
|
||||
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return - _price.purchase_land * 2;
|
||||
}
|
||||
|
||||
|
||||
#include "table/clear_land.h"
|
||||
|
||||
|
||||
void DrawClearLandTile(const TileInfo *ti, byte set)
|
||||
{
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19);
|
||||
}
|
||||
|
||||
void DrawHillyLandTile(const TileInfo *ti)
|
||||
{
|
||||
if (ti->tileh != SLOPE_FLAT) {
|
||||
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh]);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawClearLandFence(const TileInfo *ti)
|
||||
{
|
||||
byte z = ti->z;
|
||||
|
||||
if (ti->tileh & SLOPE_S) {
|
||||
z += TILE_HEIGHT;
|
||||
if (ti->tileh == SLOPE_STEEP_S) z += TILE_HEIGHT;
|
||||
}
|
||||
|
||||
if (GetFenceSW(ti->tile) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
|
||||
if (GetFenceSE(ti->tile) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawTile_Clear(TileInfo *ti)
|
||||
{
|
||||
switch (GetClearGround(ti->tile)) {
|
||||
case CLEAR_GRASS:
|
||||
DrawClearLandTile(ti, GetClearDensity(ti->tile));
|
||||
break;
|
||||
|
||||
case CLEAR_ROUGH:
|
||||
DrawHillyLandTile(ti);
|
||||
break;
|
||||
|
||||
case CLEAR_ROCKS:
|
||||
DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_FIELDS:
|
||||
DrawGroundSprite(_clear_land_sprites_1[GetFieldType(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_SNOW:
|
||||
DrawGroundSprite(_clear_land_sprites_2[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case CLEAR_DESERT:
|
||||
DrawGroundSprite(_clear_land_sprites_3[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawClearLandFence(ti);
|
||||
}
|
||||
|
||||
static uint GetSlopeZ_Clear(TileIndex tile, uint x, uint y)
|
||||
{
|
||||
uint z;
|
||||
uint tileh = GetTileSlope(tile, &z);
|
||||
|
||||
return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
|
||||
}
|
||||
|
||||
static Slope GetSlopeTileh_Clear(TileIndex tile, Slope tileh)
|
||||
{
|
||||
return tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static void AnimateTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte self;
|
||||
byte neighbour;
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
|
||||
|
||||
neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
|
||||
if (GetFenceSW(tile) == 0) {
|
||||
if (self != neighbour) {
|
||||
SetFenceSW(tile, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SetFenceSW(tile, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
|
||||
if (GetFenceSE(tile) == 0) {
|
||||
if (self != neighbour) {
|
||||
SetFenceSE(tile, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SetFenceSE(tile, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
|
||||
/* convert into snowy tiles */
|
||||
static void TileLoopClearAlps(TileIndex tile)
|
||||
{
|
||||
int k = GetTileZ(tile) - _opt.snow_line + TILE_HEIGHT;
|
||||
|
||||
if (k < 0) { // well below the snow line
|
||||
if (!IsClearGround(tile, CLEAR_SNOW)) return;
|
||||
if (GetClearDensity(tile) == 0) SetClearGroundDensity(tile, CLEAR_GRASS, 3);
|
||||
} else {
|
||||
if (!IsClearGround(tile, CLEAR_SNOW)) {
|
||||
SetClearGroundDensity(tile, CLEAR_SNOW, 0);
|
||||
} else {
|
||||
uint density = min((uint)k / TILE_HEIGHT, 3);
|
||||
|
||||
if (GetClearDensity(tile) < density) {
|
||||
AddClearDensity(tile, 1);
|
||||
} else if (GetClearDensity(tile) > density) {
|
||||
AddClearDensity(tile, -1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoopClearDesert(TileIndex tile)
|
||||
{
|
||||
if (IsClearGround(tile, CLEAR_DESERT)) return;
|
||||
|
||||
if (GetTropicZone(tile) == TROPICZONE_DESERT) {
|
||||
SetClearGroundDensity(tile, CLEAR_DESERT, 3);
|
||||
} else {
|
||||
if (GetTropicZone(tile + TileDiffXY( 1, 0)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY(-1, 0)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY( 0, 1)) != TROPICZONE_DESERT &&
|
||||
GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
|
||||
return;
|
||||
SetClearGroundDensity(tile, CLEAR_DESERT, 1);
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoop_Clear(TileIndex tile)
|
||||
{
|
||||
TileLoopClearHelper(tile);
|
||||
|
||||
switch (_opt.landscape) {
|
||||
case LT_DESERT: TileLoopClearDesert(tile); break;
|
||||
case LT_HILLY: TileLoopClearAlps(tile); break;
|
||||
}
|
||||
|
||||
switch (GetClearGround(tile)) {
|
||||
case CLEAR_GRASS:
|
||||
if (GetClearDensity(tile) == 3) return;
|
||||
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
if (GetClearCounter(tile) < 7) {
|
||||
AddClearCounter(tile, 1);
|
||||
return;
|
||||
} else {
|
||||
SetClearCounter(tile, 0);
|
||||
AddClearDensity(tile, 1);
|
||||
}
|
||||
} else {
|
||||
SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLEAR_FIELDS: {
|
||||
uint field_type;
|
||||
|
||||
if (_game_mode == GM_EDITOR) return;
|
||||
|
||||
if (GetClearCounter(tile) < 7) {
|
||||
AddClearCounter(tile, 1);
|
||||
return;
|
||||
} else {
|
||||
SetClearCounter(tile, 0);
|
||||
}
|
||||
|
||||
if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
|
||||
/* This farmfield is no longer farmfield, so make it grass again */
|
||||
MakeClear(tile, CLEAR_GRASS, 2);
|
||||
} else {
|
||||
field_type = GetFieldType(tile);
|
||||
field_type = (field_type < 8) ? field_type + 1 : 0;
|
||||
SetFieldType(tile, field_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
uint i, gi;
|
||||
TileIndex tile;
|
||||
|
||||
/* add rough tiles */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
|
||||
gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
|
||||
|
||||
SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
|
||||
do {
|
||||
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
|
||||
tile = RandomTile();
|
||||
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
|
||||
} while (--i);
|
||||
|
||||
/* add rocky tiles */
|
||||
i = gi;
|
||||
do {
|
||||
uint32 r = Random();
|
||||
tile = RandomTileSeed(r);
|
||||
|
||||
IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
|
||||
if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
|
||||
uint j = GB(r, 16, 4) + 5;
|
||||
for (;;) {
|
||||
TileIndex tile_new;
|
||||
|
||||
SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + TileOffsByDiagDir(GB(Random(), 0, 2));
|
||||
} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
static void ClickTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const StringID _clear_land_str[] = {
|
||||
STR_080D_GRASS,
|
||||
STR_080B_ROUGH_LAND,
|
||||
STR_080A_ROCKS,
|
||||
STR_080E_FIELDS,
|
||||
STR_080F_SNOW_COVERED_LAND,
|
||||
STR_0810_DESERT
|
||||
};
|
||||
|
||||
static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
|
||||
td->str = STR_080C_BARE_LAND;
|
||||
} else {
|
||||
td->str = _clear_land_str[GetClearGround(tile)];
|
||||
}
|
||||
td->owner = GetTileOwner(tile);
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, /* draw_tile_proc */
|
||||
GetSlopeZ_Clear, /* get_slope_z_proc */
|
||||
ClearTile_Clear, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Clear, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
|
||||
ClickTile_Clear, /* click_tile_proc */
|
||||
AnimateTile_Clear, /* animate_tile_proc */
|
||||
TileLoop_Clear, /* tile_loop_clear */
|
||||
ChangeTileOwner_Clear, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
|
||||
};
|
||||
+145
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
-2870
File diff suppressed because it is too large
Load Diff
@@ -1,137 +1,323 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONFIGURE_EXECUTABLE="$_"
|
||||
# On *nix systems those two are equal when ./configure is done
|
||||
if [ "$0" != "$CONFIGURE_EXECUTABLE" ]; then
|
||||
# On some systems, when ./configure is triggered from 'make'
|
||||
# the $_ is filled with 'make'. So if that is true, skip 'make'
|
||||
# and use $0 (and hope that is correct ;))
|
||||
if [ -n "`echo $CONFIGURE_EXECUTABLE | grep make`" ]; then
|
||||
CONFIGURE_EXECUTABLE="$0"
|
||||
else
|
||||
CONFIGURE_EXECUTABLE="$CONFIGURE_EXECUTABLE $0"
|
||||
# This 'configure' script is a very easy wrapper around 'make updateconf'
|
||||
# It allows cross-compilers to do their job much more easy.
|
||||
|
||||
showhelp() {
|
||||
echo "Configure for OpenTTD"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $0 --your_options"
|
||||
echo ""
|
||||
echo "Params:"
|
||||
echo " --debug Create debug-release [no]"
|
||||
echo " --profile Create profile-release [no]"
|
||||
echo " --dedicated Make a dedicated build [no]"
|
||||
echo " --revision Set the revision of the compilation [detected]"
|
||||
echo " --target-cc Sets the target-compiler [\$CC]"
|
||||
echo " --target-cxx Sets the C++ target-compiler []"
|
||||
echo " --host-cc Sets the host-compiler [\$CC]"
|
||||
echo " --host-cxx Sets the C++ host-compiler []"
|
||||
echo " --os Sets the OS. Listens to: [detected]"
|
||||
echo " UNIX, OSX, FREEBSD, MORPHOS"
|
||||
echo " BEOS, SUNOS, CYGWIN, MINGW, OS2"
|
||||
echo " --windres Sets the windres (Windows) [windres]"
|
||||
echo " --force-le Force LE platform [no]"
|
||||
echo " --force-be Force BE platform [no]"
|
||||
echo ""
|
||||
echo "Params that can be used with --with or --without"
|
||||
echo " (e.g.: --without-static disables static (default))"
|
||||
echo " static Do you want a static build? [no]"
|
||||
echo " directmusic Do you want direct-music? [no]"
|
||||
echo " zlib Do you want zlib-support? [yes]"
|
||||
echo " sdl Do you want SDL-support? [yes]"
|
||||
echo " png Do you want PNG-support? [yes]"
|
||||
echo " iconv Do you want iconv-support? [no]"
|
||||
echo " network Do you want network-support? [yes]"
|
||||
echo " cocoa Do you want cocoa-support? (MacOSX) [no]"
|
||||
echo " freetype Do you want freetype-support? [yes]"
|
||||
echo " fontconfig Do you want fontconfig-support? [yes]"
|
||||
echo ""
|
||||
echo "Params used to configure external libs:"
|
||||
echo " --static-zlib-path Set the path to your static zlib []"
|
||||
echo " --sdl-config Where is your sdl-config [sdl-config]"
|
||||
echo " --libpng-config Where is your libpng-config [libpng-config]"
|
||||
echo " --freetype-config Where is your freetype-config [freetype-config]"
|
||||
echo " --fontconfig-config Where is your fontconfig-config [pkg-config fontconfig]"
|
||||
echo " --with-iconv Set the path to your iconv headers []"
|
||||
echo " "
|
||||
}
|
||||
|
||||
handle() {
|
||||
PARAM="$PARAM \"$1=`awk 'BEGIN { FS="="; $0="'"$2"'"; print $2;}'`\""
|
||||
}
|
||||
|
||||
# The things you can use inside this case:
|
||||
# handle NAME VALUE - Sets the value to give the 'make upgradeconf'
|
||||
# Value is in form: tag=REAL_VALUE
|
||||
# ITEM="NAME" - Will set the value as above, only with the next param
|
||||
# SITEM="NAME" - Will set the var $NAME to the next param
|
||||
for n in "$@"
|
||||
do
|
||||
case "$n" in
|
||||
--help | -h)
|
||||
showhelp
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--debug)
|
||||
DEBUG_SET=1
|
||||
ITEM="DEBUG"
|
||||
;;
|
||||
--debug=*)
|
||||
handle "DEBUG" "$n"
|
||||
;;
|
||||
--profile)
|
||||
PARAM="$PARAM PROFILE=1"
|
||||
;;
|
||||
--dedicated)
|
||||
PARAM="$PARAM DEDICATED=1"
|
||||
;;
|
||||
--revision=*)
|
||||
RELEASE=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--revision)
|
||||
SITEM="RELEASE"
|
||||
;;
|
||||
--target-cc=*)
|
||||
handle "CC_TARGET" "$n"
|
||||
;;
|
||||
--target-cc)
|
||||
ITEM="CC_TARGET"
|
||||
;;
|
||||
--target-cxx=*)
|
||||
handle "CXX_TARGET" "$n"
|
||||
;;
|
||||
--target-cxx)
|
||||
SITEM="CXX_TARGET"
|
||||
;;
|
||||
--host-cc=*)
|
||||
handle "CC_HOST" "$n"
|
||||
;;
|
||||
--host-cc)
|
||||
ITEM="CC_HOST"
|
||||
;;
|
||||
--host-cxx=*)
|
||||
handle "CXX_HOST" "$n"
|
||||
;;
|
||||
--host-cxx)
|
||||
ITEM="CXX_HOST"
|
||||
;;
|
||||
--host-cflags=*)
|
||||
handle CFLAGS_HOST "$n"
|
||||
;;
|
||||
--host-cflags)
|
||||
ITEM="CFLAGS_HOST"
|
||||
;;
|
||||
--os=*)
|
||||
TARGET_OS=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--os)
|
||||
SITEM="TARGET_OS"
|
||||
;;
|
||||
--windres=*)
|
||||
handle WINDRES "$n"
|
||||
;;
|
||||
--windres)
|
||||
ITEM="WINDRES"
|
||||
;;
|
||||
--force-le)
|
||||
PARAM="$PARAM ENDIAN_FORCE=LE"
|
||||
;;
|
||||
--force-be)
|
||||
PARAM="$PARAM ENDIAN_FORCE=BE"
|
||||
;;
|
||||
|
||||
--with-static)
|
||||
PARAM="$PARAM STATIC=1"
|
||||
;;
|
||||
--without-static)
|
||||
PARAM="$PARAM STATIC="
|
||||
;;
|
||||
--with-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC=1"
|
||||
;;
|
||||
--without-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC="
|
||||
;;
|
||||
--with-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB=1"
|
||||
;;
|
||||
--without-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB="
|
||||
;;
|
||||
--with-sdl)
|
||||
PARAM="$PARAM WITH_SDL=1"
|
||||
;;
|
||||
--without-sdl)
|
||||
PARAM="$PARAM WITH_SDL="
|
||||
;;
|
||||
--with-png)
|
||||
PARAM="$PARAM WITH_PNG=1"
|
||||
;;
|
||||
--without-png)
|
||||
PARAM="$PARAM WITH_PNG="
|
||||
;;
|
||||
--with-iconv)
|
||||
PARAM="$PARAM WITH_ICONV=1"
|
||||
;;
|
||||
--with-iconv=*)
|
||||
PARAM="$PARAM WITH_ICONV=1"
|
||||
handle WITH_ICONV_PATH "$n"
|
||||
;;
|
||||
--without-iconv)
|
||||
PARAM="$PARAM WITH_ICONV="
|
||||
;;
|
||||
--with-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA=1"
|
||||
;;
|
||||
--with-network)
|
||||
PARAM="$PARAM WITH_NETWORK=1"
|
||||
;;
|
||||
--without-network)
|
||||
PARAM="$PARAM WITH_NETWORK="
|
||||
;;
|
||||
--without-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA="
|
||||
;;
|
||||
--with-freetype)
|
||||
PARAM="$PARAM WITH_FREETYPE=1"
|
||||
;;
|
||||
--without-freetype)
|
||||
PARAM="$PARAM WITH_FREETYPE="
|
||||
;;
|
||||
--with-fontconfig)
|
||||
PARAM="$PARAM WITH_FONTCONFIG=1"
|
||||
;;
|
||||
--without-fontconfig)
|
||||
PARAM="$PARAM WITH_FONTCONFIG="
|
||||
;;
|
||||
--static-zlib-path=*)
|
||||
handle STATIC_ZLIB_PATH "$n"
|
||||
;;
|
||||
--static-zlib-path)
|
||||
ITEM="STATIC_ZLIB_PATH"
|
||||
;;
|
||||
--sdl-config=*)
|
||||
handle SDL_CONFIG "$n"
|
||||
;;
|
||||
--sdl-config)
|
||||
ITEM="SDL_CONFIG"
|
||||
;;
|
||||
--libpng-config=*)
|
||||
handle LIBPNG_CONFIG "$n"
|
||||
;;
|
||||
--libpng-config)
|
||||
ITEM="LIBPNG_CONFIG"
|
||||
;;
|
||||
--freetype-config=*)
|
||||
handle FREETYPE_CONFIG "$n"
|
||||
;;
|
||||
--freetype-config)
|
||||
ITEM="FREETYPE_CONFIG"
|
||||
;;
|
||||
--fontconfig-config=*)
|
||||
handle FONTCONFIG_CONFIG "$n"
|
||||
;;
|
||||
--fontconfig-config)
|
||||
ITEM="FONTCONFIG_CONFIG"
|
||||
;;
|
||||
|
||||
--*=*)
|
||||
echo -n "Unknown switch "
|
||||
echo `awk 'BEGIN { FS="="; $0="'"$n"'"; print $1;}'`
|
||||
exit 1
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
if ! test -z "$ITEM"
|
||||
then
|
||||
PARAM="$PARAM $ITEM=\"$n\""
|
||||
ITEM="";
|
||||
elif ! test -z "$SITEM"
|
||||
then
|
||||
export $SITEM="$n"
|
||||
SITEM=""
|
||||
else
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! test -z "$TARGET_OS"
|
||||
then
|
||||
TARGET_OS=`echo $TARGET_OS | tr '[:lower:]' '[:upper:]'`
|
||||
case "$TARGET_OS" in
|
||||
WIN32)
|
||||
PARAM="$PARAM WIN32=1"
|
||||
;;
|
||||
UNIX)
|
||||
PARAM="$PARAM UNIX=1"
|
||||
;;
|
||||
OSX)
|
||||
PARAM="$PARAM OSX=1 UNIX=1"
|
||||
;;
|
||||
FREEBSD)
|
||||
PARAM="$PARAM FREEBSD=1"
|
||||
;;
|
||||
MORPHOS)
|
||||
PARAM="$PARAM MORPHOS=1 UNIX=1"
|
||||
;;
|
||||
BEOS)
|
||||
PARAM="$PARAM BEOS=1 UNIX=1"
|
||||
;;
|
||||
OS2)
|
||||
PARAM="$PARAM OS2=1 UNIX=1"
|
||||
;;
|
||||
SUNOS)
|
||||
PARAM="$PARAM SUNOS=1 UNIX=1"
|
||||
;;
|
||||
CYGWIN)
|
||||
PARAM="$PARAM CYGWIN=1 WIN32=1"
|
||||
;;
|
||||
MINGW)
|
||||
PARAM="$PARAM MINGW=1 WIN32=1"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OS: $TARGET_OS"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
PARAM="$PARAM BYPASS_OS_DETECT=1"
|
||||
fi
|
||||
|
||||
if ! test -z "$DEBUG_SET"
|
||||
then
|
||||
if test -z "`echo $PARAM | grep "DEBUG="`"
|
||||
then
|
||||
# Someone did --debug, without assigning a value, assume 1
|
||||
PARAM="$PARAM DEBUG=1"
|
||||
fi
|
||||
fi
|
||||
# Find out where configure is (in what dir)
|
||||
ROOT_DIR="`dirname $0`"
|
||||
ROOT_DIR="`cd $ROOT_DIR && pwd`"
|
||||
|
||||
PWD="`pwd`"
|
||||
PREFIX="$PWD/bin"
|
||||
# First remove the Makefile.config, else you can have double entries
|
||||
rm -f Makefile.config
|
||||
|
||||
. $ROOT_DIR/config.lib
|
||||
echo "make upgradeconf $PARAM" > ./Makefile.run
|
||||
. ./Makefile.run
|
||||
rm -f ./Makefile.run
|
||||
|
||||
# Set default dirs
|
||||
OBJS_DIR="$PWD/objs"
|
||||
BASE_SRC_OBJS_DIR="$OBJS_DIR"
|
||||
LANG_OBJS_DIR="$OBJS_DIR/lang"
|
||||
BIN_DIR="$PREFIX"
|
||||
SRC_DIR="$ROOT_DIR/src"
|
||||
LANG_DIR="$SRC_DIR/lang"
|
||||
MEDIA_DIR="$ROOT_DIR/media"
|
||||
SOURCE_LIST="$ROOT_DIR/source.list"
|
||||
# Makefile.config currently doesn't support custom RELEASE (revision), so, we add the line
|
||||
# yourself!
|
||||
|
||||
if [ "$1" = "--reconfig" ] || [ "$1" = "--reconfigure" ]; then
|
||||
if [ ! -f "config.cache" ]; then
|
||||
echo "can't reconfigure, because never configured before"
|
||||
exit 1
|
||||
fi
|
||||
# Make sure we don't lock config.cache
|
||||
cat config.cache | sed 's@\\ @\\\\ @g' > cache.tmp
|
||||
sh cache.tmp
|
||||
rm -f cache.tmp
|
||||
exit $?
|
||||
if ! test -z "$RELEASE"
|
||||
then
|
||||
echo "RELEASE=$RELEASE" >> Makefile.config
|
||||
fi
|
||||
|
||||
set_default
|
||||
detect_params "$@"
|
||||
check_params
|
||||
save_params
|
||||
make_cflags_and_ldflags
|
||||
|
||||
EXE=""
|
||||
if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ] || [ "$os" = "WINCE" ]; then
|
||||
EXE=".exe"
|
||||
fi
|
||||
|
||||
TTD="openttd$EXE"
|
||||
STRGEN="strgen$EXE"
|
||||
ENDIAN_CHECK="endian_check$EXE"
|
||||
|
||||
if [ -z "$sort" ]; then
|
||||
PIPE_SORT="sed s@a@a@"
|
||||
else
|
||||
PIPE_SORT="$sort"
|
||||
fi
|
||||
|
||||
if [ ! -f "$LANG_DIR/english.txt" ]; then
|
||||
echo "Languages not found in $LANG_DIR. Can't continue without it."
|
||||
echo "Please make sure the dir exists and contains at least english.txt"
|
||||
fi
|
||||
|
||||
# Read the source.list and process it
|
||||
SRCS="`< $ROOT_DIR/source.list tr '\r' '\n' | $awk '
|
||||
{ }
|
||||
/^( *)#end/ { if (deep == skip) { skip -= 1; } deep -= 1; next; }
|
||||
/^( *)#else/ { if (deep == skip) { skip -= 1; } else if (deep - 1 == skip) { skip += 1; } next; }
|
||||
/^( *)#if/ {
|
||||
gsub(" ", "", $0);
|
||||
gsub("^#if ", "", $0);
|
||||
|
||||
if (deep != skip) { deep += 1; next; }
|
||||
|
||||
deep += 1;
|
||||
|
||||
if ($0 == "ALLEGRO" && "'$allegro_config'" == "") { next; }
|
||||
if ($0 == "SDL" && "'$sdl_config'" == "") { next; }
|
||||
if ($0 == "PNG" && "'$png_config'" == "") { next; }
|
||||
if ($0 == "OSX" && "'$os'" != "OSX") { next; }
|
||||
if ($0 == "OS2" && "'$os'" != "OS2") { next; }
|
||||
if ($0 == "PSP" && "'$os'" != "PSP") { next; }
|
||||
if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; }
|
||||
if ($0 == "COCOA" && "'$with_cocoa'" == "0") { next; }
|
||||
if ($0 == "DOS" && "'$os'" != "DOS") { next; }
|
||||
if ($0 == "BEOS" && "'$os'" != "BEOS") { next; }
|
||||
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
|
||||
"'$os'" != "CYGWIN" && "'$os'" != "MSVC" ) { next; }
|
||||
if ($0 == "MORPHOS" && "'$os'" != "MORPHOS") { next; }
|
||||
if ($0 == "WINCE" && "'$os'" != "WINCE") { next; }
|
||||
if ($0 == "MSVC" && "'$os'" != "MSVC") { next; }
|
||||
if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; }
|
||||
if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; }
|
||||
if ($0 == "HAVE_THREAD" && "'$with_threads'" == "0") { next; }
|
||||
|
||||
skip += 1;
|
||||
|
||||
next;
|
||||
}
|
||||
/^( *)#/ { next }
|
||||
/^$/ { next }
|
||||
/\.h$/ { next }
|
||||
/\.hpp$/ { next }
|
||||
{
|
||||
if (deep == skip) {
|
||||
gsub(" ", "", $0);
|
||||
print $0;
|
||||
}
|
||||
}
|
||||
' | $PIPE_SORT`"
|
||||
|
||||
OBJS_C="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.c$/ { gsub(".c$", ".o", $0); print $0; }'`"
|
||||
OBJS_CPP="`echo \"$SRCS\" | $awk ' { ORS = " " } /\.cpp$/ { gsub(".cpp$", ".o", $0); print $0; }'`"
|
||||
OBJS_MM="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.mm$/ { gsub(".mm$", ".o", $0); print $0; }'`"
|
||||
OBJS_RC="` echo \"$SRCS\" | $awk ' { ORS = " " } /\.rc$/ { gsub(".rc$", ".o", $0); print $0; }'`"
|
||||
SRCS="` echo \"$SRCS\" | $awk ' { ORS = " " } { print $0; }'`"
|
||||
|
||||
# In makefiles, we always use -u for sort
|
||||
if [ -z "$sort" ]; then
|
||||
sort="sed s@a@a@"
|
||||
else
|
||||
sort="$sort -u"
|
||||
fi
|
||||
|
||||
CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in"
|
||||
|
||||
generate_main
|
||||
generate_lang
|
||||
generate_src
|
||||
|
||||
+376
-89
@@ -1,16 +1,21 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file console.cpp Handling of the in-game console. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "core/math_func.hpp"
|
||||
#include "string_func.h"
|
||||
#include "console_internal.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "gfx.h"
|
||||
#include "player.h"
|
||||
#include "variables.h"
|
||||
#include "string.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "console.h"
|
||||
#include "network.h"
|
||||
#include "network_data.h"
|
||||
#include "network_server.h"
|
||||
|
||||
#define ICON_BUFFER 79
|
||||
#define ICON_HISTORY_SIZE 20
|
||||
@@ -20,45 +25,244 @@
|
||||
#define ICON_MAX_ALIAS_LINES 40
|
||||
#define ICON_TOKEN_COUNT 20
|
||||
|
||||
/* console parser */
|
||||
IConsoleCmd *_iconsole_cmds; ///< list of registred commands
|
||||
IConsoleVar *_iconsole_vars; ///< list of registred vars
|
||||
IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
|
||||
// ** main console ** //
|
||||
static char *_iconsole_buffer[ICON_BUFFER + 1];
|
||||
static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
|
||||
static Textbuf _iconsole_cmdline;
|
||||
|
||||
/* ** stdlib ** */
|
||||
// ** stdlib ** //
|
||||
byte _stdlib_developer = 1;
|
||||
bool _stdlib_con_developer = false;
|
||||
FILE *_iconsole_output_file;
|
||||
|
||||
void IConsoleInit()
|
||||
// ** main console cmd buffer
|
||||
static char *_iconsole_history[ICON_HISTORY_SIZE];
|
||||
static byte _iconsole_historypos;
|
||||
|
||||
/* *************** */
|
||||
/* end of header */
|
||||
/* *************** */
|
||||
|
||||
static void IConsoleClearCommand(void)
|
||||
{
|
||||
memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
|
||||
_iconsole_cmdline.length = 0;
|
||||
_iconsole_cmdline.width = 0;
|
||||
_iconsole_cmdline.caretpos = 0;
|
||||
_iconsole_cmdline.caretxoffs = 0;
|
||||
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
|
||||
}
|
||||
|
||||
static inline void IConsoleResetHistoryPos(void) {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
|
||||
|
||||
|
||||
static void IConsoleHistoryAdd(const char *cmd);
|
||||
static void IConsoleHistoryNavigate(int direction);
|
||||
|
||||
// ** console window ** //
|
||||
static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
static byte iconsole_scroll = ICON_BUFFER;
|
||||
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int i = iconsole_scroll;
|
||||
int max = (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
int delta = 0;
|
||||
GfxFillRect(w->left, w->top, w->width, w->height - 1, 0);
|
||||
while ((i > 0) && (i > iconsole_scroll - max) && (_iconsole_buffer[i] != NULL)) {
|
||||
DoDrawString(_iconsole_buffer[i], 5,
|
||||
w->height - (iconsole_scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
|
||||
i--;
|
||||
}
|
||||
/* If the text is longer than the window, don't show the starting ']' */
|
||||
delta = w->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
|
||||
if (delta > 0) {
|
||||
DoDrawString("]", 5, w->height - ICON_LINE_HEIGHT, _icolour_cmd);
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
DoDrawString(_iconsole_cmdline.buf, 10 + delta, w->height - ICON_LINE_HEIGHT, _icolour_cmd);
|
||||
|
||||
if (_iconsole_cmdline.caret)
|
||||
DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, 12);
|
||||
break;
|
||||
}
|
||||
case WE_MOUSELOOP:
|
||||
if (HandleCaret(&_iconsole_cmdline))
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WE_DESTROY:
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
break;
|
||||
case WE_KEYPRESS:
|
||||
e->we.keypress.cont = false;
|
||||
switch (e->we.keypress.keycode) {
|
||||
case WKC_UP:
|
||||
IConsoleHistoryNavigate(+1);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_DOWN:
|
||||
IConsoleHistoryNavigate(-1);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_PAGEUP:
|
||||
if (iconsole_scroll - (w->height / ICON_LINE_HEIGHT) - 1 < 0) {
|
||||
iconsole_scroll = 0;
|
||||
} else {
|
||||
iconsole_scroll -= (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_PAGEDOWN:
|
||||
if (iconsole_scroll + (w->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
} else {
|
||||
iconsole_scroll += (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_UP:
|
||||
if (iconsole_scroll <= 0) {
|
||||
iconsole_scroll = 0;
|
||||
} else {
|
||||
--iconsole_scroll;
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_DOWN:
|
||||
if (iconsole_scroll >= ICON_BUFFER) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
} else {
|
||||
++iconsole_scroll;
|
||||
}
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_BACKQUOTE:
|
||||
IConsoleSwitch();
|
||||
break;
|
||||
case WKC_RETURN: case WKC_NUM_ENTER:
|
||||
IConsolePrintF(_icolour_cmd, "] %s", _iconsole_cmdline.buf);
|
||||
IConsoleHistoryAdd(_iconsole_cmdline.buf);
|
||||
|
||||
IConsoleCmdExec(_iconsole_cmdline.buf);
|
||||
IConsoleClearCommand();
|
||||
break;
|
||||
case WKC_CTRL | WKC_RETURN:
|
||||
_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
|
||||
IConsoleResize(w);
|
||||
MarkWholeScreenDirty();
|
||||
break;
|
||||
case (WKC_CTRL | 'V'):
|
||||
if (InsertTextBufferClipboard(&_iconsole_cmdline)) {
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
break;
|
||||
case (WKC_CTRL | 'L'):
|
||||
IConsoleCmdExec("clear");
|
||||
break;
|
||||
case (WKC_CTRL | 'U'):
|
||||
DeleteTextBufferAll(&_iconsole_cmdline);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_BACKSPACE: case WKC_DELETE:
|
||||
if (DeleteTextBufferChar(&_iconsole_cmdline, e->we.keypress.keycode)) {
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
break;
|
||||
case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
|
||||
if (MoveTextBufferPos(&_iconsole_cmdline, e->we.keypress.keycode)) {
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (IsValidChar(e->we.keypress.key, CS_ALPHANUMERAL)) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
InsertTextBufferChar(&_iconsole_cmdline, e->we.keypress.key);
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
} else {
|
||||
e->we.keypress.cont = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _iconsole_window_widgets[] = {
|
||||
{WIDGETS_END}
|
||||
};
|
||||
|
||||
static const WindowDesc _iconsole_window_desc = {
|
||||
0, 0, 2, 2,
|
||||
WC_CONSOLE, 0,
|
||||
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
_iconsole_window_widgets,
|
||||
IConsoleWndProc,
|
||||
};
|
||||
|
||||
void IConsoleInit(void)
|
||||
{
|
||||
extern const char _openttd_revision[];
|
||||
_iconsole_output_file = NULL;
|
||||
_icolour_def = 1;
|
||||
_icolour_err = 3;
|
||||
_icolour_warn = 13;
|
||||
_icolour_dbg = 5;
|
||||
_icolour_cmd = 2;
|
||||
_iconsole_historypos = ICON_HISTORY_SIZE - 1;
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
|
||||
#ifdef ENABLE_NETWORK /* Initialize network only variables */
|
||||
_redirect_console_to_client = INVALID_CLIENT_ID;
|
||||
_redirect_console_to_client = 0;
|
||||
#endif
|
||||
|
||||
IConsoleGUIInit();
|
||||
memset(_iconsole_history, 0, sizeof(_iconsole_history));
|
||||
memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
|
||||
memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
|
||||
_iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it
|
||||
_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
|
||||
|
||||
IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
|
||||
IConsolePrint(12, "------------------------------------");
|
||||
IConsolePrint(12, "use \"help\" for more information");
|
||||
IConsolePrint(12, "");
|
||||
IConsoleStdLibRegister();
|
||||
IConsoleClearCommand();
|
||||
IConsoleHistoryAdd("");
|
||||
}
|
||||
|
||||
void IConsoleClearBuffer(void)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i <= ICON_BUFFER; i++) {
|
||||
free(_iconsole_buffer[i]);
|
||||
_iconsole_buffer[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void IConsoleClear(void)
|
||||
{
|
||||
free(_iconsole_cmdline.buf);
|
||||
IConsoleClearBuffer();
|
||||
}
|
||||
|
||||
static void IConsoleWriteToLogFile(const char *string)
|
||||
{
|
||||
if (_iconsole_output_file != NULL) {
|
||||
/* if there is an console output file ... also print it there */
|
||||
if (fwrite(string, strlen(string), 1, _iconsole_output_file) != 1 ||
|
||||
fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
|
||||
fclose(_iconsole_output_file);
|
||||
_iconsole_output_file = NULL;
|
||||
IConsolePrintF(CC_DEFAULT, "cannot write to log file");
|
||||
}
|
||||
// if there is an console output file ... also print it there
|
||||
fwrite(string, strlen(string), 1, _iconsole_output_file);
|
||||
fwrite("\n", 1, 1, _iconsole_output_file);
|
||||
}
|
||||
}
|
||||
|
||||
bool CloseConsoleLogIfActive()
|
||||
bool CloseConsoleLogIfActive(void)
|
||||
{
|
||||
if (_iconsole_output_file != NULL) {
|
||||
IConsolePrintF(CC_DEFAULT, "file output complete");
|
||||
IConsolePrintF(_icolour_def, "file output complete");
|
||||
fclose(_iconsole_output_file);
|
||||
_iconsole_output_file = NULL;
|
||||
return true;
|
||||
@@ -67,28 +271,109 @@ bool CloseConsoleLogIfActive()
|
||||
return false;
|
||||
}
|
||||
|
||||
void IConsoleFree()
|
||||
void IConsoleFree(void)
|
||||
{
|
||||
IConsoleGUIFree();
|
||||
IConsoleClear();
|
||||
CloseConsoleLogIfActive();
|
||||
}
|
||||
|
||||
void IConsoleResize(Window *w)
|
||||
{
|
||||
switch (_iconsole_mode) {
|
||||
case ICONSOLE_OPENED:
|
||||
w->height = _screen.height / 3;
|
||||
w->width = _screen.width;
|
||||
break;
|
||||
case ICONSOLE_FULL:
|
||||
w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
|
||||
w->width = _screen.width;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
void IConsoleSwitch(void)
|
||||
{
|
||||
switch (_iconsole_mode) {
|
||||
case ICONSOLE_CLOSED: {
|
||||
Window *w = AllocateWindowDesc(&_iconsole_window_desc);
|
||||
w->height = _screen.height / 3;
|
||||
w->width = _screen.width;
|
||||
_iconsole_mode = ICONSOLE_OPENED;
|
||||
SETBIT(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
|
||||
} break;
|
||||
case ICONSOLE_OPENED: case ICONSOLE_FULL:
|
||||
DeleteWindowById(WC_CONSOLE, 0);
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
CLRBIT(_no_scroll, SCROLL_CON);
|
||||
break;
|
||||
}
|
||||
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
void IConsoleClose(void) {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
|
||||
void IConsoleOpen(void) {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
|
||||
|
||||
/**
|
||||
* Add the entered line into the history so you can look it back
|
||||
* scroll, etc. Put it to the beginning as it is the latest text
|
||||
* @param cmd Text to be entered into the 'history'
|
||||
*/
|
||||
static void IConsoleHistoryAdd(const char *cmd)
|
||||
{
|
||||
free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
|
||||
|
||||
memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
|
||||
_iconsole_history[0] = strdup(cmd);
|
||||
IConsoleResetHistoryPos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate Up/Down in the history of typed commands
|
||||
* @param direction Go further back in history (+1), go to recently typed commands (-1)
|
||||
*/
|
||||
static void IConsoleHistoryNavigate(int direction)
|
||||
{
|
||||
int i = _iconsole_historypos + direction;
|
||||
|
||||
// watch out for overflows, just wrap around
|
||||
if (i < 0) i = ICON_HISTORY_SIZE - 1;
|
||||
if (i >= ICON_HISTORY_SIZE) i = 0;
|
||||
|
||||
if (direction > 0)
|
||||
if (_iconsole_history[i] == NULL) i = 0;
|
||||
|
||||
if (direction < 0) {
|
||||
while (i > 0 && _iconsole_history[i] == NULL) i--;
|
||||
}
|
||||
|
||||
_iconsole_historypos = i;
|
||||
IConsoleClearCommand();
|
||||
// copy history to 'command prompt / bash'
|
||||
assert(_iconsole_history[i] != NULL && IS_INT_INSIDE(i, 0, ICON_HISTORY_SIZE));
|
||||
ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
|
||||
UpdateTextBufferSize(&_iconsole_cmdline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the printing of text entered into the console or redirected there
|
||||
* by any other means. Text can be redirected to other clients in a network game
|
||||
* by any other means. Text can be redirected to other players in a network game
|
||||
* as well as to a logfile. If the network server is a dedicated server, all activities
|
||||
* are also logged. All lines to print are added to a temporary buffer which can be
|
||||
* used as a history to print them onscreen
|
||||
* @param colour_code the colour of the command. Red in case of errors, etc.
|
||||
* @param color_code the colour of the command. Red in case of errors, etc.
|
||||
* @param string the message entered or output on the console (notice, error, etc.)
|
||||
*/
|
||||
void IConsolePrint(ConsoleColour colour_code, const char *string)
|
||||
void IConsolePrint(uint16 color_code, const char *string)
|
||||
{
|
||||
char *str;
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (_redirect_console_to_client != INVALID_CLIENT_ID) {
|
||||
if (_redirect_console_to_client != 0) {
|
||||
/* Redirect the string to the client */
|
||||
NetworkServerSendRcon(_redirect_console_to_client, colour_code, string);
|
||||
SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -97,49 +382,56 @@ void IConsolePrint(ConsoleColour colour_code, const char *string)
|
||||
* characters and (when applicable) assign it to the console buffer */
|
||||
str = strdup(string);
|
||||
str_strip_colours(str);
|
||||
str_validate(str, str + strlen(str));
|
||||
str_validate(str);
|
||||
|
||||
if (_network_dedicated) {
|
||||
fprintf(stdout, "%s\n", str);
|
||||
fflush(stdout);
|
||||
printf("%s\n", str);
|
||||
IConsoleWriteToLogFile(str);
|
||||
free(str); // free duplicated string since it's not used anymore
|
||||
return;
|
||||
}
|
||||
|
||||
IConsoleWriteToLogFile(str);
|
||||
IConsoleGUIPrint(colour_code, str);
|
||||
/* move up all the strings in the buffer one place and do the same for colour
|
||||
* to accomodate for the new command/message */
|
||||
free(_iconsole_buffer[0]);
|
||||
memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
|
||||
_iconsole_buffer[ICON_BUFFER] = str;
|
||||
|
||||
memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
|
||||
_iconsole_cbuffer[ICON_BUFFER] = color_code;
|
||||
|
||||
IConsoleWriteToLogFile(_iconsole_buffer[ICON_BUFFER]);
|
||||
|
||||
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the printing of text entered into the console or redirected there
|
||||
* by any other means. Uses printf() style format, for more information look
|
||||
* at IConsolePrint()
|
||||
* at @IConsolePrint()
|
||||
*/
|
||||
void CDECL IConsolePrintF(ConsoleColour colour_code, const char *format, ...)
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
|
||||
{
|
||||
va_list va;
|
||||
char buf[ICON_MAX_STREAMSIZE];
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(buf, sizeof(buf), format, va);
|
||||
va_start(va, s);
|
||||
vsnprintf(buf, sizeof(buf), s, va);
|
||||
va_end(va);
|
||||
|
||||
IConsolePrint(colour_code, buf);
|
||||
IConsolePrint(color_code, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* It is possible to print debugging information to the console,
|
||||
* which is achieved by using this function. Can only be used by
|
||||
* debug() in debug.cpp. You need at least a level 2 (developer) for debugging
|
||||
* @debug() in debug.c. You need at least a level 2 (developer) for debugging
|
||||
* messages to show up
|
||||
* @param dbg debugging category
|
||||
* @param string debugging message
|
||||
*/
|
||||
void IConsoleDebug(const char *dbg, const char *string)
|
||||
void IConsoleDebug(const char *string)
|
||||
{
|
||||
if (_stdlib_developer > 1)
|
||||
IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string);
|
||||
IConsolePrintF(_icolour_dbg, "dbg: %s", string);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +442,7 @@ void IConsoleDebug(const char *dbg, const char *string)
|
||||
void IConsoleWarning(const char *string)
|
||||
{
|
||||
if (_stdlib_developer > 0)
|
||||
IConsolePrintF(CC_WARNING, "WARNING: %s", string);
|
||||
IConsolePrintF(_icolour_warn, "WARNING: %s", string);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,13 +451,13 @@ void IConsoleWarning(const char *string)
|
||||
*/
|
||||
void IConsoleError(const char *string)
|
||||
{
|
||||
IConsolePrintF(CC_ERROR, "ERROR: %s", string);
|
||||
IConsolePrintF(_icolour_err, "ERROR: %s", string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a string into its number representation. Supports
|
||||
* decimal and hexadecimal numbers as well as 'on'/'off' 'true'/'false'
|
||||
* @param *value the variable a successful conversion will be put in
|
||||
* @param *value the variable a successfull conversion will be put in
|
||||
* @param *arg the string to be converted
|
||||
* @return Return true on success or false on failure
|
||||
*/
|
||||
@@ -186,13 +478,12 @@ bool GetArgumentInteger(uint32 *value, const char *arg)
|
||||
return arg != endptr;
|
||||
}
|
||||
|
||||
/* * *************************
|
||||
* hooking code *
|
||||
* *************************/
|
||||
|
||||
// * ************************* * //
|
||||
// * hooking code * //
|
||||
// * ************************* * //
|
||||
/**
|
||||
* General internal hooking code that is the same for both commands and variables
|
||||
* @param hooks IConsoleHooks structure that will be set according to
|
||||
* @param hooks @IConsoleHooks structure that will be set according to
|
||||
* @param type type access trigger
|
||||
* @param proc function called when the hook criteria is met
|
||||
*/
|
||||
@@ -217,9 +508,9 @@ static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConso
|
||||
/**
|
||||
* Handle any special hook triggers. If the hook type is met check if
|
||||
* there is a function associated with that and if so, execute it
|
||||
* @param hooks IConsoleHooks structure that will be checked
|
||||
* @param hooks @IConsoleHooks structure that will be checked
|
||||
* @param type type of hook, trigger that needs to be activated
|
||||
* @return true on a successful execution of the hook command or if there
|
||||
* @return true on a successfull execution of the hook command or if there
|
||||
* is no hook/trigger present at all. False otherwise
|
||||
*/
|
||||
static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
|
||||
@@ -319,7 +610,7 @@ void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
|
||||
{
|
||||
char *new_cmd = strdup(name);
|
||||
IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
|
||||
IConsoleCmd *item_new = malloc(sizeof(IConsoleCmd));
|
||||
|
||||
item_new->next = NULL;
|
||||
item_new->proc = proc;
|
||||
@@ -356,7 +647,7 @@ void IConsoleAliasRegister(const char *name, const char *cmd)
|
||||
{
|
||||
char *new_alias = strdup(name);
|
||||
char *cmd_aliased = strdup(cmd);
|
||||
IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);
|
||||
IConsoleAlias *item_new = malloc(sizeof(IConsoleAlias));
|
||||
|
||||
item_new->next = NULL;
|
||||
item_new->cmdline = cmd_aliased;
|
||||
@@ -372,7 +663,7 @@ void IConsoleAliasRegister(const char *name, const char *cmd)
|
||||
*/
|
||||
IConsoleAlias *IConsoleAliasGet(const char *name)
|
||||
{
|
||||
IConsoleAlias *item;
|
||||
IConsoleAlias* item;
|
||||
|
||||
for (item = _iconsole_aliases; item != NULL; item = item->next) {
|
||||
if (strcmp(item->name, name) == 0) return item;
|
||||
@@ -384,9 +675,8 @@ IConsoleAlias *IConsoleAliasGet(const char *name)
|
||||
/** copy in an argument into the aliasstream */
|
||||
static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
|
||||
{
|
||||
/* len is the amount of bytes to add excluding the '\0'-termination */
|
||||
int len = min(ICON_MAX_STREAMSIZE - bufpos - 1, (uint)strlen(src));
|
||||
strecpy(dst, src, dst + len);
|
||||
int len = min(ICON_MAX_STREAMSIZE - bufpos, (uint)strlen(src));
|
||||
strncpy(dst, src, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -409,25 +699,25 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
memset(&aliasstream, 0, sizeof(aliasstream));
|
||||
|
||||
if (_stdlib_con_developer)
|
||||
IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing...");
|
||||
IConsolePrintF(_icolour_dbg, "condbg: requested command is an alias; parsing...");
|
||||
|
||||
aliases[0] = aliasstream;
|
||||
for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) {
|
||||
if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
|
||||
|
||||
switch (*cmdptr) {
|
||||
case '\'': // ' will double for ""
|
||||
case '\'': /* ' will double for "" */
|
||||
aliasstream[astream_i++] = '"';
|
||||
break;
|
||||
case ';': // Cmd seperator, start new command
|
||||
case ';': /* Cmd seperator, start new command */
|
||||
aliasstream[astream_i] = '\0';
|
||||
aliases[++a_index] = &aliasstream[++astream_i];
|
||||
cmdptr++;
|
||||
break;
|
||||
case '%': // Some or all parameters
|
||||
case '%': /* Some or all parameters */
|
||||
cmdptr++;
|
||||
switch (*cmdptr) {
|
||||
case '+': { // All parameters seperated: "[param 1]" "[param 2]"
|
||||
case '+': { /* All parameters seperated: "[param 1]" "[param 2]" */
|
||||
for (i = 0; i != tokencount; i++) {
|
||||
aliasstream[astream_i++] = '"';
|
||||
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
|
||||
@@ -435,7 +725,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
aliasstream[astream_i++] = ' ';
|
||||
}
|
||||
} break;
|
||||
case '!': { // Merge the parameters to one: "[param 1] [param 2] [param 3...]"
|
||||
case '!': { /* Merge the parameters to one: "[param 1] [param 2] [param 3...]" */
|
||||
aliasstream[astream_i++] = '"';
|
||||
for (i = 0; i != tokencount; i++) {
|
||||
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
|
||||
@@ -444,12 +734,12 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
aliasstream[astream_i++] = '"';
|
||||
|
||||
} break;
|
||||
default: { // One specific parameter: %A = [param 1] %B = [param 2] ...
|
||||
default: { /* One specific parameter: %A = [param 1] %B = [param 2] ... */
|
||||
int param = *cmdptr - 'A';
|
||||
|
||||
if (param < 0 || param >= tokencount) {
|
||||
IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
|
||||
IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline);
|
||||
IConsolePrintF(_icolour_warn, "Usage of alias '%s': %s", alias->name, alias->cmdline);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -471,11 +761,8 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
/**
|
||||
* Special function for adding string-type variables. They in addition
|
||||
* also need a 'size' value saying how long their string buffer is.
|
||||
* @param name name of the variable that will be used
|
||||
* @param addr memory location the variable will point to
|
||||
* @param size the length of the string buffer
|
||||
* @param help the help string shown for the variable
|
||||
* For more information see IConsoleVarRegister()
|
||||
* For more information see @IConsoleVarRegister()
|
||||
*/
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
|
||||
{
|
||||
@@ -495,7 +782,7 @@ void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
|
||||
{
|
||||
char *new_cmd = strdup(name);
|
||||
IConsoleVar *item_new = MallocT<IConsoleVar>(1);
|
||||
IConsoleVar *item_new = malloc(sizeof(IConsoleVar));
|
||||
|
||||
item_new->help = (help != NULL) ? strdup(help) : NULL;
|
||||
|
||||
@@ -572,7 +859,7 @@ static void IConsoleVarSetStringvalue(const IConsoleVar *var, const char *value)
|
||||
if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
|
||||
|
||||
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
|
||||
ttd_strlcpy((char*)var->addr, value, var->size);
|
||||
ttd_strlcpy(var->addr, value, var->size);
|
||||
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
|
||||
IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
|
||||
return;
|
||||
@@ -662,7 +949,7 @@ void IConsoleVarPrintGetValue(const IConsoleVar *var)
|
||||
}
|
||||
|
||||
value = IConsoleVarGetStringValue(var);
|
||||
IConsolePrintF(CC_WARNING, "Current value for '%s' is: %s", var->name, value);
|
||||
IConsolePrintF(_icolour_warn, "Current value for '%s' is: %s", var->name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -672,7 +959,7 @@ void IConsoleVarPrintGetValue(const IConsoleVar *var)
|
||||
void IConsoleVarPrintSetValue(const IConsoleVar *var)
|
||||
{
|
||||
char *value = IConsoleVarGetStringValue(var);
|
||||
IConsolePrintF(CC_WARNING, "'%s' changed to: %s", var->name, value);
|
||||
IConsolePrintF(_icolour_warn, "'%s' changed to: %s", var->name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,9 +976,9 @@ void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_T
|
||||
uint32 value;
|
||||
|
||||
if (_stdlib_con_developer)
|
||||
IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable");
|
||||
IConsolePrintF(_icolour_dbg, "condbg: requested command is a variable");
|
||||
|
||||
if (tokencount == 0) { // Just print out value
|
||||
if (tokencount == 0) { /* Just print out value */
|
||||
IConsoleVarPrintGetValue(var);
|
||||
return;
|
||||
}
|
||||
@@ -766,13 +1053,13 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
|
||||
if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
|
||||
IConsoleError("command contains malformed characters, aborting");
|
||||
IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr);
|
||||
IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_stdlib_con_developer)
|
||||
IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr);
|
||||
IConsolePrintF(_icolour_dbg, "condbg: executing cmdline: '%s'", cmdstr);
|
||||
|
||||
memset(&tokens, 0, sizeof(tokens));
|
||||
memset(&tokenstream, 0, sizeof(tokenstream));
|
||||
@@ -784,7 +1071,7 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break;
|
||||
|
||||
switch (*cmdptr) {
|
||||
case ' ': // Token seperator
|
||||
case ' ': /* Token seperator */
|
||||
if (!foundtoken) break;
|
||||
|
||||
if (longtoken) {
|
||||
@@ -796,16 +1083,16 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
|
||||
tstream_i++;
|
||||
break;
|
||||
case '"': // Tokens enclosed in "" are one token
|
||||
case '"': /* Tokens enclosed in "" are one token */
|
||||
longtoken = !longtoken;
|
||||
break;
|
||||
case '\\': // Escape character for ""
|
||||
case '\\': /* Escape character for "" */
|
||||
if (cmdptr[1] == '"' && tstream_i + 1 < lengthof(tokenstream)) {
|
||||
tokenstream[tstream_i++] = *++cmdptr;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
default: // Normal character
|
||||
default: /* Normal character */
|
||||
tokenstream[tstream_i++] = *cmdptr;
|
||||
|
||||
if (!foundtoken) {
|
||||
@@ -820,7 +1107,7 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
uint i;
|
||||
|
||||
for (i = 0; tokens[i] != NULL; i++) {
|
||||
IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]);
|
||||
IConsolePrintF(_icolour_dbg, "condbg: token %d is: '%s'", i, tokens[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file console_internal.h Internally used functions for the console. */
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#ifndef CONSOLE_INTERNAL_H
|
||||
#define CONSOLE_INTERNAL_H
|
||||
// maximum length of a typed in command
|
||||
#define ICON_CMDLN_SIZE 255
|
||||
// maximum length of a totally expanded command
|
||||
#define ICON_MAX_STREAMSIZE 1024
|
||||
|
||||
#include "console_func.h"
|
||||
|
||||
enum {
|
||||
ICON_CMDLN_SIZE = 1024, ///< maximum length of a typed in command
|
||||
ICON_MAX_STREAMSIZE = 2048, ///< maximum length of a totally expanded command
|
||||
};
|
||||
|
||||
enum IConsoleVarTypes {
|
||||
typedef enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_BOOLEAN,
|
||||
ICONSOLE_VAR_BYTE,
|
||||
ICONSOLE_VAR_UINT16,
|
||||
@@ -20,25 +16,31 @@ enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_INT16,
|
||||
ICONSOLE_VAR_INT32,
|
||||
ICONSOLE_VAR_STRING
|
||||
};
|
||||
} IConsoleVarTypes;
|
||||
|
||||
enum IConsoleHookTypes {
|
||||
typedef enum IConsoleModes {
|
||||
ICONSOLE_FULL,
|
||||
ICONSOLE_OPENED,
|
||||
ICONSOLE_CLOSED
|
||||
} IConsoleModes;
|
||||
|
||||
typedef enum IConsoleHookTypes {
|
||||
ICONSOLE_HOOK_ACCESS,
|
||||
ICONSOLE_HOOK_PRE_ACTION,
|
||||
ICONSOLE_HOOK_POST_ACTION
|
||||
};
|
||||
} IConsoleHookTypes;
|
||||
|
||||
/** --Hooks--
|
||||
* Hooks are certain triggers get get accessed/executed on either
|
||||
* access, before execution/change or after execution/change. This allows
|
||||
* for general flow of permissions or special action needed in some cases
|
||||
*/
|
||||
typedef bool IConsoleHook();
|
||||
struct IConsoleHooks{
|
||||
IConsoleHook *access; ///< trigger when accessing the variable/command
|
||||
IConsoleHook *pre; ///< trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; ///< trigger after the variable/command is changed/executed
|
||||
};
|
||||
typedef bool IConsoleHook(void);
|
||||
typedef struct IConsoleHooks{
|
||||
IConsoleHook *access; // trigger when accessing the variable/command
|
||||
IConsoleHook *pre; // trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; // trigger after the variable/command is changed/executed
|
||||
} IConsoleHooks;
|
||||
|
||||
/** --Commands--
|
||||
* Commands are commands, or functions. They get executed once and any
|
||||
@@ -49,13 +51,14 @@ struct IConsoleHooks{
|
||||
*/
|
||||
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
|
||||
|
||||
struct IConsoleCmd {
|
||||
char *name; ///< name of command
|
||||
IConsoleCmd *next; ///< next command in list
|
||||
struct IConsoleCmd;
|
||||
typedef struct IConsoleCmd {
|
||||
char *name; // name of command
|
||||
struct IConsoleCmd *next; // next command in list
|
||||
|
||||
IConsoleCmdProc *proc; ///< process executed when command is typed
|
||||
IConsoleHooks hook; ///< any special trigger action that needs executing
|
||||
};
|
||||
IConsoleCmdProc *proc; // process executed when command is typed
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleCmd;
|
||||
|
||||
/** --Variables--
|
||||
* Variables are pointers to real ingame variables which allow for
|
||||
@@ -66,17 +69,18 @@ struct IConsoleCmd {
|
||||
* - '++' to increase value by one
|
||||
* - '--' to decrease value by one
|
||||
*/
|
||||
struct IConsoleVar {
|
||||
char *name; ///< name of the variable
|
||||
IConsoleVar *next; ///< next variable in list
|
||||
struct IConsoleVar;
|
||||
typedef struct IConsoleVar {
|
||||
char *name; // name of the variable
|
||||
struct IConsoleVar *next; // next variable in list
|
||||
|
||||
void *addr; ///< the address where the variable is pointing at
|
||||
uint32 size; ///< size of the variable, used for strings
|
||||
char *help; ///< the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; ///< type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; ///< some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; ///< any special trigger action that needs executing
|
||||
};
|
||||
void *addr; // the address where the variable is pointing at
|
||||
uint32 size; // size of the variable, used for strings
|
||||
char *help; // the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; // type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleVar;
|
||||
|
||||
/** --Aliases--
|
||||
* Aliases are like shortcuts for complex functions, variable assignments,
|
||||
@@ -89,21 +93,42 @@ struct IConsoleVar {
|
||||
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
|
||||
* - ";" allows for combining commands (see example 'ng')
|
||||
*/
|
||||
struct IConsoleAlias {
|
||||
char *name; ///< name of the alias
|
||||
IConsoleAlias *next; ///< next alias in list
|
||||
struct IConsoleAlias;
|
||||
typedef struct IConsoleAlias {
|
||||
char *name; // name of the alias
|
||||
struct IConsoleAlias *next; // next alias in list
|
||||
|
||||
char *cmdline; ///< command(s) that is/are being aliased
|
||||
};
|
||||
char *cmdline; // command(s) that is/are being aliased
|
||||
} IConsoleAlias;
|
||||
|
||||
/* console parser */
|
||||
extern IConsoleCmd *_iconsole_cmds; ///< list of registred commands
|
||||
extern IConsoleVar *_iconsole_vars; ///< list of registred vars
|
||||
extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
|
||||
VARDEF IConsoleCmd *_iconsole_cmds; // list of registred commands
|
||||
VARDEF IConsoleVar *_iconsole_vars; // list of registred vars
|
||||
VARDEF IConsoleAlias *_iconsole_aliases; // list of registred aliases
|
||||
|
||||
/* console colors/modes */
|
||||
VARDEF byte _icolour_def;
|
||||
VARDEF byte _icolour_err;
|
||||
VARDEF byte _icolour_warn;
|
||||
VARDEF byte _icolour_dbg;
|
||||
VARDEF byte _icolour_cmd;
|
||||
VARDEF IConsoleModes _iconsole_mode;
|
||||
|
||||
/* console functions */
|
||||
void IConsoleClearBuffer();
|
||||
void IConsoleOpen();
|
||||
void IConsoleInit(void);
|
||||
void IConsoleFree(void);
|
||||
void IConsoleClearBuffer(void);
|
||||
void IConsoleResize(Window *w);
|
||||
void IConsoleSwitch(void);
|
||||
void IConsoleClose(void);
|
||||
void IConsoleOpen(void);
|
||||
|
||||
/* console output */
|
||||
void IConsolePrint(uint16 color_code, const char *string);
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
|
||||
void IConsoleDebug(const char *string);
|
||||
void IConsoleWarning(const char *string);
|
||||
void IConsoleError(const char *string);
|
||||
|
||||
/* Commands */
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
|
||||
@@ -114,15 +139,16 @@ IConsoleAlias *IConsoleAliasGet(const char *name);
|
||||
/* Variables */
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
|
||||
IConsoleVar *IConsoleVarGet(const char *name);
|
||||
IConsoleVar* IConsoleVarGet(const char *name);
|
||||
void IConsoleVarPrintGetValue(const IConsoleVar *var);
|
||||
void IConsoleVarPrintSetValue(const IConsoleVar *var);
|
||||
|
||||
/* Parser */
|
||||
void IConsoleCmdExec(const char *cmdstr);
|
||||
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
|
||||
|
||||
/* console std lib (register ingame commands/aliases/variables) */
|
||||
void IConsoleStdLibRegister();
|
||||
void IConsoleStdLibRegister(void);
|
||||
|
||||
/* Hooking code */
|
||||
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
@@ -131,9 +157,4 @@ void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
|
||||
|
||||
/* Supporting functions */
|
||||
bool GetArgumentInteger(uint32 *value, const char *arg);
|
||||
|
||||
void IConsoleGUIInit();
|
||||
void IConsoleGUIFree();
|
||||
void IConsoleGUIPrint(ConsoleColour colour_code, char *string);
|
||||
|
||||
#endif /* CONSOLE_INTERNAL_H */
|
||||
#endif /* CONSOLE_H */
|
||||
+1628
File diff suppressed because it is too large
Load Diff
+187
@@ -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;
|
||||
}
|
||||
@@ -1,21 +1,16 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file currency.h Functions to handle different currencies. */
|
||||
|
||||
#ifndef CURRENCY_H
|
||||
#define CURRENCY_H
|
||||
|
||||
#include "date_type.h"
|
||||
#include "strings_type.h"
|
||||
|
||||
enum {
|
||||
CF_NOEURO = 0,
|
||||
CF_ISEURO = 1,
|
||||
NUM_CURRENCY = 29,
|
||||
NUM_CURRENCY = 28,
|
||||
CUSTOM_CURRENCY_ID = NUM_CURRENCY - 1
|
||||
};
|
||||
|
||||
struct CurrencySpec {
|
||||
typedef struct {
|
||||
uint16 rate;
|
||||
char separator;
|
||||
Year to_euro;
|
||||
@@ -32,19 +27,19 @@ struct CurrencySpec {
|
||||
*/
|
||||
byte symbol_pos;
|
||||
StringID name;
|
||||
};
|
||||
} CurrencySpec;
|
||||
|
||||
|
||||
extern CurrencySpec _currency_specs[NUM_CURRENCY];
|
||||
|
||||
/* XXX small hack, but makes the rest of the code a bit nicer to read */
|
||||
// XXX small hack, but makes the rest of the code a bit nicer to read
|
||||
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
|
||||
#define _currency ((const CurrencySpec*)&_currency_specs[_game_mode == GM_MENU ? _settings_newgame.locale.currency : _settings_game.locale.currency])
|
||||
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
|
||||
|
||||
uint GetMaskOfAllowedCurrencies();
|
||||
void CheckSwitchToEuro();
|
||||
void ResetCurrencies(bool preserve_custom = true);
|
||||
StringID *BuildCurrencyDropdown();
|
||||
uint GetMaskOfAllowedCurrencies(void);
|
||||
void CheckSwitchToEuro(void);
|
||||
void ResetCurrencies(bool preserve_custom);
|
||||
StringID* BuildCurrencyDropdown(void);
|
||||
byte GetNewgrfCurrencyIdConverted(byte grfcurr_id);
|
||||
|
||||
#endif /* CURRENCY_H */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+86
-81
@@ -1,25 +1,20 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file date.cpp Handling of dates in our native format and transforming them to something human readable. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "date.h"
|
||||
#include "variables.h"
|
||||
#include "settings_type.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
#include "currency.h"
|
||||
#include "window_func.h"
|
||||
#include "macros.h"
|
||||
#include "vehicle.h"
|
||||
#include "network.h"
|
||||
#include "network_data.h"
|
||||
#include "network_server.h"
|
||||
#include "functions.h"
|
||||
#include "date_func.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "debug.h"
|
||||
#include "rail_gui.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "currency.h"
|
||||
|
||||
Year _cur_year; ///< Current year, starting at 0
|
||||
Month _cur_month; ///< Current month (0..11)
|
||||
Date _date; ///< Current date in days (day counter)
|
||||
Year _cur_year;
|
||||
Month _cur_month;
|
||||
Date _date;
|
||||
DateFract _date_fract;
|
||||
|
||||
|
||||
@@ -31,6 +26,10 @@ void SetDate(Date date)
|
||||
ConvertDateToYMD(date, &ymd);
|
||||
_cur_year = ymd.year;
|
||||
_cur_month = ymd.month;
|
||||
#ifdef ENABLE_NETWORK
|
||||
_network_last_advertise_frame = 0;
|
||||
_network_need_advertise = true;
|
||||
#endif /* ENABLE_NETWORK */
|
||||
}
|
||||
|
||||
#define M(a, b) ((a << 5) | b)
|
||||
@@ -71,6 +70,11 @@ static const uint16 _accum_days_for_month[] = {
|
||||
ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
|
||||
};
|
||||
|
||||
static inline bool IsLeapYear(Year yr)
|
||||
{
|
||||
return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Date to a Year, Month & Day.
|
||||
* @param date the date to convert from
|
||||
@@ -84,35 +88,35 @@ void ConvertDateToYMD(Date date, YearMonthDay *ymd)
|
||||
*/
|
||||
|
||||
/* There are 97 leap years in 400 years */
|
||||
Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
|
||||
int rem = date % (DAYS_IN_YEAR * 400 + 97);
|
||||
Year yr = 400 * (date / (365 * 400 + 97));
|
||||
int rem = date % (365 * 400 + 97);
|
||||
uint16 x;
|
||||
|
||||
if (rem >= DAYS_IN_YEAR * 100 + 25) {
|
||||
if (rem >= 365 * 100 + 25) {
|
||||
/* There are 25 leap years in the first 100 years after
|
||||
* every 400th year, as every 400th year is a leap year */
|
||||
yr += 100;
|
||||
rem -= DAYS_IN_YEAR * 100 + 25;
|
||||
rem -= 365 * 100 + 25;
|
||||
|
||||
/* There are 24 leap years in the next couple of 100 years */
|
||||
yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
|
||||
rem = (rem % (DAYS_IN_YEAR * 100 + 24));
|
||||
yr += 100 * (rem / (365 * 100 + 24));
|
||||
rem = (rem % (365 * 100 + 24));
|
||||
}
|
||||
|
||||
if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
|
||||
if (!IsLeapYear(yr) && rem >= 365 * 4) {
|
||||
/* The first 4 year of the century are not always a leap year */
|
||||
yr += 4;
|
||||
rem -= DAYS_IN_YEAR * 4;
|
||||
rem -= 365 * 4;
|
||||
}
|
||||
|
||||
/* There is 1 leap year every 4 years */
|
||||
yr += 4 * (rem / (DAYS_IN_YEAR * 4 + 1));
|
||||
rem = rem % (DAYS_IN_YEAR * 4 + 1);
|
||||
yr += 4 * (rem / (365 * 4 + 1));
|
||||
rem = rem % (365 * 4 + 1);
|
||||
|
||||
/* The last (max 3) years to account for; the first one
|
||||
* can be, but is not necessarily a leap year */
|
||||
while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
|
||||
rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
|
||||
while (rem >= (IsLeapYear(yr) ? 366 : 365)) {
|
||||
rem -= IsLeapYear(yr) ? 366 : 365;
|
||||
yr++;
|
||||
}
|
||||
|
||||
@@ -149,34 +153,55 @@ Date ConvertYMDToDate(Year year, Month month, Day day)
|
||||
/* Account for the missing of the 29th of February in non-leap years */
|
||||
if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
|
||||
|
||||
return year * DAYS_IN_YEAR + nr_of_leap_years + days;
|
||||
return year * 365 + nr_of_leap_years + days;
|
||||
}
|
||||
|
||||
/** Functions used by the IncreaseDate function */
|
||||
|
||||
extern void WaypointsDailyLoop();
|
||||
extern void EnginesDailyLoop();
|
||||
extern void DisasterDailyLoop();
|
||||
extern void IndustryDailyLoop();
|
||||
extern void CompaniesMonthlyLoop();
|
||||
extern void EnginesMonthlyLoop();
|
||||
extern void TownsMonthlyLoop();
|
||||
extern void IndustryMonthlyLoop();
|
||||
extern void StationMonthlyLoop();
|
||||
extern void OnNewDay_Train(Vehicle *v);
|
||||
extern void OnNewDay_RoadVeh(Vehicle *v);
|
||||
extern void OnNewDay_Aircraft(Vehicle *v);
|
||||
extern void OnNewDay_Ship(Vehicle *v);
|
||||
static void OnNewDay_EffectVehicle(Vehicle *v) { /* empty */ }
|
||||
extern void OnNewDay_DisasterVehicle(Vehicle *v);
|
||||
|
||||
extern void CompaniesYearlyLoop();
|
||||
extern void VehiclesYearlyLoop();
|
||||
extern void TownsYearlyLoop();
|
||||
typedef void OnNewVehicleDayProc(Vehicle *v);
|
||||
|
||||
extern void ShowEndGameChart();
|
||||
static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = {
|
||||
OnNewDay_Train,
|
||||
OnNewDay_RoadVeh,
|
||||
OnNewDay_Ship,
|
||||
OnNewDay_Aircraft,
|
||||
OnNewDay_EffectVehicle,
|
||||
OnNewDay_DisasterVehicle,
|
||||
};
|
||||
|
||||
extern void WaypointsDailyLoop(void);
|
||||
extern void TextMessageDailyLoop(void);
|
||||
extern void EnginesDailyLoop(void);
|
||||
extern void DisasterDailyLoop(void);
|
||||
|
||||
extern void PlayersMonthlyLoop(void);
|
||||
extern void EnginesMonthlyLoop(void);
|
||||
extern void TownsMonthlyLoop(void);
|
||||
extern void IndustryMonthlyLoop(void);
|
||||
extern void StationMonthlyLoop(void);
|
||||
|
||||
extern void PlayersYearlyLoop(void);
|
||||
extern void TrainsYearlyLoop(void);
|
||||
extern void RoadVehiclesYearlyLoop(void);
|
||||
extern void AircraftYearlyLoop(void);
|
||||
extern void ShipsYearlyLoop(void);
|
||||
|
||||
extern void ShowEndGameChart(void);
|
||||
|
||||
|
||||
static const Month _autosave_months[] = {
|
||||
0, ///< never
|
||||
1, ///< every month
|
||||
3, ///< every 3 months
|
||||
6, ///< every 6 months
|
||||
12, ///< every 12 months
|
||||
0, // never
|
||||
1, // every month
|
||||
3, // every 3 months
|
||||
6, // every 6 months
|
||||
12, // every 12 months
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -190,15 +215,11 @@ static void RunVehicleDayProc(uint daytick)
|
||||
for (i = daytick; i < total; i += DAY_TICKS) {
|
||||
Vehicle *v = GetVehicle(i);
|
||||
|
||||
if (v->IsValid()) {
|
||||
/* Call the 32-day callback if needed */
|
||||
CheckVehicle32Day(v);
|
||||
v->OnNewDay();
|
||||
}
|
||||
if (IsValidVehicle(v)) _on_new_vehicle_day_proc[v->type - 0x10](v);
|
||||
}
|
||||
}
|
||||
|
||||
void IncreaseDate()
|
||||
void IncreaseDate(void)
|
||||
{
|
||||
YearMonthDay ymd;
|
||||
|
||||
@@ -219,13 +240,10 @@ void IncreaseDate()
|
||||
/* yeah, increase day counter and call various daily loops */
|
||||
_date++;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
NetworkChatMessageDailyLoop();
|
||||
#endif /* ENABLE_NETWORK */
|
||||
TextMessageDailyLoop();
|
||||
|
||||
DisasterDailyLoop();
|
||||
WaypointsDailyLoop();
|
||||
IndustryDailyLoop();
|
||||
|
||||
if (_game_mode != GM_MENU) {
|
||||
InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
|
||||
@@ -239,26 +257,17 @@ void IncreaseDate()
|
||||
|
||||
/* yes, call various monthly loops */
|
||||
if (_game_mode != GM_MENU) {
|
||||
if (_debug_desync_level > 2) {
|
||||
char name[MAX_PATH];
|
||||
snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
|
||||
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
|
||||
}
|
||||
|
||||
if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
|
||||
if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) {
|
||||
_do_autosave = true;
|
||||
RedrawAutosave();
|
||||
}
|
||||
|
||||
InvalidateWindowClasses(WC_CHEATS);
|
||||
CompaniesMonthlyLoop();
|
||||
PlayersMonthlyLoop();
|
||||
EnginesMonthlyLoop();
|
||||
TownsMonthlyLoop();
|
||||
IndustryMonthlyLoop();
|
||||
StationMonthlyLoop();
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (_network_server) NetworkServerMonthlyLoop();
|
||||
#endif /* ENABLE_NETWORK */
|
||||
}
|
||||
|
||||
/* check if we entered a new year? */
|
||||
@@ -266,34 +275,30 @@ void IncreaseDate()
|
||||
_cur_year = ymd.year;
|
||||
|
||||
/* yes, call various yearly loops */
|
||||
CompaniesYearlyLoop();
|
||||
VehiclesYearlyLoop();
|
||||
TownsYearlyLoop();
|
||||
#ifdef ENABLE_NETWORK
|
||||
PlayersYearlyLoop();
|
||||
TrainsYearlyLoop();
|
||||
RoadVehiclesYearlyLoop();
|
||||
AircraftYearlyLoop();
|
||||
ShipsYearlyLoop();
|
||||
if (_network_server) NetworkServerYearlyLoop();
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
|
||||
|
||||
/* check if we reached end of the game */
|
||||
if (_cur_year == ORIGINAL_END_YEAR) {
|
||||
ShowEndGameChart();
|
||||
if (_cur_year == _patches.ending_year) {
|
||||
ShowEndGameChart();
|
||||
/* check if we reached the maximum year, decrement dates by a year */
|
||||
} else if (_cur_year == MAX_YEAR + 1) {
|
||||
Vehicle *v;
|
||||
uint days_this_year;
|
||||
|
||||
_cur_year--;
|
||||
days_this_year = IsLeapYear(_cur_year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
|
||||
days_this_year = IsLeapYear(_cur_year) ? 366 : 365;
|
||||
_date -= days_this_year;
|
||||
FOR_ALL_VEHICLES(v) v->date_of_last_service -= days_this_year;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
|
||||
* all of them if the date is set back, else those messages will hang for ever */
|
||||
NetworkInitChatMessage();
|
||||
#endif /* ENABLE_NETWORK */
|
||||
InitTextMessage();
|
||||
}
|
||||
|
||||
if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
|
||||
if (_patches.auto_euro) CheckSwitchToEuro();
|
||||
}
|
||||
+21
-28
@@ -1,9 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file date_type.h Types related to the dates in OpenTTD. */
|
||||
|
||||
#ifndef DATE_TYPE_H
|
||||
#define DATE_TYPE_H
|
||||
#ifndef DATE_H
|
||||
#define DATE_H
|
||||
|
||||
/**
|
||||
* 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On
|
||||
@@ -11,11 +9,7 @@
|
||||
* 1 tick is approximately 30 ms.
|
||||
* 1 day is thus about 2 seconds (74 * 30 = 2220) on a machine that can run OpenTTD normally
|
||||
*/
|
||||
enum {
|
||||
DAY_TICKS = 74, ///< ticks per day
|
||||
DAYS_IN_YEAR = 365, ///< days per year
|
||||
DAYS_IN_LEAP_YEAR = 366, ///< sometimes, you need one day more...
|
||||
};
|
||||
#define DAY_TICKS 74
|
||||
|
||||
/*
|
||||
* ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR and DAYS_TILL_ORIGINAL_BASE_YEAR are
|
||||
@@ -26,8 +20,6 @@ enum {
|
||||
|
||||
/** The minimum starting year/base year of the original TTD */
|
||||
#define ORIGINAL_BASE_YEAR 1920
|
||||
/** The original ending year */
|
||||
#define ORIGINAL_END_YEAR 2051
|
||||
/** The maximum year of the original TTD */
|
||||
#define ORIGINAL_MAX_YEAR 2090
|
||||
|
||||
@@ -35,7 +27,7 @@ enum {
|
||||
* The offset in days from the '_date == 0' till
|
||||
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
|
||||
*/
|
||||
#define DAYS_TILL_ORIGINAL_BASE_YEAR (DAYS_IN_YEAR * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400)
|
||||
#define DAYS_TILL_ORIGINAL_BASE_YEAR (365 * ORIGINAL_BASE_YEAR + ORIGINAL_BASE_YEAR / 4 - ORIGINAL_BASE_YEAR / 100 + ORIGINAL_BASE_YEAR / 400)
|
||||
|
||||
/* The absolute minimum & maximum years in OTTD */
|
||||
#define MIN_YEAR 0
|
||||
@@ -43,24 +35,25 @@ enum {
|
||||
* be encoded in a single 32 bits date, about 2^31 / 366 years. */
|
||||
#define MAX_YEAR 5000000
|
||||
|
||||
typedef int32 Date;
|
||||
typedef uint16 DateFract;
|
||||
|
||||
typedef int32 Year;
|
||||
/* Year and Date are defined elsewhere */
|
||||
typedef uint8 Month;
|
||||
typedef uint8 Day;
|
||||
typedef uint16 DateFract;
|
||||
|
||||
/**
|
||||
* Data structure to convert between Date and triplet (year, month, and day).
|
||||
* @see ConvertDateToYMD(), ConvertYMDToDate()
|
||||
*/
|
||||
struct YearMonthDay {
|
||||
Year year; ///< Year (0...)
|
||||
Month month; ///< Month (0..11)
|
||||
Day day; ///< Day (1..31)
|
||||
};
|
||||
typedef struct YearMonthDay {
|
||||
Year year;
|
||||
Month month;
|
||||
Day day;
|
||||
} YearMonthDay;
|
||||
|
||||
static const Year INVALID_YEAR = -1;
|
||||
static const Date INVALID_DATE = -1;
|
||||
extern Year _cur_year;
|
||||
extern Month _cur_month;
|
||||
extern Date _date;
|
||||
extern DateFract _date_fract;
|
||||
|
||||
#endif /* DATE_TYPE_H */
|
||||
|
||||
void SetDate(Date date);
|
||||
void ConvertDateToYMD(Date date, YearMonthDay *ymd);
|
||||
Date ConvertYMDToDate(Year year, Month month, Day day);
|
||||
|
||||
#endif /* DATE_H */
|
||||
+29
-75
@@ -1,19 +1,13 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file debug.cpp Handling of printing debug messages. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "console_func.h"
|
||||
#include "openttd.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "string_func.h"
|
||||
#include "network/core/core.h"
|
||||
#include "fileio_func.h"
|
||||
|
||||
#if defined(ENABLE_NETWORK)
|
||||
SOCKET _debug_socket = INVALID_SOCKET;
|
||||
#endif /* ENABLE_NETWORK */
|
||||
#include "functions.h"
|
||||
#include "string.h"
|
||||
|
||||
int _debug_ai_level;
|
||||
int _debug_driver_level;
|
||||
@@ -22,22 +16,30 @@ int _debug_map_level;
|
||||
int _debug_misc_level;
|
||||
int _debug_ms_level;
|
||||
int _debug_net_level;
|
||||
int _debug_sprite_level;
|
||||
int _debug_spritecache_level;
|
||||
int _debug_oldloader_level;
|
||||
int _debug_ntp_level;
|
||||
int _debug_npf_level;
|
||||
int _debug_yapf_level;
|
||||
int _debug_freetype_level;
|
||||
int _debug_sl_level;
|
||||
int _debug_station_level;
|
||||
int _debug_gamelog_level;
|
||||
int _debug_desync_level;
|
||||
|
||||
|
||||
struct DebugLevel {
|
||||
void CDECL debug(const char *s, ...)
|
||||
{
|
||||
va_list va;
|
||||
char buf[1024];
|
||||
|
||||
va_start(va, s);
|
||||
vsnprintf(buf, lengthof(buf), s, va);
|
||||
va_end(va);
|
||||
fprintf(stderr, "dbg: %s\n", buf);
|
||||
IConsoleDebug(buf);
|
||||
}
|
||||
|
||||
typedef struct DebugLevel {
|
||||
const char *name;
|
||||
int *level;
|
||||
};
|
||||
} DebugLevel;
|
||||
|
||||
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
|
||||
static const DebugLevel debug_level[] = {
|
||||
@@ -48,70 +50,22 @@ struct DebugLevel {
|
||||
DEBUG_LEVEL(misc),
|
||||
DEBUG_LEVEL(ms),
|
||||
DEBUG_LEVEL(net),
|
||||
DEBUG_LEVEL(sprite),
|
||||
DEBUG_LEVEL(spritecache),
|
||||
DEBUG_LEVEL(oldloader),
|
||||
DEBUG_LEVEL(ntp),
|
||||
DEBUG_LEVEL(npf),
|
||||
DEBUG_LEVEL(yapf),
|
||||
DEBUG_LEVEL(freetype),
|
||||
DEBUG_LEVEL(sl),
|
||||
DEBUG_LEVEL(station),
|
||||
DEBUG_LEVEL(gamelog),
|
||||
DEBUG_LEVEL(desync),
|
||||
DEBUG_LEVEL(freetype)
|
||||
};
|
||||
#undef DEBUG_LEVEL
|
||||
|
||||
#if !defined(NO_DEBUG_MESSAGES)
|
||||
|
||||
static void debug_print(const char *dbg, const char *buf)
|
||||
{
|
||||
#if defined(ENABLE_NETWORK)
|
||||
if (_debug_socket != INVALID_SOCKET) {
|
||||
char buf2[1024 + 32];
|
||||
|
||||
snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
|
||||
send(_debug_socket, buf2, (int)strlen(buf2), 0);
|
||||
} else
|
||||
#endif /* ENABLE_NETWORK */
|
||||
if (strcmp(dbg, "desync") != 0) {
|
||||
#if defined(WINCE)
|
||||
/* We need to do OTTD2FS twice, but as it uses a static buffer, we need to store one temporary */
|
||||
TCHAR tbuf[512];
|
||||
_sntprintf(tbuf, sizeof(tbuf), _T("%s"), OTTD2FS(dbg));
|
||||
NKDbgPrintfW(_T("dbg: [%s] %s\n"), tbuf, OTTD2FS(buf));
|
||||
#else
|
||||
fprintf(stderr, "dbg: [%s] %s\n", dbg, buf);
|
||||
#endif
|
||||
IConsoleDebug(dbg, buf);
|
||||
} else {
|
||||
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
|
||||
if (f == NULL) return;
|
||||
|
||||
fprintf(f, "%s", buf);
|
||||
fflush(f);
|
||||
}
|
||||
}
|
||||
|
||||
void CDECL debug(const char *dbg, const char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsnprintf(buf, lengthof(buf), format, va);
|
||||
va_end(va);
|
||||
|
||||
debug_print(dbg, buf);
|
||||
}
|
||||
#endif /* NO_DEBUG_MESSAGES */
|
||||
|
||||
void SetDebugString(const char *s)
|
||||
{
|
||||
int v;
|
||||
char *end;
|
||||
const char *t;
|
||||
|
||||
/* global debugging level? */
|
||||
// global debugging level?
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
const DebugLevel *i;
|
||||
|
||||
@@ -121,19 +75,19 @@ void SetDebugString(const char *s)
|
||||
for (i = debug_level; i != endof(debug_level); ++i) *i->level = v;
|
||||
}
|
||||
|
||||
/* individual levels */
|
||||
// individual levels
|
||||
for (;;) {
|
||||
const DebugLevel *i;
|
||||
int *p;
|
||||
|
||||
/* skip delimiters */
|
||||
// skip delimiters
|
||||
while (*s == ' ' || *s == ',' || *s == '\t') s++;
|
||||
if (*s == '\0') break;
|
||||
|
||||
t = s;
|
||||
while (*s >= 'a' && *s <= 'z') s++;
|
||||
|
||||
/* check debugging levels */
|
||||
// check debugging levels
|
||||
p = NULL;
|
||||
for (i = debug_level; i != endof(debug_level); ++i)
|
||||
if (s == t + strlen(i->name) && strncmp(t, i->name, s - t) == 0) {
|
||||
@@ -147,7 +101,7 @@ void SetDebugString(const char *s)
|
||||
if (p != NULL) {
|
||||
*p = v;
|
||||
} else {
|
||||
ShowInfoF("Unknown debug level '%.*s'", (int)(s - t), t);
|
||||
ShowInfoF("Unknown debug level '%.*s'", s - t, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -157,10 +111,10 @@ void SetDebugString(const char *s)
|
||||
* Just return a string with the values of all the debug categorites
|
||||
* @return string with debug-levels
|
||||
*/
|
||||
const char *GetDebugString()
|
||||
const char *GetDebugString(void)
|
||||
{
|
||||
const DebugLevel *i;
|
||||
static char dbgstr[150];
|
||||
static char dbgstr[100];
|
||||
char dbgval[20];
|
||||
|
||||
memset(dbgstr, 0, sizeof(dbgstr));
|
||||
@@ -169,7 +123,7 @@ const char *GetDebugString()
|
||||
|
||||
for (i++; i != endof(debug_level); i++) {
|
||||
snprintf(dbgval, sizeof(dbgval), ", %s=%d", i->name, *i->level);
|
||||
strecat(dbgstr, dbgval, lastof(dbgstr));
|
||||
ttd_strlcat(dbgstr, dbgval, sizeof(dbgstr));
|
||||
}
|
||||
|
||||
return dbgstr;
|
||||
@@ -0,0 +1,54 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#ifdef NO_DEBUG_MESSAGES
|
||||
#define DEBUG(name, level)
|
||||
#else
|
||||
#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug
|
||||
|
||||
extern int _debug_ai_level;
|
||||
extern int _debug_driver_level;
|
||||
extern int _debug_grf_level;
|
||||
extern int _debug_map_level;
|
||||
extern int _debug_misc_level;
|
||||
extern int _debug_ms_level;
|
||||
extern int _debug_net_level;
|
||||
extern int _debug_spritecache_level;
|
||||
extern int _debug_oldloader_level;
|
||||
extern int _debug_ntp_level;
|
||||
extern int _debug_npf_level;
|
||||
extern int _debug_yapf_level;
|
||||
extern int _debug_freetype_level;
|
||||
#endif
|
||||
|
||||
void CDECL debug(const char *s, ...);
|
||||
|
||||
void SetDebugString(const char *s);
|
||||
const char *GetDebugString(void);
|
||||
|
||||
/* MSVCRT of course has to have a different syntax for long long *sigh* */
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
# define OTTD_PRINTF64 "I64"
|
||||
#else
|
||||
# define OTTD_PRINTF64 "ll"
|
||||
#endif
|
||||
|
||||
// Used for profiling
|
||||
#define TIC() {\
|
||||
extern uint64 _rdtsc(void);\
|
||||
uint64 _xxx_ = _rdtsc();\
|
||||
static uint64 __sum__ = 0;\
|
||||
static uint32 __i__ = 0;
|
||||
|
||||
#define TOC(str, count)\
|
||||
__sum__ += _rdtsc() - _xxx_;\
|
||||
if (++__i__ == count) {\
|
||||
printf("[%s]: %" OTTD_PRINTF64 "u [avg: %.1f]\n", str, __sum__, __sum__/(double)__i__);\
|
||||
__i__ = 0;\
|
||||
__sum__ = 0;\
|
||||
}\
|
||||
}
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
@@ -1,26 +1,18 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file dedicated.cpp Forking support for dedicated servers. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
||||
#if defined(UNIX) && !defined(__MORPHOS__)
|
||||
|
||||
#include "openttd.h"
|
||||
#include "variables.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(SUNOS) && !defined(_LP64) && !defined(_I32LPx)
|
||||
/* Solaris has, in certain situation, pid_t defined as long, while in other
|
||||
* cases it has it defined as int... this handles all cases nicely. */
|
||||
# define PRINTF_PID_T "%ld"
|
||||
#else
|
||||
# define PRINTF_PID_T "%d"
|
||||
#endif
|
||||
|
||||
void DedicatedFork()
|
||||
void DedicatedFork(void)
|
||||
{
|
||||
/* Fork the program */
|
||||
pid_t pid = fork();
|
||||
@@ -30,7 +22,7 @@ void DedicatedFork()
|
||||
exit(1);
|
||||
|
||||
case 0: { // We're the child
|
||||
FILE *f;
|
||||
FILE* f;
|
||||
|
||||
/* Open the log-file to log all stuff too */
|
||||
f = fopen(_log_file, "a");
|
||||
@@ -51,9 +43,9 @@ void DedicatedFork()
|
||||
}
|
||||
|
||||
default:
|
||||
/* We're the parent */
|
||||
// We're the parent
|
||||
printf("Loading dedicated server...\n");
|
||||
printf(" - Forked to background with pid " PRINTF_PID_T "\n", pid);
|
||||
printf(" - Forked to background with pid %d\n", pid);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -61,7 +53,6 @@ void DedicatedFork()
|
||||
|
||||
#else
|
||||
|
||||
/** Empty helper function call for NOT(UNIX and not MORPHOS) systems */
|
||||
void DedicatedFork() {}
|
||||
void DedicatedFork(void) {}
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
@@ -0,0 +1,127 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "depot.h"
|
||||
#include "functions.h"
|
||||
#include "tile.h"
|
||||
#include "map.h"
|
||||
#include "table/strings.h"
|
||||
#include "saveload.h"
|
||||
#include "order.h"
|
||||
|
||||
|
||||
/**
|
||||
* Called if a new block is added to the depot-pool
|
||||
*/
|
||||
static void DepotPoolNewBlock(uint start_item)
|
||||
{
|
||||
Depot *d;
|
||||
|
||||
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
|
||||
* TODO - This is just a temporary stage, this will be removed. */
|
||||
for (d = GetDepot(start_item); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) d->index = start_item++;
|
||||
}
|
||||
|
||||
DEFINE_OLD_POOL(Depot, Depot, DepotPoolNewBlock, NULL)
|
||||
|
||||
|
||||
/**
|
||||
* Gets a depot from a tile
|
||||
*
|
||||
* @return Returns the depot if the tile had a depot, else it returns NULL
|
||||
*/
|
||||
Depot *GetDepotByTile(TileIndex tile)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (depot->xy == tile) return depot;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new depot
|
||||
*/
|
||||
Depot *AllocateDepot(void)
|
||||
{
|
||||
Depot *d;
|
||||
|
||||
/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
|
||||
* TODO - This is just a temporary stage, this will be removed. */
|
||||
for (d = GetDepot(0); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) {
|
||||
if (!IsValidDepot(d)) {
|
||||
DepotID index = d->index;
|
||||
|
||||
memset(d, 0, sizeof(Depot));
|
||||
d->index = index;
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can add a block to the pool */
|
||||
if (AddBlockToPool(&_Depot_pool)) return AllocateDepot();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up a depot
|
||||
*/
|
||||
void DestroyDepot(Depot *depot)
|
||||
{
|
||||
/* Clear the tile */
|
||||
DoClearSquare(depot->xy);
|
||||
|
||||
/* Clear the depot from all order-lists */
|
||||
RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, depot->index);
|
||||
|
||||
/* Delete the depot-window */
|
||||
DeleteWindowById(WC_VEHICLE_DEPOT, depot->xy);
|
||||
}
|
||||
|
||||
void InitializeDepots(void)
|
||||
{
|
||||
CleanPool(&_Depot_pool);
|
||||
AddBlockToPool(&_Depot_pool);
|
||||
}
|
||||
|
||||
|
||||
static const SaveLoad _depot_desc[] = {
|
||||
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
|
||||
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, SL_MAX_VERSION),
|
||||
SLE_VAR(Depot, town_index, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_DEPT(void)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
SlSetArrayIndex(depot->index);
|
||||
SlObject(depot, _depot_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_DEPT(void)
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Depot *depot;
|
||||
|
||||
if (!AddBlockIfNeeded(&_Depot_pool, index))
|
||||
error("Depots: failed loading savegame: too many depots");
|
||||
|
||||
depot = GetDepot(index);
|
||||
SlObject(depot, _depot_desc);
|
||||
}
|
||||
}
|
||||
|
||||
const ChunkHandler _depot_chunk_handlers[] = {
|
||||
{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST},
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEPOT_H
|
||||
#define DEPOT_H
|
||||
|
||||
/** @file depot.h Header files for depots (not hangars)
|
||||
* @see depot.c */
|
||||
|
||||
#include "direction.h"
|
||||
#include "oldpool.h"
|
||||
#include "tile.h"
|
||||
#include "variables.h"
|
||||
|
||||
struct Depot {
|
||||
TileIndex xy;
|
||||
TownID town_index;
|
||||
DepotID index;
|
||||
};
|
||||
|
||||
DECLARE_OLD_POOL(Depot, Depot, 3, 8000)
|
||||
|
||||
/**
|
||||
* Check if a depot really exists.
|
||||
*/
|
||||
static inline bool IsValidDepot(const Depot *depot)
|
||||
{
|
||||
return depot != NULL && depot->xy != 0;
|
||||
}
|
||||
|
||||
static inline bool IsValidDepotID(uint index)
|
||||
{
|
||||
return index < GetDepotPoolSize() && IsValidDepot(GetDepot(index));
|
||||
}
|
||||
|
||||
void DestroyDepot(Depot *depot);
|
||||
|
||||
static inline void DeleteDepot(Depot *depot)
|
||||
{
|
||||
DestroyDepot(depot);
|
||||
depot->xy = 0;
|
||||
}
|
||||
|
||||
void ShowDepotWindow(TileIndex tile, byte type);
|
||||
|
||||
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) if (IsValidDepot(d))
|
||||
#define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
|
||||
|
||||
#define MIN_SERVINT_PERCENT 5
|
||||
#define MAX_SERVINT_PERCENT 90
|
||||
#define MIN_SERVINT_DAYS 30
|
||||
#define MAX_SERVINT_DAYS 800
|
||||
|
||||
/**
|
||||
* Get the service interval domain.
|
||||
* Get the new proposed service interval for the vehicle is indeed, clamped
|
||||
* within the given bounds. @see MIN_SERVINT_PERCENT ,etc.
|
||||
* @param index proposed service interval
|
||||
*/
|
||||
static inline Date GetServiceIntervalClamped(uint index)
|
||||
{
|
||||
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tile is a depot of the given type.
|
||||
*/
|
||||
static inline bool IsTileDepotType(TileIndex tile, TransportType type)
|
||||
{
|
||||
switch (type) {
|
||||
case TRANSPORT_RAIL:
|
||||
return IsTileType(tile, MP_RAILWAY) && (_m[tile].m5 & 0xFC) == 0xC0;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
return IsTileType(tile, MP_STREET) && (_m[tile].m5 & 0xF0) == 0x20;
|
||||
|
||||
case TRANSPORT_WATER:
|
||||
return IsTileType(tile, MP_WATER) && (_m[tile].m5 & ~3) == 0x80;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find out if the slope of the tile is suitable to build a depot of given direction
|
||||
* @param direction The direction in which the depot's exit points. Starts with 0 as NE and goes Clockwise
|
||||
* @param tileh The slope of the tile in question
|
||||
* @return true if the construction is possible
|
||||
|
||||
* This is checked by the ugly 0x4C >> direction magic, which does the following:
|
||||
* 0x4C is 0100 1100 and tileh has only bits 0..3 set (steep tiles are ruled out)
|
||||
* So: for direction (only the significant bits are shown)<p>
|
||||
* 00 (exit towards NE) we need either bit 2 or 3 set in tileh: 0x4C >> 0 = 1100<p>
|
||||
* 01 (exit towards SE) we need either bit 1 or 2 set in tileh: 0x4C >> 1 = 0110<p>
|
||||
* 02 (exit towards SW) we need either bit 0 or 1 set in tileh: 0x4C >> 2 = 0011<p>
|
||||
* 03 (exit towards NW) we need either bit 0 or 4 set in tileh: 0x4C >> 3 = 1001<p>
|
||||
* So ((0x4C >> direction) & tileh) determines whether the depot can be built on the current tileh
|
||||
*/
|
||||
static inline bool CanBuildDepotByTileh(uint32 direction, Slope tileh)
|
||||
{
|
||||
return ((0x4C >> direction) & tileh) != 0;
|
||||
}
|
||||
|
||||
Depot *GetDepotByTile(TileIndex tile);
|
||||
void InitializeDepots(void);
|
||||
Depot *AllocateDepot(void);
|
||||
|
||||
void DeleteDepotHighlightOfVehicle(const Vehicle *v);
|
||||
|
||||
#endif /* DEPOT_H */
|
||||
+1016
File diff suppressed because it is too large
Load Diff
+147
@@ -0,0 +1,147 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DIRECTION_H
|
||||
#define DIRECTION_H
|
||||
|
||||
/* Direction as commonly used in v->direction, 8 way. */
|
||||
typedef enum Direction {
|
||||
DIR_N = 0,
|
||||
DIR_NE = 1, /* Northeast, upper right on your monitor */
|
||||
DIR_E = 2,
|
||||
DIR_SE = 3,
|
||||
DIR_S = 4,
|
||||
DIR_SW = 5,
|
||||
DIR_W = 6,
|
||||
DIR_NW = 7,
|
||||
DIR_END,
|
||||
INVALID_DIR = 0xFF,
|
||||
} Direction;
|
||||
|
||||
static inline Direction ReverseDir(Direction d)
|
||||
{
|
||||
return (Direction)(4 ^ d);
|
||||
}
|
||||
|
||||
|
||||
typedef enum DirDiff {
|
||||
DIRDIFF_SAME = 0,
|
||||
DIRDIFF_45RIGHT = 1,
|
||||
DIRDIFF_90RIGHT = 2,
|
||||
DIRDIFF_REVERSE = 4,
|
||||
DIRDIFF_90LEFT = 6,
|
||||
DIRDIFF_45LEFT = 7
|
||||
} DirDiff;
|
||||
|
||||
static inline DirDiff DirDifference(Direction d0, Direction d1)
|
||||
{
|
||||
return (DirDiff)((d0 + 8 - d1) % 8);
|
||||
}
|
||||
|
||||
static inline DirDiff ChangeDirDiff(DirDiff d, DirDiff delta)
|
||||
{
|
||||
return (DirDiff)((d + delta) % 8);
|
||||
}
|
||||
|
||||
|
||||
static inline Direction ChangeDir(Direction d, DirDiff delta)
|
||||
{
|
||||
return (Direction)((d + delta) % 8);
|
||||
}
|
||||
|
||||
|
||||
/* Direction commonly used as the direction of entering and leaving tiles, 4-way */
|
||||
typedef enum DiagDirection {
|
||||
DIAGDIR_NE = 0, /* Northeast, upper right on your monitor */
|
||||
DIAGDIR_SE = 1,
|
||||
DIAGDIR_SW = 2,
|
||||
DIAGDIR_NW = 3,
|
||||
DIAGDIR_END,
|
||||
INVALID_DIAGDIR = 0xFF,
|
||||
} DiagDirection;
|
||||
|
||||
static inline DiagDirection ReverseDiagDir(DiagDirection d)
|
||||
{
|
||||
return (DiagDirection)(2 ^ d);
|
||||
}
|
||||
|
||||
|
||||
typedef enum DiagDirDiff {
|
||||
DIAGDIRDIFF_SAME = 0,
|
||||
DIAGDIRDIFF_90RIGHT = 1,
|
||||
DIAGDIRDIFF_REVERSE = 2,
|
||||
DIAGDIRDIFF_90LEFT = 3
|
||||
} DiagDirDiff;
|
||||
|
||||
static inline DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
|
||||
{
|
||||
return (DiagDirection)((d + delta) % 4);
|
||||
}
|
||||
|
||||
|
||||
static inline DiagDirection DirToDiagDir(Direction dir)
|
||||
{
|
||||
return (DiagDirection)(dir >> 1);
|
||||
}
|
||||
|
||||
|
||||
static inline Direction DiagDirToDir(DiagDirection dir)
|
||||
{
|
||||
return (Direction)(dir * 2 + 1);
|
||||
}
|
||||
|
||||
|
||||
/* the 2 axis */
|
||||
typedef enum Axis {
|
||||
AXIS_X = 0,
|
||||
AXIS_Y = 1,
|
||||
AXIS_END
|
||||
} Axis;
|
||||
|
||||
|
||||
static inline Axis OtherAxis(Axis a)
|
||||
{
|
||||
return (Axis)(a ^ 1);
|
||||
}
|
||||
|
||||
|
||||
static inline Axis DiagDirToAxis(DiagDirection d)
|
||||
{
|
||||
return (Axis)(d & 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Converts an Axis to a DiagDirection
|
||||
* Points always in the positive direction, i.e. S[EW]
|
||||
*/
|
||||
static inline DiagDirection AxisToDiagDir(Axis a)
|
||||
{
|
||||
return (DiagDirection)(2 - a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an axis and a flag for north/south into a DiagDirection
|
||||
* @param ns north -> 0, south -> 1
|
||||
*/
|
||||
static inline DiagDirection XYNSToDiagDir(Axis xy, uint ns)
|
||||
{
|
||||
return (DiagDirection)(xy * 3 ^ ns * 2);
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsValidDiagDirection(DiagDirection d)
|
||||
{
|
||||
return d < DIAGDIR_END;
|
||||
}
|
||||
|
||||
static inline bool IsValidDirection(Direction d)
|
||||
{
|
||||
return d < DIR_END;
|
||||
}
|
||||
|
||||
static inline bool IsValidAxis(Axis d)
|
||||
{
|
||||
return d < AXIS_END;
|
||||
}
|
||||
|
||||
#endif /* DIRECTION_H */
|
||||
+1001
File diff suppressed because it is too large
Load Diff
+378
@@ -0,0 +1,378 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "station.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "variables.h"
|
||||
|
||||
static void ShowBuildDockStationPicker(void);
|
||||
static void ShowBuildDocksDepotPicker(void);
|
||||
|
||||
static Axis _ship_depot_direction;
|
||||
|
||||
void CcBuildDocks(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
}
|
||||
|
||||
|
||||
static void PlaceDocks_Dock(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_Depot(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_AUTO | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT));
|
||||
}
|
||||
|
||||
static void PlaceDocks_Buoy(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_DemolishArea(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildCanal(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_OR_Y);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildLock(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
DTW_CANAL = 3,
|
||||
DTW_LOCK = 4,
|
||||
DTW_DEMOLISH = 6,
|
||||
DTW_DEPOT = 7,
|
||||
DTW_STATION = 8,
|
||||
DTW_BUOY = 9
|
||||
};
|
||||
|
||||
|
||||
static void BuildDocksClick_Canal(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, DTW_CANAL, SPR_CURSOR_CANAL, 1, PlaceDocks_BuildCanal);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Lock(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, DTW_LOCK, SPR_CURSOR_LOCK, 1, PlaceDocks_BuildLock);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, DTW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Depot(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Dock(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Buoy(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, DTW_BUOY, SPR_CURSOR_BOUY, 1, PlaceDocks_Buoy);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_docks_button_proc[] = {
|
||||
BuildDocksClick_Canal,
|
||||
BuildDocksClick_Lock,
|
||||
NULL,
|
||||
BuildDocksClick_Demolish,
|
||||
BuildDocksClick_Depot,
|
||||
BuildDocksClick_Dock,
|
||||
BuildDocksClick_Buoy,
|
||||
BuildDocksClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->we.click.widget - 3 >= 0 && e->we.click.widget != 5) _build_docks_button_proc[e->we.click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS:
|
||||
switch (e->we.keypress.keycode) {
|
||||
case '1': BuildDocksClick_Canal(w); break;
|
||||
case '2': BuildDocksClick_Lock(w); break;
|
||||
case '3': BuildDocksClick_Demolish(w); break;
|
||||
case '4': BuildDocksClick_Depot(w); break;
|
||||
case '5': BuildDocksClick_Dock(w); break;
|
||||
case '6': BuildDocksClick_Buoy(w); break;
|
||||
case 'l': BuildDocksClick_Landscaping(w); break;
|
||||
default: return;
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->we.place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG: {
|
||||
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->we.place.pt.x != -1) {
|
||||
if ((e->we.place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
|
||||
GUIPlaceProcDragXY(e);
|
||||
} else if (e->we.place.userdata == VPM_X_OR_Y) {
|
||||
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
RaiseWindowButtons(w);
|
||||
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != NULL) WP(w,def_d).close = true;
|
||||
|
||||
w = FindWindowById(WC_BUILD_DEPOT, 0);
|
||||
if (w != NULL) WP(w,def_d).close = true;
|
||||
break;
|
||||
|
||||
case WE_PLACE_PRESIZE: {
|
||||
TileIndex tile_from;
|
||||
TileIndex tile_to;
|
||||
|
||||
tile_from = tile_to = e->we.place.tile;
|
||||
switch (GetTileSlope(tile_from, NULL)) {
|
||||
case SLOPE_SW: tile_to += TileDiffXY(-1, 0); break;
|
||||
case SLOPE_SE: tile_to += TileDiffXY( 0, -1); break;
|
||||
case SLOPE_NW: tile_to += TileDiffXY( 0, 1); break;
|
||||
case SLOPE_NE: tile_to += TileDiffXY( 1, 0); break;
|
||||
default: break;
|
||||
}
|
||||
VpSetPresizeRange(tile_from, tile_to);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_docks_toolb_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP},
|
||||
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL},
|
||||
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 48, 69, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_SHIP_DEPOT, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_SHIP_DOCK, STR_981D_BUILD_SHIP_DOCK},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_BOUY, STR_9834_POSITION_BUOY_WHICH_CAN},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_docks_toolbar_desc = {
|
||||
WDP_ALIGN_TBR, 22, 158, 36,
|
||||
WC_BUILD_TOOLBAR, 0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_build_docks_toolb_widgets,
|
||||
BuildDocksToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildDocksToolbar(void)
|
||||
{
|
||||
if (!IsValidPlayer(_current_player)) return;
|
||||
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDesc(&_build_docks_toolbar_desc);
|
||||
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_CREATE: LowerWindowWidget(w, _station_show_coverage + 3); break;
|
||||
|
||||
case WE_PAINT: {
|
||||
int rad;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
rad = (_patches.modified_catchment) ? CA_DOCK : 4;
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK:
|
||||
switch (e->we.click.widget) {
|
||||
case 3:
|
||||
case 4:
|
||||
RaiseWindowWidget(w, _station_show_coverage + 3);
|
||||
_station_show_coverage = e->we.click.widget - 3;
|
||||
LowerWindowWidget(w, _station_show_coverage + 3);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_MOUSELOOP:
|
||||
if (WP(w,def_d).close) {
|
||||
DeleteWindow(w);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close) ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_dock_station_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 17, 30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_dock_station_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 148, 75,
|
||||
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_dock_station_widgets,
|
||||
BuildDockStationWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildDockStationPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_dock_station_desc);
|
||||
}
|
||||
|
||||
static void UpdateDocksDirection(void)
|
||||
{
|
||||
if (_ship_depot_direction != AXIS_X) {
|
||||
SetTileSelectSize(1, 2);
|
||||
} else {
|
||||
SetTileSelectSize(2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_CREATE: LowerWindowWidget(w, _ship_depot_direction + 3); break;
|
||||
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
DrawShipDepotSprite(67, 35, 0);
|
||||
DrawShipDepotSprite(35, 51, 1);
|
||||
DrawShipDepotSprite(135, 35, 2);
|
||||
DrawShipDepotSprite(167, 51, 3);
|
||||
return;
|
||||
|
||||
case WE_CLICK: {
|
||||
switch (e->we.click.widget) {
|
||||
case 3:
|
||||
case 4:
|
||||
RaiseWindowWidget(w, _ship_depot_direction + 3);
|
||||
_ship_depot_direction = e->we.click.widget - 3;
|
||||
LowerWindowWidget(w, _ship_depot_direction + 3);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
UpdateDocksDirection();
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_MOUSELOOP:
|
||||
if (WP(w,def_d).close) DeleteWindow(w);
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close) ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_docks_depot_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_docks_depot_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 204, 86,
|
||||
WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_docks_depot_widgets,
|
||||
BuildDocksDepotWndProc
|
||||
};
|
||||
|
||||
|
||||
static void ShowBuildDocksDepotPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_docks_depot_desc);
|
||||
UpdateDocksDirection();
|
||||
}
|
||||
|
||||
|
||||
void InitializeDockGui(void)
|
||||
{
|
||||
_ship_depot_direction = AXIS_X;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
32bpp and OpenTTD
|
||||
=================
|
||||
|
||||
OpenTTD has 32bpp support. This means: OpenTTD still is 8bpp, but it has the
|
||||
posibility to override the graphics with 32bpp. This means that it isn't a
|
||||
replacement of grf or newgrf, but simply an addition. If you want to use 32bpp
|
||||
graphics of a newgrf, you do need the newgrf itself too (with 8bpp graphics).
|
||||
|
||||
|
||||
The Format
|
||||
----------
|
||||
|
||||
32bpp images are stored in PNG. They should go in:
|
||||
data/sprites/<grfname>/<SpriteID>.png
|
||||
|
||||
For example, a grfname would be 'openttd' (without .grf, lowercase), and the
|
||||
SpriteID 3, to override the 3rd sprite in openttd.grf with a 32bpp version.
|
||||
|
||||
The format of this PNG can be almost anything, but we advise to use RGBA
|
||||
format. Alpha-channel is fully supported.
|
||||
|
||||
As the core of OpenTTD is 8bpp, and because you of course want company colours
|
||||
in your images, you will need to add a mask for every sprite that needs colour
|
||||
remapping. The name is simular as above, only you have to put a 'm' behind the
|
||||
SpriteID. This image should be a 8bpp palette image, where the palette is the
|
||||
OpenTTD palette. Upon load of the PNG, the mask is loaded too, and overrides
|
||||
the RGB (not the Alpha) of the original PNG image, and replacing it with a
|
||||
8bpp color remapped and converted to 32bpp.
|
||||
|
||||
An other thing that OpenTTD needs in your png, is 2 tEXt chunks: x_offs and
|
||||
y_offs. This to define the x- and y-offset, of course. Use the tool we supply
|
||||
to add this information. Sadly enough most graphical editors trashes those
|
||||
chunks upon save, so you have to readd it every time you save your image.
|
||||
|
||||
Your images should be the same as the grf, in size.
|
||||
|
||||
@@ -7,9 +7,8 @@ you have downloaded english.txt, the master language file, for. While this is
|
||||
not always true, namely when changes in the code have not touched language
|
||||
files, your safest bet is to assume this 'limitation'.
|
||||
As a first step you need to compile strgen. This is as easy as typing
|
||||
'make strgen'. You can download the precompile strgen from:
|
||||
http://www.openttd.org/download-strgen
|
||||
|
||||
'make strgen'. You can also download a precompiled binary from a release,
|
||||
nightly, etc.
|
||||
strgen takes as argument a txt file and translates it to a lng file, allowing
|
||||
it to be used inside OpenTTD. strgen needs the master language file
|
||||
english.txt to work. Below are some examples of strgen usage.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
This is a guide to compile strgen on gcc
|
||||
|
||||
All this is done in the makefile, so it's only interesting for people, who wants to alter something themselves (translators)
|
||||
|
||||
HOWTO compile lng files:
|
||||
|
||||
First you get strgen compiled (look below/download nightly build/run makefile)
|
||||
|
||||
strgen takes the argument of a txt file and translates it to a lng file and places that lng file in the same dir as the txt file.
|
||||
|
||||
Example 1:
|
||||
if you are in the root of your working copy (svn code), you should type
|
||||
strgen/strgen lang/english.txt
|
||||
to compile englist.lng. It will be placed in the lang dir
|
||||
|
||||
Example 2:
|
||||
you have strgen but not the source and you want to compile a txt file in the same dir. YOu should type
|
||||
./strgen english.txt
|
||||
and you will get english.lng in the same dir
|
||||
|
||||
You can change english to whatever language you want
|
||||
|
||||
Commands used by strgen
|
||||
|
||||
-v --version
|
||||
strgen will tell what svn revision it is based on
|
||||
|
||||
-t
|
||||
strgen will add <TODO> to the missing strings and use the english strings while compiling
|
||||
this will need english.txt to be present
|
||||
|
||||
-w
|
||||
strgen will print any missing strings to standard error output(stderr)
|
||||
this will need english.txt to be present
|
||||
+1
-1
@@ -13,7 +13,7 @@ Once you have obtained a recent copy of the source, you must build it. Windows b
|
||||
On UNIX platforms (including OS-X and BeOS), ensure you have a recent GCC (2.9 or above, or 3 and above).You will also need SDL development headers and libraries (libSDL 1.2 or higher). For PNG screenshot support and zlib compressed games, you will need libpng 1.0.12 or higher and zlib 1.2 or higher.
|
||||
|
||||
Most UNIX platforms:
|
||||
First run ./configure, them use make or gmake to compile OpenTTD. You can configure the different compile options via ./configure.
|
||||
Use make or gmake to compile OpenTTD. You can adjust Makefile.config to compile with other options.
|
||||
|
||||
BeOS:
|
||||
On BeOS, run ./configure and then use jam. There are a variaty of options you can pass to your build tool, these are reported by ./configure.
|
||||
|
||||
+1
-15
@@ -50,10 +50,6 @@ To enable music, start OpenTTD with the command line:
|
||||
If I hear enough responses that both music and sound work together (it might
|
||||
just be my system), I'll have the defaults changed.
|
||||
|
||||
Please note also that the GCC version does not currently support the MCI MIDI
|
||||
system.
|
||||
|
||||
|
||||
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
|
||||
------------------------------------------
|
||||
|
||||
@@ -64,8 +60,6 @@ directly will result in the console not being displayed. You may
|
||||
still pass any other parameters ('-D' is already passed) to
|
||||
dedicated.cmd.
|
||||
|
||||
You can find the dedicated.cmd file in the os/os2 directory.
|
||||
|
||||
=========================
|
||||
BUILDING THE OS/2 VERSION
|
||||
=========================
|
||||
@@ -80,17 +74,9 @@ may help to set one up (although some of the links from that page are broken):
|
||||
|
||||
http://www.mozilla.org/ports/os2/gccsetup.html
|
||||
|
||||
Alternatively, Paul Smedley's ready-to-go GCC build environment has been known to
|
||||
successfully build the game:
|
||||
|
||||
http://www.smedley.info/os2ports/index.php?page=build-environment
|
||||
|
||||
To build, you should, if your environment is set up well enough, be able to just
|
||||
type `./configure' (or `sh configure' if you're using the OS/2 shell) and `make'.
|
||||
|
||||
You may have to manually specify `--os OS2' on the configure command line, as
|
||||
configure cannot always detect OS/2 correctly.
|
||||
|
||||
A note on Open Watcom
|
||||
---------------------
|
||||
|
||||
@@ -136,4 +122,4 @@ issues, see the Contacting section of readme.txt.
|
||||
|
||||
Thanks to Paul Smedley for his help with getting OpenTTD to compile under GCC on OS/2.
|
||||
|
||||
- Owen Rudge, 24th June 2007
|
||||
- Owen Rudge, 8th January 2007
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
Compiling OpenTTD using Microsoft Visual C++
|
||||
January 2, 2007
|
||||
December 28, 2006
|
||||
--------------------------------------------
|
||||
PLEASE READ THE ENTIRE DOCUMENT BEFORE DOING ANY ACTUAL CHANGES!!
|
||||
|
||||
|
||||
SUPPORTED MSVC COMPILERS
|
||||
------------------------
|
||||
OpenTTD includes projects for MSVC 2005.NET and MSVC 2008.NET. Both will
|
||||
OpenTTD includes projects for MSVC 2003.NET and MSVC 2005.NET. Both will
|
||||
compile out of the box, providing you have the required libraries/headers;
|
||||
which ones, see below. There is no support for VS6 or MSVC 2002, or
|
||||
MSVC 2003.NET. You are therefore strongly encouraged to either upgrade to
|
||||
MSVC 2005 Express (free) or use GCC.
|
||||
|
||||
which ones, see below. There is no support for VS6, you are therefore
|
||||
strongly encouraged to either upgrade to MSVC 2005 Express (free) or use GCC.
|
||||
MSVC 2002 probably works as well, but it has not been tested.
|
||||
|
||||
1) REQUIRED FILES
|
||||
-----------------
|
||||
@@ -20,7 +18,7 @@ downloading; mostly because the DirectX SDK and Platform SDK are about
|
||||
500MB each.
|
||||
Download the following files:
|
||||
|
||||
* openttd-useful.zip (http://binaries.openttd.org/extra/openttd-useful/)
|
||||
* openttd-useful.zip (http://sf.net/project/showfiles.php?group_id=103924&package_id=114307)
|
||||
* DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft)
|
||||
* MS Windows Platform SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en)
|
||||
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
|
||||
@@ -29,9 +27,8 @@ Download the following files:
|
||||
|
||||
You need an SVN-client to download the source from subversion:
|
||||
|
||||
* CLI Subversion (http://subversion.tigris.org/)
|
||||
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/)
|
||||
|
||||
* CLI Subversion (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
|
||||
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
|
||||
|
||||
2) INCLUDES AND LIBRARIES
|
||||
-------------------------
|
||||
@@ -59,7 +56,6 @@ include\ directory and the library files to the Lib\ directory.
|
||||
It is recommended to use custom directories so you don't overwrite any
|
||||
default header or library files.
|
||||
|
||||
|
||||
2.2) CUSTOM DIRECTORIES
|
||||
-----------------------
|
||||
If you have put the above include and/or library files into custom folders,
|
||||
@@ -73,10 +69,9 @@ Tools > Options > Projects and Solutions > VC++ Directories > show directories f
|
||||
NOTE: make sure that the directory for the DirectX SDK is the first one in the
|
||||
list, above all others, otherwise compilation will most likely fail!!
|
||||
|
||||
|
||||
3) TTD GRAPHICS FILES
|
||||
---------------------
|
||||
Copy the following files from Transport Tycoon Deluxe to the bin/data folder
|
||||
Copy the following files from Transport Tycoon Deluxe to the data folder
|
||||
|
||||
* sample.cat
|
||||
* trg1r.grf
|
||||
@@ -88,13 +83,12 @@ Copy the following files from Transport Tycoon Deluxe to the bin/data folder
|
||||
|
||||
4) COMPILING
|
||||
------------
|
||||
Open trunk/openttd_vs[89]0.sln
|
||||
Open trunk/openttd[_vs80].sln
|
||||
Set the build mode to 'Release' in
|
||||
Build > Configuration manager > Active solution configuration > select "Release"
|
||||
Compile...
|
||||
|
||||
If everything works well the binary should be in trunk/objs/Win[32|64]/Release/openttd.exe
|
||||
|
||||
If everything works well the binary should be in trunk/Release/openttd.exe
|
||||
|
||||
5) EDITING, CHANGING SOURCE CODE
|
||||
--------------------------------
|
||||
@@ -103,7 +97,6 @@ Change the startup project to openttd by right-clicking the 'openttd' project
|
||||
in the Solution Explorer and selecting 'Set as Startup Project'. The 'openttd'
|
||||
project should now show up bold instead of 'strgen'.
|
||||
|
||||
|
||||
6) PROBLEMS?
|
||||
------------
|
||||
If compilation fails, double-check that you are using the latest SVN (!)
|
||||
@@ -112,4 +105,4 @@ to ask about reasons; or just wait. The problem will most likely solve itself
|
||||
within a few days as the problem is noticed and fixed.
|
||||
|
||||
An up-to-date version of this README can be found on the wiki:
|
||||
http://wiki.openttd.org/index.php/MicrosoftVisualCExpress
|
||||
http://wiki.openttd.org/index.php/MicrosoftVisualCExpress
|
||||
+618
-1608
File diff suppressed because it is too large
Load Diff
@@ -1,616 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="Author" content="Marcin Grzegorczyk">
|
||||
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>OpenTTD Landscape externals</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3><a name="Landscape">Landscape</a></h3>
|
||||
<p>
|
||||
These are the different house types available on standard game.<br>
|
||||
<small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th align=left>Type </th>
|
||||
<th align=left>Size </th>
|
||||
<th align=left>Climates </th>
|
||||
<th align=left>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>00</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>01</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>02</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>small block of flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>03</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>church</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>04</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-arctic, sub-tropical</td>
|
||||
<td align=left>large office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>05</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>large office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>06</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>town houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>07</tt>..<tt>08</tt> </td>
|
||||
<td>1×2</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>hotel</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>09</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-arctic, sub-tropical </td>
|
||||
<td align=left>statue</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>0A</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-arctic, sub-tropical</td>
|
||||
<td align=left>fountain</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>0B</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>park (with a pond)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>0C</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>park (with an alley)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>0D</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>0E</tt>..<tt>10</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>various types of shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>11</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-arctic, sub-tropical</td>
|
||||
<td align=left>modern office building</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>12</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>warehouse</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>13</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>office block (with spiral stairway on the side)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>14</tt>..<tt>17</tt> </td>
|
||||
<td>2×2</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>stadium</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>18</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>old houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>19</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>cottages</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1A</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1B</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1C</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1D</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1E</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-tropical</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>1F</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>theatre</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>20</tt>..<tt>23</tt> </td>
|
||||
<td>2×2</td>
|
||||
<td>temperate, sub-arctic, sub-tropical</td>
|
||||
<td align=left>stadium (modern style)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>24</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate, sub-arctic, sub-tropical</td>
|
||||
<td align=left>offices (the modern 'vertical tube' style)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>25</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>26</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>27</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>cinema</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>28</tt>..<tt>2B</tt> </td>
|
||||
<td>2×2</td>
|
||||
<td>temperate</td>
|
||||
<td align=left>shopping mall</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>2C</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>2D</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>2E</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>2F</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>30</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>31</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>32</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic, sub-tropical</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>33</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>34</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>35</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>36</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic, sub-tropical</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>37</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>38</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>39</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3A</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3B</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3C</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>church</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3D</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>church</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3E</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>3F</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>40</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>41</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>42</tt>..<tt>43</tt> </td>
|
||||
<td>1×2</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>hotel</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>44</tt>..<tt>45</tt> </td>
|
||||
<td>1×2</td>
|
||||
<td>snow</td>
|
||||
<td align=left>hotel</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>46</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic, sub-tropical</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>47</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>48</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>49</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>4A</tt>..<tt>4B</tt> </td>
|
||||
<td>2×1</td>
|
||||
<td>sub-arctic</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>4C</tt>..<tt>4D</tt> </td>
|
||||
<td>2×1</td>
|
||||
<td>snow</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>4E</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>houses (with a tree in a corner)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>4F</tt>, <tt>50</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>51</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>houses (suburb-type)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>52</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>53</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>church</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>54</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>houses (with two trees in front)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>55</tt>, <tt>56</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>57</tt>..<tt>58</tt> </td>
|
||||
<td>2×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>59</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>flats</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>5A</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>sub-tropical</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>5B</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>church</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>5C</tt>..<tt>61</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>various types of toyland houses</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>62</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>63</tt>..<tt>64</tt> </td>
|
||||
<td>1×2</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>houses ('shoe' style)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>65</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>66</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>igloo</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>67</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>tepees</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>68</tt>, <tt>69</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>shops and offices</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>6A</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>tall office block</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>6B</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>statue</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>6C</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>teapot-house</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td nowrap valign=top><tt>6D</tt> </td>
|
||||
<td>1×1</td>
|
||||
<td>toyland</td>
|
||||
<td align=left>piggy-bank</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+110
-196
@@ -6,7 +6,6 @@
|
||||
<title>OpenTTD Landscape Internals - #2</title>
|
||||
<style type="text/css">
|
||||
span.abuse { font-family: "Courier New", Courier, mono; background-color: rgb(255, 58, 31); }
|
||||
span.option{ font-family: "Courier New", Courier, mono; background-color: rgb(255,255, 30); }
|
||||
span.free { font-family: "Courier New", Courier, mono; background-color: rgb(30, 178, 54); }
|
||||
span.used { font-family: "Courier New", Courier, mono; }
|
||||
td.bits { white-space: nowrap; text-align: center; font-family: "Courier New", Courier, mono; }
|
||||
@@ -17,14 +16,13 @@
|
||||
</head>
|
||||
<body style="direction: ltr;">
|
||||
<h3 style="font-weight: bold;">Landscape</h3>
|
||||
<span style="font-weight: bold;"></span>Six attributes hold the information about a tile.
|
||||
<span style="font-weight: bold;"></span>Five attributes hold the information about a tile.
|
||||
This can be seen in the <a href="landscape.html">Landscape</a> document. This page tries to give an overview of used and free bits of
|
||||
the array so you can quickly see what is used and what is not.
|
||||
<ul>
|
||||
<li><span style="font-weight: bold;"><span class="free">O</span></span> - bit is free</li>
|
||||
<li><span style="font-weight: bold;"><span class="used">X</span></span> - bit is used</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of attribute is abused for different purposes, i.e. other bits define the actual meaning.</li>
|
||||
<li><span style="font-weight: bold;"><span class="option">~</span></span> - bit is accessed, but does not really have a meaning (e.g. owner of clear land is always OWNER_NONE)</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of attribute is abused for different purposes</li>
|
||||
</ul>
|
||||
<p>
|
||||
<ul>
|
||||
@@ -34,319 +32,235 @@ the array so you can quickly see what is used and what is not.
|
||||
<li><span style="font-weight: bold;">m3</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m4</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m5</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m6</span> - 8 bits in size, special meaning : lower 2 bits only valid in tropic climate, upper 2 bits for bridges</li>
|
||||
<li><span style="font-weight: bold;">m7</span> - 8 bits in size, is used for general storage</li>
|
||||
</ul>
|
||||
|
||||
<table align=center border="1" cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=2>class</th>
|
||||
<th>type_height (8)</th>
|
||||
<th>m1 (8)</th>
|
||||
<th>m2 (16)</th>
|
||||
<th>m3 (8)</th>
|
||||
<th>m4 (8)</th>
|
||||
<th>type_height (8)</th>
|
||||
<th>m5 (8)</th>
|
||||
<th>m6 (8)</th>
|
||||
<th>m7 (8)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 class="caption">bits</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">FEDC BA98 7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">0</td>
|
||||
<td class="caption">ground</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">farmland</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=4>1</td>
|
||||
<td rowspan=3>1</td>
|
||||
<td class="caption">rail</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX <span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO O</span>XXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">rail with signals</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">depot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">XX<span class="free">O</span>X <span class="free">O</span>XXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">waypoint</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">XX<span class="free">O</span>X <span class="free">OOO</span>X</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>2</td>
|
||||
<td class="caption">road</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX X<span class="free">O</span>XX</td>
|
||||
<td class="bits">XXX<span class="free">O</span> XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">level crossing</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX<span class="free"> OOO</span>X</td>
|
||||
<td class="bits">XXXX X<span class="free">O</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road depot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XXX<span class="free">O OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td class="caption">house</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="caption">town</td>
|
||||
<td class="bits"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="option">~ ~~</span>XX</td>
|
||||
<td class="bits">XX<span class="free">OO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="abuse">X XXXX</span></td>
|
||||
<td class="bits"><span class="abuse">XXXX XX</span>XX</td>
|
||||
<td class="bits">XXXX <span class="abuse">XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">O</span>XX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td class="caption">trees</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~</span>XX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=6>5</td>
|
||||
<td class="caption">rail station</td>
|
||||
<td>5</td>
|
||||
<td class="caption">station</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road stop</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td>6</td>
|
||||
<td class="caption">water</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits">XXXX X<span class="free">O</span>XX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">dock</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">airport</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">buoy</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">oilrig</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>6</td>
|
||||
<td class="caption">sea, shore</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">X<span class="option">~~</span>X XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">canal, river</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">shipdepot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td rowspan=6>8</td>
|
||||
<td class="caption">industry</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="free">O</span> <span class="abuse">
|
||||
XXXX</span></td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=2>9</td>
|
||||
<td class="caption">tunnel entrance</td>
|
||||
<td>bubble/sugar/toffee</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OO</span>X XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XXXX X<span class="free">O</span>XX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>toy factory</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gold/copper/coal</td>
|
||||
<td class="bits"><span class="abuse">XX</span><span class="free">OO OO</span><span class="abuse">XX</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>oil wells</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OO</span><span class="abuse">XX</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>power station</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">O</span><span class="abuse">XX XX</span><span class="free">OO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>9</td>
|
||||
<td class="caption">tunnel</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO</span> XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bridge ramp</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span> <span class="free">OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="free">O O</span>XXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=2>A</td>
|
||||
<td class="caption">unmovables</td>
|
||||
<td>bridge middle part</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A</td>
|
||||
<td class="caption">various (HQ)</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">company statue</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
;
|
||||
; Example file for the OpenTTD Base Graphics replacement sets.
|
||||
; This file consists of basically two different parts:
|
||||
; * metadata
|
||||
; * information about the files
|
||||
;
|
||||
; Metadata contains information about the name, version and palette
|
||||
; of the graphics set.
|
||||
;
|
||||
; == Getting started ==
|
||||
; - you can't add comments after values
|
||||
; - you have to fill the MD5 checksum for each file
|
||||
; - you may not miss any of the metadata or files items
|
||||
; - `openttd -h` lists all graphics replacements sets it found to be correct
|
||||
; - `openttd -d grf=1` shows warnings/errors when parsing an .obg file
|
||||
; - `openttd -I <name>` starts OpenTTD with the given set (case sensitive)
|
||||
; - adding `graphicsset = <name>` to the misc section of openttd.cfg makes
|
||||
; OpenTTD start with that graphics set by default
|
||||
; - there is a command line tool for all platforms called md5sum that can
|
||||
; create the MD5 checksum you need.
|
||||
; - all files specified in this file are search relatively to the path where
|
||||
; this file is found, i.e. if the graphics files are in a subdir you have
|
||||
; to add that subdir to the names in this file to! It will NOT search for
|
||||
; a file named like specified in here.
|
||||
|
||||
[metadata]
|
||||
; the name of the pack, preferably less than 16 characters
|
||||
name = example
|
||||
; the short name (4 characters), used to identify this set within NewGRFs
|
||||
shortname = XMPL
|
||||
; the version of this graphics set (read as single integer)
|
||||
version = 0
|
||||
; a fairly short description of the set
|
||||
description = foo
|
||||
; palette used by the set; either DOS or Windows
|
||||
palette = DOS
|
||||
|
||||
; The files section lists the files that replace sprites.
|
||||
; The file names are case sensitive.
|
||||
[files]
|
||||
; GRF file with the base sprites
|
||||
base = TRG1.GRF
|
||||
; GRF file with logos, original terrain generator sprites
|
||||
logos = TRGI.GRF
|
||||
; GRF file with extra arctic sprites
|
||||
arctic = TRGC.GRF
|
||||
; GRF file with extra tropical sprites
|
||||
tropical = TRGH.GRF
|
||||
; GRF file with extra toyland sprites
|
||||
toyland = TRGT.GRF
|
||||
; NewGRF file using Actions 5, 7, 9 and A to replace sprites
|
||||
extra = OPENTTDD.GRF
|
||||
|
||||
; The md5s section lists the MD5 checksum for the files that replace them.
|
||||
; Note that the list of files is case sensitive. Each GRF listed in the
|
||||
; files section must be listed here with it's MD5 checksum, otherwise you
|
||||
; will get a lot of warnings when starting OpenTTD.
|
||||
[md5s]
|
||||
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
|
||||
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
|
||||
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
|
||||
TRGC.GRF = ed446637e034104c5559b32c18afe78d
|
||||
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
|
||||
OPENTTDD.GRF = f829f62c137d6d7c6e272c481b796dd5
|
||||
|
||||
; The origin section provides the possibility to put and extra line into
|
||||
; the warning that a file is missing/corrupt. This can be used to tell
|
||||
; them where to find it. It works on the filename specified in the
|
||||
; files section and if that is not found it will fall back to the default
|
||||
; as shown below here.
|
||||
[origin]
|
||||
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
|
||||
OPENTTDD.GRF = This file was part of your installation.
|
||||
+15
-42
@@ -1,52 +1,34 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.Dd Feb 05, 2009
|
||||
.Dd May 29, 2007
|
||||
.Dt OPENTTD 6
|
||||
.Sh NAME
|
||||
.Nm openttd
|
||||
.Nd An open source clone of the Microprose game "Transport Tycoon Deluxe"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl efhx
|
||||
.Op Fl a Ar ai
|
||||
.Op Fl b Ar blitter
|
||||
.Op Fl c Ar config_file
|
||||
.Op Fl d Ar [level | cat=lvl[, ...]]
|
||||
.Op Fl D Ar [host][:port]
|
||||
.Op Fl g Ar [savegame]
|
||||
.Op Fl Defhi
|
||||
.Op Fl G Ar seed
|
||||
.Op Fl i Ar palette
|
||||
.Op Fl I Ar graphicsset
|
||||
.Op Fl l Ar host[:port]
|
||||
.Op Fl m Ar driver
|
||||
.Op Fl d Ar [level | cat=lvl[, ...]]
|
||||
.Op Fl g Ar [savegame]
|
||||
.Op Fl n Ar host[:port][#player]
|
||||
.Op Fl r Ar widthxheight
|
||||
.Op Fl t Ar date
|
||||
.Op Fl m Ar driver
|
||||
.Op Fl s Ar driver
|
||||
.Op Fl t Ar year
|
||||
.Op Fl v Ar driver
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width ".Fl n Ar host[:port][#player]"
|
||||
.It Fl a Ar ai
|
||||
Set the AI, see
|
||||
.Fl h
|
||||
.It Fl b Ar blitter
|
||||
Set the blitter, see
|
||||
.Fl h
|
||||
.It Fl c Ar config_file
|
||||
Use 'config_file' instead of 'openttd.cfg'
|
||||
.It Fl D
|
||||
Start a dedicated server
|
||||
.It Fl G Ar seed
|
||||
Seed the pseudo random number generator
|
||||
.It Fl d Ar [level]
|
||||
Set debug verbosity for all categories to
|
||||
.Ar level
|
||||
or 1 if omitted
|
||||
.It Fl d Ar cat=level[, ...]
|
||||
Set debug verbosity for a specific category
|
||||
.It Fl D Ar [host][:port]
|
||||
Start a dedicated server. Sets network debug level to 6. If you want to change this, use
|
||||
.Fl d
|
||||
after
|
||||
.Fl D
|
||||
.It Fl G Ar seed
|
||||
Seed the pseudo random number generator
|
||||
.It Fl e
|
||||
Start in world editor mode
|
||||
.It Fl f
|
||||
@@ -57,16 +39,9 @@ Load
|
||||
.Ar savegame
|
||||
at start or start a new game if omitted
|
||||
.It Fl h
|
||||
Display a summary of all options and available AIs, blitters, drivers and graphic sets
|
||||
.It Fl i Ar palette
|
||||
Set the palette, see
|
||||
.Fl h
|
||||
.It Fl I Ar graphicsset
|
||||
Set the graphics set, see
|
||||
.Fl h
|
||||
.It Fl l Ar host[:port]
|
||||
Redirect DEBUG(), See
|
||||
.Fl D
|
||||
Display a summary of all options and available drivers
|
||||
.It Fl i
|
||||
Force to use the DOS palette (use this if you see a lot of magenta)
|
||||
.It Fl m Ar driver
|
||||
Set the music driver, see
|
||||
.Fl h
|
||||
@@ -77,13 +52,11 @@ Set the resolution
|
||||
.It Fl s Ar driver
|
||||
Set the sound driver, see
|
||||
.Fl h
|
||||
.It Fl t Ar year
|
||||
Set the starting year
|
||||
.It Fl t Ar date
|
||||
Set the starting date
|
||||
.It Fl v Ar driver
|
||||
Set the video driver, see
|
||||
.Fl h
|
||||
.It Fl x
|
||||
Do not automatically save to config file on exit
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
http://wiki.openttd.org/, http://www.openttd.org
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "driver.h"
|
||||
#include "functions.h"
|
||||
#include "hal.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "music/bemidi.h"
|
||||
#include "music/dmusic.h"
|
||||
#include "music/extmidi.h"
|
||||
#include "music/null_m.h"
|
||||
#include "music/os2_m.h"
|
||||
#include "music/win32_m.h"
|
||||
#include "music/qtmidi.h"
|
||||
|
||||
#include "sound/null_s.h"
|
||||
#include "sound/sdl_s.h"
|
||||
#include "sound/cocoa_s.h"
|
||||
#include "sound/win32_s.h"
|
||||
|
||||
#include "video/dedicated_v.h"
|
||||
#include "video/null_v.h"
|
||||
#include "video/sdl_v.h"
|
||||
#include "video/cocoa_v.h"
|
||||
#include "video/win32_v.h"
|
||||
|
||||
typedef struct DriverDesc {
|
||||
const char* name;
|
||||
const char* longname;
|
||||
const HalCommonDriver* drv;
|
||||
} DriverDesc;
|
||||
|
||||
typedef struct DriverClass {
|
||||
const DriverDesc *descs;
|
||||
const char *name;
|
||||
const HalCommonDriver** drv;
|
||||
} DriverClass;
|
||||
|
||||
|
||||
#define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z }
|
||||
static const DriverDesc _music_driver_descs[] = {
|
||||
#ifdef __BEOS__
|
||||
M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver),
|
||||
#endif
|
||||
#if defined(__OS2__) && !defined(__INNOTEK_LIBC__)
|
||||
M("os2", "OS/2 Music Driver", &_os2_music_driver),
|
||||
#endif
|
||||
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver),
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 MIDI Driver", &_win32_music_driver),
|
||||
#endif
|
||||
#if defined(__APPLE__) && !defined(DEDICATED)
|
||||
M("qt", "QuickTime MIDI Driver", &_qtime_music_driver),
|
||||
#endif
|
||||
#ifdef UNIX
|
||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
||||
M("extmidi", "External MIDI Driver", &_extmidi_music_driver),
|
||||
#endif
|
||||
#endif
|
||||
M("null", "Null Music Driver", &_null_music_driver),
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
|
||||
static const DriverDesc _sound_driver_descs[] = {
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 WaveOut Driver", &_win32_sound_driver),
|
||||
#endif
|
||||
#ifdef WITH_SDL
|
||||
M("sdl", "SDL Sound Driver", &_sdl_sound_driver),
|
||||
#endif
|
||||
#ifdef WITH_COCOA
|
||||
M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver),
|
||||
#endif
|
||||
M("null", "Null Sound Driver", &_null_sound_driver),
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
|
||||
static const DriverDesc _video_driver_descs[] = {
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 GDI Video Driver", &_win32_video_driver),
|
||||
#endif
|
||||
#ifdef WITH_SDL
|
||||
M("sdl", "SDL Video Driver", &_sdl_video_driver),
|
||||
#endif
|
||||
#ifdef WITH_COCOA
|
||||
M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver),
|
||||
#endif
|
||||
M("null", "Null Video Driver", &_null_video_driver),
|
||||
#ifdef ENABLE_NETWORK
|
||||
M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver),
|
||||
#endif
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
#undef M
|
||||
|
||||
|
||||
#define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z }
|
||||
static const DriverClass _driver_classes[] = {
|
||||
M(_video_driver_descs, "video", &_video_driver),
|
||||
M(_sound_driver_descs, "sound", &_sound_driver),
|
||||
M(_music_driver_descs, "music", &_music_driver)
|
||||
};
|
||||
#undef M
|
||||
|
||||
static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name)
|
||||
{
|
||||
for (; dd->name != NULL; dd++) {
|
||||
if (strcmp(dd->name, name) == 0) return dd;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LoadDriver(int driver, const char *name)
|
||||
{
|
||||
const DriverClass *dc = &_driver_classes[driver];
|
||||
const DriverDesc *dd;
|
||||
const char *err;
|
||||
|
||||
if (*name == '\0') {
|
||||
for (dd = dc->descs; dd->name != NULL; dd++) {
|
||||
err = dd->drv->start(NULL);
|
||||
if (err == NULL) break;
|
||||
DEBUG(driver, 1) ("Probing %s driver \"%s\" failed with error: %s",
|
||||
dc->name, dd->name, err
|
||||
);
|
||||
}
|
||||
if (dd->name == NULL) {
|
||||
error("Couldn't find any suitable %s driver", dc->name);
|
||||
}
|
||||
|
||||
DEBUG(driver, 1)
|
||||
("Successfully probed %s driver \"%s\"", dc->name, dd->name);
|
||||
|
||||
*dc->drv = dd->drv;
|
||||
} else {
|
||||
char* parm;
|
||||
char buffer[256];
|
||||
const char* parms[32];
|
||||
|
||||
// Extract the driver name and put parameter list in parm
|
||||
ttd_strlcpy(buffer, name, sizeof(buffer));
|
||||
parm = strchr(buffer, ':');
|
||||
parms[0] = NULL;
|
||||
if (parm != NULL) {
|
||||
uint np = 0;
|
||||
// Tokenize the parm.
|
||||
do {
|
||||
*parm++ = '\0';
|
||||
if (np < lengthof(parms) - 1)
|
||||
parms[np++] = parm;
|
||||
while (*parm != '\0' && *parm != ',')
|
||||
parm++;
|
||||
} while (*parm == ',');
|
||||
parms[np] = NULL;
|
||||
}
|
||||
dd = GetDriverByName(dc->descs, buffer);
|
||||
if (dd == NULL)
|
||||
error("No such %s driver: %s\n", dc->name, buffer);
|
||||
|
||||
if (*dc->drv != NULL) (*dc->drv)->stop();
|
||||
*dc->drv = NULL;
|
||||
|
||||
err = dd->drv->start(parms);
|
||||
if (err != NULL) {
|
||||
error("Unable to load driver %s(%s). The error was: %s\n",
|
||||
dd->name, dd->longname, err
|
||||
);
|
||||
}
|
||||
*dc->drv = dd->drv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char* GetDriverParam(const char* const* parm, const char* name)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (parm == NULL) return NULL;
|
||||
|
||||
len = strlen(name);
|
||||
for (; *parm != NULL; parm++) {
|
||||
const char* p = *parm;
|
||||
|
||||
if (strncmp(p, name, len) == 0) {
|
||||
if (p[len] == '=') return p + len + 1;
|
||||
if (p[len] == '\0') return p + len;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool GetDriverParamBool(const char* const* parm, const char* name)
|
||||
{
|
||||
return GetDriverParam(parm, name) != NULL;
|
||||
}
|
||||
|
||||
int GetDriverParamInt(const char* const* parm, const char* name, int def)
|
||||
{
|
||||
const char* p = GetDriverParam(parm, name);
|
||||
return p != NULL ? atoi(p) : def;
|
||||
}
|
||||
|
||||
|
||||
char *GetDriverList(char* p, const char *last)
|
||||
{
|
||||
const DriverClass* dc;
|
||||
|
||||
for (dc = _driver_classes; dc != endof(_driver_classes); dc++) {
|
||||
const DriverDesc* dd;
|
||||
|
||||
p += snprintf(p, last - p, "List of %s drivers:\n", dc->name);
|
||||
for (dd = dc->descs; dd->name != NULL; dd++) {
|
||||
p += snprintf(p, last - p, "%10s: %s\n", dd->name, dd->longname);
|
||||
}
|
||||
p = strecpy(p, "\n", last);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
void LoadDriver(int driver, const char *name);
|
||||
|
||||
bool GetDriverParamBool(const char* const* parm, const char* name);
|
||||
int GetDriverParamInt(const char* const* parm, const char* name, int def);
|
||||
|
||||
char *GetDriverList(char *p, const char *last);
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
@@ -0,0 +1,83 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "table/sprites.h"
|
||||
|
||||
static void DrawTile_Dummy(TileInfo *ti)
|
||||
{
|
||||
DrawGroundSpriteAt(SPR_SHADOW_CELL, ti->x, ti->y, ti->z);
|
||||
}
|
||||
|
||||
|
||||
static uint GetSlopeZ_Dummy(TileIndex tile, uint x, uint y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Slope GetSlopeTileh_Dummy(TileIndex tile, Slope tileh)
|
||||
{
|
||||
return SLOPE_FLAT;
|
||||
}
|
||||
|
||||
static int32 ClearTile_Dummy(TileIndex tile, byte flags)
|
||||
{
|
||||
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
|
||||
}
|
||||
|
||||
|
||||
static void GetAcceptedCargo_Dummy(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void GetTileDesc_Dummy(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
td->str = STR_EMPTY;
|
||||
td->owner = OWNER_NONE;
|
||||
}
|
||||
|
||||
static void AnimateTile_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void TileLoop_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ClickTile_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Dummy(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_dummy_procs = {
|
||||
DrawTile_Dummy, /* draw_tile_proc */
|
||||
GetSlopeZ_Dummy, /* get_slope_z_proc */
|
||||
ClearTile_Dummy, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Dummy, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Dummy, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Dummy, /* get_tile_track_status_proc */
|
||||
ClickTile_Dummy, /* click_tile_proc */
|
||||
AnimateTile_Dummy, /* animate_tile_proc */
|
||||
TileLoop_Dummy, /* tile_loop_clear */
|
||||
ChangeTileOwner_Dummy, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
GetSlopeTileh_Dummy, /* get_slope_tileh_proc */
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user