mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-13 01:29:10 +00:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
783f82e7c4 |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -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
|
11
.hgignore
11
.hgignore
@@ -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
|
39
COPYING
39
COPYING
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -225,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -303,9 +303,10 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
|
231
Doxyfile
231
Doxyfile
@@ -1,231 +0,0 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = openttd
|
||||
OUTPUT_DIRECTORY = docs/source/
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = ./
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 2
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./src/
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
*.hpp \
|
||||
table/*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = YES
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = YES
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = YES
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED = DEF_COMMAND
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE = openttd.tag
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = 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
Makefile.in
157
Makefile.in
@@ -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
Makefile.src.in
302
Makefile.src.in
@@ -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
|
8
StdAfx.c
Normal file
8
StdAfx.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// ttd.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
259
ai.h
Normal file
259
ai.h
Normal file
@@ -0,0 +1,259 @@
|
||||
#ifndef AI_H
|
||||
#define AI_H
|
||||
|
||||
#include "aystar.h"
|
||||
|
||||
/*
|
||||
* These defines can be altered to change the behavoir of the AI
|
||||
*
|
||||
* WARNING:
|
||||
* This can also alter the AI in a negative way. I will never claim these settings
|
||||
* are perfect, but don't change them if you don't know what the effect is.
|
||||
*/
|
||||
|
||||
// How many times it the H multiplied. The higher, the more it will go straight to the
|
||||
// end point. The lower, how more it will find the route with the lowest cost.
|
||||
// also: the lower, the longer it takes before route is calculated..
|
||||
#define AI_PATHFINDER_H_MULTIPLER 100
|
||||
|
||||
// How many loops may AyStar do before it stops
|
||||
// 0 = infinite
|
||||
#define AI_PATHFINDER_LOOPS_PER_TICK 5
|
||||
|
||||
// How long may the AI search for one route?
|
||||
// 0 = infinite
|
||||
// This number is the number of tiles tested.
|
||||
// It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
|
||||
// to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
|
||||
// (that is: if the AI is on VERY FAST! :p
|
||||
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
|
||||
|
||||
// If you enable this, the AI is not allowed to make 90degree turns
|
||||
#define AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
|
||||
// Below are defines for the g-calculation
|
||||
|
||||
// Standard penalty given to a tile
|
||||
#define AI_PATHFINDER_PENALTY 150
|
||||
// The penalty given to a tile that is going up
|
||||
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
|
||||
// The penalty given to a tile which would have to use fundation
|
||||
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
|
||||
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
|
||||
// Same penalty, only for when road already exists
|
||||
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
|
||||
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
|
||||
// a bonus for using diagonal track
|
||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 95
|
||||
#else
|
||||
#define AI_PATHFINDER_DIAGONAL_BONUS 75
|
||||
#endif
|
||||
// If a roadblock already exists, it gets a bonus
|
||||
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
|
||||
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
|
||||
#define AI_PATHFINDER_CURVE_PENALTY 200
|
||||
|
||||
// Penalty a bridge gets per length
|
||||
#define AI_PATHFINDER_BRIDGE_PENALTY 180
|
||||
// The penalty for a bridge going up
|
||||
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
|
||||
|
||||
// Tunnels are expensive...
|
||||
// Because of that, every tile the cost is increased with 1/8th of his value
|
||||
// This is also true if you are building a tunnel yourself
|
||||
#define AI_PATHFINDER_TUNNEL_PENALTY 350
|
||||
|
||||
/*
|
||||
* Ai_New defines
|
||||
*/
|
||||
|
||||
// How long may we search cities and industry for a new route?
|
||||
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
|
||||
|
||||
// How many days must there be between building the first station and the second station
|
||||
// within one city. This number is in days and should be more than 4 months.
|
||||
#define AI_CHECKCITY_DATE_BETWEEN 180
|
||||
|
||||
// How many cargo is needed for one station in a city?
|
||||
#define AI_CHECKCITY_CARGO_PER_STATION 60
|
||||
// How much cargo must there not be used in a city before we can build a new station?
|
||||
#define AI_CHECKCITY_NEEDED_CARGO 50
|
||||
// When there is already a station which takes the same good and the rating of that
|
||||
// city is higher then this numer, we are not going to attempt to build anything
|
||||
// there
|
||||
#define AI_CHECKCITY_CARGO_RATING 50
|
||||
// But, there is a chance of 1 out of this number, that we do ;)
|
||||
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
|
||||
// If a city is too small to contain a station, there is a small chance
|
||||
// that we still do so.. just to make the city bigger!
|
||||
#define AI_CHECKCITY_CITY_CHANCE 5
|
||||
|
||||
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
|
||||
// from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
|
||||
// of the cargo in the other station, both stations can be 96 units away from eachother, if the
|
||||
// next number is 0.4.
|
||||
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
|
||||
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
|
||||
// In whole tiles, the minimum distance for a truck route
|
||||
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
|
||||
|
||||
// The amount of tiles in a square from -X to +X that is scanned for a station spot
|
||||
// (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
|
||||
// Safe values are between 15 and 5
|
||||
#define AI_FINDSTATION_TILE_RANGE 10
|
||||
|
||||
// Building on normal speed goes very fast. Idle this amount of ticks between every
|
||||
// building part. It is calculated like this: (4 - competitor_speed) * num + 1
|
||||
// where competitor_speed is between 0 (very slow) to 4 (very fast)
|
||||
#define AI_BUILDPATH_PAUSE 10
|
||||
|
||||
// Minimum % of reliabilty a vehicle has to have before the AI buys it
|
||||
#define AI_VEHICLE_MIN_RELIABILTY 60
|
||||
|
||||
// The minimum amount of money a player should always have
|
||||
#define AI_MINIMUM_MONEY 15000
|
||||
|
||||
// If the most cheap route is build, how much is it going to cost..
|
||||
// This is to prevent the AI from trying to build a route which can not be paid for
|
||||
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
|
||||
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
|
||||
|
||||
// The minimum amount of money before we are going to repay any money
|
||||
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
|
||||
// How many repays do we do if we have enough money to do so?
|
||||
// Every repay is 10000
|
||||
#define AI_LOAN_REPAY 2
|
||||
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
|
||||
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
|
||||
|
||||
// If there is <num> time as much cargo in the station then the vehicle can handle
|
||||
// reuse the station instead of building a new one!
|
||||
#define AI_STATION_REUSE_MULTIPLER 2
|
||||
|
||||
// No more than this amount of vehicles per station..
|
||||
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
|
||||
|
||||
// How many thick between building 2 vehicles
|
||||
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS
|
||||
|
||||
// How many days must there between vehicle checks
|
||||
// The more often, the less non-money-making lines there will be
|
||||
// but the unfair it may seem to a human player
|
||||
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30
|
||||
|
||||
// How money profit does a vehicle needs to make to stay in order
|
||||
// This is the profit of this year + profit of last year
|
||||
// But also for vehicles that are just one year old. In other words:
|
||||
// Vehicles of 2 years do easier meet this setting then vehicles
|
||||
// of one year. This is a very good thing. New vehicles are filtered,
|
||||
// while old vehicles stay longer, because we do get less in return.
|
||||
#define AI_MINIMUM_ROUTE_PROFIT 1000
|
||||
|
||||
// A vehicle is considered lost when he his cargo is more than 180 days old
|
||||
#define AI_VEHICLE_LOST_DAYS 180
|
||||
|
||||
// How many times may the AI try to find a route before it gives up
|
||||
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8
|
||||
|
||||
/*
|
||||
* End of defines
|
||||
*/
|
||||
|
||||
// This stops 90degrees curves
|
||||
static const byte _illegal_curves[6] = {
|
||||
255, 255, // Horz and vert, don't have the effect
|
||||
5, // upleft and upright are not valid
|
||||
4, // downright and downleft are not valid
|
||||
2, // downleft and upleft are not valid
|
||||
3, // upright and downright are not valid
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_STATE_STARTUP = 0,
|
||||
AI_STATE_FIRST_TIME,
|
||||
AI_STATE_NOTHING,
|
||||
AI_STATE_WAKE_UP,
|
||||
AI_STATE_LOCATE_ROUTE,
|
||||
AI_STATE_FIND_STATION,
|
||||
AI_STATE_FIND_PATH,
|
||||
AI_STATE_FIND_DEPOT,
|
||||
AI_STATE_VERIFY_ROUTE,
|
||||
AI_STATE_BUILD_STATION,
|
||||
AI_STATE_BUILD_PATH,
|
||||
AI_STATE_BUILD_DEPOT,
|
||||
AI_STATE_BUILD_VEHICLE,
|
||||
AI_STATE_GIVE_ORDERS,
|
||||
AI_STATE_START_VEHICLE,
|
||||
AI_STATE_REPAY_MONEY,
|
||||
AI_STATE_CHECK_ALL_VEHICLES,
|
||||
AI_STATE_ACTION_DONE,
|
||||
AI_STATE_STOP, // Temporary function to stop the AI
|
||||
};
|
||||
|
||||
// Used for tbt (train/bus/truck)
|
||||
enum {
|
||||
AI_TRAIN = 0,
|
||||
AI_BUS,
|
||||
AI_TRUCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_ACTION_NONE = 0,
|
||||
AI_ACTION_BUS_ROUTE,
|
||||
AI_ACTION_TRUCK_ROUTE,
|
||||
AI_ACTION_REPAY_LOAN,
|
||||
AI_ACTION_CHECK_ALL_VEHICLES,
|
||||
};
|
||||
|
||||
// Used for from_type/to_type
|
||||
enum {
|
||||
AI_NO_TYPE = 0,
|
||||
AI_CITY,
|
||||
AI_INDUSTRY,
|
||||
};
|
||||
|
||||
// Flags for in the vehicle
|
||||
enum {
|
||||
AI_VEHICLEFLAG_SELL = 1,
|
||||
// Remember, flags must be in power of 2
|
||||
};
|
||||
|
||||
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
|
||||
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
|
||||
#define AI_STATION_RANGE TILE_XY(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(uint tile_a, uint tile_b, uint tile_c);
|
||||
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c);
|
||||
int AiNew_GetDirection(uint tile_a, uint 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, uint tile);
|
||||
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag);
|
||||
int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag);
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
|
||||
int AiNew_PickVehicle(Player *p);
|
||||
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag);
|
||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag);
|
||||
|
||||
|
||||
#endif
|
260
ai_build.c
Normal file
260
ai_build.c
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "command.h"
|
||||
#include "ai.h"
|
||||
#include "engine.h"
|
||||
#include "station.h"
|
||||
|
||||
// Build HQ
|
||||
// Params:
|
||||
// tile : tile where HQ is going to be build
|
||||
bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
|
||||
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
|
||||
return false;
|
||||
DoCommandByTile(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, uint tile, byte length, byte numtracks, byte direction, byte flag) {
|
||||
if (type == AI_TRAIN)
|
||||
return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
|
||||
|
||||
if (type == AI_BUS)
|
||||
return DoCommandByTile(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
|
||||
return DoCommandByTile(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, uint tile_a, uint tile_b, byte flag) {
|
||||
int bridge_type, bridge_len, type, type2;
|
||||
|
||||
// Find a good bridgetype (the best money can buy)
|
||||
bridge_len = GetBridgeLength(tile_a, tile_b);
|
||||
type = type2 = 0;
|
||||
for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
type2 = type;
|
||||
type = bridge_type;
|
||||
// We found two bridges, exit
|
||||
if (type2 != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// There is only one bridge that can be build..
|
||||
if (type2 == 0 && type != 0) type2 = type;
|
||||
|
||||
// Now, simply, build the bridge!
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
|
||||
return DoCommandByTile(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 += DoCommandByTile(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal rail
|
||||
// Keep it doing till we go an other way
|
||||
if (route_extra[part-1] == 0 && route_extra[part] == 0) {
|
||||
while (route_extra[part] == 0) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// Build the tile
|
||||
res = DoCommandByTile(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 += DoCommandByTile(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
// Bridge code
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
|
||||
return 0;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Build normal road
|
||||
// Keep it doing till we go an other way
|
||||
// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
|
||||
// it will wait till the vehicle is gone..
|
||||
if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
|
||||
// Get the current direction
|
||||
dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
|
||||
// Is it the same as the last one?
|
||||
if (old_dir != -1 && old_dir != dir) break;
|
||||
old_dir = dir;
|
||||
// There is already some road, and it is a bridge.. don't build!!!
|
||||
if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
|
||||
// Build the tile
|
||||
res = DoCommandByTile(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// Currently, we ignore CMD_ERRORs!
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CmdFailed(res)) cost += res;
|
||||
}
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
if (part >= PathFinderInfo->route_length - 1) break;
|
||||
}
|
||||
part--;
|
||||
// We want to return the last position, so we go back one
|
||||
}
|
||||
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
|
||||
PathFinderInfo->position = part;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
// This functions tries to find the best vehicle for this type of cargo
|
||||
// It returns vehicle_id or -1 if not found
|
||||
int AiNew_PickVehicle(Player *p) {
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
// Not supported yet
|
||||
return -1;
|
||||
} else {
|
||||
int start, count, i, ret = CMD_ERROR;
|
||||
start = _cargoc.ai_roadveh_start[p->ainew.cargo];
|
||||
count = _cargoc.ai_roadveh_count[p->ainew.cargo];
|
||||
|
||||
// Let's check it backwards.. we simply want to best engine available..
|
||||
for (i=start+count-1;i>=start;i--) {
|
||||
// Is it availiable?
|
||||
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
|
||||
if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
// Can we build it?
|
||||
ret = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (!CmdFailed(ret)) break;
|
||||
}
|
||||
// We did not find a vehicle :(
|
||||
if (CmdFailed(ret)) { return -1; }
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// Builds the best vehicle possible
|
||||
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
|
||||
int i = AiNew_PickVehicle(p);
|
||||
if (i == -1) return CMD_ERROR;
|
||||
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return CMD_ERROR;
|
||||
|
||||
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
|
||||
}
|
||||
|
||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag)
|
||||
{
|
||||
static const byte _roadbits_by_dir[4] = {2,1,8,4};
|
||||
int ret, ret2;
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
|
||||
|
||||
ret = DoCommandByTile(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 = DoCommandByTile(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
return ret + ret2;
|
||||
}
|
500
ai_pathfinder.c
Normal file
500
ai_pathfinder.c
Normal file
@@ -0,0 +1,500 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "command.h"
|
||||
#include "ai.h"
|
||||
#include "depot.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(uint tile, byte dir)
|
||||
{
|
||||
Player *p = DEREF_PLAYER(_current_player);
|
||||
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
int32 ret;
|
||||
// TODO: currently we only allow spots that can be access from al 4 directions...
|
||||
// should be fixed!!!
|
||||
for (dir = 0; dir < 4; dir++) {
|
||||
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (!CmdFailed(ret)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if command succeeded, so the inverse of CmdFailed()
|
||||
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
}
|
||||
|
||||
|
||||
static bool IsRoad(TileIndex tile)
|
||||
{
|
||||
return
|
||||
// MP_STREET, but not a road depot?
|
||||
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
|
||||
// road tunnel?
|
||||
((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) ||
|
||||
// road bridge?
|
||||
((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Checks if a tile 'a' is between the tiles 'b' and 'c'
|
||||
#define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
|
||||
|
||||
// Check if the current tile is in our end-area
|
||||
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
// It is not allowed to have a station on the end of a bridge or tunnel ;)
|
||||
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
|
||||
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
|
||||
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
|
||||
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
|
||||
return AYSTAR_FOUND_END_NODE;
|
||||
|
||||
return AYSTAR_DONE;
|
||||
}
|
||||
|
||||
// Calculates the hash
|
||||
// Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
|
||||
static uint AiPathFinder_Hash(uint key1, uint key2)
|
||||
{
|
||||
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
|
||||
}
|
||||
|
||||
// Clear the memory of all the things
|
||||
static void AyStar_AiPathFinder_Free(AyStar *aystar)
|
||||
{
|
||||
AyStarMain_Free(aystar);
|
||||
free(aystar);
|
||||
}
|
||||
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
// This creates the AiPathFinder
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
// Create AyStar
|
||||
AyStar *result = malloc(sizeof(AyStar));
|
||||
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
|
||||
// Set the function pointers
|
||||
result->CalculateG = AyStar_AiPathFinder_CalculateG;
|
||||
result->CalculateH = AyStar_AiPathFinder_CalculateH;
|
||||
result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
|
||||
result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
|
||||
result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
|
||||
|
||||
result->free = AyStar_AiPathFinder_Free;
|
||||
|
||||
// Set some information
|
||||
result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
|
||||
result->max_path_cost = 0;
|
||||
result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
result->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
start_node.node.tile = TILE_XY(x, y);
|
||||
result->addstart(result, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// To reuse AyStar we sometimes have to clean all the memory
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
|
||||
{
|
||||
PathNode start_node;
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
aystar->clear(aystar);
|
||||
|
||||
// Set the user_data to the PathFinderInfo
|
||||
aystar->user_target = PathFinderInfo;
|
||||
|
||||
// Set the start node
|
||||
start_node.parent = NULL;
|
||||
start_node.node.direction = 0;
|
||||
start_node.node.user_data[0] = 0;
|
||||
start_node.node.tile = PathFinderInfo->start_tile_tl;
|
||||
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
if (!(IsTileType(TILE_XY(x, y), MP_CLEAR) || IsTileType(TILE_XY(x, y), MP_TREES))) continue;
|
||||
if (!TestCanBuildStationHere(TILE_XY(x, y), TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = TILE_XY(x, y);
|
||||
aystar->addstart(aystar, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The h-value, simple calculation
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, r2;
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
|
||||
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(PathFinderInfo->end_direction));
|
||||
} else {
|
||||
// No direction, so just get the fastest route to the station
|
||||
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
|
||||
}
|
||||
// See if the bottomright is faster than the topleft..
|
||||
if (r2 < r) r = r2;
|
||||
return r * AI_PATHFINDER_H_MULTIPLER;
|
||||
}
|
||||
|
||||
// We found the end.. let's get the route back and put it in an array
|
||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
uint i = 0;
|
||||
PathNode *parent = ¤t->path;
|
||||
|
||||
do {
|
||||
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
|
||||
PathFinderInfo->route[i++] = parent->node.tile;
|
||||
if (i > lengthof(PathFinderInfo->route)) {
|
||||
// We ran out of space for the PathFinder
|
||||
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
|
||||
PathFinderInfo->route_length = -1; // -1 indicates out of space
|
||||
return;
|
||||
}
|
||||
parent = parent->parent;
|
||||
} while (parent != NULL);
|
||||
PathFinderInfo->route_length = i;
|
||||
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
|
||||
}
|
||||
|
||||
// What tiles are around us.
|
||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
uint i;
|
||||
int ret;
|
||||
int dir;
|
||||
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
|
||||
aystar->num_neighbours = 0;
|
||||
|
||||
// Go through all surrounding tiles and check if they are within the limits
|
||||
for (i = 0; i < 4; i++) {
|
||||
TileIndex ctile = current->path.node.tile; // Current tile
|
||||
TileIndex atile = ctile + TileOffsByDir(i); // Adjacent tile
|
||||
|
||||
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
|
||||
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
|
||||
// We also directly test if the current tile can connect to this tile..
|
||||
// We do this simply by just building the tile!
|
||||
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
|
||||
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge... let's test the direction ;)
|
||||
if ((_map5[atile] & 1U) != (i & 1)) continue;
|
||||
// This problem only is valid for tunnels:
|
||||
// When the last tile was not yet a tunnel, check if we enter from the right side..
|
||||
if ((_map5[atile] & 0x80) == 0) {
|
||||
if (i != (_map5[atile] & 3U)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_map5[ctile] & 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 = DoCommandByTile(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 ((_map5[ctile] & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~_map5[ctile];
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only destruct things if it is MP_CLEAR of MP_TREES
|
||||
if (dir != 0) {
|
||||
ret = DoCommandByTile(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
if (CmdFailed(ret)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The tile can be connected
|
||||
aystar->neighbours[aystar->num_neighbours].tile = atile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Next step, check for bridges and tunnels
|
||||
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
|
||||
TileInfo ti;
|
||||
// First we get the dir from this tile and his parent
|
||||
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
// It means we can only walk with the track, so the bridge has to be in the same direction
|
||||
TileIndex tile = current->path.node.tile;
|
||||
TileIndex new_tile = tile;
|
||||
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (ti.tileh != 0 ||
|
||||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
|
||||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
|
||||
|
||||
for (;;) {
|
||||
new_tile += TileOffsByDir(dir);
|
||||
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
|
||||
|
||||
// Check if we hit the station-tile.. we don't like that!
|
||||
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
|
||||
|
||||
// Try building the bridge..
|
||||
ret = DoCommandByTile(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
if (CmdFailed(ret)) continue;
|
||||
// We can build a bridge here.. add him to the neighbours
|
||||
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
// We can only have 12 neighbours, and we need 1 left for tunnels
|
||||
if (aystar->num_neighbours == 11) break;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
|
||||
// For now, we check both sides for this tile.. terraforming gives fuzzy result
|
||||
if ((dir == 0 && ti.tileh == 12) ||
|
||||
(dir == 1 && ti.tileh == 6) ||
|
||||
(dir == 2 && ti.tileh == 3) ||
|
||||
(dir == 3 && ti.tileh == 9)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
ret = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
|
||||
if (!CmdFailed(ret) && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
|
||||
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
|
||||
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
|
||||
aystar->neighbours[aystar->num_neighbours++].direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern uint GetRailFoundation(uint tileh, uint bits);
|
||||
extern uint GetRoadFoundation(uint tileh, uint bits);
|
||||
extern uint GetBridgeFoundation(uint tileh, byte direction);
|
||||
enum {
|
||||
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
|
||||
};
|
||||
|
||||
// The most important function: it calculates the g-value
|
||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
int r, res = 0;
|
||||
TileInfo ti, parent_ti;
|
||||
|
||||
// Gather some information about the tile..
|
||||
FindLandscapeHeightByTile(&ti, current->tile);
|
||||
FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
|
||||
|
||||
// Check if we hit the end-tile
|
||||
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
|
||||
// We are at the end-tile, check if we had a direction or something...
|
||||
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction)
|
||||
// We are not pointing the right way, invalid tile
|
||||
return AYSTAR_INVALID_NODE;
|
||||
// If it was valid, drop out.. we don't build on the endtile
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Give everything a small penalty
|
||||
res += AI_PATHFINDER_PENALTY;
|
||||
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
// Road has the lovely advantage it can use other road... check if
|
||||
// the current tile is road, and if so, give a good bonus
|
||||
if (IsRoad(current->tile)) {
|
||||
res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
|
||||
}
|
||||
}
|
||||
|
||||
// We should give a penalty when the tile is going up or down.. this is one way to do so!
|
||||
// Too bad we have to count it from the parent.. but that is not so bad.
|
||||
// We also dislike long routes on slopes, since they do not look too realistic
|
||||
// when there is a flat land all around, they are more expensive to build, and
|
||||
// especially they essentially block the ability to connect or cross the road
|
||||
// from one side.
|
||||
if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
|
||||
// Skip if the tile was from a bridge or tunnel
|
||||
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
|
||||
if (PathFinderInfo->rail_or_road) {
|
||||
r = GetRailFoundation(parent_ti.tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
|
||||
if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
} else {
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
} else {
|
||||
if (!(IsRoad(parent->path.node.tile) && IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE))) {
|
||||
r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
if (r >= 15 || r == 0)
|
||||
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we part of a tunnel?
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
|
||||
// Tunnels are very expensive when build on long routes..
|
||||
// Ironicly, we are using BridgeCode here ;)
|
||||
r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
res += r + (r >> 8);
|
||||
}
|
||||
|
||||
// Are we part of a bridge?
|
||||
if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
|
||||
// That means for every length a penalty
|
||||
res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
|
||||
// Check if we are going up or down, first for the starting point
|
||||
// In user_data[0] is at the 8th bit the direction
|
||||
if (!(BRIDGE_NO_FOUNDATION & (1 << parent_ti.tileh))) {
|
||||
if (GetBridgeFoundation(parent_ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
// Second for the end point
|
||||
if (!(BRIDGE_NO_FOUNDATION & (1 << ti.tileh))) {
|
||||
if (GetBridgeFoundation(ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
if (parent_ti.tileh == 0)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
if (ti.tileh == 0)
|
||||
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
}
|
||||
|
||||
// To prevent the AI from taking the fastest way in tiles, but not the fastest way
|
||||
// in speed, we have to give a good penalty to direction changing
|
||||
// This way, we get almost the fastest way in tiles, and a very good speed on the track
|
||||
if (!PathFinderInfo->rail_or_road) {
|
||||
if (parent->path.parent != NULL &&
|
||||
AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
|
||||
// When road exists, we don't like turning, but its free, so don't be to piggy about it
|
||||
if (IsRoad(parent->path.node.tile))
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
|
||||
else
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
} else {
|
||||
// For rail we have 1 exeption: diagonal rail..
|
||||
// So we fetch 2 raildirection. That of the current one, and of the one before that
|
||||
if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
|
||||
int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
|
||||
int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
|
||||
// First, see if we are on diagonal path, that is better than straight path
|
||||
if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
|
||||
|
||||
// First see if they are different
|
||||
if (dir1 != dir2) {
|
||||
// dir 2 and 3 are 1 diagonal track, and 4 and 5.
|
||||
if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
|
||||
// It is not, so we changed of direction
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
if (parent->path.parent->parent->parent != NULL) {
|
||||
int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
|
||||
// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
|
||||
if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
|
||||
res += AI_PATHFINDER_CURVE_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Res should never be below zero.. if so, make it zero!
|
||||
if (res < 0) { res = 0; }
|
||||
|
||||
// Return our value
|
||||
return res;
|
||||
}
|
119
ai_shared.c
Normal file
119
ai_shared.c
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "ai.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c) {
|
||||
// 0 = vert
|
||||
// 1 = horz
|
||||
// 2 = dig up-left
|
||||
// 3 = dig down-right
|
||||
// 4 = dig down-left
|
||||
// 5 = dig up-right
|
||||
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
if (y1 == y2 && y2 == y3) return 0;
|
||||
if (x1 == x2 && x2 == x3) return 1;
|
||||
if (y2 > y1) {
|
||||
if (x2 > x3) return 2;
|
||||
else return 4;
|
||||
}
|
||||
if (x2 > x1) {
|
||||
if (y2 > y3) return 2;
|
||||
else return 5;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
if (x2 > x3) return 5;
|
||||
else return 3;
|
||||
}
|
||||
if (x1 > x2) {
|
||||
if (y2 > y3) return 4;
|
||||
else return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c) {
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
int r;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
r = 0;
|
||||
|
||||
if (x1 < x2) r += 8;
|
||||
if (y1 < y2) r += 1;
|
||||
if (x1 > x2) r += 2;
|
||||
if (y1 > y2) r += 4;
|
||||
|
||||
if (x2 < x3) r += 2;
|
||||
if (y2 < y3) r += 4;
|
||||
if (x2 > x3) r += 8;
|
||||
if (y2 > y3) r += 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Get's the direction between 2 tiles seen from tile_a
|
||||
int AiNew_GetDirection(uint tile_a, uint tile_b) {
|
||||
if (TileY(tile_a) < TileY(tile_b)) return 1;
|
||||
if (TileY(tile_a) > TileY(tile_b)) return 3;
|
||||
if (TileX(tile_a) < TileX(tile_b)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This functions looks up if this vehicle is special for this AI
|
||||
// and returns his flag
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v) {
|
||||
int i;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
return p->ainew.special_vehicles[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found :(
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag) {
|
||||
int i, new_id = -1;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
p->ainew.special_vehicles[i].flag |= flag;
|
||||
return true;
|
||||
}
|
||||
if (new_id == -1 && p->ainew.special_vehicles[i].veh_id == 0 &&
|
||||
p->ainew.special_vehicles[i].flag == 0)
|
||||
new_id = i;
|
||||
}
|
||||
|
||||
// Out of special_vehicle spots :s
|
||||
if (new_id == -1) {
|
||||
DEBUG(ai, 1)("special_vehicles list is too small :(");
|
||||
return false;
|
||||
}
|
||||
p->ainew.special_vehicles[new_id].veh_id = v->index;
|
||||
p->ainew.special_vehicles[new_id].flag = flag;
|
||||
return true;
|
||||
}
|
2083
aircraft_cmd.c
Normal file
2083
aircraft_cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
1113
aircraft_gui.c
Normal file
1113
aircraft_gui.c
Normal file
File diff suppressed because it is too large
Load Diff
361
airport.c
Normal file
361
airport.c
Normal file
@@ -0,0 +1,361 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
|
||||
AirportFTAClass *CountryAirport;
|
||||
AirportFTAClass *CityAirport;
|
||||
AirportFTAClass *Heliport, *Oilrig;
|
||||
AirportFTAClass *MetropolitanAirport;
|
||||
AirportFTAClass *InternationalAirport;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport);
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA);
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA);
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport);
|
||||
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
|
||||
static byte AirportBlockToString(uint32 block);*/
|
||||
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
// country airport
|
||||
CountryAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CountryAirport,
|
||||
_airport_terminal_country,
|
||||
NULL,
|
||||
16,
|
||||
ALL,
|
||||
_airport_fta_country,
|
||||
_airport_depots_country,
|
||||
lengthof(_airport_depots_country)
|
||||
);
|
||||
|
||||
// city airport
|
||||
CityAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CityAirport,
|
||||
_airport_terminal_city,
|
||||
NULL,
|
||||
19,
|
||||
ALL,
|
||||
_airport_fta_city,
|
||||
_airport_depots_city,
|
||||
lengthof(_airport_depots_city)
|
||||
);
|
||||
|
||||
// metropolitan airport
|
||||
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
MetropolitanAirport,
|
||||
_airport_terminal_metropolitan,
|
||||
NULL,
|
||||
20,
|
||||
ALL,
|
||||
_airport_fta_metropolitan,
|
||||
_airport_depots_metropolitan,
|
||||
lengthof(_airport_depots_metropolitan)
|
||||
);
|
||||
|
||||
// international airport
|
||||
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
InternationalAirport,
|
||||
_airport_terminal_international,
|
||||
_airport_helipad_international,
|
||||
37,
|
||||
ALL,
|
||||
_airport_fta_international,
|
||||
_airport_depots_international,
|
||||
lengthof(_airport_depots_international)
|
||||
);
|
||||
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
}
|
||||
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
AirportFTAClass_Destructor(Heliport);
|
||||
AirportFTAClass_Destructor(MetropolitanAirport);
|
||||
AirportFTAClass_Destructor(InternationalAirport);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups = 0;
|
||||
byte nofhelipadgroups = 0;
|
||||
const byte * curr;
|
||||
int i;
|
||||
nofterminals = nofhelipads = 0;
|
||||
|
||||
//now we read the number of terminals we have
|
||||
if (terminals != NULL) {
|
||||
i = terminals[0];
|
||||
nofterminalgroups = i;
|
||||
curr = terminals;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //we don't want to have an empty group
|
||||
nofterminals += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->terminals = terminals;
|
||||
|
||||
//read helipads
|
||||
if (helipads != NULL) {
|
||||
i = helipads[0];
|
||||
nofhelipadgroups = i;
|
||||
curr = helipads;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //no empty groups please
|
||||
nofhelipads += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->helipads = helipads;
|
||||
|
||||
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
|
||||
// same goes for helipads
|
||||
if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
|
||||
if (nofhelipads > MAX_HELIPADS) { printf("Currently only maximum of %2d helipads are supported (you wanted %2d)\n", MAX_HELIPADS, nofhelipads);}
|
||||
// terminals/helipads are divided into groups. Groups are computed by dividing the number
|
||||
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
|
||||
// will get the less # of terminals
|
||||
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
|
||||
Airport->nofelements = AirportGetNofElements(FA);
|
||||
// check
|
||||
if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
|
||||
assert(entry_point < Airport->nofelements);
|
||||
|
||||
Airport->acc_planes = acc_planes;
|
||||
Airport->entry_point = entry_point;
|
||||
Airport->airport_depots = depots;
|
||||
Airport->nof_depots = nof_depots;
|
||||
|
||||
|
||||
// build the state machine
|
||||
AirportBuildAutomata(Airport, FA);
|
||||
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d", Airport->nofelements,
|
||||
nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point);
|
||||
|
||||
|
||||
{
|
||||
byte _retval = AirportTestFTA(Airport);
|
||||
if (_retval != MAX_ELEMENTS) {printf("ERROR with element: %d\n", _retval-1);}
|
||||
assert(_retval == MAX_ELEMENTS);
|
||||
}
|
||||
// print out full information
|
||||
// true -- full info including heading, block, etc
|
||||
// false -- short info, only position and next position
|
||||
//AirportPrintOut(Airport, false);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport)
|
||||
{
|
||||
int i;
|
||||
AirportFTA *current, *next;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = Airport->layout[i].next_in_chain;
|
||||
while (current != NULL) {
|
||||
next = current->next_in_chain;
|
||||
free(current);
|
||||
current = next;
|
||||
};
|
||||
}
|
||||
free(Airport->layout);
|
||||
free(Airport);
|
||||
}
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA)
|
||||
{
|
||||
int i;
|
||||
uint16 nofelements = 0;
|
||||
int temp = FA[0].position;
|
||||
for (i = 0; i < MAX_ELEMENTS; i++) {
|
||||
if (temp != FA[i].position) {
|
||||
nofelements++;
|
||||
temp = FA[i].position;
|
||||
}
|
||||
if (FA[i].position == MAX_ELEMENTS) {break;}
|
||||
}
|
||||
return nofelements;
|
||||
}
|
||||
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA)
|
||||
{
|
||||
AirportFTA *FAutomata;
|
||||
AirportFTA *current;
|
||||
uint16 internalcounter, i;
|
||||
FAutomata = (AirportFTA *)malloc(sizeof(AirportFTA) * Airport->nofelements);
|
||||
Airport->layout = FAutomata;
|
||||
internalcounter = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = &Airport->layout[i];
|
||||
current->position = FA[internalcounter].position;
|
||||
current->heading = FA[internalcounter].heading;
|
||||
current->block = FA[internalcounter].block;
|
||||
current->next_position = FA[internalcounter].next_in_chain;
|
||||
|
||||
// outgoing nodes from the same position, create linked list
|
||||
while (current->position == FA[internalcounter+1].position) {
|
||||
AirportFTA *newNode = (AirportFTA *)malloc(sizeof(AirportFTA));
|
||||
newNode->position = FA[internalcounter+1].position;
|
||||
newNode->heading = FA[internalcounter+1].heading;
|
||||
newNode->block = FA[internalcounter+1].block;
|
||||
newNode->next_position = FA[internalcounter+1].next_in_chain;
|
||||
// create link
|
||||
current->next_in_chain = newNode;
|
||||
current = current->next_in_chain;
|
||||
internalcounter++;
|
||||
} // while
|
||||
current->next_in_chain = NULL;
|
||||
internalcounter++;
|
||||
}
|
||||
}
|
||||
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport)
|
||||
{
|
||||
byte position, i, next_element;
|
||||
AirportFTA *temp;
|
||||
next_element = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
position = Airport->layout[i].position;
|
||||
if (position != next_element) {return i;}
|
||||
temp = &Airport->layout[i];
|
||||
|
||||
do {
|
||||
if (temp->heading > MAX_HEADINGS && temp->heading != 255) {return i;}
|
||||
if (temp->heading == 0 && temp->next_in_chain != 0) {return i;}
|
||||
if (position != temp->position) {return i;}
|
||||
if (temp->next_position >= Airport->nofelements) {return i;}
|
||||
temp = temp->next_in_chain;
|
||||
} while (temp != NULL);
|
||||
next_element++;
|
||||
}
|
||||
return MAX_ELEMENTS;
|
||||
}
|
||||
|
||||
static const char* const _airport_heading_strings[MAX_HEADINGS+2] = {
|
||||
"TO_ALL",
|
||||
"HANGAR",
|
||||
"TERM1",
|
||||
"TERM2",
|
||||
"TERM3",
|
||||
"TERM4",
|
||||
"TERM5",
|
||||
"TERM6",
|
||||
"HELIPAD1",
|
||||
"HELIPAD2",
|
||||
"TAKEOFF",
|
||||
"STARTTAKEOFF",
|
||||
"ENDTAKEOFF",
|
||||
"HELITAKEOFF",
|
||||
"FLYING",
|
||||
"LANDING",
|
||||
"ENDLANDING",
|
||||
"HELILANDING",
|
||||
"HELIENDLANDING",
|
||||
"DUMMY" // extra heading for 255
|
||||
};
|
||||
|
||||
/*
|
||||
static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report)
|
||||
{
|
||||
AirportFTA *temp;
|
||||
uint16 i;
|
||||
byte heading;
|
||||
|
||||
printf("(P = Current Position; NP = Next Position)\n");
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
temp = &Airport->layout[i];
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
}
|
||||
else { printf("P:%2d NP:%2d", temp->position, temp->next_position);}
|
||||
while (temp->next_in_chain != NULL) {
|
||||
temp = temp->next_in_chain;
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
}
|
||||
else { printf("P:%2d NP:%2d", temp->position, temp->next_position);}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static byte AirportBlockToString(uint32 block)
|
||||
{
|
||||
byte i = 0;
|
||||
if (block & 0xffff0000) { block >>= 16; i += 16; }
|
||||
if (block & 0x0000ff00) { block >>= 8; i += 8; }
|
||||
if (block & 0x000000f0) { block >>= 4; i += 4; }
|
||||
if (block & 0x0000000c) { block >>= 2; i += 2; }
|
||||
if (block & 0x00000002) { i += 1; }
|
||||
return i;
|
||||
}*/
|
||||
|
||||
const AirportFTAClass* GetAirport(const byte airport_type)
|
||||
{
|
||||
AirportFTAClass *Airport = NULL;
|
||||
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
// needs constant change if more airports are added
|
||||
switch (airport_type) {
|
||||
case AT_SMALL: Airport = CountryAirport; break;
|
||||
case AT_LARGE: Airport = CityAirport; break;
|
||||
case AT_METROPOLITAN: Airport = MetropolitanAirport; break;
|
||||
case AT_HELIPORT: Airport = Heliport; break;
|
||||
case AT_OILRIG: Airport = Oilrig; break;
|
||||
case AT_INTERNATIONAL: Airport = InternationalAirport; break;
|
||||
default:
|
||||
#ifdef DEBUG__
|
||||
printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n");
|
||||
#endif
|
||||
assert(airport_type <= AT_INTERNATIONAL);
|
||||
}
|
||||
return Airport;
|
||||
}
|
67
airport.h
Normal file
67
airport.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef AIRPORT_H
|
||||
#define AIRPORT_H
|
||||
|
||||
#include "airport_movement.h"
|
||||
|
||||
enum {MAX_TERMINALS = 6};
|
||||
enum {MAX_HELIPADS = 2};
|
||||
|
||||
// Airport types
|
||||
enum {
|
||||
AT_SMALL = 0,
|
||||
AT_LARGE = 1,
|
||||
AT_HELIPORT = 2,
|
||||
AT_METROPOLITAN = 3,
|
||||
AT_INTERNATIONAL = 4,
|
||||
AT_OILRIG = 15
|
||||
};
|
||||
|
||||
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
|
||||
enum {
|
||||
AIRCRAFT_ONLY = 0,
|
||||
ALL = 1,
|
||||
HELICOPTERS_ONLY = 2
|
||||
};
|
||||
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAClass {
|
||||
byte nofelements; // number of positions the airport consists of
|
||||
const byte *terminals;
|
||||
const byte *helipads;
|
||||
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
|
||||
byte acc_planes; // accept airplanes or helicopters or both
|
||||
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
|
||||
byte nof_depots; // number of depots this airport has
|
||||
struct AirportFTA *layout; // state machine for airport
|
||||
} AirportFTAClass;
|
||||
|
||||
// internal structure used in openttd - Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTA {
|
||||
byte position; // the position that an airplane is at
|
||||
byte next_position; // next position from this position
|
||||
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
|
||||
byte heading; // heading (current orders), guiding an airplane to its target on an airport
|
||||
struct AirportFTA *next_in_chain; // possible extra movement choices from this position
|
||||
} AirportFTA;
|
||||
|
||||
void InitializeAirports(void);
|
||||
void UnInitializeAirports(void);
|
||||
const AirportFTAClass* GetAirport(const byte airport_type);
|
||||
|
||||
/** Get buildable airport bitmask.
|
||||
* @return get all buildable airports at this given time, bitmasked.
|
||||
* Bit 0 means the small airport is buildable, etc.
|
||||
* @todo set availability of airports by year, instead of airplane
|
||||
*/
|
||||
static inline uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
// 1980-1-1 is --> 21915
|
||||
// 1990-1-1 is --> 25568
|
||||
if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980
|
||||
if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990
|
||||
return bytemask;
|
||||
}
|
||||
|
||||
#endif /* AIRPORT_H */
|
245
airport_gui.c
Normal file
245
airport_gui.c
Normal file
@@ -0,0 +1,245 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.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, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceAirport(uint 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(uint tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, 4);
|
||||
}
|
||||
|
||||
|
||||
static void BuildAirClick_Airport(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 3, 0xAA4, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
}
|
||||
|
||||
static void BuildAirClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_air_button_proc[] = {
|
||||
BuildAirClick_Airport,
|
||||
BuildAirClick_Demolish,
|
||||
BuildAirClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget - 3 >= 0)
|
||||
_build_air_button_proc[e->click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch (e->keypress.keycode) {
|
||||
case '1': BuildAirClick_Airport(w); break;
|
||||
case '2': BuildAirClick_Demolish(w); break;
|
||||
case 'l': BuildAirClick_Landscaping(w); break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG: {
|
||||
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->place.pt.x != -1) {
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(w);
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != 0)
|
||||
WP(w,def_d).close = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _air_toolbar_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static const WindowDesc _air_toolbar_desc = {
|
||||
640-86, 22, 86, 36,
|
||||
WC_BUILD_TOOLBAR,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_air_toolbar_widgets,
|
||||
BuildAirToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildAirToolbar(void)
|
||||
{
|
||||
if (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDescFront(&_air_toolbar_desc, 0);
|
||||
}
|
||||
|
||||
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int sel;
|
||||
int rad = 4; // default catchment radious
|
||||
uint32 avail_airports;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
|
||||
sel = _selected_airport_type;
|
||||
avail_airports = GetValidAirports();
|
||||
|
||||
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
|
||||
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
|
||||
|
||||
/* 'Country Airport' starts at widget 3, and if its bit is set, it is available,
|
||||
* so take its opposite value to set the disabled_state. There are only 5 available
|
||||
* airports, so XOr with 0x1F (1 1111) */
|
||||
w->disabled_state = (avail_airports ^ 0x1F) << 3;
|
||||
|
||||
_selected_airport_type = sel;
|
||||
// select default the coverage area to 'Off' (8)
|
||||
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
|
||||
SetTileSelectSize(_airport_size_x[sel],_airport_size_y[sel]);
|
||||
|
||||
if (_patches.modified_catchment) {
|
||||
switch (sel) {
|
||||
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
|
||||
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
|
||||
case AT_SMALL: rad = CA_AIR_SMALL; break;
|
||||
case AT_LARGE: rad = CA_AIR_LARGE; break;
|
||||
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
|
||||
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
// strings such as 'Size' and 'Coverage Area'
|
||||
DrawStringCentered(74, 16, STR_305B_SIZE, 0);
|
||||
DrawStringCentered(74, 78, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(2, 104, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK: {
|
||||
switch(e->click.widget) {
|
||||
case 3: case 4: case 5: case 6: case 7:
|
||||
_selected_airport_type = e->click.widget - 3;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 8: case 9:
|
||||
_station_show_coverage = e->click.widget - 8;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_MOUSELOOP: {
|
||||
if (WP(w,def_d).close) {
|
||||
DeleteWindow(w);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close)
|
||||
ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_airport_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 130, 0x0, STR_NULL},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_airport_desc = {
|
||||
-1, -1, 148, 131, // height, 130+1
|
||||
WC_BUILD_STATION,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_airport_picker_widgets,
|
||||
BuildAirportPickerWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildAirportPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_airport_desc);
|
||||
}
|
||||
|
||||
void InitializeAirportGui(void)
|
||||
{
|
||||
_selected_airport_type = AT_SMALL;
|
||||
_last_built_aircraft_depot_tile = 0;
|
||||
}
|
468
airport_movement.h
Normal file
468
airport_movement.h
Normal file
@@ -0,0 +1,468 @@
|
||||
#ifndef AIRPORT_MOVEMENT_H
|
||||
#define AIRPORT_MOVEMENT_H
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "macros.h"
|
||||
|
||||
typedef struct AirportMovingData {
|
||||
int x,y;
|
||||
byte flag;
|
||||
byte direction;
|
||||
} AirportMovingData;
|
||||
|
||||
// state machine input struct (from external file, etc.)
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAbuildup {
|
||||
byte position; // the position that an airplane is at
|
||||
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
|
||||
uint32 block; // the block this position is on on the airport (st->airport_flags)
|
||||
byte next_in_chain; // next position from this position
|
||||
} AirportFTAbuildup;
|
||||
|
||||
enum {
|
||||
AMED_NOSPDCLAMP = 1<<0,
|
||||
AMED_TAKEOFF = 1<<1,
|
||||
AMED_SLOWTURN = 1<<2,
|
||||
AMED_LAND = 1<<3,
|
||||
AMED_EXACTPOS = 1<<4,
|
||||
AMED_BRAKE = 1<<5,
|
||||
AMED_HELI_RAISE = 1<<6,
|
||||
AMED_HELI_LOWER = 1<<7,
|
||||
};
|
||||
|
||||
enum {MAX_ELEMENTS = 255};
|
||||
enum {MAX_HEADINGS = 18};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////***********Movement States on Airports********************//////
|
||||
// headings target
|
||||
enum {
|
||||
TO_ALL = 0,
|
||||
HANGAR = 1,
|
||||
TERM1 = 2,
|
||||
TERM2 = 3,
|
||||
TERM3 = 4,
|
||||
TERM4 = 5,
|
||||
TERM5 = 6,
|
||||
TERM6 = 7,
|
||||
HELIPAD1 = 8,
|
||||
HELIPAD2 = 9,
|
||||
TAKEOFF = 10,
|
||||
STARTTAKEOFF = 11,
|
||||
ENDTAKEOFF = 12,
|
||||
HELITAKEOFF = 13,
|
||||
FLYING = 14,
|
||||
LANDING = 15,
|
||||
ENDLANDING = 16,
|
||||
HELILANDING = 17,
|
||||
HELIENDLANDING = 18
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////**********Movement Blocks on Airports*********************//////
|
||||
// blocks (eg_airport_flags)
|
||||
enum {
|
||||
TERM1_block = 1 << 0,
|
||||
TERM2_block = 1 << 1,
|
||||
TERM3_block = 1 << 2,
|
||||
TERM4_block = 1 << 3,
|
||||
TERM5_block = 1 << 4,
|
||||
TERM6_block = 1 << 5,
|
||||
HELIPAD1_block = 1 << 6,
|
||||
HELIPAD2_block = 1 << 7,
|
||||
RUNWAY_IN_OUT_block = 1 << 8,
|
||||
RUNWAY_IN_block = 1 << 8,
|
||||
AIRPORT_BUSY_block = 1 << 8,
|
||||
RUNWAY_OUT_block = 1 << 9,
|
||||
TAXIWAY_BUSY_block = 1 << 10,
|
||||
OUT_WAY_block = 1 << 11,
|
||||
IN_WAY_block = 1 << 12,
|
||||
AIRPORT_ENTRANCE_block = 1 << 13,
|
||||
TERM_GROUP1_block = 1 << 14,
|
||||
TERM_GROUP2_block = 1 << 15,
|
||||
HANGAR2_AREA_block = 1 << 16,
|
||||
TERM_GROUP2_ENTER1_block = 1 << 17,
|
||||
TERM_GROUP2_ENTER2_block = 1 << 18,
|
||||
TERM_GROUP2_EXIT1_block = 1 << 19,
|
||||
TERM_GROUP2_EXIT2_block = 1 << 20,
|
||||
PRE_HELIPAD_block = 1 << 21,
|
||||
NOTHING_block = 1 << 30
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////*********Movement Positions on Airports********************///////
|
||||
// Country Airfield (small) 4x3
|
||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||
{ 53, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 53, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 32, 23,AMED_EXACTPOS,7}, // 02 Terminal 1
|
||||
{ 10, 23,AMED_EXACTPOS,7}, // 03 Terminal 2
|
||||
{ 43, 37,0,0}, // 04 Going towards terminal 2
|
||||
{ 24, 37,0,0}, // 05 Going towards terminal 2
|
||||
{ 53, 37,0,0}, // 06 Going for takeoff
|
||||
{ 61, 40,AMED_EXACTPOS,1}, // 07 Taxi to start of runway (takeoff)
|
||||
{ 3, 40,AMED_NOSPDCLAMP,0}, // 08 Accelerate to end of runway
|
||||
{-79, 40,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 09 Take off
|
||||
{177, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 10 Fly to landing position in air
|
||||
{ 56, 40,AMED_NOSPDCLAMP | AMED_LAND,0}, // 11 Going down for land
|
||||
{ 3, 40,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 12 Just landed, brake until end of runway
|
||||
{ 7, 40,0,0}, // 13 Just landed, turn around and taxi 1 square
|
||||
{ 53, 40,0,0}, // 14 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 15 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 16 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 17 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (south)
|
||||
{ 44, 37,AMED_HELI_RAISE,0}, // 19 Helicopter takeoff
|
||||
{ 44, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 In position above landing spot helicopter
|
||||
{ 44, 40,AMED_HELI_LOWER,0} // 21 Helicopter landing
|
||||
};
|
||||
|
||||
// City Airport (large) 6x6
|
||||
static const AirportMovingData _airport_moving_data_town[25] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 80, 27,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 63,0,0}, // 07 Taxi to Airport center
|
||||
{ 58, 71,0,0}, // 08 Towards takeoff
|
||||
{ 72, 85,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 85,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 85,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 85,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 20, 87,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 36, 71,0,0}, // 17 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 22 Helicopter takeoff
|
||||
{ 28, 74,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 23 In position above landing spot helicopter
|
||||
{ 28, 74,AMED_HELI_LOWER,0} // 24 Helicopter landing
|
||||
};
|
||||
|
||||
// Metropolitan Airport (metropolitan) - 2 runways
|
||||
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 70, 33,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 58,0,0}, // 07 Taxi to Airport center
|
||||
{ 72, 58,0,0}, // 08 Towards takeoff
|
||||
{ 72, 69,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 69,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 69,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 69,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 21, 85,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 21, 69,0,0}, // 17 On Runway-out taxiing to In-Way
|
||||
{ 21, 54,AMED_EXACTPOS,5}, // 18 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 22 Fly around waiting for a landing spot (south)
|
||||
{ 44, 58,0,0}, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 24 Helicopter takeoff
|
||||
{ 15, 54,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 25 Get in position above landing spot helicopter
|
||||
{ 15, 54,AMED_HELI_LOWER,0} // 26 Helicopter landing
|
||||
};
|
||||
|
||||
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
|
||||
static const AirportMovingData _airport_moving_data_international[51] = {
|
||||
{ 7, 55,AMED_EXACTPOS,3}, // 00 In Hangar 1
|
||||
{100, 21,AMED_EXACTPOS,3}, // 01 In Hangar 2
|
||||
{ 7, 70,0,0}, // 02 Taxi to right outside depot
|
||||
{100, 36,0,0}, // 03 Taxi to right outside depot
|
||||
{ 38, 70,AMED_EXACTPOS,5}, // 04 Terminal 1
|
||||
{ 38, 54,AMED_EXACTPOS,5}, // 05 Terminal 2
|
||||
{ 38, 38,AMED_EXACTPOS,5}, // 06 Terminal 3
|
||||
{ 70, 70,AMED_EXACTPOS,1}, // 07 Terminal 4
|
||||
{ 70, 54,AMED_EXACTPOS,1}, // 08 Terminal 5
|
||||
{ 70, 38,AMED_EXACTPOS,1}, // 09 Terminal 6
|
||||
{104, 71,AMED_EXACTPOS,1}, // 10 Helipad 1
|
||||
{104, 55,AMED_EXACTPOS,1}, // 11 Helipad 2
|
||||
{ 22, 87,0,0}, // 12 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 60, 87,0,0}, // 13 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 66, 87,0,0}, // 14 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 87,AMED_EXACTPOS,7}, // 15 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 70,0,0}, // 16 In Front of Terminal 4 / Helipad 1
|
||||
{ 86, 54,0,0}, // 17 In Front of Terminal 5 / Helipad 2
|
||||
{ 86, 38,0,0}, // 18 In Front of Terminal 6
|
||||
{ 86, 22,0,0}, // 19 Towards Terminals Takeoff (Taxiway)
|
||||
{ 66, 22,0,0}, // 20 Towards Terminals Takeoff (Taxiway)
|
||||
{ 60, 22,0,0}, // 21 Towards Terminals Takeoff (Taxiway)
|
||||
{ 38, 22,0,0}, // 22 Towards Terminals Takeoff (Taxiway)
|
||||
{ 22, 70,0,0}, // 23 In Front of Terminal 1
|
||||
{ 22, 58,0,0}, // 24 In Front of Terminal 2
|
||||
{ 22, 38,0,0}, // 25 In Front of Terminal 3
|
||||
{ 22, 22,AMED_EXACTPOS,7}, // 26 Going for Takeoff
|
||||
{ 22, 6,0,0}, // 27 On Runway-out, prepare for takeoff
|
||||
{ 3, 6,AMED_EXACTPOS,5}, // 28 Accelerate to end of runway
|
||||
{ 60, 6,AMED_NOSPDCLAMP,0}, // 29 Release control of runway, for smoother movement
|
||||
{105, 6,AMED_NOSPDCLAMP,0}, // 30 End of runway
|
||||
{190, 6,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 31 Take off
|
||||
{193,104,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 32 Fly to landing position in air
|
||||
{105,104,AMED_NOSPDCLAMP | AMED_LAND,0}, // 33 Going down for land
|
||||
{ 3,104,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 34 Just landed, brake until end of runway
|
||||
{ 12,104,0,0}, // 35 Just landed, turn around and taxi 1 square
|
||||
{ 7, 84,0,0}, // 36 Taxi from runway to crossing
|
||||
{-31,209,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 37 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 38 Fly around waiting for a landing spot (north-west)
|
||||
{273, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 39 Fly around waiting for a landing spot (south-west)
|
||||
{305, 81,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 40 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 41 Bufferspace before helipad
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 42 Bufferspace before helipad
|
||||
{ 96, 71,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 43 Get in position for Helipad1
|
||||
{ 96, 55,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 44 Get in position for Helipad2
|
||||
{ 96, 71,AMED_HELI_LOWER,0}, // 45 Land at Helipad1
|
||||
{ 96, 55,AMED_HELI_LOWER,0}, // 46 Land at Helipad2
|
||||
{104, 71,AMED_HELI_RAISE,0}, // 47 Takeoff Helipad1
|
||||
{104, 55,AMED_HELI_RAISE,0}, // 48 Takeoff Helipad2
|
||||
{104, 32,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 49 Go to position for Hangarentrance in air
|
||||
{104, 32,AMED_HELI_LOWER,0} // 50 Land in HANGAR2_AREA to go to hangar
|
||||
};
|
||||
|
||||
// Heliport (heliport)
|
||||
static const AirportMovingData _airport_moving_data_heliport[9] = {
|
||||
{ 5, 9,AMED_EXACTPOS,1}, // 0 - At heliport terminal
|
||||
{ 2, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ -3, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ -3, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 2, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 59,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - Circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - Circle #2 (north-west)
|
||||
{ 49,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - Circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - Circle #4 (south)
|
||||
};
|
||||
|
||||
// Oilrig
|
||||
static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
{ 31, 9,AMED_EXACTPOS,1}, // 0 - At oilrig terminal
|
||||
{ 28, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ 23, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ 23, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 28, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 69,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - circle #2 (north-west)
|
||||
{ 69,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - circle #4 (south)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
// first element of depots array tells us how many depots there are (to know size of array)
|
||||
// this may be changed later when airports are moved to external file
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,AIRPORT_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM1,TERM1_block,2}, {1,TERM2,0,4}, {1,HELITAKEOFF,0,19}, {1,0,0,6},
|
||||
{ 2,TERM1,TERM1_block,1},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,255,AIRPORT_BUSY_block,0}, {4,TERM2,0,5}, {4,HANGAR,0,1}, {4,TAKEOFF,0,6}, {4,HELITAKEOFF,0,1},
|
||||
{ 5,255,AIRPORT_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,0,0,4},
|
||||
{ 6,0,AIRPORT_BUSY_block,7},
|
||||
// takeoff
|
||||
{ 7,TAKEOFF,AIRPORT_BUSY_block,8},
|
||||
{ 8,STARTTAKEOFF,NOTHING_block,9},
|
||||
{ 9,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{10,FLYING,NOTHING_block,15}, {10,LANDING,0,11}, {10,HELILANDING,0,20},
|
||||
{11,LANDING,AIRPORT_BUSY_block,12},
|
||||
{12,0,AIRPORT_BUSY_block,13},
|
||||
{13,ENDLANDING,AIRPORT_BUSY_block,14}, {13,TERM2,0,5}, {13,0,0,14},
|
||||
{14,0,AIRPORT_BUSY_block,1},
|
||||
// In air
|
||||
{15,0,NOTHING_block,16},
|
||||
{16,0,NOTHING_block,17},
|
||||
{17,0,NOTHING_block,18},
|
||||
{18,0,NOTHING_block,10},
|
||||
{19,HELITAKEOFF,NOTHING_block,0},
|
||||
{20,HELILANDING,AIRPORT_BUSY_block,21},
|
||||
{21,HELIENDLANDING,AIRPORT_BUSY_block,1},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_city[] = {{5, 0}};
|
||||
static const byte _airport_terminal_city[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1}, {0,TAKEOFF,OUT_WAY_block,1}, {0,0,0,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7}, {2,TAKEOFF,OUT_WAY_block,7}, {2,0,0,7},
|
||||
{ 3,TERM2,TERM2_block,5}, {3,TAKEOFF,OUT_WAY_block,5}, {3,0,0,5},
|
||||
{ 4,TERM3,TERM3_block,5}, {4,TAKEOFF,OUT_WAY_block,5}, {4,0,0,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,OUT_WAY_block,8}, {7,HELITAKEOFF,0,22}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_IN_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_IN_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,18}, {13,LANDING,0,14}, {13,HELILANDING,0,23},
|
||||
{14,LANDING,RUNWAY_IN_OUT_block,15},
|
||||
{15,0,RUNWAY_IN_OUT_block,16},
|
||||
{16,0,RUNWAY_IN_OUT_block,17},
|
||||
{17,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{18,0,NOTHING_block,19},
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{22,HELITAKEOFF,NOTHING_block,0},
|
||||
{23,HELILANDING,IN_WAY_block,24},
|
||||
{24,HELIENDLANDING,IN_WAY_block,17},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = {{5, 0}};
|
||||
static const byte _airport_terminal_metropolitan[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,TERM3,TERM3_block,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,0,8}, {7,HELITAKEOFF,0,23}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,19}, {13,LANDING,0,14}, {13,HELILANDING,0,25},
|
||||
{14,LANDING,RUNWAY_IN_block,15},
|
||||
{15,0,RUNWAY_IN_block,16},
|
||||
{16,255,RUNWAY_IN_block,0}, {16,ENDLANDING,IN_WAY_block,17},
|
||||
{17,255,RUNWAY_OUT_block,0}, {17,ENDLANDING,IN_WAY_block,18},
|
||||
{18,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,22},
|
||||
{22,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{23,0,NOTHING_block,24},
|
||||
{24,HELITAKEOFF,NOTHING_block,0},
|
||||
{25,HELILANDING,IN_WAY_block,26},
|
||||
{26,HELIENDLANDING,IN_WAY_block,18},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_international[] = {{0, 3}, {6, 1}};
|
||||
static const byte _airport_terminal_international[] = {2, 3, 3};
|
||||
static const byte _airport_helipad_international[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0,HANGAR,NOTHING_block,2}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER1_block,1}, {0,HELITAKEOFF,HELIPAD1_block,2}, {0,0,0,2},
|
||||
{ 1,HANGAR,NOTHING_block,3}, {1,255,HANGAR2_AREA_block,1}, {1,HELITAKEOFF,HELIPAD2_block,3}, {1,0,0,3},
|
||||
{ 2,255,AIRPORT_ENTRANCE_block,0}, {2,HANGAR,0,0}, {2,TERM4,0,12}, {2,TERM5,0,12}, {2,TERM6,0,12}, {2,HELIPAD1,0,12}, {2,HELIPAD2,0,12}, {2,HELITAKEOFF,0,12}, {2,0,0,23},
|
||||
{ 3,255,HANGAR2_AREA_block,0}, {3,HANGAR,0,1}, {3,0,0,18},
|
||||
{ 4,TERM1,TERM1_block,23}, {4,HANGAR,AIRPORT_ENTRANCE_block,23}, {4,0,0,23},
|
||||
{ 5,TERM2,TERM2_block,24}, {5,HANGAR,AIRPORT_ENTRANCE_block,24}, {5,0,0,24},
|
||||
{ 6,TERM3,TERM3_block,25}, {6,HANGAR,AIRPORT_ENTRANCE_block,25}, {6,0,0,25},
|
||||
{ 7,TERM4,TERM4_block,16}, {7,HANGAR,HANGAR2_AREA_block,16}, {7,0,0,16},
|
||||
{ 8,TERM5,TERM5_block,17}, {8,HANGAR,HANGAR2_AREA_block,17}, {8,0,0,17},
|
||||
{ 9,TERM6,TERM6_block,18}, {9,HANGAR,HANGAR2_AREA_block,18}, {9,0,0,18},
|
||||
{10,HELIPAD1,HELIPAD1_block,10}, {10,HANGAR,HANGAR2_AREA_block,16}, {10,HELITAKEOFF,0,47},
|
||||
{11,HELIPAD2,HELIPAD2_block,11}, {11,HANGAR,HANGAR2_AREA_block,17}, {11,HELITAKEOFF,0,48},
|
||||
{12,0,TERM_GROUP2_ENTER1_block,13},
|
||||
{13,0,TERM_GROUP2_ENTER1_block,14},
|
||||
{14,0,TERM_GROUP2_ENTER2_block,15},
|
||||
{15,0,TERM_GROUP2_ENTER2_block,16},
|
||||
{16,255,TERM_GROUP2_block,0}, {16,TERM4,TERM4_block,7}, {16,HELIPAD1,HELIPAD1_block,10}, {16,HELITAKEOFF,HELIPAD1_block,10}, {16,0,0,17},
|
||||
{17,255,TERM_GROUP2_block,0}, {17,TERM5,TERM5_block,8}, {17,TERM4,0,16}, {17,HELIPAD1,0,16}, {17,HELIPAD2,HELIPAD2_block,11}, {17,HELITAKEOFF,HELIPAD2_block,11}, {17,0,0,18},
|
||||
{18,255,TERM_GROUP2_block,0}, {18,TERM6,TERM6_block,9}, {18,TAKEOFF,0,19}, {18,HANGAR,HANGAR2_AREA_block,3}, {18,0,0,17},
|
||||
{19,0,TERM_GROUP2_EXIT1_block,20},
|
||||
{20,0,TERM_GROUP2_EXIT1_block,21},
|
||||
{21,0,TERM_GROUP2_EXIT2_block,22},
|
||||
{22,0,TERM_GROUP2_EXIT2_block,26},
|
||||
{23,255,TERM_GROUP1_block,0}, {23,TERM1,TERM1_block,4}, {23,HANGAR,AIRPORT_ENTRANCE_block,2}, {23,0,0,24},
|
||||
{24,255,TERM_GROUP1_block,0}, {24,TERM2,TERM2_block,5}, {24,TERM1,0,23}, {24,HANGAR,0,23}, {24,0,0,25},
|
||||
{25,255,TERM_GROUP1_block,0}, {25,TERM3,TERM3_block,6}, {25,TAKEOFF,0,26}, {25,0,0,24},
|
||||
{26,255,TAXIWAY_BUSY_block,0}, {26,TAKEOFF,0,27}, {26,0,0,25},
|
||||
{27,0,OUT_WAY_block,28},
|
||||
// takeoff
|
||||
{28,TAKEOFF,OUT_WAY_block,29},
|
||||
{29,0,RUNWAY_OUT_block,30},
|
||||
{30,STARTTAKEOFF,NOTHING_block,31},
|
||||
{31,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{32,FLYING,NOTHING_block,37}, {32,LANDING,0,33}, {32,HELILANDING,0,41},
|
||||
{33,LANDING,RUNWAY_IN_block,34},
|
||||
{34,0,RUNWAY_IN_block,35},
|
||||
{35,0,RUNWAY_IN_block,36},
|
||||
{36,ENDLANDING,IN_WAY_block,36}, {36,255,TERM_GROUP1_block,0}, {36,255,TERM_GROUP2_ENTER1_block,1}, {36,TERM4,0,12}, {36,TERM5,0,12}, {36,TERM6,0,12}, {36,0,0,2},
|
||||
// In Air
|
||||
{37,0,NOTHING_block,38},
|
||||
{38,0,NOTHING_block,39},
|
||||
{39,0,NOTHING_block,40},
|
||||
{40,0,NOTHING_block,32},
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{41,HELILANDING,PRE_HELIPAD_block,42},
|
||||
{42,HELIENDLANDING,PRE_HELIPAD_block,42}, {42,HELIPAD1,0,43}, {42,HELIPAD2,0,44}, {42,HANGAR,0,49},
|
||||
{43,0,NOTHING_block,45},
|
||||
{44,0,NOTHING_block,46},
|
||||
// landing
|
||||
{45,255,NOTHING_block,0}, {45,HELIPAD1,HELIPAD1_block,10},
|
||||
{46,255,NOTHING_block,0}, {46,HELIPAD2,HELIPAD2_block,11},
|
||||
// Helicopter -- takeoff
|
||||
{47,HELITAKEOFF,NOTHING_block,0},
|
||||
{48,HELITAKEOFF,NOTHING_block,0},
|
||||
{49,0,HANGAR2_AREA_block,50}, // need to go to hangar when waiting in air
|
||||
{50,0,HANGAR2_AREA_block,3},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = {1, 1};
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{0,HELIPAD1,HELIPAD1_block,1},
|
||||
{1,HELITAKEOFF,NOTHING_block,0}, // takeoff
|
||||
{2,255,AIRPORT_BUSY_block,0}, {2,HELILANDING,0,3}, {2,HELITAKEOFF,0,1},
|
||||
{3,HELILANDING,AIRPORT_BUSY_block,4},
|
||||
{4,HELIENDLANDING,AIRPORT_BUSY_block,4}, {4,HELIPAD1,HELIPAD1_block,0}, {4,HELITAKEOFF,0,2},
|
||||
// In Air
|
||||
{5,0,NOTHING_block,6},
|
||||
{6,0,NOTHING_block,7},
|
||||
{7,0,NOTHING_block,8},
|
||||
{8,FLYING,NOTHING_block,5}, {8,HELILANDING,HELIPAD1_block,2}, // landing
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
#endif /* AIRPORT_MOVEMENT_H */
|
@@ -1,7 +1,3 @@
|
||||
/* $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,119 +15,111 @@
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ttd.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, AyStarNode *node)
|
||||
{
|
||||
return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
/* This adds a node to the ClosedList
|
||||
* It makes a copy of the data */
|
||||
static void AyStarMain_ClosedList_Add(AyStar *aystar, const PathNode *node)
|
||||
// This adds a node to the ClosedList
|
||||
// It makes a copy of the data
|
||||
static void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node)
|
||||
{
|
||||
/* Add a node to the ClosedList */
|
||||
PathNode *new_node = MallocT<PathNode>(1);
|
||||
// Add a node to the ClosedList
|
||||
PathNode *new_node = malloc(sizeof(PathNode));
|
||||
*new_node = *node;
|
||||
Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
|
||||
}
|
||||
|
||||
/* Checks if a node is in the OpenList
|
||||
* If so, it returns the OpenListNode, else NULL */
|
||||
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, const AyStarNode *node)
|
||||
// Checks if a node is in the OpenList
|
||||
// If so, it returns the OpenListNode, else NULL
|
||||
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
|
||||
}
|
||||
|
||||
/* Gets the best node from OpenList
|
||||
* returns the best node, or NULL of none is found
|
||||
* Also it deletes the node from the OpenList */
|
||||
// Gets the best node from OpenList
|
||||
// returns the best node, or NULL of none is found
|
||||
// Also it deletes the node from the OpenList
|
||||
static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
|
||||
{
|
||||
/* Return the item the Queue returns.. the best next OpenList item. */
|
||||
OpenListNode *res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
|
||||
if (res != NULL) {
|
||||
// Return the item the Queue returns.. the best next OpenList item.
|
||||
OpenListNode* res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
|
||||
if (res != NULL)
|
||||
Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Adds a node to the OpenList
|
||||
* It makes a copy of node, and puts the pointer of parent in the struct */
|
||||
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, const AyStarNode *node, int f, int g)
|
||||
// Adds a node to the OpenList
|
||||
// It makes a copy of node, and puts the pointer of parent in the struct
|
||||
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g)
|
||||
{
|
||||
/* Add a new Node to the OpenList */
|
||||
OpenListNode *new_node = MallocT<OpenListNode>(1);
|
||||
// Add a new Node to the OpenList
|
||||
OpenListNode* new_node = malloc(sizeof(OpenListNode));
|
||||
new_node->g = g;
|
||||
new_node->path.parent = parent;
|
||||
new_node->path.node = *node;
|
||||
Hash_Set(&aystar->OpenListHash, node->tile, node->direction, new_node);
|
||||
|
||||
/* Add it to the queue */
|
||||
// Add it to the queue
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks one tile and calculate his f-value
|
||||
* return values:
|
||||
* AYSTAR_DONE : indicates we are done
|
||||
* AYSTAR_DONE : indicates we are done
|
||||
*/
|
||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
|
||||
int new_f, new_g, new_h;
|
||||
PathNode *closedlist_parent;
|
||||
OpenListNode *check;
|
||||
|
||||
/* Check the new node against the ClosedList */
|
||||
// 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 = AyStarMain_OpenList_IsInList(aystar, current);
|
||||
if (check != NULL) {
|
||||
// Check if this item is already in the OpenList
|
||||
if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
|
||||
uint i;
|
||||
/* Yes, check if this g value is lower.. */
|
||||
// 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++) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -142,23 +130,22 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
* This function is the core of AyStar. It handles one item and checks
|
||||
* his neighbour items. If they are valid, they are added to be checked too.
|
||||
* return values:
|
||||
* AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
|
||||
* has been found.
|
||||
* AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
|
||||
* reached.
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
|
||||
* AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
|
||||
* has been found.
|
||||
* AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
|
||||
* reached.
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
|
||||
*/
|
||||
int AyStarMain_Loop(AyStar *aystar)
|
||||
{
|
||||
int 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,35 +153,33 @@ 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 */
|
||||
for (i = 0; i < aystar->num_neighbours; i++) {
|
||||
/* Check and add them to the OpenList if needed */
|
||||
// Go through all neighbours
|
||||
for (i=0;i<aystar->num_neighbours;i++) {
|
||||
// Check and add them to the OpenList if needed
|
||||
r = aystar->checktile(aystar, &aystar->neighbours[i], current);
|
||||
}
|
||||
|
||||
/* Free the node */
|
||||
// Free the node
|
||||
free(current);
|
||||
|
||||
if (aystar->max_search_nodes != 0 && Hash_Size(&aystar->ClosedListHash) >= aystar->max_search_nodes) {
|
||||
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 */
|
||||
else
|
||||
// Return that we are still busy
|
||||
return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function frees the memory it allocated
|
||||
*/
|
||||
void AyStarMain_Free(AyStar *aystar)
|
||||
{
|
||||
void AyStarMain_Free(AyStar *aystar) {
|
||||
aystar->OpenListQueue.free(&aystar->OpenListQueue, false);
|
||||
/* 2nd argument above is false, below is true, to free the values only
|
||||
* once */
|
||||
@@ -209,12 +194,11 @@ void AyStarMain_Free(AyStar *aystar)
|
||||
* This function make the memory go back to zero
|
||||
* This function should be called when you are using the same instance again.
|
||||
*/
|
||||
void AyStarMain_Clear(AyStar *aystar)
|
||||
{
|
||||
/* Clean the Queue, but not the elements within. That will be done by
|
||||
* the hash. */
|
||||
void AyStarMain_Clear(AyStar *aystar) {
|
||||
// Clean the Queue, but not the elements within. That will be done by
|
||||
// the hash.
|
||||
aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
|
||||
/* Clean the hashes */
|
||||
// Clean the hashes
|
||||
clear_Hash(&aystar->OpenListHash, true);
|
||||
clear_Hash(&aystar->ClosedListHash, true);
|
||||
|
||||
@@ -226,39 +210,37 @@ void AyStarMain_Clear(AyStar *aystar)
|
||||
/*
|
||||
* This is the function you call to run AyStar.
|
||||
* return values:
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found an end node.
|
||||
* AYSTAR_NO_PATH : indicates that there was no path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
|
||||
* AYSTAR_FOUND_END_NODE : indicates we found an end node.
|
||||
* AYSTAR_NO_PATH : indicates that there was no path found.
|
||||
* AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
|
||||
* When the algorithm is done (when the return value is not AYSTAR_STILL_BUSY)
|
||||
* aystar->clear() is called. Note that when you stop the algorithm halfway,
|
||||
* you should still call clear() yourself!
|
||||
*/
|
||||
int AyStarMain_Main(AyStar *aystar) {
|
||||
int r, i = 0;
|
||||
/* Loop through the OpenList
|
||||
* Quit if result is no AYSTAR_STILL_BUSY or is more than loops_per_tick */
|
||||
// Loop through the OpenList
|
||||
// Quit if result is no AYSTAR_STILL_BUSY or is more than loops_per_tick
|
||||
while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
|
||||
#ifdef AYSTAR_DEBUG
|
||||
switch (r) {
|
||||
case AYSTAR_FOUND_END_NODE: printf("[AyStar] Found path!\n"); break;
|
||||
case AYSTAR_EMPTY_OPENLIST: printf("[AyStar] OpenList run dry, no path found\n"); break;
|
||||
case AYSTAR_LIMIT_REACHED: printf("[AyStar] Exceeded search_nodes, no path found\n"); break;
|
||||
default: break;
|
||||
}
|
||||
if (r == AYSTAR_FOUND_END_NODE)
|
||||
printf("[AyStar] Found path!\n");
|
||||
else if (r == AYSTAR_EMPTY_OPENLIST)
|
||||
printf("[AyStar] OpenList run dry, no path found\n");
|
||||
else if (r == AYSTAR_LIMIT_REACHED)
|
||||
printf("[AyStar] Exceeded search_nodes, no path found\n");
|
||||
#endif
|
||||
if (r != AYSTAR_STILL_BUSY) {
|
||||
if (r != AYSTAR_STILL_BUSY)
|
||||
/* We're done, clean up */
|
||||
_aystar_stats_open_size = aystar->OpenListHash.size;
|
||||
_aystar_stats_closed_size = aystar->ClosedListHash.size;
|
||||
aystar->clear(aystar);
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case AYSTAR_FOUND_END_NODE: return AYSTAR_FOUND_END_NODE;
|
||||
case AYSTAR_EMPTY_OPENLIST:
|
||||
case AYSTAR_LIMIT_REACHED: return AYSTAR_NO_PATH;
|
||||
default: return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
// Check result-value
|
||||
if (r == AYSTAR_FOUND_END_NODE) return AYSTAR_FOUND_END_NODE;
|
||||
// Check if we have some left in the OpenList
|
||||
if (r == AYSTAR_EMPTY_OPENLIST || r == AYSTAR_LIMIT_REACHED) return AYSTAR_NO_PATH;
|
||||
|
||||
// Return we are still busy
|
||||
return AYSTAR_STILL_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -268,8 +250,7 @@ int AyStarMain_Main(AyStar *aystar) {
|
||||
* clear() automatically when the algorithm finishes
|
||||
* g is the cost for starting with this node.
|
||||
*/
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g)
|
||||
{
|
||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g) {
|
||||
#ifdef AYSTAR_DEBUG
|
||||
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
|
||||
TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
|
||||
@@ -277,22 +258,21 @@ void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g)
|
||||
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
|
||||
}
|
||||
|
||||
void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets)
|
||||
{
|
||||
/* Allocated the Hash for the OpenList and ClosedList */
|
||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
|
||||
// Allocated the Hash for the OpenList and ClosedList
|
||||
init_Hash(&aystar->OpenListHash, hash, num_buckets);
|
||||
init_Hash(&aystar->ClosedListHash, hash, num_buckets);
|
||||
|
||||
/* Set up our sorting queue
|
||||
* BinaryHeap allocates a block of 1024 nodes
|
||||
* When thatone gets full it reserves an otherone, till this number
|
||||
* That is why it can stay this high */
|
||||
// Set up our sorting queue
|
||||
// BinaryHeap allocates a block of 1024 nodes
|
||||
// When thatone gets full it reserves an otherone, till this number
|
||||
// That is why it can stay this high
|
||||
init_BinaryHeap(&aystar->OpenListQueue, 102400);
|
||||
|
||||
aystar->addstart = AyStarMain_AddStartNode;
|
||||
aystar->main = AyStarMain_Main;
|
||||
aystar->loop = AyStarMain_Loop;
|
||||
aystar->free = AyStarMain_Free;
|
||||
aystar->clear = AyStarMain_Clear;
|
||||
aystar->checktile = AyStarMain_CheckTile;
|
||||
aystar->addstart = AyStarMain_AddStartNode;
|
||||
aystar->main = AyStarMain_Main;
|
||||
aystar->loop = AyStarMain_Loop;
|
||||
aystar->free = AyStarMain_Free;
|
||||
aystar->clear = AyStarMain_Clear;
|
||||
aystar->checktile = AyStarMain_CheckTile;
|
||||
}
|
@@ -1,19 +1,15 @@
|
||||
/* $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.
|
||||
* For more information about AyStar (A* Algorithm), you can look at
|
||||
* http://en.wikipedia.org/wiki/A-star_search_algorithm
|
||||
* http://en.wikipedia.org/wiki/A-star_search_algorithm
|
||||
*/
|
||||
|
||||
#ifndef AYSTAR_H
|
||||
#define AYSTAR_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "tile_type.h"
|
||||
#include "track_type.h"
|
||||
|
||||
//#define AYSTAR_DEBUG
|
||||
enum {
|
||||
@@ -29,33 +25,36 @@ enum{
|
||||
AYSTAR_INVALID_NODE = -1,
|
||||
};
|
||||
|
||||
typedef struct AyStarNode AyStarNode;
|
||||
struct AyStarNode {
|
||||
TileIndex tile;
|
||||
Trackdir direction;
|
||||
uint tile;
|
||||
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:
|
||||
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
|
||||
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
|
||||
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
|
||||
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
|
||||
*/
|
||||
/*
|
||||
* The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is
|
||||
@@ -70,8 +69,8 @@ typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current);
|
||||
/*
|
||||
* This function is called to calculate the G-value for AyStar Algorithm.
|
||||
* return values can be:
|
||||
* AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable)
|
||||
* Any value >= 0 : the g-value for this tile
|
||||
* AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable)
|
||||
* Any value >= 0 : the g-value for this tile
|
||||
*/
|
||||
typedef int32 AyStar_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
|
||||
@@ -80,7 +79,7 @@ typedef int32 AyStar_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNod
|
||||
* Mostly, this must result the distance (Manhattan way) between the
|
||||
* current point and the end point
|
||||
* return values can be:
|
||||
* Any value >= 0 : the h-value for this tile
|
||||
* Any value >= 0 : the h-value for this tile
|
||||
*/
|
||||
typedef int32 AyStar_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
|
||||
@@ -97,8 +96,8 @@ typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
*/
|
||||
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
/* For internal use, see aystar.cpp */
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
|
||||
// For internal use, see aystar.c
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node, uint g);
|
||||
typedef int AyStar_Main(AyStar *aystar);
|
||||
typedef int AyStar_Loop(AyStar *aystar);
|
||||
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
|
||||
@@ -111,11 +110,11 @@ struct AyStar {
|
||||
|
||||
/* These should point to the application specific routines that do the
|
||||
* actual work */
|
||||
AyStar_CalculateG *CalculateG;
|
||||
AyStar_CalculateH *CalculateH;
|
||||
AyStar_GetNeighbours *GetNeighbours;
|
||||
AyStar_EndNodeCheck *EndNodeCheck;
|
||||
AyStar_FoundEndNode *FoundEndNode;
|
||||
AyStar_CalculateG* CalculateG;
|
||||
AyStar_CalculateH* CalculateH;
|
||||
AyStar_GetNeighbours* GetNeighbours;
|
||||
AyStar_EndNodeCheck* EndNodeCheck;
|
||||
AyStar_FoundEndNode* FoundEndNode;
|
||||
|
||||
/* These are completely untouched by AyStar, they can be accesed by
|
||||
* the application specific routines to input and output data.
|
||||
@@ -143,12 +142,12 @@ struct AyStar {
|
||||
|
||||
/* These will contain the methods for manipulating the AyStar. Only
|
||||
* main() should be called externally */
|
||||
AyStar_AddStartNode *addstart;
|
||||
AyStar_Main *main;
|
||||
AyStar_Loop *loop;
|
||||
AyStar_Free *free;
|
||||
AyStar_Clear *clear;
|
||||
AyStar_CheckTile *checktile;
|
||||
AyStar_AddStartNode* addstart;
|
||||
AyStar_Main* main;
|
||||
AyStar_Loop* loop;
|
||||
AyStar_Free* free;
|
||||
AyStar_Clear* clear;
|
||||
AyStar_CheckTile* checktile;
|
||||
|
||||
/* These will contain the open and closed lists */
|
||||
|
||||
@@ -172,7 +171,7 @@ void AyStarMain_Clear(AyStar *aystar);
|
||||
/* Initialize an AyStar. You should fill all appropriate fields before
|
||||
* callling init_AyStar (see the declaration of AyStar for which fields are
|
||||
* internal */
|
||||
void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets);
|
||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets);
|
||||
|
||||
|
||||
#endif /* AYSTAR_H */
|
||||
#endif
|
@@ -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,4 +0,0 @@
|
||||
echo "Setting dedicated network server settings..."
|
||||
# empty the server password
|
||||
server_pw = "*"
|
||||
server_name = "My example dedicated gameserver"
|
@@ -1,2 +0,0 @@
|
||||
# Show a MOTD
|
||||
say "Welcome..."
|
@@ -1,3 +0,0 @@
|
||||
# set default server port, and have the dedicated server listen on all interfaces
|
||||
server_ip = all
|
||||
server_port = 3979
|
@@ -1,2 +0,0 @@
|
||||
# set the server port to the default value
|
||||
server_port = 3979
|
166
bridge_gui.c
Normal file
166
bridge_gui.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
#include "sound.h"
|
||||
|
||||
static struct BridgeData {
|
||||
int count;
|
||||
TileIndex start_tile;
|
||||
TileIndex end_tile;
|
||||
byte type;
|
||||
byte indexes[MAX_BRIDGES];
|
||||
int32 costs[MAX_BRIDGES];
|
||||
} _bridge;
|
||||
|
||||
extern const uint16 _bridge_type_price_mod[MAX_BRIDGES];
|
||||
|
||||
extern const PalSpriteID _bridge_sprites[MAX_BRIDGES];
|
||||
extern const uint16 _bridge_speeds[MAX_BRIDGES];
|
||||
extern const StringID _bridge_material[MAX_BRIDGES];
|
||||
|
||||
void CcBuildBridge(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
|
||||
}
|
||||
|
||||
static void BuildBridge(Window *w, int i)
|
||||
{
|
||||
DeleteWindow(w);
|
||||
DoCommandP(_bridge.end_tile, _bridge.start_tile, _bridge.indexes[i] | (_bridge.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: {
|
||||
int i;
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
for(i=0; i < 4 && i + w->vscroll.pos < _bridge.count; i++) {
|
||||
int ind = _bridge.indexes[i + w->vscroll.pos];
|
||||
|
||||
SetDParam(2, _bridge.costs[i + w->vscroll.pos]);
|
||||
SetDParam(1, (_bridge_speeds[ind] >> 4) * 10);
|
||||
SetDParam(0, _bridge_material[ind]);
|
||||
DrawSprite(_bridge_sprites[ind], 3, 15 + i * 22);
|
||||
|
||||
DrawString(44, 15 + i*22 , STR_500D, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
uint i = e->keypress.keycode - '1';
|
||||
if (i < 9 && i < (uint)_bridge.count) {
|
||||
e->keypress.cont = false;
|
||||
BuildBridge(w, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget == 2) {
|
||||
uint ind = ((int)e->click.pt.y - 14) / 22;
|
||||
if (ind < 4 && (ind += w->vscroll.pos) < (uint)_bridge.count)
|
||||
BuildBridge(w, ind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
static const Widget _build_road_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_road_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_road_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowBuildBridgeWindow(uint start, uint end, byte bridge_type)
|
||||
{
|
||||
int j = 0;
|
||||
int32 ret;
|
||||
uint16 errmsg;
|
||||
|
||||
DeleteWindowById(WC_BUILD_BRIDGE, 0);
|
||||
|
||||
_bridge.type = bridge_type;
|
||||
_bridge.start_tile = start;
|
||||
_bridge.end_tile = end;
|
||||
|
||||
errmsg = 0xFFFF;
|
||||
|
||||
// only query bridge building possibility once, result is the same for all bridges!
|
||||
// returns CMD_ERROR on failure, and priCe on success
|
||||
ret = DoCommandByTile(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
|
||||
|
||||
if (ret == CMD_ERROR) {
|
||||
errmsg = _error_message;
|
||||
}
|
||||
// check which bridges can be built
|
||||
else {
|
||||
int bridge_len; // length of the middle parts of the bridge
|
||||
int tot_bridge_len; // total length of bridge
|
||||
|
||||
// get absolute bridge length
|
||||
bridge_len = GetBridgeLength(start, end);
|
||||
tot_bridge_len = bridge_len + 2;
|
||||
|
||||
tot_bridge_len = CalcBridgeLenCostFactor(tot_bridge_len);
|
||||
|
||||
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
|
||||
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
// bridge is accepted, add to list
|
||||
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
|
||||
_bridge.costs[j] = ret + (((int64)tot_bridge_len * _price.build_bridge * _bridge_type_price_mod[bridge_type]) >> 8);
|
||||
_bridge.indexes[j] = bridge_type;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bridge.count = j;
|
||||
|
||||
if (j != 0) {
|
||||
Window *w = AllocateWindowDesc((_bridge.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
|
||||
w->vscroll.cap = 4;
|
||||
w->vscroll.count = (byte)j;
|
||||
} else {
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
|
||||
}
|
||||
}
|
@@ -1,62 +1,52 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.cpp All command callbacks. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "callback_table.h"
|
||||
#include "command_type.h"
|
||||
#include "ttd.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;
|
||||
|
||||
/* 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 */
|
||||
CommandCallback CcCloneVehicle;
|
||||
|
||||
/* main_gui.cpp */
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
//CommandCallback CcDemolish;
|
||||
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;
|
||||
|
||||
/* ship_gui.cpp */
|
||||
/* ship_gui.c */
|
||||
CommandCallback CcBuildShip;
|
||||
|
||||
/* train_gui.cpp */
|
||||
/* train_gui.c */
|
||||
CommandCallback CcBuildWagon;
|
||||
CommandCallback CcBuildLoco;
|
||||
|
||||
/* ai/ai_core.cpp */
|
||||
CommandCallback CcAI;
|
||||
|
||||
CommandCallback *_callback_table[] = {
|
||||
/* 0x00 */ NULL,
|
||||
/* 0x01 */ CcBuildAircraft,
|
||||
@@ -78,10 +68,7 @@ CommandCallback *_callback_table[] = {
|
||||
/* 0x11 */ CcPlaySound1D,
|
||||
/* 0x12 */ CcPlaySound1E,
|
||||
/* 0x13 */ CcStation,
|
||||
/* 0x14 */ CcTerraform,
|
||||
/* 0x15 */ CcAI,
|
||||
/* 0x16 */ CcCloneVehicle,
|
||||
/* 0x17 */ CcGiveMoney,
|
||||
/* 0x14 */ CcTerraform
|
||||
};
|
||||
|
||||
const int _callback_table_count = lengthof(_callback_table);
|
@@ -1,13 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.h Table with all command callbacks. */
|
||||
|
||||
#ifndef CALLBACK_TABLE_H
|
||||
#define CALLBACK_TABLE_H
|
||||
|
||||
#include "command_type.h"
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
|
||||
#endif /* CALLBACK_TABLE_H */
|
||||
#endif
|
1689
changelog.txt
1689
changelog.txt
File diff suppressed because it is too large
Load Diff
864
clear_cmd.c
Normal file
864
clear_cmd.c
Normal file
@@ -0,0 +1,864 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.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+TILE_XY(0,-1));
|
||||
TerraformAddDirtyTile(ts, tile+TILE_XY(-1,-1));
|
||||
TerraformAddDirtyTile(ts, tile+TILE_XY(-1,0));
|
||||
TerraformAddDirtyTile(ts, tile);
|
||||
}
|
||||
|
||||
static int TerraformProc(TerraformerState *ts, uint tile, int mode)
|
||||
{
|
||||
int r;
|
||||
int32 ret;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
|
||||
return r;
|
||||
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
static const byte _railway_modes[4] = {8, 0x10, 4, 0x20};
|
||||
static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb};
|
||||
static const byte _railway_dangslopes2[4] = {0x2, 0x1, 0x8, 0x4};
|
||||
|
||||
// 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.
|
||||
int tileh = GetTileSlope(tile, NULL) & 0xF;
|
||||
if (tileh == _railway_dangslopes[mode] ||
|
||||
tileh == _railway_dangslopes2[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 ((_map5[tile]&~0x40) == _railway_modes[mode])
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = DoCommandByTile(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
if (ret == CMD_ERROR) {
|
||||
_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, uint 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 > 0xF)
|
||||
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 + TILE_XY(0,-1), 1)<0)
|
||||
return false;
|
||||
|
||||
if (TerraformProc(ts, tile + TILE_XY(-1,-1), 2)<0)
|
||||
return false;
|
||||
|
||||
if (TerraformProc(ts, tile + TILE_XY(-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 == (TileIndex)tile)
|
||||
break;
|
||||
mod++;
|
||||
count--;
|
||||
}
|
||||
|
||||
mod->tile = (TileIndex)tile;
|
||||
mod->height = (byte)height;
|
||||
|
||||
ts->cost += _price.terraform;
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for(ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
if (!TerraformTileHeight(ts, tile, r+direction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Terraform land
|
||||
* @param x,y coordinates to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
TileIndex tile;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
TileIndex tile_table_data[625];
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_error_message = INVALID_STRING_ID;
|
||||
_terraform_err_tile = 0;
|
||||
|
||||
ts.direction = direction = p2 ? 1 : -1;
|
||||
ts.flags = flags;
|
||||
ts.modheight_count = ts.tile_table_count = 0;
|
||||
ts.cost = 0;
|
||||
ts.modheight = modheight_data;
|
||||
ts.tile_table = tile_table_data;
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
|
||||
if (p1 & 1) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,0),
|
||||
TileHeight(tile + TILE_XY(1, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,1),
|
||||
TileHeight(tile + TILE_XY(1, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,1),
|
||||
TileHeight(tile + TILE_XY(0, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,0),
|
||||
TileHeight(tile + TILE_XY(0, 0)) + 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;
|
||||
uint tile = *ti;
|
||||
|
||||
z = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,0));
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,0));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,1));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,1));
|
||||
if (t <= z) z = t;
|
||||
|
||||
if (!CheckTunnelInWay(tile, z*8))
|
||||
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++) {
|
||||
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* change the height */
|
||||
{
|
||||
int count;
|
||||
TerraformerHeightMod *mod;
|
||||
uint til;
|
||||
|
||||
mod = ts.modheight;
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
til = mod->tile;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally mark the dirty tiles dirty */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ts.cost;
|
||||
}
|
||||
|
||||
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param x,y end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
TileIndex tile;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = TileHeight(p1);
|
||||
|
||||
ex >>= 4; ey >>= 4;
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TILE_XY(sx,sy);
|
||||
|
||||
size_x = ex-sx+1;
|
||||
size_y = ey-sy+1;
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IsTileType(tile, MP_UNMOVABLE) && _map5[tile] == 3 && _map_owner[tile] == _current_player)
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
|
||||
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
ModifyTile(tile,
|
||||
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
||||
3 /* map5 */
|
||||
);
|
||||
}
|
||||
|
||||
return cost + _price.purchase_land * 10;
|
||||
}
|
||||
|
||||
|
||||
static int32 ClearTile_Clear(uint tile, byte flags)
|
||||
{
|
||||
static const int32 * _clear_price_table[] = {
|
||||
NULL,
|
||||
&_price.clear_1, &_price.clear_1,&_price.clear_1,
|
||||
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
|
||||
&_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2,
|
||||
&_price.clear_3,&_price.clear_3,&_price.clear_3,&_price.clear_3,
|
||||
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
|
||||
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
|
||||
&_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2,
|
||||
};
|
||||
const int32 *price = _clear_price_table[_map5[tile] & 0x1F];
|
||||
|
||||
if (flags & DC_EXEC)
|
||||
DoClearSquare(tile);
|
||||
|
||||
if (price == NULL)
|
||||
return 0;
|
||||
return *price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
|
||||
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(TileInfo *ti, byte set)
|
||||
{
|
||||
DrawGroundSprite(0xF54 + _tileh_to_sprite[ti->tileh] + set * 19);
|
||||
}
|
||||
|
||||
void DrawHillyLandTile(TileInfo *ti)
|
||||
{
|
||||
if (ti->tileh != 0) {
|
||||
DrawGroundSprite(0xFA0 + _tileh_to_sprite[ti->tileh]);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites[((ti->x^ti->y) >> 4) & 0x7]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawClearLandFence(TileInfo *ti, byte img)
|
||||
{
|
||||
byte z = ti->z;
|
||||
|
||||
if (ti->tileh & 2) {
|
||||
z += 8;
|
||||
if (ti->tileh == 0x17)
|
||||
z += 8;
|
||||
}
|
||||
|
||||
if (img & 0x38) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[((img >> 3) & 7) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
|
||||
if (img & 0x7) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[(img & 7) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawTile_Clear(TileInfo *ti)
|
||||
{
|
||||
|
||||
switch((ti->map5 & (7<<2)) >> 2) {
|
||||
case 0:
|
||||
DrawClearLandTile(ti, (ti->map5 & 3));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
DrawHillyLandTile(ti);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DrawGroundSprite(0xFB7 + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
DrawGroundSprite( _clear_land_sprites_1[_map3_lo[ti->tile]&0xF] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DrawGroundSprite( _clear_land_sprites_2[ti->map5&3] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
DrawGroundSprite( _clear_land_sprites_3[ti->map5&3] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawClearLandFence(ti, _map3_hi[ti->tile] >> 2);
|
||||
}
|
||||
|
||||
static uint GetSlopeZ_Clear(TileInfo *ti)
|
||||
{
|
||||
return GetPartialZ(ti->x & 0xF, ti->y & 0xF, ti->tileh) + ti->z;
|
||||
}
|
||||
|
||||
static uint GetSlopeTileh_Clear(TileInfo *ti)
|
||||
{
|
||||
return ti->tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(uint tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static void AnimateTile_Clear(uint tile)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte img_1;
|
||||
byte img_2;
|
||||
static const byte img_by_map5[] = { 0, 0, 0, 2, 1, 1, 0, 0 };
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_CLEAR:
|
||||
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[tile] & 0x30) == 0x20)
|
||||
img_1 = 1;
|
||||
else
|
||||
img_1 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
|
||||
case MP_CLEAR:
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20)
|
||||
img_2 = 1;
|
||||
else
|
||||
img_2 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((_map3_hi[tile] & 0xE0) == 0) {
|
||||
if ((img_1 & 2) != (img_2 & 2)) {
|
||||
_map3_hi[tile] |= 3 << 5;
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (img_1 == 1 && img_2 == 1) {
|
||||
_map3_hi[tile] &= ~(3 << 5);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
|
||||
case MP_CLEAR:
|
||||
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
|
||||
break;
|
||||
|
||||
case MP_TREES:
|
||||
if ((_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20)
|
||||
img_2 = 1;
|
||||
else
|
||||
img_2 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
img_2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((_map3_hi[tile] & 0x1C) == 0) {
|
||||
if ((img_1 & 2) != (img_2 & 2)) {
|
||||
_map3_hi[tile] |= 3 << 2;
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (img_1 == 1 && img_2 == 1) {
|
||||
_map3_hi[tile] &= ~(3 << 2);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != INVALID_TILE)
|
||||
MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
|
||||
/* convert into snowy tiles */
|
||||
static void TileLoopClearAlps(uint tile)
|
||||
{
|
||||
int k;
|
||||
byte m5,tmp;
|
||||
|
||||
/* distance from snow line, in steps of 8 */
|
||||
k = GetTileZ(tile) - _opt.snow_line;
|
||||
|
||||
m5 = _map5[tile] & 0x1C;
|
||||
tmp = _map5[tile] & 3;
|
||||
|
||||
if (k < -8) {
|
||||
/* snow_m2_down */
|
||||
if (m5 != 0x10)
|
||||
return;
|
||||
if (tmp == 0)
|
||||
m5 = 3;
|
||||
} else if (k == -8) {
|
||||
/* snow_m1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 0) {
|
||||
m5 = (tmp - 1) + 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k < 8) {
|
||||
/* snow_0 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 1) {
|
||||
m5 = 1;
|
||||
if (tmp != 0)
|
||||
m5 = tmp - 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k == 8) {
|
||||
/* snow_p1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 2) {
|
||||
m5 = 2;
|
||||
if (tmp <= 2)
|
||||
m5 = tmp + 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else {
|
||||
/* snow_p2_up */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 3) {
|
||||
m5 = tmp + 1 + 0x10;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
_map5[tile] = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoopClearDesert(uint tile)
|
||||
{
|
||||
if ( (_map5[tile] & 0x1C) == 0x14)
|
||||
return;
|
||||
|
||||
if (GetMapExtraBits(tile) == 1) {
|
||||
_map5[tile] = 0x17;
|
||||
} else {
|
||||
if (GetMapExtraBits(tile+TILE_XY(1,0)) != 1 &&
|
||||
GetMapExtraBits(tile+TILE_XY(-1,0)) != 1 &&
|
||||
GetMapExtraBits(tile+TILE_XY(0,1)) != 1 &&
|
||||
GetMapExtraBits(tile+TILE_XY(0,-1)) != 1)
|
||||
return;
|
||||
_map5[tile] = 0x15;
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoop_Clear(uint tile)
|
||||
{
|
||||
byte m5,m3;
|
||||
|
||||
TileLoopClearHelper(tile);
|
||||
|
||||
if (_opt.landscape == LT_DESERT) {
|
||||
TileLoopClearDesert(tile);
|
||||
} else if (_opt.landscape == LT_HILLY) {
|
||||
TileLoopClearAlps(tile);
|
||||
}
|
||||
|
||||
m5 = _map5[tile];
|
||||
if ( (m5 & 0x1C) == 0x10 || (m5 & 0x1C) == 0x14)
|
||||
return;
|
||||
|
||||
if ( (m5 & 0x1C) != 0xC) {
|
||||
if ( (m5 & 3) == 3)
|
||||
return;
|
||||
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_map5[tile] = m5;
|
||||
return;
|
||||
}
|
||||
/* did overflow, so continue */
|
||||
} else {
|
||||
m5 = ((byte)Random() > 21) ? (2) : (6);
|
||||
}
|
||||
m5++;
|
||||
} else if (_game_mode != GM_EDITOR) {
|
||||
/* handle farm field */
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_map5[tile] = m5;
|
||||
return;
|
||||
}
|
||||
/* overflowed */
|
||||
m3 = _map3_lo[tile] + 1;
|
||||
assert( (m3 & 0xF) != 0);
|
||||
if ( (m3 & 0xF) >= 9) /* NOTE: will not work properly if m3&0xF == 0xF */
|
||||
m3 &= ~0xF;
|
||||
_map3_lo[tile] = m3;
|
||||
}
|
||||
|
||||
_map5[tile] = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
int i,j;
|
||||
uint tile,tile_new;
|
||||
uint32 r;
|
||||
|
||||
/* add hills */
|
||||
i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
|
||||
do {
|
||||
tile = TILE_MASK(Random());
|
||||
if (IsTileType(tile, MP_CLEAR))
|
||||
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (1<<2));
|
||||
} while (--i);
|
||||
|
||||
/* add grey squares */
|
||||
i = ScaleByMapSize((Random() & 0x7F) + 0x80);
|
||||
do {
|
||||
r = Random();
|
||||
tile = TILE_MASK(r);
|
||||
if (IsTileType(tile, MP_CLEAR)) {
|
||||
j = ((r >> 16) & 0xF) + 5;
|
||||
for(;;) {
|
||||
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (2<<2));
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + TileOffsByDir(Random() & 3);
|
||||
} while (!IsTileType(tile_new, MP_CLEAR));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
static void ClickTile_Clear(uint tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Clear(uint tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const StringID _clear_land_str[4+8-1] = {
|
||||
STR_080B_ROUGH_LAND,
|
||||
STR_080A_ROCKS,
|
||||
STR_080E_FIELDS,
|
||||
STR_080F_SNOW_COVERED_LAND,
|
||||
STR_0810_DESERT,
|
||||
0,
|
||||
0,
|
||||
STR_080C_BARE_LAND,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
};
|
||||
|
||||
static void GetTileDesc_Clear(uint tile, TileDesc *td)
|
||||
{
|
||||
int i = (_map5[tile]>>2) & 7;
|
||||
if (i == 0)
|
||||
i = (_map5[tile] & 3) + 8;
|
||||
td->str = _clear_land_str[i - 1];
|
||||
td->owner = _map_owner[tile];
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Clear(uint tile, byte old_player, byte new_player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * 8;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, /* draw_tile_proc */
|
||||
GetSlopeZ_Clear, /* get_slope_z_proc */
|
||||
ClearTile_Clear, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Clear, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
|
||||
ClickTile_Clear, /* click_tile_proc */
|
||||
AnimateTile_Clear, /* animate_tile_proc */
|
||||
TileLoop_Clear, /* tile_loop_clear */
|
||||
ChangeTileOwner_Clear, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
NULL, /* vehicle_leave_tile_proc */
|
||||
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
|
||||
};
|
536
command.c
Normal file
536
command.c
Normal file
@@ -0,0 +1,536 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "map.h"
|
||||
#include "gui.h"
|
||||
#include "command.h"
|
||||
#include "player.h"
|
||||
#include "network.h"
|
||||
|
||||
const char* _cmd_text = NULL;
|
||||
|
||||
#define DEF_COMMAND(yyyy) int32 yyyy(int x, int y, 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(CmdChangeTrainServiceInt);
|
||||
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(CmdChangeAircraftServiceInt);
|
||||
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(CmdChangeRoadVehServiceInt);
|
||||
|
||||
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(CmdChangeShipServiceInt);
|
||||
DEF_COMMAND(CmdRefitShip);
|
||||
|
||||
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(CmdReplaceVehicle);
|
||||
|
||||
/* 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 */
|
||||
|
||||
{CmdChangeTrainServiceInt, 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 */
|
||||
{CmdChangeAircraftServiceInt, 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 */
|
||||
{CmdChangeRoadVehServiceInt, 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 */
|
||||
{CmdChangeShipServiceInt, 0}, /* 90 */
|
||||
{CmdRefitShip, 0}, /* 91 */
|
||||
|
||||
{NULL, 0}, /* 92 */
|
||||
{NULL, 0}, /* 93 */
|
||||
{NULL, 0}, /* 94 */
|
||||
{NULL, 0}, /* 95 */
|
||||
{NULL, 0}, /* 96 */
|
||||
{NULL, 0}, /* 97 */
|
||||
{NULL, 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 */
|
||||
{CmdReplaceVehicle, 0}, /* 115 */
|
||||
};
|
||||
|
||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||
bool IsValidCommand(uint cmd)
|
||||
{
|
||||
cmd = cmd & 0xFF;
|
||||
|
||||
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd].proc == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
|
||||
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
|
||||
}
|
||||
|
||||
|
||||
//extern void _stdcall Sleep(int s);
|
||||
|
||||
int32 DoCommand(int x, int y, 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_FROM_XY(x,y) > MapSize()) {
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
proc = _command_proc_table[procc].proc;
|
||||
|
||||
if (_docommand_recursive == 0) {
|
||||
_error_message = INVALID_STRING_ID;
|
||||
// update last build coord of player
|
||||
if ( (x|y) != 0 && _current_player < MAX_PLAYERS) {
|
||||
DEREF_PLAYER(_current_player)->last_build_coordinate = TILE_FROM_XY(x,y);
|
||||
}
|
||||
}
|
||||
|
||||
_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(x, y, flags&~DC_EXEC, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_docommand_recursive == 1) {
|
||||
if (!(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(x, y, 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);
|
||||
}
|
||||
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32 GetAvailableMoneyForCommand(void)
|
||||
{
|
||||
PlayerID pid = _current_player;
|
||||
if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
|
||||
return DEREF_PLAYER(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;
|
||||
|
||||
int x = TileX(tile) * 16;
|
||||
int y = TileY(tile) * 16;
|
||||
|
||||
/* Do not even think about executing out-of-bounds tile-commands */
|
||||
if (tile > MapSize()) {
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(_docommand_recursive == 0);
|
||||
|
||||
_error_message = INVALID_STRING_ID;
|
||||
_error_message_2 = cmd >> 16;
|
||||
_additional_cash_required = 0;
|
||||
|
||||
// spectator has no rights.
|
||||
if (_current_player == OWNER_SPECTATOR) {
|
||||
ShowErrorMessage(_error_message, _error_message_2, 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;
|
||||
|
||||
// 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 (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
|
||||
// estimate the cost.
|
||||
res = proc(x, y, flags, p1, p2);
|
||||
if (CmdFailed(res)) {
|
||||
if (res & 0xFFFF) _error_message = res & 0xFFFF;
|
||||
ShowErrorMessage(_error_message, _error_message_2, 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(x,y, 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 (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
|
||||
NetworkSend_Command(tile, p1, p2, cmd, callback);
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
// update last build coordinate of player.
|
||||
if ( tile != 0 && _current_player < MAX_PLAYERS) DEREF_PLAYER(_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(x,y, 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 (_current_player == _local_player && _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_message_2, 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 (_current_player == _local_player && _error_message_2 != 0)
|
||||
ShowErrorMessage(_error_message, _error_message_2, x,y);
|
||||
|
||||
callb_err:
|
||||
_docommand_recursive = 0;
|
||||
|
||||
if (callback) callback(false, tile, p1, p2);
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
199
command.h
Normal file
199
command.h
Normal file
@@ -0,0 +1,199 @@
|
||||
#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_TRAIN_GOTO_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_TRAIN_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_CHANGE_AIRCRAFT_SERVICE_INT = 63,
|
||||
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_CHANGE_ROADVEH_SERVICE_INT = 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_CHANGE_SHIP_SERVICE_INT = 90,
|
||||
CMD_REFIT_SHIP = 91,
|
||||
|
||||
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_REPLACE_VEHICLE = 115,
|
||||
};
|
||||
|
||||
enum {
|
||||
DC_EXEC = 1,
|
||||
DC_AUTO = 2, // don't allow building on structures
|
||||
DC_QUERY_COST = 4, // query cost only, don't build.
|
||||
DC_NO_WATER = 8, // 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 = 0x200,
|
||||
CMD_NO_WATER = 0x400,
|
||||
CMD_NETWORK_COMMAND = 0x800, // 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 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 */
|
||||
int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
|
||||
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 */
|
2843
config.lib
2843
config.lib
File diff suppressed because it is too large
Load Diff
137
configure
vendored
137
configure
vendored
@@ -1,137 +0,0 @@
|
||||
#!/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"
|
||||
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"
|
||||
|
||||
. $ROOT_DIR/config.lib
|
||||
|
||||
# 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"
|
||||
|
||||
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 $?
|
||||
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
|
File diff suppressed because it is too large
Load Diff
163
console.h
Normal file
163
console.h
Normal file
@@ -0,0 +1,163 @@
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
// maximum length of a typed in command
|
||||
#define ICON_CMDLN_SIZE 255
|
||||
// maximum length of a totally expanded command
|
||||
#define ICON_MAX_STREAMSIZE 1024
|
||||
|
||||
typedef enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_BOOLEAN,
|
||||
ICONSOLE_VAR_BYTE,
|
||||
ICONSOLE_VAR_UINT16,
|
||||
ICONSOLE_VAR_UINT32,
|
||||
ICONSOLE_VAR_INT16,
|
||||
ICONSOLE_VAR_INT32,
|
||||
ICONSOLE_VAR_STRING
|
||||
} IConsoleVarTypes;
|
||||
|
||||
typedef enum IConsoleModes {
|
||||
ICONSOLE_FULL,
|
||||
ICONSOLE_OPENED,
|
||||
ICONSOLE_CLOSED
|
||||
} IConsoleModes;
|
||||
|
||||
typedef enum IConsoleHookTypes {
|
||||
ICONSOLE_HOOK_ACCESS,
|
||||
ICONSOLE_HOOK_PRE_ACTION,
|
||||
ICONSOLE_HOOK_POST_ACTION
|
||||
} IConsoleHookTypes;
|
||||
|
||||
/** --Hooks--
|
||||
* Hooks are certain triggers get get accessed/executed on either
|
||||
* access, before execution/change or after execution/change. This allows
|
||||
* for general flow of permissions or special action needed in some cases
|
||||
*/
|
||||
typedef bool IConsoleHook(void);
|
||||
typedef struct IConsoleHooks{
|
||||
IConsoleHook *access; // trigger when accessing the variable/command
|
||||
IConsoleHook *pre; // trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; // trigger after the variable/command is changed/executed
|
||||
} IConsoleHooks;
|
||||
|
||||
/** --Commands--
|
||||
* Commands are commands, or functions. They get executed once and any
|
||||
* effect they produce are carried out. The arguments to the commands
|
||||
* are given to them, each input word seperated by a double-quote (") is an argument
|
||||
* If you want to handle multiple words as one, enclose them in double-quotes
|
||||
* eg. 'say "hello sexy boy"'
|
||||
*/
|
||||
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
|
||||
|
||||
struct IConsoleCmd;
|
||||
typedef struct IConsoleCmd {
|
||||
char *name; // name of command
|
||||
struct IConsoleCmd *next; // next command in list
|
||||
|
||||
IConsoleCmdProc *proc; // process executed when command is typed
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleCmd;
|
||||
|
||||
/** --Variables--
|
||||
* Variables are pointers to real ingame variables which allow for
|
||||
* changing while ingame. After changing they keep their new value
|
||||
* and can be used for debugging, gameplay, etc. It accepts:
|
||||
* - no arguments; just print out current value
|
||||
* - '= <new value>' to assign a new value to the variable
|
||||
* - '++' to increase value by one
|
||||
* - '--' to decrease value by one
|
||||
*/
|
||||
struct IConsoleVar;
|
||||
typedef struct IConsoleVar {
|
||||
char *name; // name of the variable
|
||||
struct IConsoleVar *next; // next variable in list
|
||||
|
||||
void *addr; // the address where the variable is pointing at
|
||||
uint32 size; // size of the variable, used for strings
|
||||
char *help; // the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; // type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleVar;
|
||||
|
||||
/** --Aliases--
|
||||
* Aliases are like shortcuts for complex functions, variable assignments,
|
||||
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
|
||||
* 'list_vars' for example), or concatenate more commands into one
|
||||
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
|
||||
* given to them in the command line.
|
||||
* - "%A - %Z" substitute arguments 1 t/m 26
|
||||
* - "%+" lists all parameters keeping them seperated
|
||||
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
|
||||
* - ";" allows for combining commands (see example 'ng')
|
||||
*/
|
||||
struct IConsoleAlias;
|
||||
typedef struct IConsoleAlias {
|
||||
char *name; // name of the alias
|
||||
struct IConsoleAlias *next; // next alias in list
|
||||
|
||||
char *cmdline; // command(s) that is/are being aliased
|
||||
} IConsoleAlias;
|
||||
|
||||
// ** console parser ** //
|
||||
IConsoleCmd *_iconsole_cmds; // list of registred commands
|
||||
IConsoleVar *_iconsole_vars; // list of registred vars
|
||||
IConsoleAlias *_iconsole_aliases; // list of registred aliases
|
||||
|
||||
// ** console colors/modes ** //
|
||||
VARDEF byte _icolour_def;
|
||||
VARDEF byte _icolour_err;
|
||||
VARDEF byte _icolour_warn;
|
||||
VARDEF byte _icolour_dbg;
|
||||
VARDEF byte _icolour_cmd;
|
||||
VARDEF IConsoleModes _iconsole_mode;
|
||||
|
||||
// ** console functions ** //
|
||||
void IConsoleInit(void);
|
||||
void IConsoleClear(void);
|
||||
void IConsoleFree(void);
|
||||
void IConsoleResize(void);
|
||||
void IConsoleSwitch(void);
|
||||
void IConsoleClose(void);
|
||||
void IConsoleOpen(void);
|
||||
|
||||
// ** console cmd buffer ** //
|
||||
void IConsoleHistoryAdd(const char *cmd);
|
||||
void IConsoleHistoryNavigate(signed char direction);
|
||||
|
||||
// ** console output ** //
|
||||
void IConsolePrint(uint16 color_code, const char *string);
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
|
||||
void IConsoleDebug(const char *string);
|
||||
void IConsoleWarning(const char *string);
|
||||
void IConsoleError(const char *string);
|
||||
|
||||
// *** Commands *** //
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
|
||||
void IConsoleAliasRegister(const char *name, const char *cmd);
|
||||
IConsoleCmd *IConsoleCmdGet(const char *name);
|
||||
IConsoleAlias *IConsoleAliasGet(const char *name);
|
||||
|
||||
// *** Variables *** //
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
|
||||
IConsoleVar* IConsoleVarGet(const char *name);
|
||||
void IConsoleVarPrintGetValue(const IConsoleVar *var);
|
||||
void IConsoleVarPrintSetValue(const IConsoleVar *var);
|
||||
|
||||
// *** Parser *** //
|
||||
void IConsoleCmdExec(const char *cmdstr);
|
||||
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
|
||||
void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
|
||||
|
||||
// ** console std lib (register ingame commands/aliases/variables) ** //
|
||||
void IConsoleStdLibRegister(void);
|
||||
|
||||
// ** Hooking code ** //
|
||||
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
|
||||
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
|
||||
|
||||
// ** Supporting functions **//
|
||||
bool GetArgumentInteger(uint32 *value, const char *arg);
|
||||
#endif /* CONSOLE_H */
|
1333
console_cmds.c
Normal file
1333
console_cmds.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
data/autorail.grf
Normal file
BIN
data/autorail.grf
Normal file
Binary file not shown.
BIN
data/canalsw.grf
Normal file
BIN
data/canalsw.grf
Normal file
Binary file not shown.
BIN
data/dosdummy.grf
Normal file
BIN
data/dosdummy.grf
Normal file
Binary file not shown.
BIN
data/openttd.grf
Normal file
BIN
data/openttd.grf
Normal file
Binary file not shown.
BIN
data/signalsw.grf
Normal file
BIN
data/signalsw.grf
Normal file
Binary file not shown.
BIN
data/trkfoundw.grf
Normal file
BIN
data/trkfoundw.grf
Normal file
Binary file not shown.
98
debug.c
Normal file
98
debug.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "ttd.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
|
||||
int _debug_ai_level;
|
||||
int _debug_grf_level;
|
||||
int _debug_map_level;
|
||||
int _debug_misc_level;
|
||||
int _debug_ms_level;
|
||||
int _debug_net_level;
|
||||
int _debug_spritecache_level;
|
||||
int _debug_oldloader_level;
|
||||
int _debug_npf_level;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void SetDebugString(const char *s)
|
||||
{
|
||||
int v;
|
||||
char *end;
|
||||
const char *t;
|
||||
|
||||
typedef struct DebugLevel {
|
||||
const char* name;
|
||||
int* level;
|
||||
} DebugLevel;
|
||||
|
||||
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
|
||||
static const DebugLevel debug_level[] = {
|
||||
DEBUG_LEVEL(ai),
|
||||
DEBUG_LEVEL(grf),
|
||||
DEBUG_LEVEL(map),
|
||||
DEBUG_LEVEL(misc),
|
||||
DEBUG_LEVEL(ms),
|
||||
DEBUG_LEVEL(net),
|
||||
DEBUG_LEVEL(spritecache),
|
||||
DEBUG_LEVEL(oldloader),
|
||||
DEBUG_LEVEL(npf)
|
||||
};
|
||||
#undef DEBUG_LEVEL
|
||||
|
||||
// global debugging level?
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
const DebugLevel *i;
|
||||
|
||||
v = strtoul(s, &end, 0);
|
||||
s = end;
|
||||
|
||||
for (i = debug_level; i != endof(debug_level); ++i)
|
||||
*i->level = v;
|
||||
}
|
||||
|
||||
// individual levels
|
||||
for(;;) {
|
||||
const DebugLevel *i;
|
||||
int *p;
|
||||
|
||||
// skip delimiters
|
||||
while (*s == ' ' || *s == ',' || *s == '\t') s++;
|
||||
if (*s == '\0') break;
|
||||
|
||||
t = s;
|
||||
while (*s >= 'a' && *s <= 'z') s++;
|
||||
|
||||
// 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) {
|
||||
p = i->level;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*s == '=') s++;
|
||||
v = strtoul(s, &end, 0);
|
||||
s = end;
|
||||
if (p != NULL)
|
||||
*p = v;
|
||||
else {
|
||||
ShowInfoF("Unknown debug level '%.*s'", s - t, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
24
debug.h
Normal file
24
debug.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#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_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_npf_level;
|
||||
#endif
|
||||
|
||||
void CDECL debug(const char *s, ...);
|
||||
|
||||
void SetDebugString(const char *s);
|
||||
|
||||
#endif
|
352
dedicated.c
Normal file
352
dedicated.c
Normal file
@@ -0,0 +1,352 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "debug.h"
|
||||
#include "network.h"
|
||||
#include "hal.h"
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
||||
#include "gfx.h"
|
||||
#include "window.h"
|
||||
#include "command.h"
|
||||
#include "console.h"
|
||||
#ifdef WIN32
|
||||
# include <windows.h> /* GetTickCount */
|
||||
# include <conio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
# include <sys/time.h> /* gettimeofday */
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <conio.h>
|
||||
# define STDIN 0 /* file descriptor for standard input */
|
||||
|
||||
extern void OS2_SwitchToConsoleMode();
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
# include <sys/time.h> /* gettimeofday */
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# define STDIN 0 /* file descriptor for standard input */
|
||||
#endif
|
||||
#ifdef __MORPHOS__
|
||||
/* Voids the fork, option will be disabled for MorphOS build anyway, because
|
||||
* MorphOS doesn't support forking (could only implemented with lots of code
|
||||
* changes here). */
|
||||
int fork(void) { return -1; }
|
||||
int dup2(int oldd, int newd) { return -1; }
|
||||
#endif
|
||||
|
||||
// This file handles all dedicated-server in- and outputs
|
||||
|
||||
static void *_dedicated_video_mem;
|
||||
|
||||
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
|
||||
extern void SwitchMode(int new_mode);
|
||||
|
||||
#ifdef UNIX
|
||||
/* We want to fork our dedicated server */
|
||||
void DedicatedFork(void)
|
||||
{
|
||||
/* Fork the program */
|
||||
pid_t pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
perror("Unable to fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
// We're the child
|
||||
|
||||
/* Open the log-file to log all stuff too */
|
||||
_log_file_fd = fopen(_log_file, "a");
|
||||
if (!_log_file_fd) {
|
||||
perror("Unable to open logfile");
|
||||
exit(1);
|
||||
}
|
||||
/* Redirect stdout and stderr to log-file */
|
||||
if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) {
|
||||
perror("Rerouting stdout");
|
||||
exit(1);
|
||||
}
|
||||
if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) {
|
||||
perror("Rerouting stderr");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// We're the parent
|
||||
printf("Loading dedicated server...\n");
|
||||
printf(" - Forked to background with pid %d\n", pid);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal handlers */
|
||||
static void DedicatedSignalHandler(int sig)
|
||||
{
|
||||
_exit_game = true;
|
||||
signal(sig, DedicatedSignalHandler);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <time.h>
|
||||
HANDLE hEvent;
|
||||
static HANDLE hThread; // Thread to close
|
||||
static char _win_console_thread_buffer[200];
|
||||
|
||||
/* Windows Console thread. Just loop and signal when input has been received */
|
||||
void WINAPI CheckForConsoleInput(void)
|
||||
{
|
||||
while (true) {
|
||||
fgets(_win_console_thread_buffer, lengthof(_win_console_thread_buffer), stdin);
|
||||
SetEvent(hEvent); // signal input waiting that the line is ready
|
||||
}
|
||||
}
|
||||
|
||||
void CreateWindowsConsoleThread(void)
|
||||
{
|
||||
static char tbuffer[9];
|
||||
DWORD dwThreadId;
|
||||
/* Create event to signal when console input is ready */
|
||||
hEvent = CreateEvent(NULL, false, false, _strtime(tbuffer));
|
||||
if (hEvent == NULL)
|
||||
error("Cannot create console event!");
|
||||
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, NULL, 0, &dwThreadId);
|
||||
if (hThread == NULL)
|
||||
error("Cannot create console thread!");
|
||||
|
||||
DEBUG(misc, 0) ("Windows console thread started...");
|
||||
}
|
||||
|
||||
void CloseWindowsConsoleThread(void)
|
||||
{
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(hEvent);
|
||||
DEBUG(misc, 0) ("Windows console thread shut down...");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char *DedicatedVideoStart(const char * const *parm)
|
||||
{
|
||||
_screen.width = _screen.pitch = _cur_resolution[0];
|
||||
_screen.height = _cur_resolution[1];
|
||||
_dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
|
||||
|
||||
_debug_net_level = 6;
|
||||
_debug_misc_level = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
// For win32 we need to allocate an console (debug mode does the same)
|
||||
CreateConsole();
|
||||
CreateWindowsConsoleThread();
|
||||
SetConsoleTitle("OpenTTD Dedicated Server");
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
// For OS/2 we also need to switch to console mode instead of PM mode
|
||||
OS2_SwitchToConsoleMode();
|
||||
#endif
|
||||
|
||||
DEBUG(misc,0)("Loading dedicated server...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void DedicatedVideoStop(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
CloseWindowsConsoleThread();
|
||||
#endif
|
||||
free(_dedicated_video_mem);
|
||||
}
|
||||
|
||||
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
|
||||
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
|
||||
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
static bool InputWaiting(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set readfds;
|
||||
byte ret;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(STDIN, &readfds);
|
||||
|
||||
/* don't care about writefds and exceptfds: */
|
||||
ret = select(STDIN + 1, &readfds, NULL, NULL, &tv);
|
||||
|
||||
if (ret > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static bool InputWaiting(void)
|
||||
{
|
||||
if (WaitForSingleObject(hEvent, 1) == WAIT_OBJECT_0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void DedicatedHandleKeyInput(void)
|
||||
{
|
||||
static char input_line[200] = "";
|
||||
|
||||
if (!InputWaiting())
|
||||
return;
|
||||
|
||||
if (_exit_game)
|
||||
return;
|
||||
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
fgets(input_line, lengthof(input_line), stdin);
|
||||
#else
|
||||
strncpy(input_line, _win_console_thread_buffer, lengthof(input_line));
|
||||
#endif
|
||||
|
||||
/* XXX - strtok() does not 'forget' \n\r if it is the first character! */
|
||||
strtok(input_line, "\r\n"); // Forget about the final \n (or \r)
|
||||
{ /* Remove any special control characters */
|
||||
uint i;
|
||||
for (i = 0; i < lengthof(input_line); i++) {
|
||||
if (input_line[i] == '\n' || input_line[i] == '\r') // cut missed beginning '\0'
|
||||
input_line[i] = '\0';
|
||||
|
||||
if (input_line[i] == '\0')
|
||||
break;
|
||||
|
||||
if (!IS_INT_INSIDE(input_line[i], ' ', 256))
|
||||
input_line[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
IConsoleCmdExec(input_line); // execute command
|
||||
}
|
||||
|
||||
static int DedicatedVideoMainLoop(void)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct timeval tim;
|
||||
#endif
|
||||
uint32 next_tick;
|
||||
uint32 cur_ticks;
|
||||
|
||||
#ifdef WIN32
|
||||
next_tick = GetTickCount() + 30;
|
||||
#else
|
||||
gettimeofday(&tim, NULL);
|
||||
next_tick = (tim.tv_usec / 1000) + 30 + (tim.tv_sec * 1000);
|
||||
#endif
|
||||
|
||||
/* Signal handlers */
|
||||
#ifdef UNIX
|
||||
signal(SIGTERM, DedicatedSignalHandler);
|
||||
signal(SIGINT, DedicatedSignalHandler);
|
||||
signal(SIGQUIT, DedicatedSignalHandler);
|
||||
#endif
|
||||
|
||||
// Load the dedicated server stuff
|
||||
_is_network_server = true;
|
||||
_network_dedicated = true;
|
||||
_network_playas = OWNER_SPECTATOR;
|
||||
_local_player = OWNER_SPECTATOR;
|
||||
|
||||
/* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */
|
||||
if (_switch_mode != SM_LOAD) {
|
||||
_switch_mode = SM_NONE;
|
||||
GenRandomNewGame(Random(), InteractiveRandom());
|
||||
} else {
|
||||
_switch_mode = SM_NONE;
|
||||
/* First we need to test if the savegame can be loaded, else we will end up playing the
|
||||
* intro game... */
|
||||
if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
|
||||
/* Loading failed, pop out.. */
|
||||
DEBUG(net, 0)("Loading requested map failed. Aborting.");
|
||||
_networking = false;
|
||||
} else {
|
||||
/* We can load this game, so go ahead */
|
||||
SwitchMode(SM_LOAD);
|
||||
}
|
||||
}
|
||||
|
||||
// Done loading, start game!
|
||||
|
||||
if (!_networking) {
|
||||
DEBUG(net, 1)("Dedicated server could not be launched. Aborting.");
|
||||
return ML_QUIT;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
InteractiveRandom(); // randomness
|
||||
|
||||
if (_exit_game) return ML_QUIT;
|
||||
|
||||
if (!_dedicated_forks)
|
||||
DedicatedHandleKeyInput();
|
||||
|
||||
#ifdef WIN32
|
||||
cur_ticks = GetTickCount();
|
||||
#else
|
||||
gettimeofday(&tim, NULL);
|
||||
cur_ticks = (tim.tv_usec / 1000) + (tim.tv_sec * 1000);
|
||||
#endif
|
||||
|
||||
if (cur_ticks >= next_tick) {
|
||||
next_tick += 30;
|
||||
|
||||
GameLoop();
|
||||
_screen.dst_ptr = _dedicated_video_mem;
|
||||
UpdateWindows();
|
||||
}
|
||||
CSleep(1);
|
||||
}
|
||||
|
||||
return ML_QUIT;
|
||||
}
|
||||
|
||||
|
||||
const HalVideoDriver _dedicated_video_driver = {
|
||||
DedicatedVideoStart,
|
||||
DedicatedVideoStop,
|
||||
DedicatedVideoMakeDirty,
|
||||
DedicatedVideoMainLoop,
|
||||
DedicatedVideoChangeRes,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static void *_dedicated_video_mem;
|
||||
|
||||
static const char *DedicatedVideoStart(const char * const *parm)
|
||||
{
|
||||
DEBUG(misc, 0) ("OpenTTD compiled without network support, exiting.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DedicatedFork(void) {}
|
||||
static void DedicatedVideoStop(void) { free(_dedicated_video_mem); }
|
||||
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
|
||||
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
|
||||
static int DedicatedVideoMainLoop(void) { return ML_QUIT; }
|
||||
|
||||
const HalVideoDriver _dedicated_video_driver = {
|
||||
DedicatedVideoStart,
|
||||
DedicatedVideoStop,
|
||||
DedicatedVideoMakeDirty,
|
||||
DedicatedVideoMainLoop,
|
||||
DedicatedVideoChangeRes,
|
||||
};
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
142
depot.c
Normal file
142
depot.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "depot.h"
|
||||
#include "tile.h"
|
||||
#include "map.h"
|
||||
#include "table/strings.h"
|
||||
#include "saveload.h"
|
||||
#include "order.h"
|
||||
|
||||
enum {
|
||||
/* Max depots: 64000 (8 * 8000) */
|
||||
DEPOT_POOL_BLOCK_SIZE_BITS = 3, /* In bits, so (1 << 3) == 8 */
|
||||
DEPOT_POOL_MAX_BLOCKS = 8000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Called if a new block is added to the depot-pool
|
||||
*/
|
||||
static void DepotPoolNewBlock(uint start_item)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS_FROM(depot, start_item)
|
||||
depot->index = start_item++;
|
||||
}
|
||||
|
||||
/* Initialize the town-pool */
|
||||
MemoryPool _depot_pool = { "Depots", DEPOT_POOL_MAX_BLOCKS, DEPOT_POOL_BLOCK_SIZE_BITS, sizeof(Depot), &DepotPoolNewBlock, 0, 0, NULL };
|
||||
|
||||
|
||||
/**
|
||||
* Gets a depot from a tile
|
||||
*
|
||||
* @return Returns the depot if the tile had a depot, else it returns NULL
|
||||
*/
|
||||
Depot *GetDepotByTile(uint tile)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (depot->xy == tile)
|
||||
return depot;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new depot
|
||||
*/
|
||||
Depot *AllocateDepot(void)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (!IsValidDepot(depot)) {
|
||||
uint index = depot->index;
|
||||
|
||||
memset(depot, 0, sizeof(Depot));
|
||||
depot->index = index;
|
||||
|
||||
return depot;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can add a block to the pool */
|
||||
if (AddBlockToPool(&_depot_pool))
|
||||
return AllocateDepot();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a depot
|
||||
*/
|
||||
void DoDeleteDepot(uint tile)
|
||||
{
|
||||
Order order;
|
||||
Depot *depot;
|
||||
|
||||
/* Get the depot */
|
||||
depot = GetDepotByTile(tile);
|
||||
|
||||
/* Clear the tile */
|
||||
DoClearSquare(tile);
|
||||
|
||||
/* Clear the depot */
|
||||
depot->xy = 0;
|
||||
|
||||
/* Clear the depot from all order-lists */
|
||||
order.type = OT_GOTO_DEPOT;
|
||||
order.station = depot->index;
|
||||
DeleteDestinationFromVehicleOrder(order);
|
||||
|
||||
/* Delete the depot-window */
|
||||
DeleteWindowById(WC_VEHICLE_DEPOT, tile);
|
||||
}
|
||||
|
||||
void InitializeDepot(void)
|
||||
{
|
||||
CleanPool(&_depot_pool);
|
||||
AddBlockToPool(&_depot_pool);
|
||||
}
|
||||
|
||||
|
||||
static const byte _depot_desc[] = {
|
||||
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
|
||||
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, 255),
|
||||
SLE_VAR(Depot,town_index, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_DEPT(void)
|
||||
{
|
||||
Depot *depot;
|
||||
|
||||
FOR_ALL_DEPOTS(depot) {
|
||||
if (IsValidDepot(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},
|
||||
};
|
120
depot.h
Normal file
120
depot.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef DEPOT_H
|
||||
#define DEPOT_H
|
||||
|
||||
#include "pool.h"
|
||||
#include "tile.h"
|
||||
|
||||
struct Depot {
|
||||
TileIndex xy;
|
||||
uint16 town_index;
|
||||
uint16 index;
|
||||
};
|
||||
|
||||
extern MemoryPool _depot_pool;
|
||||
|
||||
/**
|
||||
* Get the pointer to the depot with index 'index'
|
||||
*/
|
||||
static inline Depot *GetDepot(uint index)
|
||||
{
|
||||
return (Depot*)GetItemFromPool(&_depot_pool, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current size of the DepotPool
|
||||
*/
|
||||
static inline uint16 GetDepotPoolSize(void)
|
||||
{
|
||||
return _depot_pool.total_items;
|
||||
}
|
||||
|
||||
static inline bool IsDepotIndex(uint index)
|
||||
{
|
||||
return index < GetDepotPoolSize();
|
||||
}
|
||||
|
||||
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1 < GetDepotPoolSize()) ? GetDepot(d->index + 1) : NULL)
|
||||
#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 uint16 GetServiceIntervalClamped(uint index)
|
||||
{
|
||||
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
|
||||
}
|
||||
|
||||
VARDEF TileIndex _last_built_train_depot_tile;
|
||||
VARDEF TileIndex _last_built_road_depot_tile;
|
||||
VARDEF TileIndex _last_built_aircraft_depot_tile;
|
||||
VARDEF TileIndex _last_built_ship_depot_tile;
|
||||
|
||||
/**
|
||||
* Check if a depot really exists.
|
||||
*/
|
||||
static inline bool IsValidDepot(const Depot* depot)
|
||||
{
|
||||
return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) && (_map5[tile] & 0xFC) == 0xC0;
|
||||
break;
|
||||
case TRANSPORT_ROAD:
|
||||
return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20;
|
||||
break;
|
||||
case TRANSPORT_WATER:
|
||||
return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direction the exit of the depot on the given tile is facing.
|
||||
*/
|
||||
static inline uint GetDepotDirection(TileIndex tile, TransportType type)
|
||||
{
|
||||
assert(IsTileDepotType(tile, type));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TRANSPORT_RAIL:
|
||||
case TRANSPORT_ROAD:
|
||||
/* Rail and road store a diagonal direction in bits 0 and 1 */
|
||||
return _map5[tile] & 3;
|
||||
case TRANSPORT_WATER:
|
||||
/* Water is stubborn, it stores the directions in a different order. */
|
||||
switch (_map5[tile] & 3) {
|
||||
case 0: return 0;
|
||||
case 1: return 2;
|
||||
case 2: return 3;
|
||||
case 3: return 1;
|
||||
}
|
||||
default:
|
||||
return 0; /* Not reached */
|
||||
}
|
||||
}
|
||||
|
||||
Depot *GetDepotByTile(uint tile);
|
||||
void InitializeDepot(void);
|
||||
Depot *AllocateDepot(void);
|
||||
void DoDeleteDepot(uint tile);
|
||||
|
||||
#endif /* DEPOT_H */
|
1000
disaster_cmd.c
Normal file
1000
disaster_cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
359
dock_gui.c
Normal file
359
dock_gui.c
Normal file
@@ -0,0 +1,359 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.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"
|
||||
|
||||
static void ShowBuildDockStationPicker(void);
|
||||
static void ShowBuildDocksDepotPicker(void);
|
||||
|
||||
static byte _ship_depot_direction;
|
||||
|
||||
void CcBuildDocks(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
}
|
||||
|
||||
|
||||
static void PlaceDocks_Dock(uint tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_Depot(uint 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(uint tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_DemolishArea(uint tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildCanal(uint tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_OR_Y);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildLock(uint tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
|
||||
}
|
||||
|
||||
|
||||
static void BuildDocksClick_Canal(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 3, SPR_OPENTTD_BASE + 11, 1, PlaceDocks_BuildCanal);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Lock(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, SPR_OPENTTD_BASE + 64, 1, PlaceDocks_BuildLock);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 6, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Depot(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 7, 0x2D1, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Dock(Window *w)
|
||||
{
|
||||
|
||||
if (HandlePlacePushButton(w, 8, 0xE54, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Buoy(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 9, 0x2BE, 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,
|
||||
0,
|
||||
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->click.widget - 3 >= 0 && e->click.widget != 5) _build_docks_button_proc[e->click.widget - 3](w);
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch(e->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->place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG: {
|
||||
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->click.pt.x != -1) {
|
||||
if ((e->place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
|
||||
GUIPlaceProcDragXY(e);
|
||||
} else if(e->place.userdata == VPM_X_OR_Y)
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(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: {
|
||||
uint tile_from, tile_to;
|
||||
|
||||
tile_from = tile_to = e->place.tile;
|
||||
switch(GetTileSlope(tile_from, NULL)) {
|
||||
case 3: tile_to += TILE_XY(-1,0); break;
|
||||
case 6: tile_to += TILE_XY(0,-1); break;
|
||||
case 9: tile_to += TILE_XY(0,1); break;
|
||||
case 12:tile_to += TILE_XY(1,0); break;
|
||||
}
|
||||
VpSetPresizeRange(tile_from, tile_to);
|
||||
} 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_PANEL, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
|
||||
{ WWT_PANEL, 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_PANEL, RESIZE_NONE, 7, 48, 69, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 70, 91, 14, 35, 748, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 92, 113, 14, 35, 746, STR_981D_BUILD_SHIP_DOCK},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 114, 135, 14, 35, 693, STR_9834_POSITION_BUOY_WHICH_CAN},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_docks_toolbar_desc = {
|
||||
640-158, 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 (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDesc(&_build_docks_toolbar_desc);
|
||||
}
|
||||
|
||||
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
int rad;
|
||||
|
||||
switch(e->event) {
|
||||
case WE_PAINT: {
|
||||
if (WP(w,def_d).close)
|
||||
return;
|
||||
w->click_state = (1<<3) << _station_show_coverage;
|
||||
DrawWindowWidgets(w);
|
||||
if (_patches.modified_catchment) {
|
||||
rad = CA_DOCK;
|
||||
} else {
|
||||
rad = 4;
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
else SetTileSelectBigSize(0, 0, 0, 0);
|
||||
|
||||
DrawStringCentered(74, 17, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
|
||||
} break;
|
||||
|
||||
case WE_CLICK: {
|
||||
switch(e->click.widget) {
|
||||
case 3: case 4:
|
||||
_station_show_coverage = e->click.widget - 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_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_dock_station_desc = {
|
||||
-1, -1, 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 != 0) {
|
||||
SetTileSelectSize(1, 2);
|
||||
} else {
|
||||
SetTileSelectSize(2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
w->click_state = (1<<3) << _ship_depot_direction;
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
DrawShipDepotSprite(67, 35, 0);
|
||||
DrawShipDepotSprite(35, 51, 1);
|
||||
DrawShipDepotSprite(135, 35, 2);
|
||||
DrawShipDepotSprite(167, 51, 3);
|
||||
return;
|
||||
|
||||
case WE_CLICK: {
|
||||
switch(e->click.widget) {
|
||||
case 3:
|
||||
case 4:
|
||||
_ship_depot_direction = e->click.widget - 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 = {
|
||||
-1, -1, 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 = 0;
|
||||
}
|
@@ -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.
|
||||
|
@@ -1,60 +0,0 @@
|
||||
STRGEN USAGE
|
||||
------------
|
||||
This guide is only interesting for people who want to alter something
|
||||
themselves without access to WT2 (translator2.openttd.org). Please note that
|
||||
your compiled language file will only be compatible with the OpenTTD version
|
||||
you have downloaded english.txt, the master language file, for. While this is
|
||||
not always true, namely when changes in the code have not touched language
|
||||
files, your safest bet is to assume this 'limitation'.
|
||||
As a first step you need to compile strgen. This is as easy as typing
|
||||
'make strgen'. You can download the precompile strgen from:
|
||||
http://www.openttd.org/download-strgen
|
||||
|
||||
strgen takes as argument a txt file and translates it to a lng file, allowing
|
||||
it to be used inside OpenTTD. strgen needs the master language file
|
||||
english.txt to work. Below are some examples of strgen usage.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
Example 1:
|
||||
if you are in the root of your working copy (svn code), you should type
|
||||
strgen/strgen -s lang lang/english.txt
|
||||
to compile englist.txt into english.lng. It will be placed in the lang dir
|
||||
|
||||
Example 2:
|
||||
you only have the strgen executable (no working copy) and you want to compile
|
||||
a txt file in the same directory. You should type
|
||||
./strgen english.txt
|
||||
and you will get and english.lng in the same dir
|
||||
|
||||
Example 3:
|
||||
you have strgen somewhere, english.txt in /usr/openttd/lang and you want the
|
||||
resulting language file to go to /tmp. Use
|
||||
./strgen -s /usr/openttd/lang -d /tmp english.txt
|
||||
|
||||
You can interchange english.txt to whichever language you want to generate a
|
||||
.lng file for.
|
||||
|
||||
STRGEN COMMAND SWITCHES
|
||||
-----------------------
|
||||
-v | --version
|
||||
strgen will tell what svn revision it was last modified
|
||||
|
||||
-t | --todo
|
||||
strgen will add <TODO> to any untranslated/missing strings and use the english
|
||||
strings while compiling the language file
|
||||
|
||||
-w | --warning
|
||||
strgen will print any missing strings or wrongly translated (bad format)
|
||||
to standard error output(stderr)
|
||||
|
||||
-h | --help | -?
|
||||
Print out a summarized help message explaining these switches
|
||||
|
||||
-s | --source_dir
|
||||
strgen will search for the master file english.txt in the directory specified
|
||||
by this switch instead of the current directory
|
||||
|
||||
-d | --dest_dir
|
||||
strgen will put <language>.lng in the directory specified by this switch; if
|
||||
no dest_dir is given, output is the same as source_dir
|
49
docs/Howto_compile_lng_files_from_CLI.txt
Normal file
49
docs/Howto_compile_lng_files_from_CLI.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
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
|
||||
|
||||
here are a very useful tool for translators:
|
||||
http://openttd.rulez.org/
|
||||
|
||||
|
||||
HOWTO compile strgen:
|
||||
(this should be useless as you can just type make)
|
||||
Goto the main dir
|
||||
Compile by typing
|
||||
gcc strgen/strgen.c -o strgen/strgen -DUNIX
|
||||
or if you want it to tell the revision too
|
||||
gcc strgen/strgen.c rev.o -o strgen/strgen -DUNIX -DWITH_REV (this is the one the makefile uses)
|
||||
|
||||
you now have a program called strgen in the strgen directory
|
||||
|
@@ -2,9 +2,9 @@ Welcome to the manual for OpenTTD. The latest release version at the time of wr
|
||||
|
||||
1 Obtaining OpenTTD.
|
||||
|
||||
You can obtain built binaries of OpenTTD for the 4 supported platforms - Win32, Linux,-x86, BeOS 5 and MacOS-X from the projects Sourceforge page, at http://sourceforge.net/projects/openttd . For the non-Win32 builds you will need libSDL.so, libpng.so and zlib.so compiled for your platform. Some builds will include these.
|
||||
You can obtain built binaries of OpenTTD for the 4 supported platforms - Win32, Linux,-x86, BeOS 5 and MacOS-X from the projects Sourceforge page, at http://sourceforge.net/projects/openttd . For the non-Win32 builds you will need libSDL.so, libpng.so and zlib.so compiled for your platform. Some builds will include these.
|
||||
|
||||
If you use another platform, such as FreeBSD, which has POSIX file i/o and an SDL port, you should be able to build OpenTTD from its source. This is available in the proejcts Subversion repository at svn://svn.openttd.com . The module name is "trunk".
|
||||
If you use another platform, such as FreeBSD, which has POSIX file i/o and an SDL port, you should be able to build OpenTTD from its source. This is available in the proejcts Subversion repository at svn://svn.openttd.com . The module name is "trunk".
|
||||
|
||||
1.1 Building OpenTTD.
|
||||
|
||||
@@ -13,16 +13,17 @@ 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.2 Installing OpenTTD.
|
||||
|
||||
On Windows, insert your "Transport Tycoon Deluxe for Windows 95" disk. You can use a DOS version, but your graphics will be purple. NB: Even if your version of Transport Tycoon Deluxe ran on Windows 95, it may still be the DOS version. Then run the OpenTTD installer.
|
||||
On Windows, insert your "Transport Tycoon Deluxe for Windows 95" disk. You can use a DOS version, but your graphics will be purple. NB: Even if your version of Transport Tycoon Deluxe ran on Windows 95, it may still be the DOS version. Then run the OpenTTD installer.
|
||||
|
||||
On UNIX platforms; decompress your OpenTTD archive, or otherwise run the installer. You should be left with an OpenTTD directory on your system. In this directory, make a subdirectory called 'data', and into this place the sample.cat file and all the .grf files from the install CD of 'Transport Tycoon Deluxe for Windows 95".
|
||||
On UNIX platforms; decompress your OpenTTD archive, or otherwise run the installer. You should be left with an OpenTTD directory on your system. In this directory, make a subdirectory called 'data', and into this place the sample.cat file and all the .grf files from the install CD of 'Transport Tycoon Deluxe for Windows 95".
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
If you want MIDI music, copy the 'gm' folder from the original game directory/CD to the OpenTTD folder.
|
||||
@@ -37,7 +38,7 @@ On BeOS and Mac OS-X, just double click the ttd binary in the Tracker/Finder. Yo
|
||||
|
||||
1.4 Configuring OpenTTD
|
||||
|
||||
OpenTTD's launch menu contains three configuration menus - Difficulty Settings, Configure Patches and Game Settings. Most of these menus can be configured from within a running game as well.
|
||||
OpenTTD's launch menu contains three configuration menus - Difficulty Settings, Configure Patches and Game Settings. Most of these menus can be configured from within a running game as well.
|
||||
|
||||
Difficulty Settings lets you configure settings that affect the difficulty of playing the game. These include when your (computer-controlled) competitors can start building, how many of them there are, and how intelligent they are. You can also control how much the subsidy mutliplier is for subsidised routes, and how stable/volitile the in-game economy is. You can also set how you want the terrain to be configured in a random game.
|
||||
|
||||
@@ -51,13 +52,14 @@ This section of the manual is written with the assumption that you already know
|
||||
|
||||
2.2 Station Construction
|
||||
|
||||
In OpenTTD, you can build rail stations up to seven squares long and with up to seven platforms. You can also have stations spreading across far larger distances, allowing a large rail station to be connected to a large airport, for instance.
|
||||
In OpenTTD, you can build rail stations up to seven squares long and with up to seven platforms. You can also have stations spreading across far larger distances, allowing a large rail station to be connected to a large airport, for instance.
|
||||
|
||||
However, there is an even more noticable difference in rail station construction. You may now add platforms and lenght to a station after it has been built, and you may also add platforms of a different type. Users of TTDPatch will be used to this behaviour. But beyond what TTDPatch has, you can make stations of uneven lenght/width, and even ones with perpendicular tracks. You can also delete single tiles or tracks from a station, by holding down Shift before pressing the station construction button.
|
||||
|
||||
2.3 Checkpoint Stations
|
||||
|
||||
Checkpoint stations (the small blue item in the rail construction window) are small 1x1 stations. They must be built on top of pre-existing track. They do not accept or produce carge of any kind. They exist solely for use as route points. They become useful when dealing with large networks where trains may attempt to route themselves along undesirable or impossible routes. As an alternative to checkpoint stations, you can also direct trains to visit depots along the way. This has the advantage of also servicing the train and hence the train will rarely to never need to depart from its route to be serviced.
|
||||
|
||||
Checkpoint stations (the small blue item in the rail construction window) are small 1x1 stations. They must be built on top of pre-existing track. They do not accept or produce carge of any kind. They exist solely for use as route points. They become useful when dealing with large networks where trains may attempt to route themselves along undesirable or impossible routes. As an alternative to checkpoint stations, you can also direct trains to visit depots along the way. This has the advantage of also servicing the train and hence the train will rarely to never need to depart from its route to be serviced.
|
||||
|
||||
2.4 Freeform Rail Laying.
|
||||
|
||||
@@ -73,7 +75,7 @@ This allows you to build roads, rails, stations and depots on slopes. It also al
|
||||
|
||||
2.7 Long Bridges
|
||||
|
||||
OpenTTD allows you to constuct bridges up to 127 squares - half the size of the current map. This means that the crossing of large estuaries, such at the Bristol Channel in the original "West Country 90210" scenario can be acheived with one bridge instead of many bridges with staging points.
|
||||
OpenTTD allows you to constuct bridges up to 127 squares - half the size of the current map. This means that the crossing of large estuaries, such at the Bristol Channel in the original "West Country 90210" scenario can be acheived with one bridge instead of many bridges with staging points.
|
||||
|
||||
2.8 Long trains
|
||||
|
||||
@@ -87,7 +89,7 @@ This addition to OpenTTD allows you to see the current speed of any vehicle in t
|
||||
|
||||
Virtually any settings - train numbers, start date, what vehicles your competitors can use, etc - can be set in OpenTTD. Just use the Configure Patches menu on the main screen.
|
||||
|
||||
2.11 Network Play
|
||||
2.11 Network Play
|
||||
|
||||
See multiplayer.txt for more info.
|
||||
|
||||
@@ -97,4 +99,4 @@ This button, at the end of the train construction window, lets you 'recycle' tra
|
||||
|
||||
2.13 Canal Building
|
||||
|
||||
This button, at the end of the water construction window, lets you build canals and shiplifts across the landscape. These act just like normal water.
|
||||
This button, at the end of the water construction window, lets you build canals and shiplifts across the landscape. These act just like normal water.
|
@@ -1,23 +0,0 @@
|
||||
To install OpenTTD, you should drag the game to any location you want and in that folder, you should create a folder called "data". It should contain:
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
You should also use the data folder to add any custom grf files if you like
|
||||
|
||||
if you want music, you can add a GM folder and add all .gm files from TTD inside it
|
||||
|
||||
If you want to use the scenarios, you can copy the scenario folder as well. If you already have one, just copy the content so you don't overwrite old ones that have been removed.
|
||||
|
||||
In the end, you should have a folder containing:
|
||||
OpenTTD (the actual game)
|
||||
data (containing the grf files)
|
||||
GM (optional for music)
|
||||
scenario (optional pregenerated maps)
|
||||
|
||||
The game adds some items by itself when it runs, like a save folder and a setting file
|
24
docs/OSX_where_did_the_package_go.txt
Normal file
24
docs/OSX_where_did_the_package_go.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
It's gone
|
||||
|
||||
The main goal with the package system was to make it as simple as possible to update. The problem was that some files inside the data folder should be updated and not others. Now the data files have been moved inside OpenTTD itself and to make it even easier, the same goes for the lang dir. There will no longer be an issue where people have different versions of grf files, language files and OpenTTD.
|
||||
|
||||
To install simply copy OpenTTD into the folder you want
|
||||
If it is your current folder with outdated grf files, you should remove
|
||||
canalsw.grf
|
||||
openttd.grf
|
||||
opntitle.dat
|
||||
signalsw.grf
|
||||
trkfoundw.grf
|
||||
|
||||
THE TTD GRF FILES ARE STILL NEEDED!
|
||||
They need to be inside a folder called "data" in the same folder as OpenTTD. Create it if you have none. It should contain:
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
You should also use the data folder to add any custom grf files if you like
|
36
docs/README_if_game_crashed_on_OSX.txt
Normal file
36
docs/README_if_game_crashed_on_OSX.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
Since you are reading this, OpenTTD have crashed. This file tells you how
|
||||
to fix the most common problems or make to make a bug report, that the
|
||||
developers can use to track down the problem
|
||||
|
||||
If it is an assert, OpenTTD will open the console for you, if it is truly a crash, you have to do it yourself. The Console is located at /Applications/Utilities/Console.
|
||||
The problem is near the button of the page
|
||||
|
||||
The problems are as follows:
|
||||
NOTE: build from source means to download the source and compile
|
||||
yourself. If you get one of the build from source error with the version
|
||||
that is downloaded on a dmg file, you should make a bug report
|
||||
|
||||
--Didn't find a needed file:
|
||||
you just give it the file it asks for. It even tells you what
|
||||
folder it wants it in
|
||||
most common version of this problem is "Error: Cannot open file
|
||||
'data/sample.cat'"
|
||||
if you get that one, that means that you haven't got all the
|
||||
needed files from the WINDOWS version of TTD
|
||||
or if you build from source,
|
||||
|
||||
--Error: No available language packs
|
||||
you need at least one .lng file in your lang folder. This applies
|
||||
only to people who build from source
|
||||
|
||||
--spritecache.c:237: failed assertion `b'
|
||||
you got an outdated grf file. Update from the data folder in the
|
||||
source. This applies only to people, who build from source
|
||||
|
||||
--assertion error that are not triggered by one of the errors listed in
|
||||
this file:
|
||||
you most likely found a bug. Write down the assertion and try to
|
||||
see if you can reproduce it. If you can, make a
|
||||
savegame from just before it happens (autosaves are useful here)
|
||||
and post a bugreport with it on sourceforge
|
||||
Write what you did to trigger the bug and what assertion it made
|
62
docs/Readme_Mandrake_Linux.txt
Normal file
62
docs/Readme_Mandrake_Linux.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
Compiling and developing OpenTTD on MandrakeLinux 10.0 Official
|
||||
|
||||
A quick guide to get started with OpenTTD development on Linux.
|
||||
---------------------------------------------------------------
|
||||
|
||||
1.) RPMs:
|
||||
|
||||
Most packages that are required for development (like gcc) should already be installed on your box. You will require those RPMs additionally:
|
||||
- libsdl1.2-devel-1.2.7-2mdk
|
||||
- subversion-1.0.1-1mdk (+ dependencies)
|
||||
- libsvn_ra_svn1_0-1.0.1-1mdk
|
||||
|
||||
|
||||
2.) Subversion:
|
||||
|
||||
To obtain the source code from the subversion server type
|
||||
$ svn co svn://svn.openttd.com/openttd/trunk openttd
|
||||
from command line to dump the code into the directory 'openttd'.
|
||||
|
||||
To update your working copy to the latest revision use
|
||||
$ svn update
|
||||
Don't worry, your version will be merged with the latest version.
|
||||
|
||||
The command
|
||||
$ svn diff > mypatch.diff
|
||||
creates a patch file (aka diff file) which you can submit to the developers to share your improvements.
|
||||
|
||||
You can undo changes to a file with
|
||||
$svn revert filename
|
||||
|
||||
|
||||
3.) Required data files:
|
||||
|
||||
Copy the following files from Transport Tycoon Deluxe to openttd/data/
|
||||
sample.cat
|
||||
trg1r.grf
|
||||
trgcr.grf
|
||||
trghr.grf
|
||||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
|
||||
4.) Compiling and running:
|
||||
|
||||
Compile OpenTTD with
|
||||
$ make
|
||||
and run it with
|
||||
$ ./ttd
|
||||
|
||||
|
||||
5.) Playing the soundtrack:
|
||||
|
||||
If you want the original TTD music you need to copy the whole /gm/ directory from Windows. Additionally the TiMidity driver is required:
|
||||
TiMidity++-2.12.0-0.pre1.4mdk (+ dependencies)
|
||||
To run OpenTTD with music support type
|
||||
$ ./ttd -m extmidi
|
||||
|
||||
|
||||
X.) Last Update: $Date: 2004-06-01 19:08:09 +0200 (Tue, 01 Jun 2004) $
|
||||
Written for revision $Rev: 710 $
|
@@ -15,13 +15,10 @@ LIBRARIES REQUIRED FOR END USERS
|
||||
|
||||
SDL.DLL (SDL 1.2.7) and FSLib.dll are required to use this program:
|
||||
these can be downloaded from the Files section at
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip".
|
||||
Version 20051222 of SDL or later is required. This can be found at
|
||||
http://sdl.netlabs.org/.
|
||||
|
||||
Please note that earlier SDL releases will probably NOT work with
|
||||
OpenTTD. If you experience problems with OpenTTD, please check
|
||||
your SDL and FSLib.dll versions (both must match).
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
|
||||
(Note that a newer version of SDL is now available at
|
||||
ftp://ftp.netlabs.org/pub/sdl/sdl-dev-os2-2004-12-22.zip which may
|
||||
help solve some problems).
|
||||
|
||||
Note that to actually play the game, I have found in my own
|
||||
experience that a version of the Scitech Display Drivers or its later
|
||||
@@ -50,10 +47,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 +57,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
|
||||
=========================
|
||||
@@ -73,33 +64,16 @@ BUILDING THE OS/2 VERSION
|
||||
Compiler
|
||||
--------
|
||||
|
||||
Innotek GCC, an OS/2 port of the popular GCC compiler, was used to build OpenTTD.
|
||||
See www.innotek.de for more information. You WILL need a reasonably UNIX-like
|
||||
build environment in order to build OpenTTD successfully - the following link
|
||||
may help to set one up (although some of the links from that page are broken):
|
||||
Open Watcom 1.3 was used to build OpenTTD (earlier versions will
|
||||
NOT work). See http://www.openwatcom.org/ to download it. It may
|
||||
also be possible to build OpenTTD with GCC: I attempted this
|
||||
before using Open Watcom, but found the tools available for OS/2
|
||||
at the time to be a bit more tricky to get working.
|
||||
|
||||
http://www.mozilla.org/ports/os2/gccsetup.html
|
||||
|
||||
Alternatively, Paul Smedley's ready-to-go GCC build environment has been known to
|
||||
successfully build the game:
|
||||
|
||||
http://www.smedley.info/os2ports/index.php?page=build-environment
|
||||
|
||||
To build, you should, if your environment is set up well enough, be able to just
|
||||
type `./configure' (or `sh configure' if you're using the OS/2 shell) and `make'.
|
||||
|
||||
You may have to manually specify `--os OS2' on the configure command line, as
|
||||
configure cannot always detect OS/2 correctly.
|
||||
|
||||
A note on Open Watcom
|
||||
---------------------
|
||||
|
||||
Open Watcom C/C++ was previously used to build OpenTTD (version 0.4.x and earlier).
|
||||
However, due to advanced C++ features used in the YAPF portion of OpenTTD 0.5
|
||||
in particular, the compiler is no longer able to build the game at the moment.
|
||||
Hopefully one day Open Watcom will be able to catch up and we will be able to build
|
||||
the game once again (it's easier than getting an OS/2 UNIX-like environment set up
|
||||
in my opinion!), but until then, OpenTTD 0.5 and later can only be built with GCC.
|
||||
Due to complexities in my set-up, I actually used the Win32 version
|
||||
of Open Watcom to initially compile OpenTTD for OS/2. There should
|
||||
be no reason of course why the OS/2 version cannot be used, and I
|
||||
have subsequently built OpenTTD successfully this way.
|
||||
|
||||
Libraries Required
|
||||
------------------
|
||||
@@ -110,22 +84,42 @@ to an IDE project file and built a library. Do not use the makefiles
|
||||
provided, they are not designed for Watcom (apart from SDL):
|
||||
|
||||
- zlib
|
||||
http://www.zlib.org/
|
||||
http://www.zlib.org/ - contains a makefile for OS/2, but is out
|
||||
of date and uses EMX, ignore this
|
||||
|
||||
- libpng
|
||||
http://www.libpng.org/
|
||||
http://www.libpng.org/ - contains an EMX/gcc makefile, ignore this
|
||||
|
||||
- SDL for OS/2
|
||||
ftp://ftp.netlabs.org/pub/sdl/sdl-1.2.7-src-20051222.zip used for
|
||||
0.4.7
|
||||
For 0.3.5, I used ftp://ftp.netlabs.org/pub/sdl/SDL-1.2.7-src-20040908a.zip -
|
||||
take SDL.dll and SDL.lib from the src/ directory. Note that 20041222 is
|
||||
out now, which is recommended for stability updates.
|
||||
|
||||
- Freetype
|
||||
http://freetype.sourceforge.net/
|
||||
If you do not wish to build the libraries yourself, pre-built versions
|
||||
can be downloaded from the Files section at
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
|
||||
|
||||
Currently, there are no pre-built libraries available for GCC. If you manage to get
|
||||
OpenTTD working on Watcom though (do let us know if this is the case!), pre-built
|
||||
versions can be downloaded from the Files section at
|
||||
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip".
|
||||
A Note About Subversion Revision Numbers
|
||||
----------------------------------------
|
||||
|
||||
The project file uses a bit of a hack to find out the SVN revision number and
|
||||
create an appropriate rev.c file. You'll need the SVN tools in your path
|
||||
(specifically, "svnversion"). If "svnversion" can't be found, a generic rev.c
|
||||
with the revision set to "norev000" will be created. To specifically force a
|
||||
version number, set the environment variable "RELEASE" to the number (eg, "0.3.6")
|
||||
-before- starting the Open Watcom IDE (which must be launched from the same shell
|
||||
session). Also, beware, as you WILL cause incompatibilities if you try to
|
||||
play a multiplayer game with a different version.
|
||||
|
||||
Compiling
|
||||
---------
|
||||
|
||||
To compile, open the os/os2/openttd.wpj file in the IDE and first build
|
||||
the strgen.exe target. This will build the .lng file generator, and will
|
||||
also attempt to build all the language files (plus the table\strings.h
|
||||
file which is required for openttd.exe to be built). Once strgen.exe and
|
||||
the language files are built successfully, you can build the openttd.exe
|
||||
target.
|
||||
|
||||
Contact Information
|
||||
-------------------
|
||||
@@ -134,6 +128,4 @@ If you have any questions regarding OS/2 issues, please contact me
|
||||
(owen@owenrudge.net) and I'll try to help you out. For general OpenTTD
|
||||
issues, see the Contacting section of readme.txt.
|
||||
|
||||
Thanks to Paul Smedley for his help with getting OpenTTD to compile under GCC on OS/2.
|
||||
|
||||
- Owen Rudge, 24th June 2007
|
||||
- Owen Rudge
|
||||
|
@@ -1,115 +0,0 @@
|
||||
Compiling OpenTTD using Microsoft Visual C++
|
||||
January 2, 2007
|
||||
--------------------------------------------
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
1) REQUIRED FILES
|
||||
-----------------
|
||||
You might already have some of the files already installed, so check before
|
||||
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/)
|
||||
* 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)
|
||||
|
||||
...and of course the newest source from svn://svn.openttd.org/trunk
|
||||
|
||||
You need an SVN-client to download the source from subversion:
|
||||
|
||||
* CLI Subversion (http://subversion.tigris.org/)
|
||||
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/)
|
||||
|
||||
|
||||
2) INCLUDES AND LIBRARIES
|
||||
-------------------------
|
||||
Put the newly downloaded files in the VC lib\ and include\ directories; where
|
||||
"C:\Program Files\Microsoft Visual Studio 8\VC" is your location of Visual C.
|
||||
If you are compiling for an x64 system, use the include\ and lib\ directories
|
||||
from the win64/ folder.
|
||||
|
||||
* openttd-useful.zip\include\*
|
||||
* afxresh.h
|
||||
to > C:\Program Files\Microsoft Visual Studio 8\VC\Include
|
||||
|
||||
* openttd-useful.zip\lib\*
|
||||
to > C:\Program Files\Microsoft Visual Studio 8\VC\Lib
|
||||
|
||||
Custom directories might be recommended, check 2.2)
|
||||
|
||||
|
||||
2.1) INCLUDES AND LIBRARIES - DIRECTX/PLATFORM SDK
|
||||
--------------------------------------------------
|
||||
Basically the same procedure as with the useful zip file, providing
|
||||
you are not using the Microsoft installer. Put the include files in the
|
||||
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,
|
||||
MSVC will not find them by default. You need to add these paths to VC through:
|
||||
|
||||
Tools > Options > Projects and Solutions > VC++ Directories > show directories for
|
||||
|
||||
* Include files: Add the DirectX/Platform SDK include dir you've created
|
||||
* Library files: Add the path to the SDK custom lib dir
|
||||
|
||||
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
|
||||
|
||||
* sample.cat
|
||||
* trg1r.grf
|
||||
* trgcr.grf
|
||||
* trghr.grf
|
||||
* trgir.grf
|
||||
* trgtr.grf
|
||||
|
||||
|
||||
4) COMPILING
|
||||
------------
|
||||
Open trunk/openttd_vs[89]0.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
|
||||
|
||||
|
||||
5) EDITING, CHANGING SOURCE CODE
|
||||
--------------------------------
|
||||
Set the build mode (back to) 'Debug'
|
||||
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 (!)
|
||||
source. If it still doesn't work, check in on IRC (irc://irc.oftc.net/openttd),
|
||||
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
|
105
docs/Readme_Windows_MSVC6.0.txt
Normal file
105
docs/Readme_Windows_MSVC6.0.txt
Normal file
@@ -0,0 +1,105 @@
|
||||
Compiling OpenTTD using Microsoft Visual C++ 6.0
|
||||
|
||||
|
||||
---Step 1
|
||||
|
||||
Download the following files:
|
||||
|
||||
* Useful.zip (http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633)
|
||||
* SDL-1.2.8-VC6.zip (http://www.libsdl.org/release/SDL-devel-1.2.8-VC6.zip)
|
||||
* DirectX7.0 SDK (http://www.tt-forums.net/download.php?id=15989) (or alternatively the latest DirectX SDK from Microsoft)
|
||||
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
|
||||
|
||||
...and of course the newest source from svn://svn.openttd.com/trunk
|
||||
|
||||
(The alpha version of the new map array can be found at svn://svn.openttd.com/branch/map)
|
||||
|
||||
You have to have and SVN-client to download the source:
|
||||
|
||||
* Command line version (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
|
||||
* TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
|
||||
|
||||
|
||||
---Step 2
|
||||
|
||||
Put the newly downloaded files in the VC lib and include directories (Where C:\program files\ is your local location of VC)
|
||||
|
||||
|
||||
* zconf.h [useful.zip]
|
||||
* zlib.h [useful.zip]
|
||||
* png.h [useful.zip]
|
||||
* pngconf.h [useful.zip]
|
||||
* afxres.h
|
||||
|
||||
in
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Include
|
||||
|
||||
and
|
||||
|
||||
* zlibstat.lib [useful.zip]
|
||||
* SDL.lib [SDL.zip]
|
||||
* libpng.lib [useful.zip]
|
||||
|
||||
in
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Lib
|
||||
|
||||
|
||||
---Step 3: DirectX SDK
|
||||
|
||||
(This should work with the latest DirectX SDK as well.) The installation with DirectX 7 was odd, so you'd better use the version available via the forum, see also the download link on top.
|
||||
|
||||
There are 2 folder in the compressed file: Include and Lib
|
||||
|
||||
Copy all files from Include folder to
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Include
|
||||
|
||||
and all files from Lib folder to
|
||||
|
||||
C:\Program Files\Microsoft Visual Studio\VC98\Lib
|
||||
|
||||
|
||||
|
||||
You can also make custom directories, for libraries (.lib) and includes/header files (.h) and add it to the VC paths via:
|
||||
|
||||
Tools -> Options -> Directories -> show directories for:
|
||||
|
||||
a) include files (the include dir: C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include )
|
||||
|
||||
b) library files (the lib dir, C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib )
|
||||
|
||||
|
||||
---Step 4
|
||||
|
||||
Copy the following files from Transport Tycoon Deluxe to the data folder
|
||||
|
||||
* sample.cat
|
||||
* trg1r.grf
|
||||
* trgcr.grf
|
||||
* trghr.grf
|
||||
* trgir.grf
|
||||
* trgtr.grf
|
||||
|
||||
|
||||
---Step 5
|
||||
|
||||
Open trunk/ttd.dsw
|
||||
|
||||
Build menu > Set active configuration > Select: "ttd - Win32 Release with PNG"
|
||||
|
||||
Compile...
|
||||
|
||||
|
||||
Now it should work, it worked for me :)
|
||||
|
||||
From r1319 you can compile branch/map in Debug mode (by Bociusz)
|
||||
|
||||
If it's not working, and you checked that you using the newest SVN (!) report to Bociusz on IRC (irc://irc.freenode.net/#openttd)
|
||||
|
||||
Go ahead and make that patch! Happy Hacking! :)
|
||||
|
||||
Originally written by Dribbel
|
||||
|
||||
Project file updating by Bociusz
|
58
docs/console.txt
Normal file
58
docs/console.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
OPENTTD INGAME CONSOLE DOCUMENTATION
|
||||
====================================
|
||||
http://wiki.openttd.org/index.php/OpenTTDDevBlackBook
|
||||
for detailed information
|
||||
|
||||
*** WARNING **
|
||||
This document is out of date
|
||||
*** WARNING **
|
||||
|
||||
HOTKEY: BACKQUOTE (aka tilde, the key left to "1")
|
||||
|
||||
COMMANDS:
|
||||
---------
|
||||
|
||||
echo [string]
|
||||
echoc [color-code] [string]
|
||||
exit
|
||||
debug_level [0-9]
|
||||
dump_vars [filter]
|
||||
help
|
||||
list_cmds [filter]
|
||||
list_vars [filter]
|
||||
printf [formatstring] [var] [var] [var]....
|
||||
printfc [color-code] [formatstring] [var] [var] [var]....
|
||||
quit
|
||||
random
|
||||
screenshot ["big"/"no_con"]
|
||||
|
||||
VARIABLES:
|
||||
----------
|
||||
*con_developer
|
||||
-> true = console debugging info
|
||||
-> false = no output
|
||||
|
||||
*developer
|
||||
-> 0 = no output
|
||||
-> 1 = console error output [like command not found]
|
||||
-> 2 = console error and debug output
|
||||
|
||||
*cursor_rate
|
||||
-> 1-12 = defines the cursor blink interval
|
||||
|
||||
|
||||
VARIABLE HANDLING:
|
||||
------------------
|
||||
|
||||
developer = 0
|
||||
developer ++
|
||||
|
||||
temp_string = test
|
||||
temp_string = "my little"
|
||||
|
||||
printf "%s world" temp_string
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
feel free to add more commands and use this in-game
|
||||
console for your debugging / enhancements
|
20
docs/directmusic.txt
Normal file
20
docs/directmusic.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Notes about DirectMusic driver for Win32
|
||||
----------------------------------------
|
||||
|
||||
If compiling under MinGW32, you require the DirectX 7.0 files for MinGW32, available from
|
||||
http://alleg.sourceforge.net/files/dx70_mgw.zip.
|
||||
|
||||
If compiling under MSVC 6.0, you require the equivalent for MSVC, available from
|
||||
http://alleg.sourceforge.net/files/dx70_min.zip. MSVC 7.0/7.1 include header files that
|
||||
are recent enough.
|
||||
|
||||
If you do not want to compile the DirectMusic driver, undefine WIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
in stdafx.h.
|
||||
|
||||
Bugs, etc
|
||||
---------
|
||||
|
||||
- The volume control doesn't work properly. I'll fix this soon.
|
||||
|
||||
Owen Rudge
|
||||
14th March 2004
|
1091
docs/elrail.svg
1091
docs/elrail.svg
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
Before Width: | Height: | Size: 61 KiB |
2217
docs/landscape.html
2217
docs/landscape.html
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>
|
@@ -5,348 +5,232 @@
|
||||
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays #2">
|
||||
<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; }
|
||||
td.caption { white-space: nowrap; text-align: left; }
|
||||
td li { white-space: nowrap; text-align: left; }
|
||||
th { white-space: nowrap; text-align: center; }
|
||||
.freebits { background-color: rgb(30, 178, 54);}
|
||||
.abuse { background-color: rgb(255, 58, 31);}
|
||||
</style>
|
||||
</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 arrays are used to encode the information of the contents of the 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="freebits">O</span></span> - bit is free</li>
|
||||
<li><span style="font-weight: bold;">X</span> - bit is used</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of _map_* is abused for different purposes</li>
|
||||
</ul>
|
||||
<p>
|
||||
<ul>
|
||||
<li><span style="font-weight: bold;">type_height</span> - 8 bits in size, stores tile height (lower 4 bits) and tile class (upper 4 bits)</li>
|
||||
<li><span style="font-weight: bold;">m1</span> - 8 bits in size, used to identify the owner of that tile (eg piece of rail, bridge, etc.)</li>
|
||||
<li><span style="font-weight: bold;">m2</span> - 16 bits in size, used to identify the index of the given tile (object) in the (object-)array</li>
|
||||
<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>
|
||||
<li><span style="font-weight: bold;">_map_owner[]</span> - 8 bits in size, used to identify the owner of that tile (eg piece of rail, bridge, etc.).</li>
|
||||
<li><span style="font-weight: bold;">_map2[]</span> - 16 bits in size, used to identify the index of the given tile (object) in the (object-)array.</li>
|
||||
<li><span style="font-weight: bold;">_map3[]</span> - 16 bits in size, which is split up into _map3lo[] and _map3hi[] is used for general storage.</li>
|
||||
<li><span style="font-weight: bold;">_map_type_and_height[]</span> - 8 bits in size, stores tile height (lower 4 bits) and tile class (upper 4 bits).</li>
|
||||
<li><span style="font-weight: bold;">_map5[]</span> - 8 bits in size, is used for general storage.</li>
|
||||
</ul>
|
||||
|
||||
<table align=center border="1" cellpadding="2" cellspacing="2">
|
||||
<table style="text-align: left;" border="1" cellpadding="2"
|
||||
cellspacing="2" width="100%">
|
||||
<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>m5 (8)</th>
|
||||
<th>m6 (8)</th>
|
||||
<th>m7 (8)</th>
|
||||
<th style="white-space: nowrap; text-align: left;">class</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map_owner[L1] (8)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map2[L2] (16)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map3[lo& hi,L3] (16)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map_type_and_height[L4] (8)</th>
|
||||
<th style="white-space: nowrap; text-align: center;">_map5[L5] (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>
|
||||
<td style="white-space: nowrap; text-align: left;">(0) ground</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OO</span>XX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">O</span>XX</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 style="white-space: nowrap; text-align: left;">(1) rail</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span><br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXX<span class="freebits">O OOOO</span><br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX<br>
|
||||
</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>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">depot/checkpoint</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=4>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">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 style="white-space: nowrap; text-align: left;">(2) road</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">level crossing</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
|
||||
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OO</span>XX XXXX</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>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">road depot</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOO</span>X</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX</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 style="white-space: nowrap; text-align: left;">(3) town</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
|
||||
</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">O</span>X</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 style="white-space: nowrap; text-align: left;">(4) trees</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">OO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OO</span>XX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</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 style="white-space: nowrap; text-align: left;">(5) station</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</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</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 style="white-space: nowrap; text-align: left;">(6) water</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">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="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="option">~ ~~</span>XX</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 style="white-space: nowrap; text-align: left;">(8) industry</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX X</span><span class="freebits">OO</span><span class="abuse">X</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX 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 XX<span class="free">OO</span></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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">bubble/sugar/toffee</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=6>5</td>
|
||||
<td class="caption">rail 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>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">toy factory</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road stop</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">gold/copper/coal</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">oil wells</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">power station</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XX<span class="freebits">O</span>X</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</td>
|
||||
<td style="text-align: center;">-inherit-</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>
|
||||
<td style="white-space: nowrap; text-align: left;">(9) tunnel</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OOOO OOO</span>X</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</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>
|
||||
<td>
|
||||
<ul>
|
||||
<li style="white-space: nowrap; text-align: left;">bridge</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;"><span class="abuse">XXXX XXXX</span> <span class="freebits">OOOO OOOO</span></td>
|
||||
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOO</span>X</td>
|
||||
<td style="text-align: center;">XXXX XXXX</td>
|
||||
<td style="text-align: center;">XXXX XXXX</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>
|
||||
</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 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">XXXX XXXX XXXX XXXX</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 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>
|
||||
</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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=2>A</td>
|
||||
<td class="caption">unmovables</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">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 style="white-space: nowrap; text-align: left;">(10) various (HQ)</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@@ -9,7 +9,7 @@ Multiplayer Manual for OpenTTD (0.3.5)
|
||||
- Type in a game name
|
||||
- Select the type of game ('LAN/Internet' or 'Internet (advertise)'. With the last one
|
||||
other people are able to see you online. Else they need your IP and port to join)
|
||||
- Click "start game", "load game" or "load scenario"
|
||||
- Click "start game" ,"load game" or "load scenario"
|
||||
- Start playing
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Multiplayer Manual for OpenTTD (0.3.5)
|
||||
|
||||
- Open the console and type in the following command:
|
||||
|
||||
connect <ip/host>:<port>#<player-no>
|
||||
]connect <ip/host>:<port>#<player-no>
|
||||
|
||||
|
||||
4. Playing Internet-Games
|
||||
@@ -54,9 +54,7 @@ Multiplayer Manual for OpenTTD (0.3.5)
|
||||
|
||||
- Since OpenTTD 0.3.5 the network protocol has been rewritten and is very stable, even over slow connections.
|
||||
|
||||
- Servers with a red dot behind it have a different version then you have. You will not be able to join those servers.
|
||||
|
||||
- Servers with a yellow dot behind it have NewGRFs that you do not have. You will not be able to join those servers.
|
||||
- Server with a red dot behind it have a different version then you have. You will not be able to join those servers.
|
||||
|
||||
- It can happen that a connection is that slow, or you have that many clients connected to your server, that your clients start to loose their connection. Some things you can do about it:
|
||||
|
||||
@@ -112,10 +110,3 @@ Multiplayer Manual for OpenTTD (0.3.5)
|
||||
- From 0.3.5, desyncs should not happen anymore
|
||||
|
||||
- From 0.3.5, patch-settings are also synced. You can now play without deleting openttd.cfg, and with, for example, extra large trains enabled.
|
||||
|
||||
7. Troubleshooting
|
||||
------------------
|
||||
|
||||
- My advertised server does not show up in the 'advertised server list' (servers.openttd.org)
|
||||
Run openttd with the '-d net=2' parameter, as this will show whether it receives replies from the master server.
|
||||
If it does not receive replies it is most likely that you need to configure your router to forward the OpenTTD ports 3979 (both TCP and UDP) to the computer that is hosting the game.
|
||||
|
@@ -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.
|
139
docs/openttd.6
139
docs/openttd.6
@@ -1,93 +1,50 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH OPENTTD 6 "September 16, 2004"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.Dd Feb 05, 2009
|
||||
.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 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 n Ar host[:port][#player]
|
||||
.Op Fl r Ar widthxheight
|
||||
.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 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
|
||||
Fork into background (dedicated only, see
|
||||
.Fl D )
|
||||
.It Fl g Ar [savegame]
|
||||
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
|
||||
.It Fl m Ar driver
|
||||
Set the music driver, see
|
||||
.Fl h
|
||||
.It Fl n Ar host[:port][#player]
|
||||
Join a network game, optionally specify player to play as and port to connect to
|
||||
.It Fl r Ar widthxheight
|
||||
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 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
|
||||
.Sh HISTORY
|
||||
Transport Tycoon Deluxe was written by Chris Sawyer and published by Microprose.
|
||||
.Nm
|
||||
is a free reimplementation.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
openttd \- An open source clone of the Microprose game "Transport Tycoon Deluxe"
|
||||
.SH SYNOPSIS
|
||||
.B openttd
|
||||
.RI [ options ]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
Unfortunately, there is no real manpage for openttd yet. Hopefully someone
|
||||
will write one soon. For now you should use
|
||||
.B openttd -h
|
||||
for more information, or check our Wiki manual: http://wiki.openttd.org/
|
||||
.PP
|
||||
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
|
||||
.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
|
||||
.\" respectively.
|
||||
.\" \fBopenttd\fP is a program that...
|
||||
.SH OPTIONS
|
||||
Wouldn't we like to have something here?
|
||||
.\" below are commented out, to serve as layout examples for when somebody
|
||||
.\" does actually fill this page
|
||||
.\" .TP
|
||||
.\" .B \-h, \-\-help
|
||||
.\" Show summary of options.
|
||||
.\" .TP
|
||||
.\" .B \-v, \-\-version
|
||||
.\" Show version of program.
|
||||
.\" .SH SEE ALSO
|
||||
.\" .BR bar (1),
|
||||
.\" .BR baz (1).
|
||||
.br
|
||||
.SH AUTHOR
|
||||
This manual page was written by Matthijs Kooijman <matthijs@katherina.student.utwente.nl>,
|
||||
for the Debian project (but may be used by others).
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
38
docs/textcolor.txt
Normal file
38
docs/textcolor.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
0,9,10,2,3,13,9,9,0,10,4,15,6,11,14,1
|
||||
dark blue=0 =0
|
||||
pale_green=1 =9
|
||||
pink=2 =10
|
||||
yellow=3 =2
|
||||
red=4 =3
|
||||
light blue=5 =13
|
||||
green=6 =9
|
||||
dark green=7 =9
|
||||
blue=8 =0
|
||||
cream=9 =10
|
||||
mauve=10 =4
|
||||
purple=11 =15
|
||||
orange=12 =6
|
||||
brown=13 =11
|
||||
grey=14 =14
|
||||
white=15 =1
|
||||
|
||||
|
||||
=blue=0
|
||||
=white=1
|
||||
=yellow=2
|
||||
=red=3
|
||||
=blue=4
|
||||
=grey=5
|
||||
=orange=6
|
||||
=green=7
|
||||
=light yellow=8
|
||||
=light green=9
|
||||
=cream=10
|
||||
=brown=11
|
||||
=white=12
|
||||
=light blue=13
|
||||
=dark grey=14
|
||||
=purple=15
|
||||
=black=16
|
||||
=dark green=17=not good
|
||||
=dark grey=21
|
78
dummy_land.c
Normal file
78
dummy_land.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
|
||||
static void DrawTile_Dummy(TileInfo *ti)
|
||||
{
|
||||
DrawGroundSpriteAt(0x3EC, ti->x, ti->y, ti->z);
|
||||
}
|
||||
|
||||
|
||||
static uint GetSlopeZ_Dummy(TileInfo *ti) {
|
||||
return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z;
|
||||
}
|
||||
|
||||
static uint GetSlopeTileh_Dummy(TileInfo *ti) {
|
||||
return ti->tileh;
|
||||
}
|
||||
|
||||
static int32 ClearTile_Dummy(uint tile, byte flags) {
|
||||
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
|
||||
}
|
||||
|
||||
|
||||
static void GetAcceptedCargo_Dummy(uint tile, AcceptedCargo ac)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void GetTileDesc_Dummy(uint tile, TileDesc *td)
|
||||
{
|
||||
td->str = STR_EMPTY;
|
||||
td->owner = OWNER_NONE;
|
||||
}
|
||||
|
||||
static void AnimateTile_Dummy(uint tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void TileLoop_Dummy(uint tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ClickTile_Dummy(uint tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Dummy(uint tile, byte old_player, byte new_player)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Dummy(uint 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 */
|
||||
NULL, /* vehicle_leave_tile_proc */
|
||||
GetSlopeTileh_Dummy, /* get_slope_tileh_proc */
|
||||
};
|
||||
|
78
economy.h
Normal file
78
economy.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef ECONOMY_H
|
||||
#define ECONOMY_H
|
||||
|
||||
typedef struct {
|
||||
// Maximum possible loan
|
||||
int32 max_loan;
|
||||
int32 max_loan_unround;
|
||||
// Economy fluctuation status
|
||||
int fluct;
|
||||
// Interest
|
||||
byte interest_rate;
|
||||
byte infl_amount;
|
||||
byte infl_amount_pr;
|
||||
} Economy;
|
||||
|
||||
VARDEF Economy _economy;
|
||||
|
||||
typedef struct Subsidy {
|
||||
byte cargo_type;
|
||||
byte age;
|
||||
uint16 from;
|
||||
uint16 to;
|
||||
} Subsidy;
|
||||
|
||||
|
||||
enum {
|
||||
SCORE_VEHICLES = 0,
|
||||
SCORE_STATIONS = 1,
|
||||
SCORE_MIN_PROFIT = 2,
|
||||
SCORE_MIN_INCOME = 3,
|
||||
SCORE_MAX_INCOME = 4,
|
||||
SCORE_DELIVERED = 5,
|
||||
SCORE_CARGO = 6,
|
||||
SCORE_MONEY = 7,
|
||||
SCORE_LOAN = 8,
|
||||
SCORE_TOTAL = 9, // This must always be the last entry
|
||||
|
||||
NUM_SCORE = 10, // How many scores are there..
|
||||
|
||||
SCORE_MAX = 1000, // The max score that can be in the performance history
|
||||
// the scores together of score_info is allowed to be more!
|
||||
};
|
||||
|
||||
typedef struct ScoreInfo {
|
||||
byte id; // Unique ID of the score
|
||||
int needed; // How much you need to get the perfect score
|
||||
int score; // How much score it will give
|
||||
} ScoreInfo;
|
||||
|
||||
static const ScoreInfo score_info[] = {
|
||||
{SCORE_VEHICLES, 120, 100},
|
||||
{SCORE_STATIONS, 80, 100},
|
||||
{SCORE_MIN_PROFIT, 10000, 100},
|
||||
{SCORE_MIN_INCOME, 50000, 50},
|
||||
{SCORE_MAX_INCOME, 100000, 100},
|
||||
{SCORE_DELIVERED, 40000, 400},
|
||||
{SCORE_CARGO, 8, 50},
|
||||
{SCORE_MONEY, 10000000, 50},
|
||||
{SCORE_LOAN, 250000, 50},
|
||||
{SCORE_TOTAL, 0, 0}
|
||||
};
|
||||
|
||||
int _score_part[MAX_PLAYERS][NUM_SCORE];
|
||||
|
||||
int UpdateCompanyRatingAndValue(Player *p, bool update);
|
||||
void UpdatePlayerHouse(Player *p, uint score);
|
||||
|
||||
|
||||
VARDEF Subsidy _subsidies[MAX_PLAYERS];
|
||||
Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode);
|
||||
void DeleteSubsidyWithIndustry(uint16 index);
|
||||
void DeleteSubsidyWithStation(uint16 index);
|
||||
void RemoteSubsidyAdd(Subsidy *s_new);
|
||||
|
||||
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type);
|
||||
uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount);
|
||||
|
||||
#endif /* ECONOMY_H */
|
30
endian_check.c
Normal file
30
endian_check.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
|
||||
// This pretty simple file checks if the system is LITTLE_ENDIAN or BIG_ENDIAN
|
||||
// it does that by putting a 1 and a 0 in an array, and read it out as one
|
||||
// number. If it is 1, it is LITTLE_ENDIAN, if it is 256, it is BIG_ENDIAN
|
||||
//
|
||||
// After that it outputs the contents of an include files (endian.h)
|
||||
// that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes
|
||||
// care of the real writing to the file.
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
unsigned char EndianTest[2] = { 1, 0 };
|
||||
int force_BE = 0, force_LE = 0;
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "BE") == 0)
|
||||
force_BE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "LE") == 0)
|
||||
force_LE = 1;
|
||||
|
||||
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
|
||||
|
||||
if ( (*(short *) EndianTest == 1 && force_BE != 1) || force_LE == 1)
|
||||
printf("#define TTD_LITTLE_ENDIAN\n");
|
||||
else
|
||||
printf("#define TTD_BIG_ENDIAN\n");
|
||||
|
||||
printf("#endif\n");
|
||||
|
||||
return 0;
|
||||
}
|
233
engine.h
Normal file
233
engine.h
Normal file
@@ -0,0 +1,233 @@
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
typedef struct RailVehicleInfo {
|
||||
byte image_index;
|
||||
byte flags; /* 1=multihead engine, 2=wagon */
|
||||
byte base_cost;
|
||||
uint16 max_speed;
|
||||
uint16 power;
|
||||
byte weight;
|
||||
byte running_cost_base;
|
||||
byte engclass; // 0: steam, 1: diesel, 2: electric
|
||||
byte capacity;
|
||||
byte cargo_type;
|
||||
} RailVehicleInfo;
|
||||
|
||||
typedef struct ShipVehicleInfo {
|
||||
byte image_index;
|
||||
byte base_cost;
|
||||
uint16 max_speed;
|
||||
byte cargo_type;
|
||||
uint16 capacity;
|
||||
byte running_cost;
|
||||
byte sfx;
|
||||
byte refittable;
|
||||
} ShipVehicleInfo;
|
||||
|
||||
typedef struct AircraftVehicleInfo {
|
||||
byte image_index;
|
||||
byte base_cost;
|
||||
byte running_cost;
|
||||
byte subtype;
|
||||
byte sfx;
|
||||
byte acceleration;
|
||||
byte max_speed;
|
||||
byte mail_capacity;
|
||||
uint16 passenger_capacity;
|
||||
} AircraftVehicleInfo;
|
||||
|
||||
typedef struct RoadVehicleInfo {
|
||||
byte image_index;
|
||||
byte base_cost;
|
||||
byte running_cost;
|
||||
byte sfx;
|
||||
byte max_speed;
|
||||
byte capacity;
|
||||
byte cargo_type;
|
||||
} RoadVehicleInfo;
|
||||
|
||||
typedef struct EngineInfo {
|
||||
uint16 base_intro;
|
||||
byte unk2;
|
||||
byte lifelength;
|
||||
byte base_life;
|
||||
byte railtype_climates;
|
||||
} EngineInfo;
|
||||
|
||||
typedef struct Engine {
|
||||
uint16 intro_date;
|
||||
uint16 age;
|
||||
uint16 reliability;
|
||||
uint16 reliability_spd_dec;
|
||||
uint16 reliability_start, reliability_max, reliability_final;
|
||||
uint16 duration_phase_1, duration_phase_2, duration_phase_3;
|
||||
byte lifelength;
|
||||
byte flags;
|
||||
PlayerID preview_player;
|
||||
byte preview_wait;
|
||||
byte railtype;
|
||||
PlayerID player_avail;
|
||||
byte type; // type, ie VEH_Road, VEH_Train, etc. Same as in vehicle.h
|
||||
} Engine;
|
||||
|
||||
|
||||
enum {
|
||||
RVI_MULTIHEAD = 1,
|
||||
RVI_WAGON = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
NUM_VEHICLE_TYPES = 6
|
||||
};
|
||||
|
||||
void AddTypeToEngines(void);
|
||||
void StartupEngines(void);
|
||||
|
||||
enum GlobalCargo {
|
||||
GC_PASSENGERS = 0,
|
||||
GC_COAL = 1,
|
||||
GC_MAIL = 2,
|
||||
GC_OIL = 3,
|
||||
GC_LIVESTOCK = 4,
|
||||
GC_GOODS = 5,
|
||||
GC_GRAIN = 6, // GC_WHEAT / GC_MAIZE
|
||||
GC_WOOD = 7,
|
||||
GC_IRON_ORE = 8,
|
||||
GC_STEEL = 9,
|
||||
GC_VALUABLES = 10, // GC_GOLD / GC_DIAMONDS
|
||||
GC_PAPER = 11,
|
||||
GC_FOOD = 12,
|
||||
GC_FRUIT = 13,
|
||||
GC_COPPER_ORE = 14,
|
||||
GC_WATER = 15,
|
||||
GC_RUBBER = 16,
|
||||
GC_SUGAR = 17,
|
||||
GC_TOYS = 18,
|
||||
GC_BATTERIES = 19,
|
||||
GC_CANDY = 20,
|
||||
GC_TOFFEE = 21,
|
||||
GC_COLA = 22,
|
||||
GC_COTTON_CANDY = 23,
|
||||
GC_BUBBLES = 24,
|
||||
GC_PLASTIC = 25,
|
||||
GC_FIZZY_DRINKS = 26,
|
||||
GC_PAPER_TEMP = 27,
|
||||
GC_UNDEFINED = 28, // undefined; unused slot in arctic climate
|
||||
GC_DEFAULT = 29,
|
||||
GC_PURCHASE = 30,
|
||||
GC_INVALID = 255,
|
||||
NUM_GLOBAL_CID = 31
|
||||
};
|
||||
|
||||
VARDEF const uint32 _default_refitmasks[NUM_VEHICLE_TYPES];
|
||||
VARDEF const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
|
||||
VARDEF const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE];
|
||||
VARDEF const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID];
|
||||
|
||||
VARDEF uint32 _engine_refit_masks[256];
|
||||
VARDEF byte _engine_original_sprites[256];
|
||||
void SetWagonOverrideSprites(byte engine, struct SpriteGroup *group, byte *train_id, int trains);
|
||||
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteGroup *group);
|
||||
// loaded is in percents, overriding_engine 0xffff is none
|
||||
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction);
|
||||
#define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction)
|
||||
#define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction)
|
||||
|
||||
typedef enum VehicleTrigger {
|
||||
VEHICLE_TRIGGER_NEW_CARGO = 1,
|
||||
// Externally triggered only for the first vehicle in chain
|
||||
VEHICLE_TRIGGER_DEPOT = 2,
|
||||
// Externally triggered only for the first vehicle in chain, only if whole chain is empty
|
||||
VEHICLE_TRIGGER_EMPTY = 4,
|
||||
// Not triggered externally (called for the whole chain if we got NEW_CARGO)
|
||||
VEHICLE_TRIGGER_ANY_NEW_CARGO = 8,
|
||||
} VehicleTrigger;
|
||||
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger);
|
||||
|
||||
void SetCustomEngineName(int engine, const char *name);
|
||||
StringID GetCustomEngineName(int engine);
|
||||
|
||||
|
||||
void DrawTrainEngine(int x, int y, int engine, uint32 image_ormod);
|
||||
void DrawRoadVehEngine(int x, int y, int engine, uint32 image_ormod);
|
||||
void DrawShipEngine(int x, int y, int engine, uint32 image_ormod);
|
||||
void DrawAircraftEngine(int x, int y, int engine, uint32 image_ormod);
|
||||
|
||||
void DrawTrainEngineInfo(int engine, int x, int y, int maxw);
|
||||
void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw);
|
||||
void DrawShipEngineInfo(int engine, int x, int y, int maxw);
|
||||
void DrawAircraftEngineInfo(int engine, int x, int y, int maxw);
|
||||
|
||||
void AcceptEnginePreview(Engine *e, PlayerID player);
|
||||
|
||||
void LoadCustomEngineNames(void);
|
||||
void DeleteCustomEngineNames(void);
|
||||
|
||||
bool IsEngineBuildable(uint engine, byte type);
|
||||
void UnInitNewgrEngines(void);
|
||||
|
||||
enum {
|
||||
NUM_NORMAL_RAIL_ENGINES = 54,
|
||||
NUM_MONORAIL_ENGINES = 30,
|
||||
NUM_MAGLEV_ENGINES = 32,
|
||||
NUM_TRAIN_ENGINES = NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES + NUM_MAGLEV_ENGINES,
|
||||
NUM_ROAD_ENGINES = 88,
|
||||
NUM_SHIP_ENGINES = 11,
|
||||
NUM_AIRCRAFT_ENGINES = 41,
|
||||
TOTAL_NUM_ENGINES = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES + NUM_AIRCRAFT_ENGINES,
|
||||
AIRCRAFT_ENGINES_INDEX = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES,
|
||||
SHIP_ENGINES_INDEX = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES,
|
||||
ROAD_ENGINES_INDEX = NUM_TRAIN_ENGINES,
|
||||
};
|
||||
VARDEF Engine _engines[TOTAL_NUM_ENGINES];
|
||||
#define FOR_ALL_ENGINES(e) for (e = _engines; e != endof(_engines); e++)
|
||||
#define DEREF_ENGINE(i) (GetEngine(i))
|
||||
static inline Engine* GetEngine(uint i)
|
||||
{
|
||||
assert(i < lengthof(_engines));
|
||||
return &_engines[i];
|
||||
}
|
||||
|
||||
VARDEF StringID _engine_name_strings[TOTAL_NUM_ENGINES];
|
||||
|
||||
static inline bool IsEngineIndex(uint index)
|
||||
{
|
||||
return index < TOTAL_NUM_ENGINES;
|
||||
}
|
||||
|
||||
/* Access Vehicle Data */
|
||||
//#include "table/engines.h"
|
||||
extern EngineInfo _engine_info[TOTAL_NUM_ENGINES];
|
||||
extern RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
|
||||
extern ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES];
|
||||
extern AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
|
||||
extern RoadVehicleInfo _road_vehicle_info[NUM_ROAD_ENGINES];
|
||||
|
||||
static inline RailVehicleInfo *RailVehInfo(uint e)
|
||||
{
|
||||
assert(e < lengthof(_rail_vehicle_info));
|
||||
return &_rail_vehicle_info[e];
|
||||
}
|
||||
|
||||
static inline ShipVehicleInfo *ShipVehInfo(uint e)
|
||||
{
|
||||
assert(e - SHIP_ENGINES_INDEX < lengthof(_ship_vehicle_info));
|
||||
return &_ship_vehicle_info[e - SHIP_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline AircraftVehicleInfo *AircraftVehInfo(uint e)
|
||||
{
|
||||
assert(e - AIRCRAFT_ENGINES_INDEX < lengthof(_aircraft_vehicle_info));
|
||||
return &_aircraft_vehicle_info[e - AIRCRAFT_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline RoadVehicleInfo *RoadVehInfo(uint e)
|
||||
{
|
||||
assert(e - ROAD_ENGINES_INDEX < lengthof(_road_vehicle_info));
|
||||
return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
#endif
|
223
engine_gui.c
Normal file
223
engine_gui.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "engine.h"
|
||||
#include "command.h"
|
||||
#include "news.h"
|
||||
|
||||
|
||||
static StringID GetEngineCategoryName(byte engine)
|
||||
{
|
||||
if (engine < NUM_TRAIN_ENGINES) {
|
||||
switch (_engines[engine].railtype) {
|
||||
case 0:
|
||||
return STR_8102_RAILROAD_LOCOMOTIVE;
|
||||
case 1:
|
||||
return STR_8106_MONORAIL_LOCOMOTIVE;
|
||||
case 2:
|
||||
return STR_8107_MAGLEV_LOCOMOTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES)
|
||||
return STR_8103_ROAD_VEHICLE;
|
||||
|
||||
if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES)
|
||||
return STR_8105_SHIP;
|
||||
|
||||
return STR_8104_AIRCRAFT;
|
||||
}
|
||||
|
||||
static const Widget _engine_preview_widgets[] = {
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 5, 11, 299, 0, 13, STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_IMGBTN, RESIZE_NONE, 5, 0, 299, 14, 191, 0x0, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 5, 85, 144, 172, 183, STR_00C9_NO, STR_NULL},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 5, 155, 214, 172, 183, STR_00C8_YES, STR_NULL},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
typedef void DrawEngineProc(int x, int y, int engine, uint32 image_ormod);
|
||||
typedef void DrawEngineInfoProc(int x, int y, int engine, int maxw);
|
||||
|
||||
typedef struct DrawEngineInfo {
|
||||
DrawEngineProc *engine_proc;
|
||||
DrawEngineInfoProc *info_proc;
|
||||
} DrawEngineInfo;
|
||||
|
||||
static const DrawEngineInfo _draw_engine_list[4] = {
|
||||
{DrawTrainEngine,DrawTrainEngineInfo},
|
||||
{DrawRoadVehEngine,DrawRoadVehEngineInfo},
|
||||
{DrawShipEngine,DrawShipEngineInfo},
|
||||
{DrawAircraftEngine,DrawAircraftEngineInfo},
|
||||
};
|
||||
|
||||
static void EnginePreviewWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
byte eng;
|
||||
int engine;
|
||||
const DrawEngineInfo *dei;
|
||||
int width;
|
||||
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
engine = w->window_number;
|
||||
|
||||
SetDParam(0, GetEngineCategoryName(engine));
|
||||
DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
|
||||
|
||||
DrawStringCentered(w->width >> 1, 80, GetCustomEngineName(engine), 0x10);
|
||||
|
||||
eng = (byte)engine;
|
||||
(dei = _draw_engine_list,eng < NUM_TRAIN_ENGINES) ||
|
||||
(dei++,eng < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES) ||
|
||||
(dei++,eng < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES) ||
|
||||
(dei++, true);
|
||||
|
||||
width = w->width;
|
||||
dei->engine_proc(width >> 1, 100, engine, 0);
|
||||
dei->info_proc(engine, width >> 1, 130, width - 52);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
switch(e->click.widget) {
|
||||
case 3: DeleteWindow(w); break;
|
||||
case 4:
|
||||
DoCommandP(0, w->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW);
|
||||
DeleteWindow(w);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const WindowDesc _engine_preview_desc = {
|
||||
WDP_CENTER, WDP_CENTER, 300, 192,
|
||||
WC_ENGINE_PREVIEW,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_engine_preview_widgets,
|
||||
EnginePreviewWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowEnginePreviewWindow(int engine)
|
||||
{
|
||||
Window *w;
|
||||
|
||||
w = AllocateWindowDesc(&_engine_preview_desc);
|
||||
w->window_number = engine;
|
||||
}
|
||||
|
||||
void DrawNewsNewTrainAvail(Window *w)
|
||||
{
|
||||
int engine;
|
||||
|
||||
DrawNewsBorder(w);
|
||||
|
||||
engine = WP(w,news_d).ni->string_id;
|
||||
SetDParam(0, GetEngineCategoryName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_8859_NEW_NOW_AVAILABLE, w->width - 2);
|
||||
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_885A, w->width - 2);
|
||||
|
||||
DrawTrainEngine(w->width >> 1, 88, engine, 0);
|
||||
GfxFillRect(25, 56, w->width - 56, 112, 0x4323);
|
||||
DrawTrainEngineInfo(engine, w->width >> 1, 129, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewTrainAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SetDParam(0, STR_8859_NEW_NOW_AVAILABLE);
|
||||
SetDParam(1, GetEngineCategoryName(engine));
|
||||
SetDParam(2, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
void DrawNewsNewAircraftAvail(Window *w)
|
||||
{
|
||||
int engine;
|
||||
|
||||
DrawNewsBorder(w);
|
||||
|
||||
engine = WP(w,news_d).ni->string_id;
|
||||
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_A02D, w->width - 2);
|
||||
|
||||
DrawAircraftEngine(w->width >> 1, 93, engine, 0);
|
||||
GfxFillRect(25, 56, w->width - 56, 110, 0x4323);
|
||||
DrawAircraftEngineInfo(engine, w->width >> 1, 131, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewAircraftAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SetDParam(0, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
void DrawNewsNewRoadVehAvail(Window *w)
|
||||
{
|
||||
int engine;
|
||||
|
||||
DrawNewsBorder(w);
|
||||
|
||||
engine = WP(w,news_d).ni->string_id;
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_9029, w->width - 2);
|
||||
|
||||
DrawRoadVehEngine(w->width >> 1, 88, engine, 0);
|
||||
GfxFillRect(25, 56, w->width - 56, 112, 0x4323);
|
||||
DrawRoadVehEngineInfo(engine, w->width >> 1, 129, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewRoadVehAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SetDParam(0, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
void DrawNewsNewShipAvail(Window *w)
|
||||
{
|
||||
int engine;
|
||||
|
||||
DrawNewsBorder(w);
|
||||
|
||||
engine = WP(w,news_d).ni->string_id;
|
||||
|
||||
DrawStringMultiCenter(w->width >> 1, 20, STR_982C_NEW_SHIP_NOW_AVAILABLE, w->width - 2);
|
||||
GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
|
||||
|
||||
SetDParam(0, GetCustomEngineName(engine));
|
||||
DrawStringMultiCenter(w->width >> 1, 57, STR_982D, w->width - 2);
|
||||
|
||||
DrawShipEngine(w->width >> 1, 93, engine, 0);
|
||||
GfxFillRect(25, 56, w->width - 56, 110, 0x4323);
|
||||
DrawShipEngineInfo(engine, w->width >> 1, 131, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewShipAvail(NewsItem *ni)
|
||||
{
|
||||
int engine = ni->string_id;
|
||||
SetDParam(0, STR_982C_NEW_SHIP_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user