mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-07-16 07:39:52 +00:00
Compare commits
161 Commits
0.6.3
..
release/0.4
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e11b36000 | |||
| 2452a20e07 | |||
| ffa39381d9 | |||
| f2e4b69d5c | |||
| a597fd50e6 | |||
| 6f920cee6c | |||
| bd736e240a | |||
| 6c3eedee86 | |||
| 9214c5e0a5 | |||
| 6af2e64186 | |||
| 58b4fd7683 | |||
| f3cce610c8 | |||
| 5c30032fe5 | |||
| 6708e181eb | |||
| d81a7bf904 | |||
| 9c95e99871 | |||
| 8ecd975951 | |||
| 955d4393e0 | |||
| f0ba57ea82 | |||
| ebae6200c0 | |||
| 47fc5a070b | |||
| a22933719b | |||
| 5fe523dfcd | |||
| 514eee8067 | |||
| 3ed386c180 | |||
| 22df8a8d6b | |||
| a2fc417d86 | |||
| 339160760b | |||
| 93713354a2 | |||
| e3e64430d7 | |||
| 20b5c17faa | |||
| f0fd9921a2 | |||
| 47a1e50406 | |||
| c96daf6230 | |||
| 257ba823a0 | |||
| 7fd164deba | |||
| 73dab80259 | |||
| 91fc18dcdc | |||
| 6d4c3f9636 | |||
| d070a97f7a | |||
| a8d2aa157a | |||
| af0354ad24 | |||
| 12a68cc7c3 | |||
| 45ea5388fe | |||
| 1be4771689 | |||
| 590cd1d07b | |||
| 4f27e53d17 | |||
| f026c645e3 | |||
| 00f2b3e713 | |||
| ca175e873f | |||
| 86e4f20be8 | |||
| d24165ea71 | |||
| c2e9eb7d7b | |||
| ec9870a611 | |||
| 1f9a69bc89 | |||
| a707c043fc | |||
| 587cedc35b | |||
| f5e0e18dca | |||
| 5c8bd4b143 | |||
| d1ca343504 | |||
| a27b563c40 | |||
| f6e8773297 | |||
| 0f012198c4 | |||
| d27bedce36 | |||
| 8892c1d1de | |||
| 660d991cc1 | |||
| 63a1bc7ee7 | |||
| 2aba4c3354 | |||
| 4021f48c58 | |||
| ca6ccf035f | |||
| f2143b3d9b | |||
| 9c97eb32ba | |||
| f9fc273d2a | |||
| 343fdd71ef | |||
| 3d8b1c4fec | |||
| 00c45347fd | |||
| 6fc56409e6 | |||
| 8e4cf4d599 | |||
| 52d25fe06f | |||
| 17b691188d | |||
| ec18908c82 | |||
| 271af9fbfc | |||
| ba6fcc84c8 | |||
| a8ddd50157 | |||
| dcfd3acc8f | |||
| d5bcaec677 | |||
| a336c7cd0c | |||
| a343d86500 | |||
| 61370f9e14 | |||
| f7228e0b3a | |||
| eb703a5768 | |||
| f0e3fa29e5 | |||
| aba21dd563 | |||
| f8eb72e188 | |||
| f9a2d113ab | |||
| f26027da17 | |||
| a32fdb390f | |||
| 8bfb955d4b | |||
| 3a3a1da4e7 | |||
| ec47441ce4 | |||
| 39ebb55b9b | |||
| c59beffe6b | |||
| 2576164325 | |||
| bacbe211e7 | |||
| 0381a100fa | |||
| 6573b46ca3 | |||
| 05b541f63a | |||
| 8a74170da0 | |||
| a0bf18c3c9 | |||
| 31b226dc9f | |||
| b320aa40fa | |||
| 37835e9158 | |||
| 749a4f8c7d | |||
| e72232dc4c | |||
| 45a4c69842 | |||
| a2c882af6f | |||
| bb7c37b515 | |||
| ec54b3ac24 | |||
| a9032183df | |||
| 90feff4982 | |||
| e434485dd8 | |||
| dcc4ccf4e9 | |||
| ef7e4abf7f | |||
| 5d0ed8fab8 | |||
| ed7df6e2bf | |||
| 7cf9e0d8ca | |||
| 85141929a8 | |||
| f4d5c1b01b | |||
| 31d6286cb4 | |||
| ca0a0cdbfd | |||
| 04572ed7fe | |||
| ebfef9683e | |||
| c05d3dd558 | |||
| 6e029fe97d | |||
| 26ed195319 | |||
| 7170357a10 | |||
| e4bbd3b41c | |||
| 5ed5e6beed | |||
| 5de94db9df | |||
| 6b664a3ba0 | |||
| beee5698f9 | |||
| a86ec733a0 | |||
| 37c1135d6b | |||
| 923dee9bec | |||
| 1856976d8e | |||
| 818a5a596f | |||
| 2be4b388ec | |||
| 300aba48cc | |||
| f470a87dea | |||
| 4b938510a5 | |||
| 7ddae93da8 | |||
| f75365fcf4 | |||
| e89a98d296 | |||
| 8157969b2b | |||
| b3ccef7045 | |||
| af0fb58264 | |||
| 5f2e2ef32a | |||
| 8353c1260a | |||
| 8de919ce50 | |||
| f9cacc9f5c | |||
| af3ac4954a |
-11
@@ -1,11 +0,0 @@
|
||||
Makefile*
|
||||
bin/*
|
||||
!bin/data/chars.grf
|
||||
!bin/data/openttdd.grf
|
||||
!bin/data/openttdw.grf
|
||||
!bin/data/opntitle.grf
|
||||
!bin/scenario/README
|
||||
!bin/scripts*
|
||||
config.*
|
||||
objs/*
|
||||
src/rev.cpp
|
||||
@@ -1,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.
|
||||
|
||||
@@ -5,6 +5,7 @@ PROJECT_NAME = openttd
|
||||
OUTPUT_DIRECTORY = docs/source/
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
@@ -83,7 +84,6 @@ FILE_PATTERNS = *.c \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.h \
|
||||
*.hpp \
|
||||
table/*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
@@ -158,7 +158,7 @@ RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_MAN = YES
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
@@ -185,13 +185,13 @@ PERLMOD_MAKEVAR_PREFIX =
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED = DEF_COMMAND
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
@@ -220,6 +220,8 @@ DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
|
||||
@@ -0,0 +1,994 @@
|
||||
# $Id$
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Usage
|
||||
#
|
||||
|
||||
# Synopsis:
|
||||
#
|
||||
# make WITH_ZLIB=1 UNIX=1 MANUAL_CONFIG=1
|
||||
#
|
||||
# (See below for the list of possible options.)
|
||||
#
|
||||
# Alternately, you can run make without the MANUAL_CONFIG part. It then
|
||||
# generates Makefile.config, where you can customize all the options.
|
||||
# However beware that for all subsequent calls the option values from
|
||||
# Makefile.config take precedence to the commandline options.
|
||||
#
|
||||
# (That means that you probably want to either specify the options on command
|
||||
# line together with MANUAL_CONFIG=1 or you want to specify no commandline
|
||||
# options at all.)
|
||||
|
||||
# Targets:
|
||||
#
|
||||
# Defaults to building binary
|
||||
# clean: remove intermediate build files
|
||||
# mrproper: remove intermediate files and makefile configuration
|
||||
# upgradeconf: add new options to old Makefile.config
|
||||
# osx: OS X application
|
||||
# release: used by OSX to make a dmg file ready to release
|
||||
|
||||
# Options:
|
||||
#
|
||||
# Summary of OS choice defines
|
||||
# WIN32: building on Windows
|
||||
# UNIX: building on *nix derivate (Linux, FreeBSD)
|
||||
# OSX: building on Mac OS X
|
||||
# MORPHOS: building on MorphOS
|
||||
# BEOS: building on BeOS
|
||||
# SUNOS: building on SunOS (Solaris)
|
||||
#
|
||||
# Summary of library choice defines
|
||||
# WITH_ZLIB: savegames using zlib
|
||||
# WITH_PNG: screenshots using PNG
|
||||
# WITH_SDL: SDL video driver support
|
||||
# WITH_COCOA: Cocoa video driver support
|
||||
#
|
||||
# Summary of other defines:
|
||||
# DEBUG: build in debug mode
|
||||
# PROFILE: build in profile mode, disables -s and -fomit-frame-pointer
|
||||
# TRANSLATOR: build in translator mode (untranslated strings are prepended by
|
||||
# a <TODO> mark)
|
||||
# RELEASE: this will be the released version number. It replaces all places
|
||||
# where it normally would print the revision number
|
||||
# MIDI: if set, it will use it as custom path to midi player.
|
||||
# If unset, it will use the hardcoded path in the c code
|
||||
# This can still be overriden by the music.extmidi openttd.cfg option.
|
||||
# WITH_DIRECTMUSIC: enable DirectMusic MIDI support
|
||||
# WITH_NETWORK: enable networking
|
||||
# DEDICATED: allows compilation on UNIX without SDL. Useful for dedicated servers
|
||||
# MAX_NUM_AUTOSAVES: sets the number of autosaves the games will make before starting
|
||||
# to overwrite the old ones. If not set, the game will use 16.
|
||||
# NOTE: assign a number, not a string of a number
|
||||
#
|
||||
# Paths:
|
||||
# INSTALL: If not set, the game uses the directory of the binary to
|
||||
# store everything (lang, data, gm, save and openttd.cfg), this is the `old' behaviour.
|
||||
# In this case, none of the following paths are used, you also should _not_
|
||||
# use `make install', but copy the required stuff yourself (or just play out
|
||||
# of you source directory, which should work fine).
|
||||
# If you want to use `make install' to install the game globally, you should
|
||||
# define it _before_ you build the game. If you only define INSTALL when you
|
||||
# do `make install', the game won't be able to find it's files (so you should
|
||||
# also define all the following paths before building).
|
||||
#
|
||||
# So, the following paths should be defined if INSTALL is defined.
|
||||
# None of these paths have to end with /
|
||||
# PREFIX: Normally /usr/local
|
||||
# BINARY_DIR: The location of the binary, normally games. (Will be prefixed
|
||||
# with $PREFIX)
|
||||
# DATA_DIR: The location of the data (lang, data, gm and scenario), normally
|
||||
# share/games/openttd. (Will be prefixed with $PREFIX) Note that scenarios
|
||||
# are only put here if USE_HOMEDIR is true, otherwise they are placed in
|
||||
# PERSONAL_DIR/scenario
|
||||
# ICON_DIR: The location of the openttd icon. (Will be prefixed with
|
||||
# $PREFIX).
|
||||
# PERSONAL_DIR: The directory where openttd.cfg and the save folder will be
|
||||
# stored. You cannot use ~ here, define USE_HOMEDIR for that.
|
||||
# USE_HOMEDIR: If this variable is set, PERSONAL_DIR will be prefixed with
|
||||
# ~/ at runtime (the user's homedir)
|
||||
# SECOND_DATA_PATH Use this data dir if a file is not found in the data dir in the data path
|
||||
# CUSTOM_LANG_PATH If this is set, it will use the path given to search for lng files
|
||||
# instead of the lang dir in the data path
|
||||
# NOTE: both SECOND_DATA_PATH and CUSTOM_LANG_PATH uses paths relative to where OTTD is opened
|
||||
#
|
||||
# DEST_DIR: make install will use this directory instead of the filesystem
|
||||
# root to install its files. This should normally not be used by
|
||||
# ordinary users, currently it is only used for the debian
|
||||
# packaging. This value should only be set when calling `make
|
||||
# install' and is not saved in Makefile.config
|
||||
# (Note that DESTDIR is checked if DEST_DIR is not set.)
|
||||
#
|
||||
# STATIC: link statically
|
||||
# CYGWIN: build in Cygwin environment
|
||||
# MINGW: build with MingW compiler, link with MingW libraries
|
||||
#
|
||||
# VERBOSE: show full compiler invocations instead of brief progress messages
|
||||
#
|
||||
# Special for crosscompiling there are some commands available:
|
||||
#
|
||||
# UNIVERSAL_BINARY: builds a universal binary for OSX. Make sure you got both PPC and x86 libs. Only works with GCC 4 or newer
|
||||
# TRIPLE_BINARY: builds a universal binary with the addition of code optimised for G5 (which means a total of 3 binaries in one file)
|
||||
# OTTD_PPC, OTTD_PPC970, OTTD_i386: compile for target architecture.
|
||||
# Multiple flags can be used so OTTD_PPC:=1 OTTD_i386:=1 produces the same result as UNIVERSAL_BINARY
|
||||
#
|
||||
# JAGUAR: Crosscompiling for OSX 1.2.8 (codenamed Jaguar). Only works if OSX is defined too. Only works with GCC 4 or newer
|
||||
# This can be changed to any PPC version of OSX by changing the ppc flags in Makefile.config
|
||||
#
|
||||
# ENDIAN_FORCE: forces the endian-check to give a certain result. Can be BE, LE or PREPROCESSOR.
|
||||
# PREPROCESSOR is always used on all OSX targets and will make the preprocessor pick the right endian.
|
||||
# this means that you don't have to think about endianess when compiling for OSX.
|
||||
# Very useful for universal binaries and crosscompilers. Not sure if it works on non OSX targets
|
||||
# WINDRES: the location of your windres
|
||||
# CC_HOST: the gcc of your localhost if you are making a target that produces incompatible executables
|
||||
# CFLAGS_HOST: cflags used for CC_HOST. Make it something if you are getting errors when you try to compi
|
||||
# windows executables on linux. (just: CFLAGS_HOST:='-I' or something)
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
|
||||
# Makefile version tag
|
||||
# it checks if the version tag in Makefile.config is the same and force update outdated config files
|
||||
MAKEFILE_VERSION:=10
|
||||
|
||||
# Automatic configuration
|
||||
MAKE_CONFIG:=Makefile.config
|
||||
MAKEFILE:=Makefile
|
||||
LIB_DETECTION=makefiledir/Makefile.libdetection
|
||||
CONFIG_WRITER=makefiledir/Makefile.config_writer
|
||||
|
||||
# Apply automatic configuration
|
||||
# See target section for how this is built, suppress errors
|
||||
# since first time it isn't found but make reads this twice
|
||||
-include $(MAKE_CONFIG)
|
||||
|
||||
|
||||
# updates Makefile.config if it's outdated
|
||||
ifneq ($(MAKEFILE_VERSION),$(CONFIG_VERSION))
|
||||
UPDATECONFIG:=upgradeconf
|
||||
CONFIG_INCLUDED:=
|
||||
endif
|
||||
|
||||
# this is used if there aren't any Makefile.config
|
||||
ifndef CONFIG_INCLUDED
|
||||
# sets network on by default if there aren't any config file
|
||||
ENABLE_NETWORK:=1
|
||||
|
||||
# paths for make install
|
||||
# disabled as they would break it for some (many?) people if they were default
|
||||
#PREFIX:=/usr/local
|
||||
#DATA_DIR:=share/games/openttd
|
||||
#BINARY_DIR:=games
|
||||
#PERSONAL_DIR:=.openttd
|
||||
#USE_HOMEDIR:=1
|
||||
|
||||
-include $(LIB_DETECTION)
|
||||
endif
|
||||
|
||||
ifdef SUPRESS_LANG_ERRORS
|
||||
LANG_ERRORS = >/dev/null 2>&1
|
||||
endif
|
||||
|
||||
ifdef OSX
|
||||
-include os/MacOSX/Makefile.setup
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
ifndef WIN32
|
||||
ifndef OSX
|
||||
ifndef MORPHOS
|
||||
ifndef SKIP_STATIC_CHECK
|
||||
$(error Static is only known to work on MorphOS and MacOSX!!! --- Check Makefile.config for more info and howto bypass this check)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WITH_COCOA
|
||||
ifdef WITH_SDL
|
||||
$(error You can not use both the SDL video driver and the Cocoa video driver at the same time)
|
||||
endif
|
||||
ifdef DEDICATED
|
||||
$(error You can not use the Cocoa video driver in a dedicated server)
|
||||
endif
|
||||
else
|
||||
# Force SDL on UNIX platforms
|
||||
ifndef WITH_SDL
|
||||
ifdef UNIX
|
||||
ifndef DEDICATED
|
||||
$(error You need to have SDL installed in order to run OpenTTD on UNIX. Use DEDICATED if you want to compile a CLI based server)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# remove the dependancy for sdl if DEDICALTED is used
|
||||
ifdef DEDICATED
|
||||
WITH_SDL:=
|
||||
endif
|
||||
|
||||
# add -lpthread to LDFLAGS
|
||||
ifndef WIN32
|
||||
ifndef MORPHOS
|
||||
ifndef OSX
|
||||
LDFLAGS+=-lpthread
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef OSX
|
||||
LDFLAGS+=-framework Cocoa
|
||||
endif
|
||||
|
||||
ifdef WITH_SDL
|
||||
ifndef SDL_CONFIG
|
||||
$(error WITH_SDL can't be used when SDL_CONFIG is not set. Edit Makefile.config to correct this)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WITH_PNG
|
||||
ifndef LIBPNG_CONFIG
|
||||
$(error WITH_PNG can't be used when LIBPNG_CONFIG is not set. Edit Makefile.config to correct this)
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Compiler configuration
|
||||
#
|
||||
|
||||
# Executable file extension
|
||||
ifdef WIN32
|
||||
EXE=.exe
|
||||
else
|
||||
EXE=
|
||||
endif
|
||||
|
||||
# Set output executable names
|
||||
TTD=openttd$(EXE)
|
||||
ENDIAN_CHECK=endian_check$(EXE)
|
||||
STRGEN=strgen/strgen$(EXE)
|
||||
OSXAPP="OpenTTD.app"
|
||||
|
||||
REV := 0.4.8-$(shell if test -d .svn; then svnversion . | awk '{ print "r"$$0 }'; fi)
|
||||
|
||||
# MorphOS needs builddate
|
||||
BUILDDATE=`date +%d.%m.%y`
|
||||
|
||||
# Check if there is a windres override
|
||||
ifndef WINDRES
|
||||
WINDRES = windres
|
||||
endif
|
||||
|
||||
# Check if we have a new target
|
||||
ifdef CC_TARGET
|
||||
CC = $(CC_TARGET)
|
||||
endif
|
||||
|
||||
# Check if CC_HOST is defined. If not, it is CC
|
||||
ifndef CC_HOST
|
||||
CC_HOST = $(CC)
|
||||
endif
|
||||
ifndef CFLAGS_HOST
|
||||
CFLAGS_HOST = $(BASECFLAGS)
|
||||
endif
|
||||
|
||||
|
||||
CC_VERSION = $(shell $(CC) -dumpversion | cut -c 1,3)
|
||||
|
||||
# GNU make can only test for (in)equality
|
||||
# this is a workaround to test for >=
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 29), 1)
|
||||
CFLAGS += -O -Wall -Wno-multichar -Wsign-compare -Wstrict-prototypes -Wundef
|
||||
CFLAGS += -Wwrite-strings -Wpointer-arith
|
||||
endif
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 30), 1)
|
||||
CFLAGS += -W -Wno-unused-parameter
|
||||
endif
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 34), 1)
|
||||
CFLAGS += -Wdeclaration-after-statement -Wold-style-definition
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
ifeq ($(shell expr $(DEBUG) \>= 1), 1)
|
||||
CFLAGS += -g -D_DEBUG
|
||||
endif
|
||||
ifeq ($(shell expr $(DEBUG) \>= 2), 1)
|
||||
CFLAGS += -fno-inline
|
||||
endif
|
||||
ifeq ($(shell expr $(DEBUG) \>= 3), 1)
|
||||
CFLAGS += -O0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef PROFILE
|
||||
CFLAGS += -pg
|
||||
LDFLAGS += -pg
|
||||
endif
|
||||
|
||||
CDEFS=-DWITH_REV
|
||||
|
||||
ifndef DEBUG
|
||||
ifndef PROFILE
|
||||
# Release mode
|
||||
ifndef MORPHOS
|
||||
ifndef IRIX
|
||||
# automatical strip breaks under morphos
|
||||
BASECFLAGS += -s
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef OSX
|
||||
# these compilerflags makes the app run as fast as possible without making the app unstable. It works on G3 or newer
|
||||
BASECFLAGS += -O3 -funroll-loops -fsched-interblock -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-jumps-max-skip=15 -falign-loops-max-skip=15 -mdynamic-no-pic
|
||||
else
|
||||
ifdef MORPHOS
|
||||
BASECFLAGS += -I/gg/os-include -O2 -noixemul -fstrict-aliasing -fexpensive-optimizations
|
||||
BASECFLAGS += -mcpu=604 -fno-inline -mstring -mmultiple
|
||||
else
|
||||
BASECFLAGS += -O2
|
||||
endif
|
||||
ifndef PROFILE
|
||||
ifndef IRIX
|
||||
BASECFLAGS += -fomit-frame-pointer
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
ifndef OSX # OSX can't build static if -static flag is used
|
||||
LDFLAGS += -static
|
||||
endif
|
||||
endif
|
||||
|
||||
# If building on MingW don't link with Cygwin libs
|
||||
ifdef WIN32
|
||||
ifdef CYGWIN
|
||||
BASECFLAGS += -mwin32
|
||||
LDFLAGS += -mwin32
|
||||
endif
|
||||
ifdef MINGW
|
||||
BASECFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += $(BASECFLAGS)
|
||||
|
||||
ifdef UNIX
|
||||
CDEFS += -DUNIX
|
||||
endif
|
||||
|
||||
ifdef BEOS
|
||||
CDEFS += -DBEOS
|
||||
LDFLAGS += -lmidi -lbe -lpthread
|
||||
ifdef WITH_NETWORK
|
||||
ifdef BEOS_NET_SERVER
|
||||
CDEFS += -DBEOS_NET_SERVER
|
||||
LDFLAGS += -lnet
|
||||
else
|
||||
# BONE needs a few more libraries than R5
|
||||
LDFLAGS += -lbind -lsocket
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MORPHOS
|
||||
# -Wstrict-prototypes generates much noise because of system headers
|
||||
CFLAGS += -Wno-strict-prototypes
|
||||
endif
|
||||
|
||||
ifdef SUNOS
|
||||
CDEFS += -DSUNOS
|
||||
ifdef WITH_NETWORK
|
||||
LDFLAGS += -lnsl -lsocket
|
||||
endif
|
||||
endif
|
||||
|
||||
# tell the source that we are building a dedicated server
|
||||
ifdef DEDICATED
|
||||
CDEFS += -DDEDICATED
|
||||
endif
|
||||
|
||||
# SDL config
|
||||
ifdef WITH_SDL
|
||||
CDEFS += -DWITH_SDL
|
||||
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
|
||||
ifdef STATIC
|
||||
LIBS += $(shell $(SDL_CONFIG) --static-libs)
|
||||
else
|
||||
LIBS += $(shell $(SDL_CONFIG) --libs)
|
||||
endif
|
||||
endif
|
||||
|
||||
# zlib config
|
||||
ifdef WITH_ZLIB
|
||||
CDEFS += -DWITH_ZLIB
|
||||
ifdef STATIC
|
||||
ifdef OSX
|
||||
# OSX links dynamically to zlib, even in static builds since it's always present in the system
|
||||
LIBS += -lz
|
||||
else
|
||||
LIBS += $(STATIC_ZLIB_PATH)
|
||||
endif
|
||||
else
|
||||
LIBS += -lz
|
||||
endif
|
||||
endif
|
||||
|
||||
# libpng config
|
||||
ifdef WITH_PNG
|
||||
CDEFS += -DWITH_PNG
|
||||
CFLAGS += $(shell $(LIBPNG_CONFIG) --cppflags --I_opts)
|
||||
|
||||
# seems like older libpng versions are broken and need this
|
||||
PNGCONFIG_FLAGS = --ldflags --libs
|
||||
ifdef STATIC
|
||||
ifdef OSX
|
||||
# Seems like we need a tiny hack for OSX static to work
|
||||
LIBS += $(shell $(LIBPNG_CONFIG) --prefix)/lib/libpng.a
|
||||
else
|
||||
LIBS += $(shell $(LIBPNG_CONFIG) --static $(PNGCONFIG_FLAGS))
|
||||
endif
|
||||
else
|
||||
LIBS += $(shell $(LIBPNG_CONFIG) --L_opts $(PNGCONFIG_FLAGS))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef OSX
|
||||
ifndef JAGUAR
|
||||
LIBS += -liconv
|
||||
endif
|
||||
endif
|
||||
|
||||
# enables/disables assert()
|
||||
ifdef DISABLE_ASSERTS
|
||||
CFLAGS += -DNDEBUG
|
||||
endif
|
||||
|
||||
# automatically disables asserts for release
|
||||
ifdef RELEASE
|
||||
ifndef ENABLE_ASSERTS
|
||||
CFLAGS += -DNDEBUG
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef TRANSLATOR
|
||||
STRGEN_FLAGS=-t
|
||||
else
|
||||
STRGEN_FLAGS=
|
||||
endif
|
||||
|
||||
# OSX specific setup
|
||||
ifdef OSX
|
||||
# set the endian flag for OSX, that can't fail
|
||||
ENDIAN_FORCE:=PREPROCESSOR
|
||||
|
||||
ifndef DEDICATED
|
||||
LIBS += -framework QuickTime
|
||||
endif
|
||||
|
||||
ifdef WITH_COCOA
|
||||
CDEFS += -DWITH_COCOA
|
||||
LIBS += -F/System/Library/Frameworks -framework Cocoa -framework Carbon -framework AudioUnit
|
||||
endif
|
||||
|
||||
# OSX path setup
|
||||
ifndef SECOND_DATA_PATH
|
||||
SECOND_DATA_PATH:="$(OSXAPP)/Contents/Data/"
|
||||
endif
|
||||
|
||||
ifndef CUSTOM_LANG_DIR
|
||||
ifndef DEDICATED
|
||||
CUSTOM_LANG_DIR:="$(OSXAPP)/Contents/Lang/"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MIDI
|
||||
CDEFS += -DEXTERNAL_PLAYER=\"$(MIDI)\"
|
||||
ifdef MIDI_ARG
|
||||
CDEFS += -DMIDI_ARG=\"$(MIDI_ARG)\"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MAX_NUM_AUTOSAVES
|
||||
CDEFS += -DMAX_NUM_AUTOSAVES=$(MAX_NUM_AUTOSAVES)
|
||||
endif
|
||||
|
||||
ifdef WITH_NETWORK
|
||||
CDEFS += -DENABLE_NETWORK
|
||||
ifdef QNX
|
||||
LIBS += -lsocket
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifdef SECOND_DATA_PATH
|
||||
CDEFS += -DSECOND_DATA_DIR=\"$(SECOND_DATA_PATH)/\"
|
||||
endif
|
||||
|
||||
ifdef CUSTOM_LANG_DIR
|
||||
CDEFS += -DCUSTOM_LANG_DIR=\"$(CUSTOM_LANG_DIR)/\"
|
||||
endif
|
||||
|
||||
ifdef WITH_DIRECTMUSIC
|
||||
CDEFS += -DWIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
endif
|
||||
|
||||
ifdef WIN32
|
||||
LIBS += -lws2_32 -lwinmm -lgdi32 -ldxguid -lole32
|
||||
ifdef WITH_DIRECTMUSIC
|
||||
LIBS += -lstdc++
|
||||
endif
|
||||
TTDLDFLAGS += -Wl,--subsystem,windows
|
||||
endif
|
||||
|
||||
ifndef DEST_DIR
|
||||
DEST_DIR = $(DESTDIR)
|
||||
endif
|
||||
|
||||
# sets up the paths for use for make install
|
||||
ifdef INSTALL
|
||||
# We use _PREFIXED vars here, so the paths are recalculated every time, and
|
||||
# the prefix is not prepended in the makefile config
|
||||
BINARY_DIR_PREFIXED:=$(PREFIX)/$(BINARY_DIR)
|
||||
DATA_DIR_PREFIXED:=$(PREFIX)/$(DATA_DIR)
|
||||
ICON_DIR_PREFIXED:=$(PREFIX)/$(ICON_DIR)
|
||||
# We use _INSTALL vars here, these vars are the locations where the files will
|
||||
# be installed
|
||||
DATA_DIR_INSTALL=$(DEST_DIR)/$(DATA_DIR_PREFIXED)
|
||||
BINARY_DIR_INSTALL=$(DEST_DIR)/$(BINARY_DIR_PREFIXED)
|
||||
ICON_DIR_INSTALL=$(DEST_DIR)/$(ICON_DIR_PREFIXED)
|
||||
# Let the code know where to find stuff
|
||||
ifdef DATA_DIR_PREFIXED
|
||||
CDEFS += -DGAME_DATA_DIR=\"$(DATA_DIR_PREFIXED)/\"
|
||||
endif
|
||||
|
||||
ifdef PERSONAL_DIR
|
||||
CDEFS += -DPERSONAL_DIR=\"$(PERSONAL_DIR)/\"
|
||||
endif
|
||||
|
||||
ifdef USE_HOMEDIR
|
||||
CDEFS += -DUSE_HOMEDIR
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# What to compile
|
||||
# (users do not want to modify anything below)
|
||||
#
|
||||
|
||||
|
||||
### Sources
|
||||
|
||||
# clean up C_SOURCES first. Needed since building universal binaries on OSX calls the makefile recursively (just one time)
|
||||
SRCS :=
|
||||
|
||||
SRCS += aircraft_cmd.c
|
||||
SRCS += aircraft_gui.c
|
||||
SRCS += airport.c
|
||||
SRCS += airport_gui.c
|
||||
SRCS += aystar.c
|
||||
SRCS += bridge_gui.c
|
||||
SRCS += callback_table.c
|
||||
SRCS += clear_cmd.c
|
||||
SRCS += command.c
|
||||
SRCS += console.c
|
||||
SRCS += console_cmds.c
|
||||
SRCS += currency.c
|
||||
SRCS += debug.c
|
||||
SRCS += dedicated.c
|
||||
SRCS += depot.c
|
||||
SRCS += disaster_cmd.c
|
||||
SRCS += dock_gui.c
|
||||
SRCS += driver.c
|
||||
SRCS += dummy_land.c
|
||||
SRCS += economy.c
|
||||
SRCS += engine.c
|
||||
SRCS += engine_gui.c
|
||||
SRCS += fileio.c
|
||||
SRCS += gfx.c
|
||||
SRCS += gfxinit.c
|
||||
SRCS += graph_gui.c
|
||||
SRCS += industry_cmd.c
|
||||
SRCS += industry_gui.c
|
||||
SRCS += intro_gui.c
|
||||
SRCS += landscape.c
|
||||
SRCS += main_gui.c
|
||||
SRCS += map.c
|
||||
SRCS += md5.c
|
||||
SRCS += mersenne.c
|
||||
SRCS += minilzo.c
|
||||
SRCS += misc.c
|
||||
SRCS += misc_cmd.c
|
||||
SRCS += misc_gui.c
|
||||
SRCS += mixer.c
|
||||
SRCS += music_gui.c
|
||||
SRCS += namegen.c
|
||||
SRCS += network.c
|
||||
SRCS += network_client.c
|
||||
SRCS += network_data.c
|
||||
SRCS += network_gamelist.c
|
||||
SRCS += network_gui.c
|
||||
SRCS += network_server.c
|
||||
SRCS += network_udp.c
|
||||
SRCS += newgrf.c
|
||||
SRCS += news_gui.c
|
||||
SRCS += npf.c
|
||||
SRCS += oldloader.c
|
||||
SRCS += openttd.c
|
||||
SRCS += order_cmd.c
|
||||
SRCS += order_gui.c
|
||||
SRCS += pathfind.c
|
||||
SRCS += player_gui.c
|
||||
SRCS += players.c
|
||||
SRCS += pool.c
|
||||
SRCS += queue.c
|
||||
SRCS += rail.c
|
||||
SRCS += rail_cmd.c
|
||||
SRCS += rail_gui.c
|
||||
SRCS += rev.c
|
||||
SRCS += road_cmd.c
|
||||
SRCS += road_gui.c
|
||||
SRCS += roadveh_cmd.c
|
||||
SRCS += roadveh_gui.c
|
||||
SRCS += saveload.c
|
||||
SRCS += screenshot.c
|
||||
SRCS += settings.c
|
||||
SRCS += settings_gui.c
|
||||
SRCS += ship_cmd.c
|
||||
SRCS += ship_gui.c
|
||||
SRCS += signs.c
|
||||
SRCS += smallmap_gui.c
|
||||
SRCS += sound.c
|
||||
SRCS += sprite.c
|
||||
SRCS += spritecache.c
|
||||
SRCS += station_cmd.c
|
||||
SRCS += station_gui.c
|
||||
SRCS += station_newgrf.c
|
||||
SRCS += string.c
|
||||
SRCS += strings.c
|
||||
SRCS += subsidy_gui.c
|
||||
SRCS += terraform_gui.c
|
||||
SRCS += texteff.c
|
||||
SRCS += thread.c
|
||||
SRCS += tile.c
|
||||
SRCS += town_cmd.c
|
||||
SRCS += town_gui.c
|
||||
SRCS += train_cmd.c
|
||||
SRCS += train_gui.c
|
||||
SRCS += tree_cmd.c
|
||||
SRCS += tunnel_map.c
|
||||
SRCS += tunnelbridge_cmd.c
|
||||
SRCS += unmovable_cmd.c
|
||||
SRCS += vehicle.c
|
||||
SRCS += vehicle_gui.c
|
||||
SRCS += viewport.c
|
||||
SRCS += water_cmd.c
|
||||
SRCS += waypoint.c
|
||||
SRCS += widget.c
|
||||
SRCS += window.c
|
||||
SRCS += music/null_m.c
|
||||
SRCS += sound/null_s.c
|
||||
SRCS += video/dedicated_v.c
|
||||
SRCS += video/null_v.c
|
||||
|
||||
# AI related files
|
||||
SRCS += ai/ai.c
|
||||
SRCS += ai/default/default.c
|
||||
SRCS += ai/trolly/build.c
|
||||
SRCS += ai/trolly/pathfinder.c
|
||||
SRCS += ai/trolly/shared.c
|
||||
SRCS += ai/trolly/trolly.c
|
||||
|
||||
ifdef WITH_SDL
|
||||
SRCS += sdl.c
|
||||
SRCS += sound/sdl_s.c
|
||||
SRCS += video/sdl_v.c
|
||||
endif
|
||||
|
||||
ifdef WIN32
|
||||
SRCS += win32.c
|
||||
SRCS += music/win32_m.c
|
||||
SRCS += sound/win32_s.c
|
||||
SRCS += video/win32_v.c
|
||||
else
|
||||
SRCS += unix.c
|
||||
SRCS += music/extmidi.c
|
||||
endif
|
||||
|
||||
ifdef OSX
|
||||
SRCS += os/macosx/macos.m
|
||||
ifndef DEDICATED
|
||||
SRCS += music/qtmidi.c
|
||||
endif
|
||||
ifdef WITH_COCOA
|
||||
SRCS += video/cocoa_v.m
|
||||
SRCS += sound/cocoa_s.c
|
||||
SRCS += os/macosx/splash.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef BEOS
|
||||
SRCS += music/bemidi.cpp
|
||||
endif
|
||||
|
||||
ifdef WIN32
|
||||
SRCS += ottdres.rc
|
||||
endif
|
||||
|
||||
ifdef WITH_DIRECTMUSIC
|
||||
SRCS += music/dmusic.cpp
|
||||
endif
|
||||
|
||||
OBJS += $(filter %.o, $(SRCS:%.cpp=%.o) $(SRCS:%.m=%.o) $(SRCS:%.c=%.o) $(SRCS:%.rc=%.o))
|
||||
DEPS = $(OBJS:%.o=.deps/%.d)
|
||||
|
||||
LANG_TXT = $(filter-out %.unfinished.txt,$(wildcard lang/*.txt))
|
||||
LANGS = $(LANG_TXT:%.txt=%.lng)
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Build commands
|
||||
#
|
||||
|
||||
# If we are verbose, we will show commands prefixed by $(Q).
|
||||
# The $(Q)s get replaced by @ in non-verbose mode.
|
||||
# Inspired by the Linux kernel build system.
|
||||
ifdef VERBOSE
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
|
||||
|
||||
### Normal build rules
|
||||
|
||||
|
||||
ifdef OSX
|
||||
# needs to be before all
|
||||
OSX:=OSX
|
||||
endif
|
||||
|
||||
|
||||
all: endian_target.h endian_host.h $(UPDATECONFIG) $(LANGS) $(TTD) $(OSX)
|
||||
|
||||
ifdef OSX
|
||||
-include os/macosx/Makefile
|
||||
endif
|
||||
|
||||
endian_host.h: $(ENDIAN_CHECK)
|
||||
@echo '===> Testing endianness for host'
|
||||
$(Q)./$(ENDIAN_CHECK) > $@
|
||||
|
||||
endian_target.h: $(ENDIAN_CHECK)
|
||||
@echo '===> Testing endianness for target'
|
||||
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
|
||||
|
||||
$(ENDIAN_CHECK): endian_check.c
|
||||
@echo '===> Compiling and Linking $@'
|
||||
$(Q)$(CC_HOST) $(CFLAGS_HOST) $(CDEFS) $< -o $@
|
||||
|
||||
|
||||
ifndef NATIVE_OSX
|
||||
# OSX links in os/macosx/Makefile to handle universal binaries better
|
||||
$(TTD): $(OBJS) $(MAKE_CONFIG)
|
||||
@echo '===> Linking $@'
|
||||
$(Q)$(CC) $(LDFLAGS) $(TTDLDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
endif
|
||||
|
||||
$(STRGEN): strgen/strgen.c endian_host.h
|
||||
@echo '===> Compiling and Linking $@'
|
||||
$(Q)$(CC_HOST) $(CFLAGS_HOST) $(CDEFS) $< -o $@
|
||||
|
||||
table/strings.h: lang/english.txt $(STRGEN)
|
||||
@echo '===> Generating $@'
|
||||
$(Q)$(STRGEN)
|
||||
|
||||
lang/%.lng: lang/%.txt $(STRGEN) lang/english.txt
|
||||
@echo '===> Compiling language $(*F)'
|
||||
$(Q)$(STRGEN) $(STRGEN_FLAGS) $< $(LANG_ERRORS) || rm -f $@
|
||||
|
||||
ifdef MORPHOS
|
||||
release: all
|
||||
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos.lha"
|
||||
$(Q)mkdir -p "/t/"
|
||||
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos"
|
||||
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/docs"
|
||||
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/data"
|
||||
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/lang"
|
||||
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/scenario"
|
||||
$(Q)cp -R $(TTD) "/t/openttd-$(RELEASE)-morphos/"
|
||||
$(Q)cp data/* "/t/openttd-$(RELEASE)-morphos/data/"
|
||||
$(Q)cp lang/*.lng "/t/openttd-$(RELEASE)-morphos/lang/"
|
||||
$(Q)cp scenario/* "/t/openttd-$(RELEASE)-morphos/scenario/"
|
||||
$(Q)cp readme.txt "/t/openttd-$(RELEASE)-morphos/docs/ReadMe"
|
||||
$(Q)cp docs/console.txt "/t/openttd-$(RELEASE)-morphos/docs/Console"
|
||||
$(Q)cp COPYING "/t/openttd-$(RELEASE)-morphos/docs/"
|
||||
$(Q)cp changelog.txt "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog"
|
||||
$(Q)cp known-bugs.txt "/t/openttd-$(RELEASE)-morphos/docs/known-bugs.txt"
|
||||
$(Q)cp os/morphos/icons/openttd.info "/t/openttd-$(RELEASE)-morphos/$(TTD).info"
|
||||
$(Q)cp os/morphos/icons/docs.info "/t/openttd-$(RELEASE)-morphos/docs.info"
|
||||
$(Q)cp os/morphos/icons/drawer.info "/t/openttd-$(RELEASE)-morphos.info"
|
||||
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ReadMe.info"
|
||||
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/Console.info"
|
||||
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/COPYING.info"
|
||||
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog.info"
|
||||
$(Q)strip --strip-all --strip-unneeded --remove-section .comment "/t/openttd-$(RELEASE)-morphos/$(TTD)"
|
||||
$(Q)lha a -r "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos"
|
||||
$(Q)lha a "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos.info"
|
||||
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos"
|
||||
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos.info"
|
||||
@echo "Release archive can be found in RAM:t/ now."
|
||||
|
||||
.PHONY: release
|
||||
endif
|
||||
|
||||
rev.c: FORCE
|
||||
@# setting the revision number in a place, there the binary can read it
|
||||
@echo 'const char _openttd_revision[] = "$(REV)";' >>rev.c.new
|
||||
@# some additions for MorphOS versions tag
|
||||
@echo '#ifdef __MORPHOS__' >>rev.c.new
|
||||
@echo 'const char morphos_versions_tag[] = "\\0$$VER: OpenTTD $(REV) ('${BUILDDATE}') © OpenTTD Team [MorphOS, PowerPC]";' >>rev.c.new
|
||||
@echo '#endif' >>rev.c.new
|
||||
@# Only update the real rev.c if it actually changed, to prevent
|
||||
@# useless rebuilds.
|
||||
@cmp -s rev.c rev.c.new 2>/dev/null || mv rev.c.new rev.c
|
||||
@rm -f rev.c.new
|
||||
|
||||
FORCE:
|
||||
|
||||
|
||||
clean:
|
||||
@echo '===> Cleaning up'
|
||||
# endian.h is out-dated and no longer in use, so it can be removed soon
|
||||
$(Q)rm -rf .deps *~ $(TTD) $(STRGEN) core table/strings.h $(LANGS) $(OBJS) $(OSX_MIDI_PLAYER_FILE) endian.h endian_host.h endian_target.h $(ENDIAN_CHECK) .OSX
|
||||
|
||||
mrproper: clean
|
||||
$(Q)rm -rf $(MAKE_CONFIG)
|
||||
|
||||
ifndef OSX
|
||||
ifndef MORPHOS
|
||||
install:
|
||||
ifeq ($(INSTALL),)
|
||||
$(error make install is highly experimental at his state and not\
|
||||
tested very much - use at your own risk - to use run \"make install INSTALL:=1\" - make sure Makefile.config\
|
||||
is set correctly up - run \"make upgradeconf\")
|
||||
endif
|
||||
|
||||
ifeq ($(PREFIX), )
|
||||
$(error no prefix set - check Makefile.config)
|
||||
endif
|
||||
# We compare against the non prefixed version here, so we won't install
|
||||
# if only the prefix has been set
|
||||
ifeq ($(DATA_DIR),)
|
||||
$(error no data path set - check Makefile.config)
|
||||
endif
|
||||
ifeq ($(BINARY_DIR),)
|
||||
$(error no binary path set - check Makefile.config)
|
||||
endif
|
||||
# We'll install in $DEST_DIR instead of root if it is set (we don't
|
||||
# care about extra /'s
|
||||
install -d $(DATA_DIR_INSTALL)/lang \
|
||||
$(DATA_DIR_INSTALL)/data \
|
||||
$(DATA_DIR_INSTALL)/gm \
|
||||
$(ICON_DIR_INSTALL) \
|
||||
$(BINARY_DIR_INSTALL)
|
||||
ifndef USE_HOMEDIR
|
||||
mkdir -p $(PERSONAL_DIR)/scenario
|
||||
else
|
||||
mkdir -p $(DATA_DIR_INSTALL)/scenario
|
||||
endif
|
||||
install $(TTD) $(BINARY_DIR_INSTALL)
|
||||
install -m 644 lang/*.lng $(DATA_DIR_INSTALL)/lang
|
||||
install -m 644 data/*.grf $(DATA_DIR_INSTALL)/data
|
||||
install -m 644 data/opntitle.dat $(DATA_DIR_INSTALL)/data
|
||||
install -m 644 media/openttd.64.png $(ICON_DIR_INSTALL)
|
||||
install -m 644 media/openttd.32.xpm $(ICON_DIR_INSTALL)
|
||||
ifndef USE_HOMEDIR
|
||||
cp scenario/* $(PERSONAL_DIR)/scenario/
|
||||
else
|
||||
cp scenario/* $(DATA_DIR_INSTALL)/scenario/
|
||||
endif
|
||||
else #MorphOS
|
||||
install:
|
||||
$(error make install is not supported on MorphOS)
|
||||
endif
|
||||
else # OSX
|
||||
install:
|
||||
$(error make install is not supported on MacOSX)
|
||||
endif
|
||||
|
||||
|
||||
love:
|
||||
@echo "YES! I thought you would never ask. We will have a great time. You can keep me turned on all night"
|
||||
|
||||
.PHONY: clean all $(OSX) install love
|
||||
|
||||
|
||||
### Automatic configuration
|
||||
-include $(CONFIG_WRITER)
|
||||
|
||||
|
||||
# Export all variables set to subprocesses (a bit dirty)
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
upgradeconf: $(MAKE_CONFIG)
|
||||
$(Q)rm $(MAKE_CONFIG)
|
||||
$(Q)$(MAKE) $(MAKE_CONFIG)
|
||||
|
||||
.PHONY: upgradeconf
|
||||
|
||||
|
||||
### Internal build rules
|
||||
|
||||
# This makes sure the .deps dir is always around.
|
||||
DEPS_MAGIC := $(shell mkdir -p $(sort $(dir $(DEPS))))
|
||||
|
||||
depend:
|
||||
@true # The include handles this automagically
|
||||
|
||||
# Introduce the dependencies
|
||||
ifeq ($(findstring $(MAKECMDGOALS), clean info),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
||||
# Silence stale header dependency errors
|
||||
%.h:
|
||||
@true
|
||||
|
||||
.deps/%.d: %.c $(MAKE_CONFIG) table/strings.h endian_target.h
|
||||
@echo '===> DEP $<'
|
||||
$(Q)$(CC) $(CFLAGS) $(CDEFS) -MM $< | sed 's#^$(@F:%.d=%.o):#$@ $(@:.deps/%.d=%.o):#' > $@
|
||||
|
||||
.deps/%.d: %.cpp $(MAKE_CONFIG) table/strings.h endian_target.h
|
||||
@echo '===> DEP $<'
|
||||
$(Q)$(CXX) $(CFLAGS) $(CDEFS) -MM $< | sed 's#^$(@F:%.d=%.o):#$@ $(@:.deps/%.d=%.o):#' > $@
|
||||
|
||||
.deps/%.d: %.m $(MAKE_CONFIG) table/strings.h endian_target.h
|
||||
@echo '===> DEP $<'
|
||||
$(Q)$(CC) $(OBJCFLAGS) $(CDEFS) -MM $< | sed 's#^$(@F:%.d=%.o):#$@ $(@:.deps/%.d=%.o):#' > $@
|
||||
|
||||
|
||||
ifndef NATIVE_OSX
|
||||
# OSX uses os/macosx/Makefile to compile files
|
||||
%.o: %.c $(MAKE_CONFIG)
|
||||
@echo '===> Compiling $<'
|
||||
$(Q)$(CC) $(CFLAGS) $(CDEFS) -c -o $@ $<
|
||||
|
||||
%.o: %.cpp $(MAKE_CONFIG)
|
||||
@echo '===> Compiling $<'
|
||||
$(Q)$(CXX) $(CFLAGS) $(CDEFS) -c -o $@ $<
|
||||
|
||||
%.o: %.m $(MAKE_CONFIG)
|
||||
@echo '===> Compiling $<'
|
||||
$(Q)$(CC) $(CFLAGS) $(CDEFS) -c -o $@ $<
|
||||
endif
|
||||
|
||||
%.o: %.rc
|
||||
@echo '===> Compiling resource $<'
|
||||
$(Q)$(WINDRES) -o $@ $<
|
||||
|
||||
|
||||
info:
|
||||
@echo 'CFLAGS = $(CFLAGS)'
|
||||
@echo 'LDFLAGS = $(LDFLAGS)'
|
||||
@echo 'LIBS = $(LIBS)'
|
||||
@echo 'CDEFS = $(CDEFS)'
|
||||
@@ -1,173 +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)
|
||||
endif
|
||||
|
||||
# Make sure we have something in REV
|
||||
ifeq ($(REV),)
|
||||
REV := norev000
|
||||
endif
|
||||
|
||||
ifndef BUNDLE_NAME
|
||||
BUNDLE_NAME = OTTD-$(OS)-custom-$(REV)
|
||||
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)/scenario"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/scenario/heightmap"
|
||||
$(Q)mkdir -p "$(BUNDLE_DIR)/media"
|
||||
$(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/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/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 "$(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/"
|
||||
ifdef MENU_DIR
|
||||
$(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/"
|
||||
endif
|
||||
ifeq ($(shell if test -n "`ls -l \"$(BIN_DIR)/scenario/\"*.scn 2> /dev/null`"; then echo 1; fi), 1)
|
||||
$(Q)cp "$(BIN_DIR)/scenario/"*.scn "$(BUNDLE_DIR)/scenario/"
|
||||
endif
|
||||
ifeq ($(shell if test -n "`ls -l \"$(BIN_DIR)/scenario/heightmaps/\"* 2>/dev/null`"; then echo 1; fi), 1)
|
||||
$(Q)cp "$(BIN_DIR)/scenario/heightmaps/"* "$(BUNDLE_DIR)/scenario/heightmap/"
|
||||
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"
|
||||
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_DOC_DIR)"
|
||||
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)"
|
||||
$(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)/docs/"* "$(INSTALL_DOC_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)"
|
||||
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"
|
||||
$(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"
|
||||
$(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"
|
||||
$(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"
|
||||
$(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"
|
||||
$(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"
|
||||
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)"
|
||||
endif
|
||||
ifdef MENU_DIR
|
||||
$(Q)install -d "$(INSTALL_MENU_DIR)"
|
||||
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.desktop" "$(INSTALL_MENU_DIR)"
|
||||
endif
|
||||
$(Q)cp -R "$(BUNDLE_DIR)/scenario" "$(INSTALL_DATA_DIR)"
|
||||
endif # OSXAPP
|
||||
-152
@@ -1,152 +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!!
|
||||
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
|
||||
|
||||
%.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
|
||||
-296
@@ -1,296 +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!!
|
||||
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) $(LANG_OBJS_DIR)/table/strings.h 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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
REV_NR := $(shell echo "$(VERSIONS)" | cut -f 2)
|
||||
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, "^$(SRC_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 file is deleted without the deps
|
||||
# being updated. Now the Makefile continues, the deps are recreated
|
||||
# and all will be fine.
|
||||
%.h %.hpp:
|
||||
@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) $@
|
||||
endif
|
||||
|
||||
# The targets to compile the endian-code
|
||||
|
||||
endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN)
|
||||
$(E) '$(STAGE) Testing endianness for target'
|
||||
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
|
||||
|
||||
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
|
||||
$(E) '$(STAGE) Compiling and Linking $@'
|
||||
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
|
||||
|
||||
# Revision files
|
||||
|
||||
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
|
||||
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@MODIFIED@@#$(MODIFIED)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/rev.cpp
|
||||
|
||||
$(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in
|
||||
$(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/ottdres.rc
|
||||
|
||||
FORCE:
|
||||
|
||||
depend: $(DEPS)
|
||||
|
||||
clean:
|
||||
$(E) '$(STAGE) Cleaning up object files'
|
||||
$(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(TTD:%=$(BIN_DIR)/%) $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS)
|
||||
|
||||
mrproper: clean
|
||||
$(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/ottdres.rc
|
||||
|
||||
%.o:
|
||||
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
|
||||
|
||||
.PHONY: all mrproper depend clean FORCE
|
||||
@@ -0,0 +1,10 @@
|
||||
/* $Id$ */
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// ttd.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
+66
-51
@@ -3,23 +3,15 @@
|
||||
#include "../stdafx.h"
|
||||
#include "../openttd.h"
|
||||
#include "../variables.h"
|
||||
#include "../command_func.h"
|
||||
#include "../network/network.h"
|
||||
#include "../core/alloc_func.hpp"
|
||||
#include "../player_func.h"
|
||||
#include "../player_base.h"
|
||||
#include "../command.h"
|
||||
#include "../network.h"
|
||||
#include "ai.h"
|
||||
#include "default/default.h"
|
||||
#include "trolly/trolly.h"
|
||||
#include "../signal_func.h"
|
||||
|
||||
AIStruct _ai;
|
||||
AIPlayer _ai_player[MAX_PLAYERS];
|
||||
|
||||
/**
|
||||
* Dequeues commands put in the queue via AI_PutCommandInQueue.
|
||||
*/
|
||||
static void AI_DequeueCommands(PlayerID player)
|
||||
static void AI_DequeueCommands(byte player)
|
||||
{
|
||||
AICommand *com, *entry_com;
|
||||
|
||||
@@ -38,12 +30,14 @@ static void AI_DequeueCommands(PlayerID player)
|
||||
while ((com = entry_com) != NULL) {
|
||||
_current_player = player;
|
||||
|
||||
/* Copy the DP back in place */
|
||||
_cmd_text = com->text;
|
||||
DoCommandP(com->tile, com->p1, com->p2, com->callback, com->procc);
|
||||
|
||||
/* Free item */
|
||||
entry_com = com->next;
|
||||
free(com->text);
|
||||
if (com->text != NULL)
|
||||
free(com->text);
|
||||
free(com);
|
||||
}
|
||||
}
|
||||
@@ -52,17 +46,17 @@ static void AI_DequeueCommands(PlayerID player)
|
||||
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
|
||||
* will make infinite loops (AIScript).
|
||||
*/
|
||||
static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint32 procc, CommandCallback* callback)
|
||||
static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCallback* callback)
|
||||
{
|
||||
AICommand *com;
|
||||
|
||||
if (_ai_player[player].queue_tail == NULL) {
|
||||
/* There is no item in the queue yet, create the queue */
|
||||
_ai_player[player].queue = MallocT<AICommand>(1);
|
||||
_ai_player[player].queue = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue;
|
||||
} else {
|
||||
/* Add an item at the end */
|
||||
_ai_player[player].queue_tail->next = MallocT<AICommand>(1);
|
||||
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
|
||||
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
|
||||
}
|
||||
|
||||
@@ -88,56 +82,66 @@ static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uin
|
||||
/**
|
||||
* Executes a raw DoCommand for the AI.
|
||||
*/
|
||||
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 procc, CommandCallback* callback)
|
||||
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
|
||||
{
|
||||
PlayerID old_lp;
|
||||
CommandCost res;
|
||||
const char* tmp_cmdtext;
|
||||
int32 res = 0;
|
||||
char *tmp_cmdtext = NULL;
|
||||
|
||||
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
|
||||
* person.. should we check for those funny jokes?
|
||||
*/
|
||||
|
||||
/* The test already resets _cmd_text, so backup the pointer */
|
||||
tmp_cmdtext = _cmd_text;
|
||||
/* The test already free _cmd_text in most cases, so let's backup the string, else we have a problem ;) */
|
||||
if (_cmd_text != NULL)
|
||||
tmp_cmdtext = strdup(_cmd_text);
|
||||
|
||||
/* First, do a test-run to see if we can do this */
|
||||
res = DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc);
|
||||
res = DoCommandByTile(tile, p1, p2, flags & ~DC_EXEC, procc);
|
||||
/* The command failed, or you didn't want to execute, or you are quering, return */
|
||||
if (CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
|
||||
if ((CmdFailed(res)) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
|
||||
if (tmp_cmdtext != NULL)
|
||||
free(tmp_cmdtext);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Restore _cmd_text */
|
||||
_cmd_text = tmp_cmdtext;
|
||||
/* Recover _cmd_text */
|
||||
if (tmp_cmdtext != NULL)
|
||||
_cmd_text = tmp_cmdtext;
|
||||
|
||||
/* If we did a DC_EXEC, and the command did not return an error, execute it
|
||||
over the network */
|
||||
if (flags & DC_AUTO) procc |= CMD_AUTO;
|
||||
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
|
||||
|
||||
/* NetworkSend_Command needs _local_player to be set correctly, so
|
||||
* adjust it, and put it back right after the function */
|
||||
adjust it, and put it back right after the function */
|
||||
old_lp = _local_player;
|
||||
_local_player = _current_player;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* Send the command */
|
||||
if (_networking) {
|
||||
if (_networking)
|
||||
/* Network is easy, send it to his handler */
|
||||
NetworkSend_Command(tile, p1, p2, procc, callback);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
else
|
||||
#endif
|
||||
/* If we execute BuildCommands directly in SP, we have a big problem with events
|
||||
* so we need to delay is for 1 tick */
|
||||
AI_PutCommandInQueue(_current_player, tile, p1, p2, procc, callback);
|
||||
}
|
||||
|
||||
/* Set _local_player back */
|
||||
_local_player = old_lp;
|
||||
|
||||
/* Free the temp _cmd_text var */
|
||||
if (tmp_cmdtext != NULL)
|
||||
free(tmp_cmdtext);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 procc)
|
||||
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
|
||||
}
|
||||
@@ -161,9 +165,6 @@ static void AI_RunTick(PlayerID player)
|
||||
AiDoGameLoop(p);
|
||||
_is_old_ai_player = false;
|
||||
}
|
||||
|
||||
/* AI could change some track, so update signals */
|
||||
UpdateSignalsInBuffer();
|
||||
}
|
||||
|
||||
|
||||
@@ -171,25 +172,35 @@ static void AI_RunTick(PlayerID player)
|
||||
* The gameloop for AIs.
|
||||
* Handles one tick for all the AIs.
|
||||
*/
|
||||
void AI_RunGameLoop()
|
||||
void AI_RunGameLoop(void)
|
||||
{
|
||||
/* Don't do anything if ai is disabled */
|
||||
if (!_ai.enabled) return;
|
||||
|
||||
/* Don't do anything if we are a network-client, or the AI has been disabled */
|
||||
if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
|
||||
/* Don't do anything if we are a network-client
|
||||
* (too bad when a client joins, he thinks the AIs are real, so it wants to control
|
||||
* them.. this avoids that, while loading a network game in singleplayer, does make
|
||||
* the AIs to continue ;))
|
||||
*/
|
||||
if (_networking && !_network_server && !_ai.network_client)
|
||||
return;
|
||||
|
||||
/* New tick */
|
||||
_ai.tick++;
|
||||
|
||||
/* Make sure the AI follows the difficulty rule.. */
|
||||
assert(_opt.diff.competitor_speed <= 4);
|
||||
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
|
||||
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0)
|
||||
return;
|
||||
|
||||
/* Check for AI-client (so joining a network with an AI) */
|
||||
if (!_networking || _network_server) {
|
||||
if (_ai.network_client && _ai_player[_ai.network_playas].active) {
|
||||
/* Run the script */
|
||||
AI_DequeueCommands(_ai.network_playas);
|
||||
AI_RunTick(_ai.network_playas);
|
||||
} else if (!_networking || _network_server) {
|
||||
/* Check if we want to run AIs (server or SP only) */
|
||||
const Player* p;
|
||||
Player *p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) {
|
||||
@@ -211,7 +222,7 @@ void AI_RunGameLoop()
|
||||
*/
|
||||
void AI_StartNewAI(PlayerID player)
|
||||
{
|
||||
assert(IsValidPlayer(player));
|
||||
assert(player < MAX_PLAYERS);
|
||||
|
||||
/* Called if a new AI is booted */
|
||||
_ai_player[player].active = true;
|
||||
@@ -222,35 +233,39 @@ void AI_StartNewAI(PlayerID player)
|
||||
*/
|
||||
void AI_PlayerDied(PlayerID player)
|
||||
{
|
||||
if (_ai.network_client && _ai.network_playas == player)
|
||||
_ai.network_playas = OWNER_SPECTATOR;
|
||||
|
||||
/* Called if this AI died */
|
||||
_ai_player[player].active = false;
|
||||
|
||||
if (_players_ainew[player].pathfinder == NULL) return;
|
||||
|
||||
AyStarMain_Free(_players_ainew[player].pathfinder);
|
||||
delete _players_ainew[player].pathfinder;
|
||||
_players_ainew[player].pathfinder = NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize some AI-related stuff.
|
||||
*/
|
||||
void AI_Initialize()
|
||||
void AI_Initialize(void)
|
||||
{
|
||||
bool ai_network_client = _ai.network_client;
|
||||
|
||||
/* First, make sure all AIs are DEAD! */
|
||||
AI_Uninitialize();
|
||||
|
||||
memset(&_ai, 0, sizeof(_ai));
|
||||
memset(&_ai_player, 0, sizeof(_ai_player));
|
||||
|
||||
_ai.network_client = ai_network_client;
|
||||
_ai.network_playas = OWNER_SPECTATOR;
|
||||
_ai.enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializer for AI-related stuff.
|
||||
*/
|
||||
void AI_Uninitialize()
|
||||
void AI_Uninitialize(void)
|
||||
{
|
||||
for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) AI_PlayerDied(p);
|
||||
Player* p;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
|
||||
}
|
||||
}
|
||||
+31
-30
@@ -1,58 +1,59 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AI_H
|
||||
#define AI_H
|
||||
|
||||
#include "../network/network.h"
|
||||
#include "../command_type.h"
|
||||
#include "../core/random_func.hpp"
|
||||
#include "../settings_type.h"
|
||||
#include "../functions.h"
|
||||
#include "../network.h"
|
||||
#include "../player.h"
|
||||
|
||||
/* How DoCommands look like for an AI */
|
||||
struct AICommand {
|
||||
typedef struct AICommand {
|
||||
uint32 tile;
|
||||
uint32 p1;
|
||||
uint32 p2;
|
||||
uint32 procc;
|
||||
CommandCallback *callback;
|
||||
CommandCallback* callback;
|
||||
|
||||
char *text;
|
||||
uint uid;
|
||||
|
||||
AICommand *next;
|
||||
};
|
||||
struct AICommand *next;
|
||||
} AICommand;
|
||||
|
||||
/* The struct for an AIScript Player */
|
||||
struct AIPlayer {
|
||||
bool active; ///< Is this AI active?
|
||||
AICommand *queue; ///< The commands that he has in his queue
|
||||
AICommand *queue_tail; ///< The tail of this queue
|
||||
};
|
||||
typedef struct AIPlayer {
|
||||
bool active; //! Is this AI active?
|
||||
AICommand *queue; //! The commands that he has in his queue
|
||||
AICommand *queue_tail; //! The tail of this queue
|
||||
} AIPlayer;
|
||||
|
||||
/* The struct to keep some data about the AI in general */
|
||||
struct AIStruct {
|
||||
typedef struct AIStruct {
|
||||
/* General */
|
||||
bool enabled; ///< Is AI enabled?
|
||||
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
|
||||
};
|
||||
bool enabled; //! Is AI enabled?
|
||||
uint tick; //! The current tick (something like _frame_counter, only for AIs)
|
||||
|
||||
extern AIStruct _ai;
|
||||
extern AIPlayer _ai_player[MAX_PLAYERS];
|
||||
/* For network-clients (a OpenTTD client who acts as an AI connected to a server) */
|
||||
bool network_client; //! Are we a network_client?
|
||||
uint8 network_playas; //! The current network player we are connected as
|
||||
} AIStruct;
|
||||
|
||||
VARDEF AIStruct _ai;
|
||||
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
|
||||
|
||||
// ai.c
|
||||
void AI_StartNewAI(PlayerID player);
|
||||
void AI_PlayerDied(PlayerID player);
|
||||
void AI_RunGameLoop();
|
||||
void AI_Initialize();
|
||||
void AI_Uninitialize();
|
||||
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
|
||||
void AI_RunGameLoop(void);
|
||||
void AI_Initialize(void);
|
||||
void AI_Uninitialize(void);
|
||||
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
|
||||
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
|
||||
|
||||
/** Is it allowed to start a new AI.
|
||||
* This function checks some boundries to see if we should launch a new AI.
|
||||
* @return True if we can start a new AI.
|
||||
*/
|
||||
static inline bool AI_AllowNewAI()
|
||||
static inline bool AI_AllowNewAI(void)
|
||||
{
|
||||
/* If disabled, no AI */
|
||||
if (!_ai.enabled)
|
||||
@@ -79,8 +80,8 @@ static inline bool AI_AllowNewAI()
|
||||
return true;
|
||||
}
|
||||
|
||||
#define AI_CHANCE16(a, b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
|
||||
#define AI_CHANCE16R(a, b, r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
|
||||
#define AI_CHANCE16(a,b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
|
||||
#define AI_CHANCE16R(a,b,r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
|
||||
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
@@ -99,7 +100,7 @@ static inline uint AI_RandomRange(uint max)
|
||||
/**
|
||||
* The random-function that should be used by ALL AIs.
|
||||
*/
|
||||
static inline uint32 AI_Random()
|
||||
static inline uint32 AI_Random(void)
|
||||
{
|
||||
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
|
||||
* but we pick InteractiveRandomRange if we are a network_server or network-client.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEFAULT_H
|
||||
#define DEFAULT_H
|
||||
|
||||
void AiDoGameLoop(Player*);
|
||||
|
||||
#endif
|
||||
@@ -3,20 +3,16 @@
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../road_map.h"
|
||||
#include "../../command_func.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../vehicle.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../engine.h"
|
||||
#include "../../station.h"
|
||||
#include "../../variables.h"
|
||||
#include "../../bridge.h"
|
||||
#include "../../vehicle_func.h"
|
||||
#include "../../vehicle_base.h"
|
||||
#include "../../player_base.h"
|
||||
#include "../../player_func.h"
|
||||
#include "../ai.h"
|
||||
#include "../../tunnelbridge.h"
|
||||
|
||||
|
||||
// Build HQ
|
||||
// Params:
|
||||
@@ -38,15 +34,15 @@ bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
|
||||
// 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)
|
||||
CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
|
||||
{
|
||||
if (type == AI_TRAIN)
|
||||
return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
|
||||
|
||||
if (type == AI_BUS)
|
||||
return AI_DoCommand(tile, direction, ROADTYPES_ROAD << 2 | RoadStop::BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
|
||||
return AI_DoCommand(tile, direction, ROADTYPES_ROAD << 2 | RoadStop::TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
return AI_DoCommand(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +51,12 @@ CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte lengt
|
||||
// tile_a : starting point
|
||||
// tile_b : end point
|
||||
// flag : flag passed to DoCommand
|
||||
CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
|
||||
{
|
||||
int bridge_type, bridge_len, type, type2;
|
||||
|
||||
// Find a good bridgetype (the best money can buy)
|
||||
bridge_len = GetTunnelBridgeLength(tile_a, tile_b);
|
||||
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)) {
|
||||
@@ -70,15 +66,14 @@ CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, by
|
||||
if (type2 != 0) break;
|
||||
}
|
||||
}
|
||||
// There is only one bridge that can be built
|
||||
// There is only one bridge that can be build..
|
||||
if (type2 == 0 && type != 0) type2 = type;
|
||||
|
||||
// Now, simply, build the bridge!
|
||||
if (_players_ainew[p->index].tbt == AI_TRAIN) {
|
||||
return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
} else {
|
||||
return AI_DoCommand(tile_a, tile_b, ((0x80 | ROADTYPES_ROAD) << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
}
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return AI_DoCommand(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
|
||||
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,52 +87,49 @@ CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, by
|
||||
// part : Which part we need to build
|
||||
//
|
||||
// TODO: skip already builded road-pieces (e.g.: cityroad)
|
||||
CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
|
||||
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;
|
||||
CommandCost cost;
|
||||
CommandCost res;
|
||||
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 CommandCost();
|
||||
}
|
||||
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.AddCost(AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL));
|
||||
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
|
||||
return CommandCost();
|
||||
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.AddCost(AiNew_Build_Bridge(p, route[part], route[part - 1], flag));
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part - 1]);
|
||||
return CommandCost();
|
||||
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) {
|
||||
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]);
|
||||
@@ -148,10 +140,10 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
|
||||
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
|
||||
if (CmdFailed(res)) {
|
||||
// Problem.. let's just abort it all!
|
||||
_players_ainew[p->index].state = AI_STATE_NOTHING;
|
||||
return CommandCost();
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
cost.AddCost(res);
|
||||
cost += res;
|
||||
// Go to the next tile
|
||||
part++;
|
||||
// Check if it is still in range..
|
||||
@@ -164,33 +156,33 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
|
||||
} else {
|
||||
// Tunnel code
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
|
||||
cost.AddCost(AI_DoCommand(route[part], 0x200 | ROADTYPES_ROAD, 0, flag, CMD_BUILD_TUNNEL));
|
||||
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
|
||||
return CommandCost();
|
||||
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.AddCost(AiNew_Build_Bridge(p, route[part], route[part + 1], flag));
|
||||
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
|
||||
PathFinderInfo->position++;
|
||||
// TODO: problems!
|
||||
if (CmdFailed(cost)) {
|
||||
DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part + 1]);
|
||||
return CommandCost();
|
||||
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
|
||||
// EnsureNoVehicleOnGround makes sure we don't build on a tile where a vehicle is. This 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 || EnsureNoVehicleOnGround(route[part]))) {
|
||||
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicleOnGround(route[part]))) {
|
||||
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?
|
||||
@@ -201,14 +193,14 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
|
||||
// Build the tile
|
||||
res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// Currently, we ignore CMD_ERRORs!
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_ROAD) && !EnsureNoVehicleOnGround(route[part])) {
|
||||
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
|
||||
// Problem.. let's just abort it all!
|
||||
DEBUG(ai, 0, "[BuidPath] route building failed at tile 0x%X, aborting", route[part]);
|
||||
_players_ainew[p->index].state = AI_STATE_NOTHING;
|
||||
return CommandCost();
|
||||
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CmdSucceeded(res)) cost.AddCost(res);
|
||||
if (!CmdFailed(res)) cost += res;
|
||||
}
|
||||
// Go to the next tile
|
||||
part++;
|
||||
@@ -218,7 +210,7 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
|
||||
part--;
|
||||
// We want to return the last position, so we go back one
|
||||
}
|
||||
if (!EnsureNoVehicleOnGround(route[part]) && flag == DC_EXEC) part--;
|
||||
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
|
||||
PathFinderInfo->position = part;
|
||||
}
|
||||
|
||||
@@ -227,45 +219,29 @@ CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo,
|
||||
|
||||
|
||||
// This functions tries to find the best vehicle for this type of cargo
|
||||
// It returns INVALID_ENGINE if not suitable engine is found
|
||||
EngineID AiNew_PickVehicle(Player *p)
|
||||
// It returns vehicle_id or -1 if not found
|
||||
int AiNew_PickVehicle(Player *p)
|
||||
{
|
||||
if (_players_ainew[p->index].tbt == AI_TRAIN) {
|
||||
if (p->ainew.tbt == AI_TRAIN) {
|
||||
// Not supported yet
|
||||
return INVALID_ENGINE;
|
||||
return -1;
|
||||
} else {
|
||||
EngineID best_veh_index = INVALID_ENGINE;
|
||||
int32 best_veh_rating = 0;
|
||||
EngineID i;
|
||||
|
||||
/* Loop through all road vehicles */
|
||||
FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
|
||||
const RoadVehicleInfo *rvi = RoadVehInfo(i);
|
||||
const Engine* e = GetEngine(i);
|
||||
|
||||
/* Skip vehicles which can't take our cargo type */
|
||||
if (rvi->cargo_type != _players_ainew[p->index].cargo && !CanRefitTo(i, _players_ainew[p->index].cargo)) continue;
|
||||
|
||||
/* Skip trams */
|
||||
if (HasBit(EngInfo(i)->misc_flags, EF_ROAD_TRAM)) continue;
|
||||
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(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
|
||||
/* Rate and compare the engine by speed & capacity */
|
||||
int rating = rvi->max_speed * rvi->capacity;
|
||||
if (rating <= best_veh_rating) continue;
|
||||
|
||||
if (!HASBIT(GetEngine(i)->player_avail, _current_player) || GetEngine(i)->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
|
||||
// Can we build it?
|
||||
CommandCost ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (CmdFailed(ret)) continue;
|
||||
|
||||
best_veh_rating = rating;
|
||||
best_veh_index = i;
|
||||
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
|
||||
if (!CmdFailed(ret)) break;
|
||||
}
|
||||
|
||||
return best_veh_index;
|
||||
// We did not find a vehicle :(
|
||||
if (CmdFailed(ret)) return -1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,31 +251,22 @@ void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
Player* p = GetPlayer(_current_player);
|
||||
|
||||
if (success) {
|
||||
_players_ainew[p->index].state = AI_STATE_GIVE_ORDERS;
|
||||
_players_ainew[p->index].veh_id = _new_vehicle_id;
|
||||
|
||||
if (GetVehicle(_players_ainew[p->index].veh_id)->cargo_type != _players_ainew[p->index].cargo) {
|
||||
/* Cargo type doesn't match, so refit it */
|
||||
if (CmdFailed(DoCommand(tile, _players_ainew[p->index].veh_id, _players_ainew[p->index].cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
|
||||
/* Refit failed, so sell the vehicle */
|
||||
DoCommand(tile, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
|
||||
_players_ainew[p->index].state = AI_STATE_NOTHING;
|
||||
}
|
||||
}
|
||||
p->ainew.state = AI_STATE_GIVE_ORDERS;
|
||||
p->ainew.veh_id = _new_vehicle_id;
|
||||
} else {
|
||||
/* XXX this should be handled more gracefully */
|
||||
_players_ainew[p->index].state = AI_STATE_NOTHING;
|
||||
p->ainew.state = AI_STATE_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Builds the best vehicle possible
|
||||
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
|
||||
{
|
||||
EngineID i = AiNew_PickVehicle(p);
|
||||
int i = AiNew_PickVehicle(p);
|
||||
if (i == -1) return CMD_ERROR;
|
||||
|
||||
if (i == INVALID_ENGINE) return CMD_ERROR;
|
||||
if (_players_ainew[p->index].tbt == AI_TRAIN) return CMD_ERROR;
|
||||
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
|
||||
|
||||
if (flag & DC_EXEC) {
|
||||
return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
|
||||
@@ -308,19 +275,18 @@ CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
|
||||
}
|
||||
}
|
||||
|
||||
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
|
||||
int AiNew_Build_Depot(Player *p, TileIndex tile, byte direction, byte flag)
|
||||
{
|
||||
CommandCost ret, ret2;
|
||||
if (_players_ainew[p->index].tbt == AI_TRAIN) {
|
||||
static const byte _roadbits_by_dir[4] = {2,1,8,4};
|
||||
int ret, ret2;
|
||||
if (p->ainew.tbt == AI_TRAIN)
|
||||
return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
|
||||
} else {
|
||||
ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
// Try to build the road from the depot
|
||||
ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
ret.AddCost(ret2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
|
||||
if (CmdFailed(ret)) return ret;
|
||||
// Try to build the road from the depot
|
||||
ret2 = AI_DoCommand(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
// If it fails, ignore it..
|
||||
if (CmdFailed(ret2)) return ret;
|
||||
return ret + ret2;
|
||||
}
|
||||
@@ -2,20 +2,15 @@
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../bridge_map.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../command_func.h"
|
||||
#include "../../functions.h"
|
||||
#include "../../map.h"
|
||||
#include "../../tile.h"
|
||||
#include "../../command.h"
|
||||
#include "trolly.h"
|
||||
#include "../../depot.h"
|
||||
#include "../../tunnel_map.h"
|
||||
#include "../../bridge.h"
|
||||
#include "../../tunnelbridge_map.h"
|
||||
#include "../ai.h"
|
||||
#include "../../variables.h"
|
||||
#include "../../player_base.h"
|
||||
#include "../../player_func.h"
|
||||
#include "../../tunnelbridge.h"
|
||||
|
||||
#include "../ai.h"
|
||||
|
||||
#define TEST_STATION_NO_DIR 0xFF
|
||||
|
||||
@@ -26,27 +21,32 @@ static bool TestCanBuildStationHere(TileIndex tile, byte dir)
|
||||
Player *p = GetPlayer(_current_player);
|
||||
|
||||
if (dir == TEST_STATION_NO_DIR) {
|
||||
CommandCost ret;
|
||||
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, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST);
|
||||
if (CmdSucceeded(ret)) return true;
|
||||
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 CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
|
||||
}
|
||||
|
||||
|
||||
static bool IsRoad(TileIndex tile)
|
||||
{
|
||||
return
|
||||
// MP_ROAD, but not a road depot?
|
||||
(IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD);
|
||||
// MP_STREET, but not a road depot?
|
||||
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
|
||||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
|
||||
// road tunnel?
|
||||
((_m[tile].m5 & 0x80) == 0 && (_m[tile].m5 & 0x4) == 0x4) ||
|
||||
// road bridge?
|
||||
((_m[tile].m5 & 0x80) != 0 && (_m[tile].m5 & 0x2) == 0x2)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@ static bool IsRoad(TileIndex tile)
|
||||
// Check if the current tile is in our end-area
|
||||
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
|
||||
{
|
||||
const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
|
||||
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))
|
||||
@@ -82,7 +81,7 @@ static uint AiPathFinder_Hash(uint key1, uint key2)
|
||||
static void AyStar_AiPathFinder_Free(AyStar *aystar)
|
||||
{
|
||||
AyStarMain_Free(aystar);
|
||||
delete aystar;
|
||||
free(aystar);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +98,7 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
|
||||
uint x;
|
||||
uint y;
|
||||
// Create AyStar
|
||||
AyStar *result = new AyStar();
|
||||
AyStar *result = malloc(sizeof(AyStar));
|
||||
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
|
||||
// Set the function pointers
|
||||
result->CalculateG = AyStar_AiPathFinder_CalculateG;
|
||||
@@ -156,11 +155,9 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
|
||||
// Now we add all the starting tiles
|
||||
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
|
||||
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
|
||||
TileIndex tile = TileXY(x, y);
|
||||
|
||||
if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
|
||||
if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = tile;
|
||||
if (!(IsTileType(TileXY(x, y), MP_CLEAR) || IsTileType(TileXY(x, y), MP_TREES))) continue;
|
||||
if (!TestCanBuildStationHere(TileXY(x, y), TEST_STATION_NO_DIR)) continue;
|
||||
start_node.node.tile = TileXY(x, y);
|
||||
aystar->addstart(aystar, &start_node.node, 0);
|
||||
}
|
||||
}
|
||||
@@ -170,13 +167,12 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
|
||||
// The h-value, simple calculation
|
||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
|
||||
{
|
||||
const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
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 + TileOffsByDiagDir(PathFinderInfo->end_direction));
|
||||
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
|
||||
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);
|
||||
@@ -200,21 +196,22 @@ static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *curre
|
||||
PathFinderInfo->route[i++] = parent->node.tile;
|
||||
if (i > lengthof(PathFinderInfo->route)) {
|
||||
// We ran out of space for the PathFinder
|
||||
DEBUG(ai, 0, "No more space in pathfinder route[] array");
|
||||
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, "Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
|
||||
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)
|
||||
{
|
||||
CommandCost ret;
|
||||
uint i;
|
||||
int ret;
|
||||
int dir;
|
||||
|
||||
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
|
||||
@@ -222,9 +219,9 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
aystar->num_neighbours = 0;
|
||||
|
||||
// Go through all surrounding tiles and check if they are within the limits
|
||||
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
TileIndex ctile = current->path.node.tile; // Current tile
|
||||
TileIndex atile = ctile + TileOffsByDiagDir(i); // Adjacent tile
|
||||
TileIndex atile = ctile + TileOffsByDir(i); // Adjacent tile
|
||||
|
||||
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
|
||||
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
|
||||
@@ -234,7 +231,20 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
// If the next step is a bridge, we have to enter it the right way
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
|
||||
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
|
||||
if (GetTunnelBridgeDirection(atile) != i) continue;
|
||||
// An existing bridge... let's test the direction ;)
|
||||
if ((_m[atile].m5 & 1U) != (i & 1)) continue;
|
||||
// This problem only is valid for tunnels:
|
||||
// When the last tile was not yet a tunnel, check if we enter from the right side..
|
||||
if ((_m[atile].m5 & 0x80) == 0) {
|
||||
if (i != (_m[atile].m5 & 3U)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// But also if we are on a bridge, we can only move a certain direction
|
||||
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
|
||||
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
|
||||
// An existing bridge/tunnel... let's test the direction ;)
|
||||
if ((_m[ctile].m5 & 1U) != (i & 1)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +252,7 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
(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 ((uint)i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
if (i != (current->path.node.user_data[0] >> 8)) continue;
|
||||
}
|
||||
dir = 0;
|
||||
|
||||
@@ -280,9 +290,9 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
dir = 0;
|
||||
} else {
|
||||
// It already has road.. check if we miss any bits!
|
||||
if ((GetAnyRoadBits(ctile, ROADTYPE_ROAD) & dir) != dir) {
|
||||
if ((_m[ctile].m5 & dir) != dir) {
|
||||
// We do miss some pieces :(
|
||||
dir &= ~GetAnyRoadBits(ctile, ROADTYPE_ROAD);
|
||||
dir &= ~_m[ctile].m5;
|
||||
} else {
|
||||
dir = 0;
|
||||
}
|
||||
@@ -305,23 +315,25 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
|
||||
// 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
|
||||
DiagDirection dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
|
||||
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;
|
||||
Slope tileh = GetTileSlope(tile, NULL);
|
||||
|
||||
FindLandscapeHeightByTile(&ti, tile);
|
||||
|
||||
// Bridges can only be build on land that is not flat
|
||||
// And if there is a road or rail blocking
|
||||
if (tileh != SLOPE_FLAT ||
|
||||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_ROAD)) ||
|
||||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
|
||||
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 += TileOffsByDiagDir(dir);
|
||||
new_tile += TileOffsByDir(dir);
|
||||
|
||||
// Precheck, is the length allowed?
|
||||
if (!CheckBridge_Stuff(0, GetTunnelBridgeLength(tile, new_tile))) break;
|
||||
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;
|
||||
@@ -339,13 +351,16 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
}
|
||||
|
||||
// Next, check for tunnels!
|
||||
// Tunnels can only be built on slopes corresponding to the direction
|
||||
// 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 (tileh == InclinedSlope(dir)) {
|
||||
if ((dir == 0 && ti.tileh == 12) ||
|
||||
(dir == 1 && ti.tileh == 6) ||
|
||||
(dir == 2 && ti.tileh == 3) ||
|
||||
(dir == 3 && ti.tileh == 9)) {
|
||||
// Now simply check if a tunnel can be build
|
||||
ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
tileh = GetTileSlope(_build_tunnel_endtile, NULL);
|
||||
if (CmdSucceeded(ret) && IsInclinedSlope(tileh)) {
|
||||
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;
|
||||
@@ -355,16 +370,23 @@ static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *curr
|
||||
}
|
||||
|
||||
|
||||
extern Foundation GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c
|
||||
extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits); // XXX function declaration in .c
|
||||
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 res = 0;
|
||||
Slope tileh = GetTileSlope(current->tile, NULL);
|
||||
Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
|
||||
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)) {
|
||||
@@ -394,24 +416,24 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
// when there is a flat land all around, they are more expensive to build, and
|
||||
// especially they essentially block the ability to connect or cross the road
|
||||
// from one side.
|
||||
if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
|
||||
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) {
|
||||
Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)));
|
||||
if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
|
||||
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)) {
|
||||
Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
|
||||
if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
|
||||
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 {
|
||||
else
|
||||
res += AI_PATHFINDER_FOUNDATION_PENALTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,22 +441,29 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
|
||||
// Are we part of a tunnel?
|
||||
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
|
||||
int r;
|
||||
// Tunnels are very expensive when build on long routes..
|
||||
// Ironicly, we are using BridgeCode here ;)
|
||||
r = AI_PATHFINDER_TUNNEL_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
|
||||
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 * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
|
||||
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 (!HasBridgeFlatRamp(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
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 (!HasBridgeFlatRamp(tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
|
||||
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
|
||||
@@ -444,11 +473,10 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
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)) {
|
||||
if (IsRoad(parent->path.node.tile))
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
|
||||
} else {
|
||||
else
|
||||
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For rail we have 1 exeption: diagonal rail..
|
||||
@@ -457,7 +485,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
|
||||
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;
|
||||
if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
|
||||
|
||||
// First see if they are different
|
||||
if (dir1 != dir2) {
|
||||
@@ -0,0 +1,124 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../openttd.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../map.h"
|
||||
#include "trolly.h"
|
||||
#include "../../vehicle.h"
|
||||
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
// 0 = vert
|
||||
// 1 = horz
|
||||
// 2 = dig up-left
|
||||
// 3 = dig down-right
|
||||
// 4 = dig down-left
|
||||
// 5 = dig up-right
|
||||
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
if (y1 == y2 && y2 == y3) return 0;
|
||||
if (x1 == x2 && x2 == x3) return 1;
|
||||
if (y2 > y1) {
|
||||
if (x2 > x3) return 2;
|
||||
else return 4;
|
||||
}
|
||||
if (x2 > x1) {
|
||||
if (y2 > y3) return 2;
|
||||
else return 5;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
if (x2 > x3) return 5;
|
||||
else return 3;
|
||||
}
|
||||
if (x1 > x2) {
|
||||
if (y2 > y3) return 4;
|
||||
else return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
|
||||
{
|
||||
int x1, x2, x3;
|
||||
int y1, y2, y3;
|
||||
int r;
|
||||
|
||||
x1 = TileX(tile_a);
|
||||
x2 = TileX(tile_b);
|
||||
x3 = TileX(tile_c);
|
||||
|
||||
y1 = TileY(tile_a);
|
||||
y2 = TileY(tile_b);
|
||||
y3 = TileY(tile_c);
|
||||
|
||||
r = 0;
|
||||
|
||||
if (x1 < x2) r += 8;
|
||||
if (y1 < y2) r += 1;
|
||||
if (x1 > x2) r += 2;
|
||||
if (y1 > y2) r += 4;
|
||||
|
||||
if (x2 < x3) r += 2;
|
||||
if (y2 < y3) r += 4;
|
||||
if (x2 > x3) r += 8;
|
||||
if (y2 > y3) r += 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Get's the direction between 2 tiles seen from tile_a
|
||||
int AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b)
|
||||
{
|
||||
if (TileY(tile_a) < TileY(tile_b)) return 1;
|
||||
if (TileY(tile_a) > TileY(tile_b)) return 3;
|
||||
if (TileX(tile_a) < TileX(tile_b)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This functions looks up if this vehicle is special for this AI
|
||||
// and returns his flag
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v) {
|
||||
int i;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
return p->ainew.special_vehicles[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found :(
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag) {
|
||||
int i, new_id = -1;
|
||||
for (i=0;i<AI_MAX_SPECIAL_VEHICLES;i++) {
|
||||
if (p->ainew.special_vehicles[i].veh_id == v->index) {
|
||||
p->ainew.special_vehicles[i].flag |= flag;
|
||||
return true;
|
||||
}
|
||||
if (new_id == -1 && p->ainew.special_vehicles[i].veh_id == 0 &&
|
||||
p->ainew.special_vehicles[i].flag == 0)
|
||||
new_id = i;
|
||||
}
|
||||
|
||||
// Out of special_vehicle spots :s
|
||||
if (new_id == -1) {
|
||||
DEBUG(ai, 1)("special_vehicles list is too small :(");
|
||||
return false;
|
||||
}
|
||||
p->ainew.special_vehicles[new_id].veh_id = v->index;
|
||||
p->ainew.special_vehicles[new_id].flag = flag;
|
||||
return true;
|
||||
}
|
||||
+1353
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,7 @@
|
||||
#define AI_TROLLY_H
|
||||
|
||||
#include "../../aystar.h"
|
||||
#include "../../player_type.h"
|
||||
#include "../../vehicle_type.h"
|
||||
#include "../../date_type.h"
|
||||
#include "../../player.h"
|
||||
|
||||
/*
|
||||
* These defines can be altered to change the behavoir of the AI
|
||||
@@ -241,22 +239,6 @@ typedef void AiNew_StateFunction(Player *p);
|
||||
// ai_new.c
|
||||
void AiNewDoGameLoop(Player *p);
|
||||
|
||||
struct Ai_PathFinderInfo {
|
||||
TileIndex start_tile_tl; ///< tl = top-left
|
||||
TileIndex start_tile_br; ///< br = bottom-right
|
||||
TileIndex end_tile_tl; ///< tl = top-left
|
||||
TileIndex end_tile_br; ///< br = bottom-right
|
||||
DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
|
||||
DiagDirection end_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
|
||||
|
||||
TileIndex route[500];
|
||||
byte route_extra[500]; ///< Some extra information about the route like bridge/tunnel
|
||||
int route_length;
|
||||
int position; ///< Current position in the build-path, needed to build the path
|
||||
|
||||
bool rail_or_road; ///< true = rail, false = road
|
||||
};
|
||||
|
||||
// ai_pathfinder.c
|
||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
|
||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
|
||||
@@ -264,77 +246,17 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
|
||||
// ai_shared.c
|
||||
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
|
||||
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
|
||||
int AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
|
||||
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag);
|
||||
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
|
||||
|
||||
// ai_build.c
|
||||
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
|
||||
CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
|
||||
CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
|
||||
CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
|
||||
EngineID AiNew_PickVehicle(Player *p);
|
||||
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
|
||||
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
|
||||
|
||||
/* The amount of memory reserved for the AI-special-vehicles */
|
||||
#define AI_MAX_SPECIAL_VEHICLES 100
|
||||
|
||||
struct Ai_SpecialVehicle {
|
||||
VehicleID veh_id;
|
||||
uint32 flag;
|
||||
};
|
||||
|
||||
struct PlayerAiNew {
|
||||
uint8 state;
|
||||
uint tick;
|
||||
uint idle;
|
||||
|
||||
int temp; ///< A value used in more than one function, but it just temporary
|
||||
///< The use is pretty simple: with this we can 'think' about stuff
|
||||
///< in more than one tick, and more than one AI. A static will not
|
||||
///< do, because they are not saved. This way, the AI is almost human ;)
|
||||
int counter; ///< For the same reason as temp, we have counter. It can count how
|
||||
///< long we are trying something, and just abort if it takes too long
|
||||
|
||||
/* Pathfinder stuff */
|
||||
Ai_PathFinderInfo path_info;
|
||||
AyStar *pathfinder;
|
||||
|
||||
/* Route stuff */
|
||||
|
||||
CargoID cargo;
|
||||
byte tbt; ///< train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK
|
||||
Money new_cost;
|
||||
|
||||
byte action;
|
||||
|
||||
int last_id; ///< here is stored the last id of the searched city/industry
|
||||
Date last_vehiclecheck_date; // Used in CheckVehicle
|
||||
Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; ///< Some vehicles have some special flags
|
||||
|
||||
TileIndex from_tile;
|
||||
TileIndex to_tile;
|
||||
|
||||
DiagDirectionByte from_direction;
|
||||
DiagDirectionByte to_direction;
|
||||
|
||||
bool from_deliver; ///< True if this is the station that GIVES cargo
|
||||
bool to_deliver;
|
||||
|
||||
TileIndex depot_tile;
|
||||
DiagDirectionByte depot_direction;
|
||||
|
||||
byte amount_veh; ///< How many vehicles we are going to build in this route
|
||||
byte cur_veh; ///< How many vehicles did we bought?
|
||||
VehicleID veh_id; ///< Used when bought a vehicle
|
||||
VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy
|
||||
|
||||
int from_ic; ///< ic = industry/city. This is the ID of them
|
||||
byte from_type; ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY
|
||||
int to_ic;
|
||||
byte to_type;
|
||||
};
|
||||
extern PlayerAiNew _players_ainew[MAX_PLAYERS];
|
||||
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
|
||||
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
|
||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
|
||||
int AiNew_PickVehicle(Player *p);
|
||||
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
|
||||
int AiNew_Build_Depot(Player *p, TileIndex tile, byte direction, byte flag);
|
||||
|
||||
#endif /* AI_TROLLY_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "station_map.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
|
||||
static inline bool IsAircraftInHangar(const Vehicle* v)
|
||||
{
|
||||
assert(v->type == VEH_Aircraft);
|
||||
return v->vehstatus & VS_HIDDEN && IsHangarTile(v->tile);
|
||||
}
|
||||
|
||||
static inline bool IsAircraftInHangarStopped(const Vehicle* v)
|
||||
{
|
||||
return IsAircraftInHangar(v) && v->vehstatus & VS_STOPPED;
|
||||
}
|
||||
+1988
File diff suppressed because it is too large
Load Diff
+1193
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,383 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "map.h"
|
||||
#include "airport.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
|
||||
static AirportFTAClass* CountryAirport;
|
||||
static AirportFTAClass* CityAirport;
|
||||
static AirportFTAClass* Oilrig;
|
||||
static AirportFTAClass* Heliport;
|
||||
static AirportFTAClass* MetropolitanAirport;
|
||||
static AirportFTAClass* InternationalAirport;
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots);
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport);
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA);
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA);
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport);
|
||||
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
|
||||
static byte AirportBlockToString(uint32 block);*/
|
||||
|
||||
void InitializeAirports(void)
|
||||
{
|
||||
// country airport
|
||||
CountryAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CountryAirport,
|
||||
_airport_terminal_country,
|
||||
NULL,
|
||||
16,
|
||||
ALL,
|
||||
_airport_fta_country,
|
||||
_airport_depots_country,
|
||||
lengthof(_airport_depots_country)
|
||||
);
|
||||
|
||||
// city airport
|
||||
CityAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
CityAirport,
|
||||
_airport_terminal_city,
|
||||
NULL,
|
||||
19,
|
||||
ALL,
|
||||
_airport_fta_city,
|
||||
_airport_depots_city,
|
||||
lengthof(_airport_depots_city)
|
||||
);
|
||||
|
||||
// metropolitan airport
|
||||
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
MetropolitanAirport,
|
||||
_airport_terminal_metropolitan,
|
||||
NULL,
|
||||
20,
|
||||
ALL,
|
||||
_airport_fta_metropolitan,
|
||||
_airport_depots_metropolitan,
|
||||
lengthof(_airport_depots_metropolitan)
|
||||
);
|
||||
|
||||
// international airport
|
||||
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
InternationalAirport,
|
||||
_airport_terminal_international,
|
||||
_airport_helipad_international,
|
||||
37,
|
||||
ALL,
|
||||
_airport_fta_international,
|
||||
_airport_depots_international,
|
||||
lengthof(_airport_depots_international)
|
||||
);
|
||||
|
||||
// heliport, oilrig
|
||||
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
|
||||
|
||||
AirportFTAClass_Constructor(
|
||||
Heliport,
|
||||
NULL,
|
||||
_airport_helipad_heliport_oilrig,
|
||||
7,
|
||||
HELICOPTERS_ONLY,
|
||||
_airport_fta_heliport_oilrig,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
|
||||
}
|
||||
|
||||
void UnInitializeAirports(void)
|
||||
{
|
||||
AirportFTAClass_Destructor(CountryAirport);
|
||||
AirportFTAClass_Destructor(CityAirport);
|
||||
AirportFTAClass_Destructor(Heliport);
|
||||
AirportFTAClass_Destructor(MetropolitanAirport);
|
||||
AirportFTAClass_Destructor(InternationalAirport);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
|
||||
const byte *terminals, const byte *helipads,
|
||||
const byte entry_point, const byte acc_planes,
|
||||
const AirportFTAbuildup *FA,
|
||||
const TileIndexDiffC *depots, const byte nof_depots)
|
||||
{
|
||||
byte nofterminals, nofhelipads;
|
||||
byte nofterminalgroups = 0;
|
||||
byte nofhelipadgroups = 0;
|
||||
const byte * curr;
|
||||
int i;
|
||||
nofterminals = nofhelipads = 0;
|
||||
|
||||
//now we read the number of terminals we have
|
||||
if (terminals != NULL) {
|
||||
i = terminals[0];
|
||||
nofterminalgroups = i;
|
||||
curr = terminals;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //we don't want to have an empty group
|
||||
nofterminals += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->terminals = terminals;
|
||||
|
||||
//read helipads
|
||||
if (helipads != NULL) {
|
||||
i = helipads[0];
|
||||
nofhelipadgroups = i;
|
||||
curr = helipads;
|
||||
while (i-- > 0) {
|
||||
curr++;
|
||||
assert(*curr != 0); //no empty groups please
|
||||
nofhelipads += *curr;
|
||||
}
|
||||
|
||||
}
|
||||
Airport->helipads = helipads;
|
||||
|
||||
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
|
||||
// same goes for helipads
|
||||
if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
|
||||
if (nofhelipads > MAX_HELIPADS) { printf("Currently only maximum of %2d helipads are supported (you wanted %2d)\n", MAX_HELIPADS, nofhelipads);}
|
||||
// terminals/helipads are divided into groups. Groups are computed by dividing the number
|
||||
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
|
||||
// will get the less # of terminals
|
||||
|
||||
assert(nofterminals <= MAX_TERMINALS);
|
||||
assert(nofhelipads <= MAX_HELIPADS);
|
||||
|
||||
Airport->nofelements = AirportGetNofElements(FA);
|
||||
// check
|
||||
if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
|
||||
assert(entry_point < Airport->nofelements);
|
||||
|
||||
Airport->acc_planes = acc_planes;
|
||||
Airport->entry_point = entry_point;
|
||||
Airport->airport_depots = depots;
|
||||
Airport->nof_depots = nof_depots;
|
||||
|
||||
|
||||
// build the state machine
|
||||
AirportBuildAutomata(Airport, FA);
|
||||
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d",
|
||||
Airport->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point
|
||||
);
|
||||
|
||||
|
||||
{
|
||||
byte ret = AirportTestFTA(Airport);
|
||||
if (ret != MAX_ELEMENTS) printf("ERROR with element: %d\n", ret - 1);
|
||||
assert(ret == MAX_ELEMENTS);
|
||||
}
|
||||
// print out full information
|
||||
// true -- full info including heading, block, etc
|
||||
// false -- short info, only position and next position
|
||||
//AirportPrintOut(Airport, false);
|
||||
}
|
||||
|
||||
static void AirportFTAClass_Destructor(AirportFTAClass *Airport)
|
||||
{
|
||||
int i;
|
||||
AirportFTA *current, *next;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = Airport->layout[i].next_in_chain;
|
||||
while (current != NULL) {
|
||||
next = current->next_in_chain;
|
||||
free(current);
|
||||
current = next;
|
||||
};
|
||||
}
|
||||
free(Airport->layout);
|
||||
free(Airport);
|
||||
}
|
||||
|
||||
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA)
|
||||
{
|
||||
int i;
|
||||
uint16 nofelements = 0;
|
||||
int temp = FA[0].position;
|
||||
|
||||
for (i = 0; i < MAX_ELEMENTS; i++) {
|
||||
if (temp != FA[i].position) {
|
||||
nofelements++;
|
||||
temp = FA[i].position;
|
||||
}
|
||||
if (FA[i].position == MAX_ELEMENTS) break;
|
||||
}
|
||||
return nofelements;
|
||||
}
|
||||
|
||||
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA)
|
||||
{
|
||||
AirportFTA *FAutomata;
|
||||
AirportFTA *current;
|
||||
uint16 internalcounter, i;
|
||||
FAutomata = malloc(sizeof(AirportFTA) * Airport->nofelements);
|
||||
Airport->layout = FAutomata;
|
||||
internalcounter = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
current = &Airport->layout[i];
|
||||
current->position = FA[internalcounter].position;
|
||||
current->heading = FA[internalcounter].heading;
|
||||
current->block = FA[internalcounter].block;
|
||||
current->next_position = FA[internalcounter].next_in_chain;
|
||||
|
||||
// outgoing nodes from the same position, create linked list
|
||||
while (current->position == FA[internalcounter + 1].position) {
|
||||
AirportFTA* newNode = malloc(sizeof(AirportFTA));
|
||||
|
||||
newNode->position = FA[internalcounter + 1].position;
|
||||
newNode->heading = FA[internalcounter + 1].heading;
|
||||
newNode->block = FA[internalcounter + 1].block;
|
||||
newNode->next_position = FA[internalcounter + 1].next_in_chain;
|
||||
// create link
|
||||
current->next_in_chain = newNode;
|
||||
current = current->next_in_chain;
|
||||
internalcounter++;
|
||||
} // while
|
||||
current->next_in_chain = NULL;
|
||||
internalcounter++;
|
||||
}
|
||||
}
|
||||
|
||||
static byte AirportTestFTA(const AirportFTAClass *Airport)
|
||||
{
|
||||
byte position, i, next_element;
|
||||
AirportFTA *temp;
|
||||
next_element = 0;
|
||||
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
position = Airport->layout[i].position;
|
||||
if (position != next_element) return i;
|
||||
temp = &Airport->layout[i];
|
||||
|
||||
do {
|
||||
if (temp->heading > MAX_HEADINGS && temp->heading != 255) return i;
|
||||
if (temp->heading == 0 && temp->next_in_chain != 0) return i;
|
||||
if (position != temp->position) return i;
|
||||
if (temp->next_position >= Airport->nofelements) return i;
|
||||
temp = temp->next_in_chain;
|
||||
} while (temp != NULL);
|
||||
next_element++;
|
||||
}
|
||||
return MAX_ELEMENTS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const char* const _airport_heading_strings[] = {
|
||||
"TO_ALL",
|
||||
"HANGAR",
|
||||
"TERM1",
|
||||
"TERM2",
|
||||
"TERM3",
|
||||
"TERM4",
|
||||
"TERM5",
|
||||
"TERM6",
|
||||
"HELIPAD1",
|
||||
"HELIPAD2",
|
||||
"TAKEOFF",
|
||||
"STARTTAKEOFF",
|
||||
"ENDTAKEOFF",
|
||||
"HELITAKEOFF",
|
||||
"FLYING",
|
||||
"LANDING",
|
||||
"ENDLANDING",
|
||||
"HELILANDING",
|
||||
"HELIENDLANDING",
|
||||
"DUMMY" // extra heading for 255
|
||||
};
|
||||
|
||||
static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report)
|
||||
{
|
||||
AirportFTA *temp;
|
||||
uint16 i;
|
||||
byte heading;
|
||||
|
||||
printf("(P = Current Position; NP = Next Position)\n");
|
||||
for (i = 0; i < Airport->nofelements; i++) {
|
||||
temp = &Airport->layout[i];
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", temp->position, temp->next_position);
|
||||
}
|
||||
while (temp->next_in_chain != NULL) {
|
||||
temp = temp->next_in_chain;
|
||||
if (full_report) {
|
||||
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
|
||||
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
|
||||
_airport_heading_strings[heading], AirportBlockToString(temp->block));
|
||||
} else {
|
||||
printf("P:%2d NP:%2d", temp->position, temp->next_position);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static byte AirportBlockToString(uint32 block)
|
||||
{
|
||||
byte i = 0;
|
||||
if (block & 0xffff0000) { block >>= 16; i += 16; }
|
||||
if (block & 0x0000ff00) { block >>= 8; i += 8; }
|
||||
if (block & 0x000000f0) { block >>= 4; i += 4; }
|
||||
if (block & 0x0000000c) { block >>= 2; i += 2; }
|
||||
if (block & 0x00000002) { i += 1; }
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
const AirportFTAClass* GetAirport(const byte airport_type)
|
||||
{
|
||||
AirportFTAClass *Airport = NULL;
|
||||
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
|
||||
// needs constant change if more airports are added
|
||||
switch (airport_type) {
|
||||
case AT_SMALL: Airport = CountryAirport; break;
|
||||
case AT_LARGE: Airport = CityAirport; break;
|
||||
case AT_METROPOLITAN: Airport = MetropolitanAirport; break;
|
||||
case AT_HELIPORT: Airport = Heliport; break;
|
||||
case AT_OILRIG: Airport = Oilrig; break;
|
||||
case AT_INTERNATIONAL: Airport = InternationalAirport; break;
|
||||
default:
|
||||
#ifdef DEBUG__
|
||||
printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n");
|
||||
#endif
|
||||
assert(airport_type <= AT_INTERNATIONAL);
|
||||
}
|
||||
return Airport;
|
||||
}
|
||||
|
||||
uint32 GetValidAirports(void)
|
||||
{
|
||||
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
|
||||
|
||||
// 1980-1-1 is --> 21915
|
||||
// 1990-1-1 is --> 25568
|
||||
if (_date >= 21915) SETBIT(bytemask, 3); // metropilitan airport 1980
|
||||
if (_date >= 25568) SETBIT(bytemask, 4); // international airport 1990
|
||||
return bytemask;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_H
|
||||
#define AIRPORT_H
|
||||
|
||||
#include "airport_movement.h"
|
||||
|
||||
enum {MAX_TERMINALS = 6};
|
||||
enum {MAX_HELIPADS = 2};
|
||||
|
||||
// Airport types
|
||||
enum {
|
||||
AT_SMALL = 0,
|
||||
AT_LARGE = 1,
|
||||
AT_HELIPORT = 2,
|
||||
AT_METROPOLITAN = 3,
|
||||
AT_INTERNATIONAL = 4,
|
||||
AT_OILRIG = 15
|
||||
};
|
||||
|
||||
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
|
||||
enum {
|
||||
AIRCRAFT_ONLY = 0,
|
||||
ALL = 1,
|
||||
HELICOPTERS_ONLY = 2
|
||||
};
|
||||
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAClass {
|
||||
byte nofelements; // number of positions the airport consists of
|
||||
const byte *terminals;
|
||||
const byte *helipads;
|
||||
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
|
||||
byte acc_planes; // accept airplanes or helicopters or both
|
||||
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
|
||||
byte nof_depots; // number of depots this airport has
|
||||
struct AirportFTA *layout; // state machine for airport
|
||||
} AirportFTAClass;
|
||||
|
||||
// internal structure used in openttd - Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTA {
|
||||
byte position; // the position that an airplane is at
|
||||
byte next_position; // next position from this position
|
||||
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
|
||||
byte heading; // heading (current orders), guiding an airplane to its target on an airport
|
||||
struct AirportFTA *next_in_chain; // possible extra movement choices from this position
|
||||
} AirportFTA;
|
||||
|
||||
void InitializeAirports(void);
|
||||
void UnInitializeAirports(void);
|
||||
const AirportFTAClass* GetAirport(const byte airport_type);
|
||||
|
||||
/** Get buildable airport bitmask.
|
||||
* @return get all buildable airports at this given time, bitmasked.
|
||||
* Bit 0 means the small airport is buildable, etc.
|
||||
* @todo set availability of airports by year, instead of airplane
|
||||
*/
|
||||
uint32 GetValidAirports(void);
|
||||
|
||||
#endif /* AIRPORT_H */
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "vehicle.h"
|
||||
#include "station.h"
|
||||
#include "airport.h"
|
||||
#include "depot.h"
|
||||
|
||||
static byte _selected_airport_type;
|
||||
|
||||
static void ShowBuildAirportPicker(void);
|
||||
|
||||
|
||||
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceAirport(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
|
||||
}
|
||||
|
||||
static void PlaceAir_DemolishArea(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, 4);
|
||||
}
|
||||
|
||||
|
||||
static void BuildAirClick_Airport(Window *w)
|
||||
{
|
||||
if (HandlePlacePushButton(w, 3, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
|
||||
}
|
||||
|
||||
static void BuildAirClick_Demolish(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
|
||||
}
|
||||
|
||||
static void BuildAirClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_air_button_proc[] = {
|
||||
BuildAirClick_Airport,
|
||||
BuildAirClick_Demolish,
|
||||
BuildAirClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget - 3 >= 0)
|
||||
_build_air_button_proc[e->click.widget - 3](w);
|
||||
break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
switch (e->keypress.keycode) {
|
||||
case '1': BuildAirClick_Airport(w); break;
|
||||
case '2': BuildAirClick_Demolish(w); break;
|
||||
case 'l': BuildAirClick_Landscaping(w); break;
|
||||
default: return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_PLACE_OBJ:
|
||||
_place_proc(e->place.tile);
|
||||
break;
|
||||
|
||||
case WE_PLACE_DRAG: {
|
||||
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
case WE_PLACE_MOUSEUP:
|
||||
if (e->place.pt.x != -1) {
|
||||
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
}
|
||||
break;
|
||||
|
||||
case WE_ABORT_PLACE_OBJ:
|
||||
UnclickWindowButtons(w);
|
||||
SetWindowDirty(w);
|
||||
w = FindWindowById(WC_BUILD_STATION, 0);
|
||||
if (w != 0)
|
||||
WP(w,def_d).close = true;
|
||||
break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _air_toolbar_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
|
||||
static const WindowDesc _air_toolbar_desc = {
|
||||
640-86, 22, 86, 36,
|
||||
WC_BUILD_TOOLBAR,0,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||
_air_toolbar_widgets,
|
||||
BuildAirToolbWndProc
|
||||
};
|
||||
|
||||
void ShowBuildAirToolbar(void)
|
||||
{
|
||||
if (_current_player == OWNER_SPECTATOR) return;
|
||||
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
|
||||
AllocateWindowDescFront(&_air_toolbar_desc, 0);
|
||||
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int sel;
|
||||
int rad = 4; // default catchment radious
|
||||
uint32 avail_airports;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
|
||||
sel = _selected_airport_type;
|
||||
avail_airports = GetValidAirports();
|
||||
|
||||
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
|
||||
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
|
||||
|
||||
/* 'Country Airport' starts at widget 3, and if its bit is set, it is
|
||||
* available, so take its opposite value to set the disabled_state. There
|
||||
* are only 5 available airports, so XOR with 0x1F (1 1111) */
|
||||
w->disabled_state = (avail_airports ^ 0x1F) << 3;
|
||||
|
||||
_selected_airport_type = sel;
|
||||
// select default the coverage area to 'Off' (8)
|
||||
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
|
||||
SetTileSelectSize(_airport_size_x[sel],_airport_size_y[sel]);
|
||||
|
||||
if (_patches.modified_catchment) {
|
||||
switch (sel) {
|
||||
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
|
||||
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
|
||||
case AT_SMALL: rad = CA_AIR_SMALL; break;
|
||||
case AT_LARGE: rad = CA_AIR_LARGE; break;
|
||||
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
|
||||
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
// strings such as 'Size' and 'Coverage Area'
|
||||
DrawStringCentered(74, 16, STR_305B_SIZE, 0);
|
||||
DrawStringCentered(74, 78, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
|
||||
DrawStationCoverageAreaText(2, 104, (uint)-1, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK: {
|
||||
switch (e->click.widget) {
|
||||
case 3: case 4: case 5: case 6: case 7:
|
||||
_selected_airport_type = e->click.widget - 3;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 8: case 9:
|
||||
_station_show_coverage = e->click.widget - 8;
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_MOUSELOOP: {
|
||||
if (WP(w,def_d).close) {
|
||||
DeleteWindow(w);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckRedrawStationCoverage(w);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (!WP(w,def_d).close) ResetObjectToPlace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_airport_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 130, 0x0, STR_NULL},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_airport_desc = {
|
||||
-1, -1, 148, 131, // height, 130+1
|
||||
WC_BUILD_STATION,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_airport_picker_widgets,
|
||||
BuildAirportPickerWndProc
|
||||
};
|
||||
|
||||
static void ShowBuildAirportPicker(void)
|
||||
{
|
||||
AllocateWindowDesc(&_build_airport_desc);
|
||||
}
|
||||
|
||||
void InitializeAirportGui(void)
|
||||
{
|
||||
_selected_airport_type = AT_SMALL;
|
||||
_last_built_aircraft_depot_tile = 0;
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AIRPORT_MOVEMENT_H
|
||||
#define AIRPORT_MOVEMENT_H
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
typedef struct AirportMovingData {
|
||||
int x,y;
|
||||
byte flag;
|
||||
byte direction;
|
||||
} AirportMovingData;
|
||||
|
||||
// state machine input struct (from external file, etc.)
|
||||
// Finite sTate mAchine --> FTA
|
||||
typedef struct AirportFTAbuildup {
|
||||
byte position; // the position that an airplane is at
|
||||
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
|
||||
uint32 block; // the block this position is on on the airport (st->airport_flags)
|
||||
byte next_in_chain; // next position from this position
|
||||
} AirportFTAbuildup;
|
||||
|
||||
enum {
|
||||
AMED_NOSPDCLAMP = 1<<0,
|
||||
AMED_TAKEOFF = 1<<1,
|
||||
AMED_SLOWTURN = 1<<2,
|
||||
AMED_LAND = 1<<3,
|
||||
AMED_EXACTPOS = 1<<4,
|
||||
AMED_BRAKE = 1<<5,
|
||||
AMED_HELI_RAISE = 1<<6,
|
||||
AMED_HELI_LOWER = 1<<7,
|
||||
};
|
||||
|
||||
enum {MAX_ELEMENTS = 255};
|
||||
enum {MAX_HEADINGS = 18};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////***********Movement States on Airports********************//////
|
||||
// headings target
|
||||
enum {
|
||||
TO_ALL = 0,
|
||||
HANGAR = 1,
|
||||
TERM1 = 2,
|
||||
TERM2 = 3,
|
||||
TERM3 = 4,
|
||||
TERM4 = 5,
|
||||
TERM5 = 6,
|
||||
TERM6 = 7,
|
||||
HELIPAD1 = 8,
|
||||
HELIPAD2 = 9,
|
||||
TAKEOFF = 10,
|
||||
STARTTAKEOFF = 11,
|
||||
ENDTAKEOFF = 12,
|
||||
HELITAKEOFF = 13,
|
||||
FLYING = 14,
|
||||
LANDING = 15,
|
||||
ENDLANDING = 16,
|
||||
HELILANDING = 17,
|
||||
HELIENDLANDING = 18
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////**********Movement Blocks on Airports*********************//////
|
||||
// blocks (eg_airport_flags)
|
||||
enum {
|
||||
TERM1_block = 1 << 0,
|
||||
TERM2_block = 1 << 1,
|
||||
TERM3_block = 1 << 2,
|
||||
TERM4_block = 1 << 3,
|
||||
TERM5_block = 1 << 4,
|
||||
TERM6_block = 1 << 5,
|
||||
HELIPAD1_block = 1 << 6,
|
||||
HELIPAD2_block = 1 << 7,
|
||||
RUNWAY_IN_OUT_block = 1 << 8,
|
||||
RUNWAY_IN_block = 1 << 8,
|
||||
AIRPORT_BUSY_block = 1 << 8,
|
||||
RUNWAY_OUT_block = 1 << 9,
|
||||
TAXIWAY_BUSY_block = 1 << 10,
|
||||
OUT_WAY_block = 1 << 11,
|
||||
IN_WAY_block = 1 << 12,
|
||||
AIRPORT_ENTRANCE_block = 1 << 13,
|
||||
TERM_GROUP1_block = 1 << 14,
|
||||
TERM_GROUP2_block = 1 << 15,
|
||||
HANGAR2_AREA_block = 1 << 16,
|
||||
TERM_GROUP2_ENTER1_block = 1 << 17,
|
||||
TERM_GROUP2_ENTER2_block = 1 << 18,
|
||||
TERM_GROUP2_EXIT1_block = 1 << 19,
|
||||
TERM_GROUP2_EXIT2_block = 1 << 20,
|
||||
PRE_HELIPAD_block = 1 << 21,
|
||||
NOTHING_block = 1 << 30
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////*********Movement Positions on Airports********************///////
|
||||
// Country Airfield (small) 4x3
|
||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||
{ 53, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 53, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 32, 23,AMED_EXACTPOS,7}, // 02 Terminal 1
|
||||
{ 10, 23,AMED_EXACTPOS,7}, // 03 Terminal 2
|
||||
{ 43, 37,0,0}, // 04 Going towards terminal 2
|
||||
{ 24, 37,0,0}, // 05 Going towards terminal 2
|
||||
{ 53, 37,0,0}, // 06 Going for takeoff
|
||||
{ 61, 40,AMED_EXACTPOS,1}, // 07 Taxi to start of runway (takeoff)
|
||||
{ 3, 40,AMED_NOSPDCLAMP,0}, // 08 Accelerate to end of runway
|
||||
{-79, 40,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 09 Take off
|
||||
{177, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 10 Fly to landing position in air
|
||||
{ 56, 40,AMED_NOSPDCLAMP | AMED_LAND,0}, // 11 Going down for land
|
||||
{ 3, 40,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 12 Just landed, brake until end of runway
|
||||
{ 7, 40,0,0}, // 13 Just landed, turn around and taxi 1 square
|
||||
{ 53, 40,0,0}, // 14 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 15 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 16 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 17 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (south)
|
||||
{ 44, 37,AMED_HELI_RAISE,0}, // 19 Helicopter takeoff
|
||||
{ 44, 40,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 In position above landing spot helicopter
|
||||
{ 44, 40,AMED_HELI_LOWER,0} // 21 Helicopter landing
|
||||
};
|
||||
|
||||
// City Airport (large) 6x6
|
||||
static const AirportMovingData _airport_moving_data_town[25] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 80, 27,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 63,0,0}, // 07 Taxi to Airport center
|
||||
{ 58, 71,0,0}, // 08 Towards takeoff
|
||||
{ 72, 85,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 85,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 85,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 85,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 20, 87,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 36, 71,0,0}, // 17 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 18 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 22 Helicopter takeoff
|
||||
{ 28, 74,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 23 In position above landing spot helicopter
|
||||
{ 28, 74,AMED_HELI_LOWER,0} // 24 Helicopter landing
|
||||
};
|
||||
|
||||
// Metropolitan Airport (metropolitan) - 2 runways
|
||||
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
|
||||
{ 85, 3,AMED_EXACTPOS,3}, // 00 In Hangar
|
||||
{ 85, 27,0,0}, // 01 Taxi to right outside depot
|
||||
{ 26, 41,AMED_EXACTPOS,5}, // 02 Terminal 1
|
||||
{ 56, 20,AMED_EXACTPOS,3}, // 03 Terminal 2
|
||||
{ 38, 8,AMED_EXACTPOS,5}, // 04 Terminal 3
|
||||
{ 65, 6,0,0}, // 05 Taxi to right in infront of terminal 2/3
|
||||
{ 70, 33,0,0}, // 06 Taxiway terminals 2-3
|
||||
{ 44, 58,0,0}, // 07 Taxi to Airport center
|
||||
{ 72, 58,0,0}, // 08 Towards takeoff
|
||||
{ 72, 69,0,0}, // 09 Taxi to runway (takeoff)
|
||||
{ 89, 69,AMED_EXACTPOS,1}, // 10 Taxi to start of runway (takeoff)
|
||||
{ 3, 69,AMED_NOSPDCLAMP,0}, // 11 Accelerate to end of runway
|
||||
{-79, 69,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 12 Take off
|
||||
{177, 85,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 13 Fly to landing position in air
|
||||
{ 89, 85,AMED_NOSPDCLAMP | AMED_LAND,0}, // 14 Going down for land
|
||||
{ 3, 85,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 15 Just landed, brake until end of runway
|
||||
{ 21, 85,0,0}, // 16 Just landed, turn around and taxi 1 square
|
||||
{ 21, 69,0,0}, // 17 On Runway-out taxiing to In-Way
|
||||
{ 21, 54,AMED_EXACTPOS,5}, // 18 Taxi from runway to crossing
|
||||
{-31,193,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 19 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 20 Fly around waiting for a landing spot (north-west)
|
||||
{257, 1,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 21 Fly around waiting for a landing spot (south-west)
|
||||
{273, 49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 22 Fly around waiting for a landing spot (south)
|
||||
{ 44, 58,0,0}, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
|
||||
{ 44, 63,AMED_HELI_RAISE,0}, // 24 Helicopter takeoff
|
||||
{ 15, 54,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 25 Get in position above landing spot helicopter
|
||||
{ 15, 54,AMED_HELI_LOWER,0} // 26 Helicopter landing
|
||||
};
|
||||
|
||||
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
|
||||
static const AirportMovingData _airport_moving_data_international[51] = {
|
||||
{ 7, 55,AMED_EXACTPOS,3}, // 00 In Hangar 1
|
||||
{100, 21,AMED_EXACTPOS,3}, // 01 In Hangar 2
|
||||
{ 7, 70,0,0}, // 02 Taxi to right outside depot
|
||||
{100, 36,0,0}, // 03 Taxi to right outside depot
|
||||
{ 38, 70,AMED_EXACTPOS,5}, // 04 Terminal 1
|
||||
{ 38, 54,AMED_EXACTPOS,5}, // 05 Terminal 2
|
||||
{ 38, 38,AMED_EXACTPOS,5}, // 06 Terminal 3
|
||||
{ 70, 70,AMED_EXACTPOS,1}, // 07 Terminal 4
|
||||
{ 70, 54,AMED_EXACTPOS,1}, // 08 Terminal 5
|
||||
{ 70, 38,AMED_EXACTPOS,1}, // 09 Terminal 6
|
||||
{104, 71,AMED_EXACTPOS,1}, // 10 Helipad 1
|
||||
{104, 55,AMED_EXACTPOS,1}, // 11 Helipad 2
|
||||
{ 22, 87,0,0}, // 12 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 60, 87,0,0}, // 13 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 66, 87,0,0}, // 14 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 87,AMED_EXACTPOS,7}, // 15 Towards Terminals 4/5/6, Helipad 1/2
|
||||
{ 86, 70,0,0}, // 16 In Front of Terminal 4 / Helipad 1
|
||||
{ 86, 54,0,0}, // 17 In Front of Terminal 5 / Helipad 2
|
||||
{ 86, 38,0,0}, // 18 In Front of Terminal 6
|
||||
{ 86, 22,0,0}, // 19 Towards Terminals Takeoff (Taxiway)
|
||||
{ 66, 22,0,0}, // 20 Towards Terminals Takeoff (Taxiway)
|
||||
{ 60, 22,0,0}, // 21 Towards Terminals Takeoff (Taxiway)
|
||||
{ 38, 22,0,0}, // 22 Towards Terminals Takeoff (Taxiway)
|
||||
{ 22, 70,0,0}, // 23 In Front of Terminal 1
|
||||
{ 22, 58,0,0}, // 24 In Front of Terminal 2
|
||||
{ 22, 38,0,0}, // 25 In Front of Terminal 3
|
||||
{ 22, 22,AMED_EXACTPOS,7}, // 26 Going for Takeoff
|
||||
{ 22, 6,0,0}, // 27 On Runway-out, prepare for takeoff
|
||||
{ 3, 6,AMED_EXACTPOS,5}, // 28 Accelerate to end of runway
|
||||
{ 60, 6,AMED_NOSPDCLAMP,0}, // 29 Release control of runway, for smoother movement
|
||||
{105, 6,AMED_NOSPDCLAMP,0}, // 30 End of runway
|
||||
{190, 6,AMED_NOSPDCLAMP | AMED_TAKEOFF,0}, // 31 Take off
|
||||
{193,104,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 32 Fly to landing position in air
|
||||
{105,104,AMED_NOSPDCLAMP | AMED_LAND,0}, // 33 Going down for land
|
||||
{ 3,104,AMED_NOSPDCLAMP | AMED_BRAKE,0}, // 34 Just landed, brake until end of runway
|
||||
{ 12,104,0,0}, // 35 Just landed, turn around and taxi 1 square
|
||||
{ 7, 84,0,0}, // 36 Taxi from runway to crossing
|
||||
{-31,209,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 37 Fly around waiting for a landing spot (north-east)
|
||||
{ 1, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 38 Fly around waiting for a landing spot (north-west)
|
||||
{273, 6,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 39 Fly around waiting for a landing spot (south-west)
|
||||
{305, 81,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 40 Fly around waiting for a landing spot (south)
|
||||
// Helicopter
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 41 Bufferspace before helipad
|
||||
{128, 80,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 42 Bufferspace before helipad
|
||||
{ 96, 71,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 43 Get in position for Helipad1
|
||||
{ 96, 55,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 44 Get in position for Helipad2
|
||||
{ 96, 71,AMED_HELI_LOWER,0}, // 45 Land at Helipad1
|
||||
{ 96, 55,AMED_HELI_LOWER,0}, // 46 Land at Helipad2
|
||||
{104, 71,AMED_HELI_RAISE,0}, // 47 Takeoff Helipad1
|
||||
{104, 55,AMED_HELI_RAISE,0}, // 48 Takeoff Helipad2
|
||||
{104, 32,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 49 Go to position for Hangarentrance in air
|
||||
{104, 32,AMED_HELI_LOWER,0} // 50 Land in HANGAR2_AREA to go to hangar
|
||||
};
|
||||
|
||||
// Heliport (heliport)
|
||||
static const AirportMovingData _airport_moving_data_heliport[9] = {
|
||||
{ 5, 9,AMED_EXACTPOS,1}, // 0 - At heliport terminal
|
||||
{ 2, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ -3, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ -3, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 2, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 59,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - Circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - Circle #2 (north-west)
|
||||
{ 49,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - Circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - Circle #4 (south)
|
||||
};
|
||||
|
||||
// Oilrig
|
||||
static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||
{ 31, 9,AMED_EXACTPOS,1}, // 0 - At oilrig terminal
|
||||
{ 28, 9,AMED_HELI_RAISE,0}, // 1 - Take off (play sound)
|
||||
{ 23, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 2 - In position above landing spot helicopter
|
||||
{ 23, 9,AMED_HELI_LOWER,0}, // 3 - Land
|
||||
{ 28, 9,0,0}, // 4 - Goto terminal on ground
|
||||
{-31, 69,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 5 - circle #1 (north-east)
|
||||
{-31,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 6 - circle #2 (north-west)
|
||||
{ 69,-49,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 7 - circle #3 (south-west)
|
||||
{ 70, 9,AMED_NOSPDCLAMP | AMED_SLOWTURN,0}, // 8 - circle #4 (south)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/////**********Movement Machine on Airports*********************///////
|
||||
// first element of depots array tells us how many depots there are (to know size of array)
|
||||
// this may be changed later when airports are moved to external file
|
||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||
static const byte _airport_terminal_country[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_country[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,AIRPORT_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM1,TERM1_block,2}, {1,TERM2,0,4}, {1,HELITAKEOFF,0,19}, {1,0,0,6},
|
||||
{ 2,TERM1,TERM1_block,1},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,255,AIRPORT_BUSY_block,0}, {4,TERM2,0,5}, {4,HANGAR,0,1}, {4,TAKEOFF,0,6}, {4,HELITAKEOFF,0,1},
|
||||
{ 5,255,AIRPORT_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,0,0,4},
|
||||
{ 6,0,AIRPORT_BUSY_block,7},
|
||||
// takeoff
|
||||
{ 7,TAKEOFF,AIRPORT_BUSY_block,8},
|
||||
{ 8,STARTTAKEOFF,NOTHING_block,9},
|
||||
{ 9,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{10,FLYING,NOTHING_block,15}, {10,LANDING,0,11}, {10,HELILANDING,0,20},
|
||||
{11,LANDING,AIRPORT_BUSY_block,12},
|
||||
{12,0,AIRPORT_BUSY_block,13},
|
||||
{13,ENDLANDING,AIRPORT_BUSY_block,14}, {13,TERM2,0,5}, {13,0,0,14},
|
||||
{14,0,AIRPORT_BUSY_block,1},
|
||||
// In air
|
||||
{15,0,NOTHING_block,16},
|
||||
{16,0,NOTHING_block,17},
|
||||
{17,0,NOTHING_block,18},
|
||||
{18,0,NOTHING_block,10},
|
||||
{19,HELITAKEOFF,NOTHING_block,0},
|
||||
{20,HELILANDING,AIRPORT_BUSY_block,21},
|
||||
{21,HELIENDLANDING,AIRPORT_BUSY_block,1},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_city[] = {{5, 0}};
|
||||
static const byte _airport_terminal_city[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_city[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1}, {0,TAKEOFF,OUT_WAY_block,1}, {0,0,0,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7}, {2,TAKEOFF,OUT_WAY_block,7}, {2,0,0,7},
|
||||
{ 3,TERM2,TERM2_block,5}, {3,TAKEOFF,OUT_WAY_block,5}, {3,0,0,5},
|
||||
{ 4,TERM3,TERM3_block,5}, {4,TAKEOFF,OUT_WAY_block,5}, {4,0,0,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,OUT_WAY_block,8}, {7,HELITAKEOFF,0,22}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_IN_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_IN_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,18}, {13,LANDING,0,14}, {13,HELILANDING,0,23},
|
||||
{14,LANDING,RUNWAY_IN_OUT_block,15},
|
||||
{15,0,RUNWAY_IN_OUT_block,16},
|
||||
{16,0,RUNWAY_IN_OUT_block,17},
|
||||
{17,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{18,0,NOTHING_block,19},
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{22,HELITAKEOFF,NOTHING_block,0},
|
||||
{23,HELILANDING,IN_WAY_block,24},
|
||||
{24,HELIENDLANDING,IN_WAY_block,17},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_metropolitan[] = {{5, 0}};
|
||||
static const byte _airport_terminal_metropolitan[] = {1, 3};
|
||||
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
|
||||
{ 0,HANGAR,NOTHING_block,1},
|
||||
{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
|
||||
{ 2,TERM1,TERM1_block,7},
|
||||
{ 3,TERM2,TERM2_block,5},
|
||||
{ 4,TERM3,TERM3_block,5},
|
||||
{ 5,255,TAXIWAY_BUSY_block,0}, {5,TERM2,TERM2_block,3}, {5,TERM3,TERM3_block,4}, {5,0,0,6},
|
||||
{ 6,255,TAXIWAY_BUSY_block,0}, {6,TERM2,0,5}, {6,TERM3,0,5}, {6,HANGAR,0,1}, {6,0,0,7},
|
||||
{ 7,255,TAXIWAY_BUSY_block,0}, {7,TERM1,TERM1_block,2}, {7,TAKEOFF,0,8}, {7,HELITAKEOFF,0,23}, {7,HANGAR,0,1}, {7,0,0,6},
|
||||
{ 8,0,OUT_WAY_block,9},
|
||||
{ 9,0,RUNWAY_OUT_block,10},
|
||||
// takeoff
|
||||
{10,TAKEOFF,RUNWAY_OUT_block,11},
|
||||
{11,STARTTAKEOFF,NOTHING_block,12},
|
||||
{12,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{13,FLYING,NOTHING_block,19}, {13,LANDING,0,14}, {13,HELILANDING,0,25},
|
||||
{14,LANDING,RUNWAY_IN_block,15},
|
||||
{15,0,RUNWAY_IN_block,16},
|
||||
{16,255,RUNWAY_IN_block,0}, {16,ENDLANDING,IN_WAY_block,17},
|
||||
{17,255,RUNWAY_OUT_block,0}, {17,ENDLANDING,IN_WAY_block,18},
|
||||
{18,ENDLANDING,IN_WAY_block,7},
|
||||
// In Air
|
||||
{19,0,NOTHING_block,20},
|
||||
{20,0,NOTHING_block,21},
|
||||
{21,0,NOTHING_block,22},
|
||||
{22,0,NOTHING_block,13},
|
||||
// helicopter
|
||||
{23,0,NOTHING_block,24},
|
||||
{24,HELITAKEOFF,NOTHING_block,0},
|
||||
{25,HELILANDING,IN_WAY_block,26},
|
||||
{26,HELIENDLANDING,IN_WAY_block,18},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const TileIndexDiffC _airport_depots_international[] = {{0, 3}, {6, 1}};
|
||||
static const byte _airport_terminal_international[] = {2, 3, 3};
|
||||
static const byte _airport_helipad_international[] = {1, 2};
|
||||
static const AirportFTAbuildup _airport_fta_international[] = {
|
||||
{ 0,HANGAR,NOTHING_block,2}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER1_block,1}, {0,HELITAKEOFF,HELIPAD1_block,2}, {0,0,0,2},
|
||||
{ 1,HANGAR,NOTHING_block,3}, {1,255,HANGAR2_AREA_block,1}, {1,HELITAKEOFF,HELIPAD2_block,3}, {1,0,0,3},
|
||||
{ 2,255,AIRPORT_ENTRANCE_block,0}, {2,HANGAR,0,0}, {2,TERM4,0,12}, {2,TERM5,0,12}, {2,TERM6,0,12}, {2,HELIPAD1,0,12}, {2,HELIPAD2,0,12}, {2,HELITAKEOFF,0,12}, {2,0,0,23},
|
||||
{ 3,255,HANGAR2_AREA_block,0}, {3,HANGAR,0,1}, {3,0,0,18},
|
||||
{ 4,TERM1,TERM1_block,23}, {4,HANGAR,AIRPORT_ENTRANCE_block,23}, {4,0,0,23},
|
||||
{ 5,TERM2,TERM2_block,24}, {5,HANGAR,AIRPORT_ENTRANCE_block,24}, {5,0,0,24},
|
||||
{ 6,TERM3,TERM3_block,25}, {6,HANGAR,AIRPORT_ENTRANCE_block,25}, {6,0,0,25},
|
||||
{ 7,TERM4,TERM4_block,16}, {7,HANGAR,HANGAR2_AREA_block,16}, {7,0,0,16},
|
||||
{ 8,TERM5,TERM5_block,17}, {8,HANGAR,HANGAR2_AREA_block,17}, {8,0,0,17},
|
||||
{ 9,TERM6,TERM6_block,18}, {9,HANGAR,HANGAR2_AREA_block,18}, {9,0,0,18},
|
||||
{10,HELIPAD1,HELIPAD1_block,10}, {10,HANGAR,HANGAR2_AREA_block,16}, {10,HELITAKEOFF,0,47},
|
||||
{11,HELIPAD2,HELIPAD2_block,11}, {11,HANGAR,HANGAR2_AREA_block,17}, {11,HELITAKEOFF,0,48},
|
||||
{12,0,TERM_GROUP2_ENTER1_block,13},
|
||||
{13,0,TERM_GROUP2_ENTER1_block,14},
|
||||
{14,0,TERM_GROUP2_ENTER2_block,15},
|
||||
{15,0,TERM_GROUP2_ENTER2_block,16},
|
||||
{16,255,TERM_GROUP2_block,0}, {16,TERM4,TERM4_block,7}, {16,HELIPAD1,HELIPAD1_block,10}, {16,HELITAKEOFF,HELIPAD1_block,10}, {16,0,0,17},
|
||||
{17,255,TERM_GROUP2_block,0}, {17,TERM5,TERM5_block,8}, {17,TERM4,0,16}, {17,HELIPAD1,0,16}, {17,HELIPAD2,HELIPAD2_block,11}, {17,HELITAKEOFF,HELIPAD2_block,11}, {17,0,0,18},
|
||||
{18,255,TERM_GROUP2_block,0}, {18,TERM6,TERM6_block,9}, {18,TAKEOFF,0,19}, {18,HANGAR,HANGAR2_AREA_block,3}, {18,0,0,17},
|
||||
{19,0,TERM_GROUP2_EXIT1_block,20},
|
||||
{20,0,TERM_GROUP2_EXIT1_block,21},
|
||||
{21,0,TERM_GROUP2_EXIT2_block,22},
|
||||
{22,0,TERM_GROUP2_EXIT2_block,26},
|
||||
{23,255,TERM_GROUP1_block,0}, {23,TERM1,TERM1_block,4}, {23,HANGAR,AIRPORT_ENTRANCE_block,2}, {23,0,0,24},
|
||||
{24,255,TERM_GROUP1_block,0}, {24,TERM2,TERM2_block,5}, {24,TERM1,0,23}, {24,HANGAR,0,23}, {24,0,0,25},
|
||||
{25,255,TERM_GROUP1_block,0}, {25,TERM3,TERM3_block,6}, {25,TAKEOFF,0,26}, {25,0,0,24},
|
||||
{26,255,TAXIWAY_BUSY_block,0}, {26,TAKEOFF,0,27}, {26,0,0,25},
|
||||
{27,0,OUT_WAY_block,28},
|
||||
// takeoff
|
||||
{28,TAKEOFF,OUT_WAY_block,29},
|
||||
{29,0,RUNWAY_OUT_block,30},
|
||||
{30,STARTTAKEOFF,NOTHING_block,31},
|
||||
{31,ENDTAKEOFF,NOTHING_block,0},
|
||||
// landing
|
||||
{32,FLYING,NOTHING_block,37}, {32,LANDING,0,33}, {32,HELILANDING,0,41},
|
||||
{33,LANDING,RUNWAY_IN_block,34},
|
||||
{34,0,RUNWAY_IN_block,35},
|
||||
{35,0,RUNWAY_IN_block,36},
|
||||
{36,ENDLANDING,IN_WAY_block,36}, {36,255,TERM_GROUP1_block,0}, {36,255,TERM_GROUP2_ENTER1_block,1}, {36,TERM4,0,12}, {36,TERM5,0,12}, {36,TERM6,0,12}, {36,0,0,2},
|
||||
// In Air
|
||||
{37,0,NOTHING_block,38},
|
||||
{38,0,NOTHING_block,39},
|
||||
{39,0,NOTHING_block,40},
|
||||
{40,0,NOTHING_block,32},
|
||||
// Helicopter -- stay in air in special place as a buffer to choose from helipads
|
||||
{41,HELILANDING,PRE_HELIPAD_block,42},
|
||||
{42,HELIENDLANDING,PRE_HELIPAD_block,42}, {42,HELIPAD1,0,43}, {42,HELIPAD2,0,44}, {42,HANGAR,0,49},
|
||||
{43,0,NOTHING_block,45},
|
||||
{44,0,NOTHING_block,46},
|
||||
// landing
|
||||
{45,255,NOTHING_block,0}, {45,HELIPAD1,HELIPAD1_block,10},
|
||||
{46,255,NOTHING_block,0}, {46,HELIPAD2,HELIPAD2_block,11},
|
||||
// Helicopter -- takeoff
|
||||
{47,HELITAKEOFF,NOTHING_block,0},
|
||||
{48,HELITAKEOFF,NOTHING_block,0},
|
||||
{49,0,HANGAR2_AREA_block,50}, // need to go to hangar when waiting in air
|
||||
{50,0,HANGAR2_AREA_block,3},
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
// heliports, oilrigs don't have depots
|
||||
static const byte _airport_helipad_heliport_oilrig[] = {1, 1};
|
||||
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
|
||||
{0,HELIPAD1,HELIPAD1_block,1},
|
||||
{1,HELITAKEOFF,NOTHING_block,0}, // takeoff
|
||||
{2,255,AIRPORT_BUSY_block,0}, {2,HELILANDING,0,3}, {2,HELITAKEOFF,0,1},
|
||||
{3,HELILANDING,AIRPORT_BUSY_block,4},
|
||||
{4,HELIENDLANDING,AIRPORT_BUSY_block,4}, {4,HELIPAD1,HELIPAD1_block,0}, {4,HELITAKEOFF,0,2},
|
||||
// In Air
|
||||
{5,0,NOTHING_block,6},
|
||||
{6,0,NOTHING_block,7},
|
||||
{7,0,NOTHING_block,8},
|
||||
{8,FLYING,NOTHING_block,5}, {8,HELILANDING,HELIPAD1_block,2}, // landing
|
||||
{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
|
||||
};
|
||||
|
||||
static const AirportMovingData * const _airport_moving_datas[] = {
|
||||
_airport_moving_data_country, // Country Airfield (small) 4x3
|
||||
_airport_moving_data_town, // City Airport (large) 6x6
|
||||
_airport_moving_data_heliport, // Heliport
|
||||
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
|
||||
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_airport_moving_data_oilrig // Oilrig
|
||||
};
|
||||
|
||||
#endif /* AIRPORT_MOVEMENT_H */
|
||||
+49
-68
@@ -1,7 +1,5 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file aystar.cpp */
|
||||
|
||||
/*
|
||||
* This file has the core function for AyStar
|
||||
* AyStar is a fast pathfinding routine and is used for things like
|
||||
@@ -21,31 +19,26 @@
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "aystar.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
|
||||
int _aystar_stats_open_size;
|
||||
int _aystar_stats_closed_size;
|
||||
|
||||
// This looks in the Hash if a node exists in ClosedList
|
||||
// If so, it returns the PathNode, else NULL
|
||||
static PathNode* AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
|
||||
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)
|
||||
static void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node)
|
||||
{
|
||||
// Add a node to the ClosedList
|
||||
PathNode *new_node = MallocT<PathNode>(1);
|
||||
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)
|
||||
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node)
|
||||
{
|
||||
return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
|
||||
}
|
||||
@@ -56,20 +49,19 @@ static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, const AyStarNo
|
||||
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) {
|
||||
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)
|
||||
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);
|
||||
OpenListNode* new_node = malloc(sizeof(OpenListNode));
|
||||
new_node->g = g;
|
||||
new_node->path.parent = parent;
|
||||
new_node->path.node = *node;
|
||||
@@ -82,10 +74,9 @@ static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, const AySt
|
||||
/*
|
||||
* 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;
|
||||
@@ -116,8 +107,7 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
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) {
|
||||
if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
|
||||
uint i;
|
||||
// Yes, check if this g value is lower..
|
||||
if (new_g > check->g) return AYSTAR_DONE;
|
||||
@@ -126,9 +116,8 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
|
||||
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
|
||||
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
|
||||
} else {
|
||||
@@ -143,15 +132,14 @@ 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
|
||||
@@ -174,7 +162,7 @@ int AyStarMain_Loop(AyStar *aystar)
|
||||
aystar->GetNeighbours(aystar, current);
|
||||
|
||||
// Go through all neighbours
|
||||
for (i = 0; i < aystar->num_neighbours; i++) {
|
||||
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);
|
||||
}
|
||||
@@ -182,20 +170,18 @@ int AyStarMain_Loop(AyStar *aystar)
|
||||
// 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 {
|
||||
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 */
|
||||
@@ -210,8 +196,7 @@ 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)
|
||||
{
|
||||
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);
|
||||
@@ -227,9 +212,9 @@ 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!
|
||||
@@ -240,26 +225,24 @@ int AyStarMain_Main(AyStar *aystar) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -269,8 +252,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);
|
||||
@@ -278,8 +260,7 @@ 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)
|
||||
{
|
||||
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);
|
||||
@@ -290,10 +271,10 @@ void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets)
|
||||
// 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;
|
||||
}
|
||||
+25
-23
@@ -1,18 +1,17 @@
|
||||
/* $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"
|
||||
|
||||
//#define AYSTAR_DEBUG
|
||||
enum {
|
||||
@@ -28,13 +27,15 @@ enum{
|
||||
AYSTAR_INVALID_NODE = -1,
|
||||
};
|
||||
|
||||
typedef struct AyStarNode AyStarNode;
|
||||
struct AyStarNode {
|
||||
TileIndex tile;
|
||||
int direction;
|
||||
uint direction;
|
||||
uint user_data[2];
|
||||
};
|
||||
|
||||
// The resulting path has nodes looking like this.
|
||||
typedef struct PathNode PathNode;
|
||||
struct PathNode {
|
||||
AyStarNode node;
|
||||
// The parent of this item
|
||||
@@ -44,17 +45,18 @@ struct PathNode {
|
||||
// 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
|
||||
@@ -69,8 +71,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);
|
||||
|
||||
@@ -79,7 +81,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,7 +99,7 @@ typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
|
||||
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
|
||||
|
||||
// For internal use, see aystar.c
|
||||
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
|
||||
typedef 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);
|
||||
@@ -110,11 +112,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.
|
||||
@@ -142,12 +144,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 */
|
||||
|
||||
@@ -171,7 +173,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 */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +0,0 @@
|
||||
You can place you scenarios in this dir.
|
||||
|
||||
This file is really here to make the Makefile happy, it should be modified to
|
||||
properly handle scenarios (or maybe even not at all...).
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bridge.h Header file for bridges */
|
||||
|
||||
#ifndef BRIDGE_H
|
||||
#define BRIDGE_H
|
||||
|
||||
/** Struct containing information about a single bridge type
|
||||
*/
|
||||
typedef struct Bridge {
|
||||
byte avail_year; ///< the year in which the bridge becomes available
|
||||
byte min_length; ///< the minimum length of the bridge (not counting start and end tile)
|
||||
byte max_length; ///< the maximum length of the bridge (not counting start and end tile)
|
||||
uint16 price; ///< the relative price of the bridge
|
||||
uint16 speed; ///< maximum travel speed
|
||||
PalSpriteID sprite; ///< the sprite which is used in the GUI (possibly with a recolor sprite)
|
||||
StringID material; ///< the string that contains the bridge description
|
||||
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
|
||||
byte flags; ///< bit 0 set: disable drawing of far pillars.
|
||||
} Bridge;
|
||||
|
||||
extern const Bridge orig_bridge[MAX_BRIDGES];
|
||||
extern Bridge _bridge[MAX_BRIDGES];
|
||||
|
||||
#endif /* BRIDGE_H */
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file bridge_gui.c Graphical user interface for bridge construction*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "command.h"
|
||||
#include "sound.h"
|
||||
#include "variables.h"
|
||||
#include "bridge.h"
|
||||
|
||||
static struct BridgeData {
|
||||
uint count;
|
||||
TileIndex start_tile;
|
||||
TileIndex end_tile;
|
||||
byte type;
|
||||
byte indexes[MAX_BRIDGES];
|
||||
int32 costs[MAX_BRIDGES];
|
||||
} _bridgedata;
|
||||
|
||||
void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
|
||||
}
|
||||
|
||||
static void BuildBridge(Window *w, int i)
|
||||
{
|
||||
DeleteWindow(w);
|
||||
DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
|
||||
_bridgedata.indexes[i] | (_bridgedata.type << 8), CcBuildBridge,
|
||||
CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
|
||||
}
|
||||
|
||||
static void BuildBridgeWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT: {
|
||||
uint i;
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
for (i = 0; i < 4 && i + w->vscroll.pos < _bridgedata.count; i++) {
|
||||
const Bridge *b = &_bridge[_bridgedata.indexes[i + w->vscroll.pos]];
|
||||
|
||||
SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
|
||||
SetDParam(1, (b->speed >> 4) * 10);
|
||||
SetDParam(0, b->material);
|
||||
DrawSprite(b->sprite, 3, 15 + i * 22);
|
||||
|
||||
DrawString(44, 15 + i * 22 , STR_500D, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WE_KEYPRESS: {
|
||||
uint i = e->keypress.keycode - '1';
|
||||
if (i < 9 && i < _bridgedata.count) {
|
||||
e->keypress.cont = false;
|
||||
BuildBridge(w, i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->click.widget == 2) {
|
||||
uint ind = ((int)e->click.pt.y - 14) / 22;
|
||||
if (ind < 4 && (ind += w->vscroll.pos) < _bridgedata.count)
|
||||
BuildBridge(w, ind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
static const Widget _build_road_bridge_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
|
||||
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _build_road_bridge_desc = {
|
||||
-1, -1, 200, 102,
|
||||
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_build_road_bridge_widgets,
|
||||
BuildBridgeWndProc
|
||||
};
|
||||
|
||||
|
||||
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, byte bridge_type)
|
||||
{
|
||||
uint j = 0;
|
||||
int32 ret;
|
||||
StringID errmsg;
|
||||
|
||||
DeleteWindowById(WC_BUILD_BRIDGE, 0);
|
||||
|
||||
_bridgedata.type = bridge_type;
|
||||
_bridgedata.start_tile = start;
|
||||
_bridgedata.end_tile = end;
|
||||
|
||||
errmsg = INVALID_STRING_ID;
|
||||
|
||||
// only query bridge building possibility once, result is the same for all bridges!
|
||||
// returns CMD_ERROR on failure, and price on success
|
||||
ret = DoCommandByTile(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
|
||||
|
||||
if (CmdFailed(ret)) {
|
||||
errmsg = _error_message;
|
||||
} else {
|
||||
// check which bridges can be built
|
||||
int bridge_len; // length of the middle parts of the bridge
|
||||
int tot_bridgedata_len; // total length of bridge
|
||||
|
||||
// get absolute bridge length
|
||||
bridge_len = GetBridgeLength(start, end);
|
||||
tot_bridgedata_len = bridge_len + 2;
|
||||
|
||||
tot_bridgedata_len = CalcBridgeLenCostFactor(tot_bridgedata_len);
|
||||
|
||||
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
|
||||
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
|
||||
const Bridge *b = &_bridge[bridge_type];
|
||||
// bridge is accepted, add to list
|
||||
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
|
||||
_bridgedata.costs[j] = ret + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
|
||||
_bridgedata.indexes[j] = bridge_type;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bridgedata.count = j;
|
||||
|
||||
if (j != 0) {
|
||||
Window *w = AllocateWindowDesc((_bridgedata.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
|
||||
w->vscroll.cap = 4;
|
||||
w->vscroll.count = (byte)j;
|
||||
} else {
|
||||
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef BRIDGE_MAP_H
|
||||
#define BRIDGE_MAP_H
|
||||
|
||||
#include "direction.h"
|
||||
#include "macros.h"
|
||||
#include "map.h"
|
||||
#include "rail.h"
|
||||
#include "tile.h"
|
||||
|
||||
|
||||
static inline bool IsBridge(TileIndex t)
|
||||
{
|
||||
assert(IsTileType(t, MP_TUNNELBRIDGE));
|
||||
return HASBIT(_m[t].m5, 7);
|
||||
}
|
||||
|
||||
static inline bool IsBridgeTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_TUNNELBRIDGE) && IsBridge(t);
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsBridgeRamp(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return !HASBIT(_m[t].m5, 6);
|
||||
}
|
||||
|
||||
static inline bool IsBridgeMiddle(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeTile(t));
|
||||
return HASBIT(_m[t].m5, 6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the direction pointing onto the bridge
|
||||
*/
|
||||
static inline DiagDirection GetBridgeRampDirection(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeRamp(t));
|
||||
/* Heavy wizardry to convert the X/Y (bit 0) + N/S (bit 5) encoding of
|
||||
* bridges to a DiagDirection
|
||||
*/
|
||||
return (DiagDirection)((6 - (_m[t].m5 >> 4 & 2) - (_m[t].m5 & 1)) % 4);
|
||||
}
|
||||
|
||||
|
||||
static inline Axis GetBridgeAxis(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return (Axis)GB(_m[t].m5, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsTransportUnderBridge(TileIndex t)
|
||||
{
|
||||
assert(IsBridgeMiddle(t));
|
||||
return HASBIT(_m[t].m5, 5);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,58 +1,57 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.cpp */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "callback_table.h"
|
||||
#include "functions.h"
|
||||
|
||||
/* If you add a callback for DoCommandP, also add the callback in here
|
||||
* see below for the full list!
|
||||
* If you don't do it, it won't work across the network!! */
|
||||
// If you add a callback for DoCommandP, also add the callback in here
|
||||
// see below for the full list!
|
||||
// If you don't do it, it won't work across the network!!
|
||||
|
||||
/* aircraft_gui.cpp */
|
||||
/* aircraft_gui.c */
|
||||
CommandCallback CcBuildAircraft;
|
||||
CommandCallback CcCloneAircraft;
|
||||
|
||||
/* airport_gui.cpp */
|
||||
/* airport_gui.c */
|
||||
CommandCallback CcBuildAirport;
|
||||
|
||||
/* bridge_gui.cpp */
|
||||
/* bridge_gui.c */
|
||||
CommandCallback CcBuildBridge;
|
||||
|
||||
/* dock_gui.cpp */
|
||||
/* dock_gui.c */
|
||||
CommandCallback CcBuildDocks;
|
||||
CommandCallback CcBuildCanal;
|
||||
|
||||
/* depot_gui.cpp */
|
||||
CommandCallback CcCloneVehicle;
|
||||
|
||||
/* main_gui.cpp */
|
||||
/* main_gui.c */
|
||||
CommandCallback CcPlaySound10;
|
||||
CommandCallback CcPlaceSign;
|
||||
CommandCallback CcTerraform;
|
||||
CommandCallback CcBuildTown;
|
||||
CommandCallback CcGiveMoney;
|
||||
|
||||
/* rail_gui.cpp */
|
||||
/* rail_gui.c */
|
||||
CommandCallback CcPlaySound1E;
|
||||
CommandCallback CcRailDepot;
|
||||
CommandCallback CcStation;
|
||||
CommandCallback CcBuildRailTunnel;
|
||||
|
||||
/* road_gui.cpp */
|
||||
/* road_gui.c */
|
||||
CommandCallback CcPlaySound1D;
|
||||
CommandCallback CcBuildRoadTunnel;
|
||||
CommandCallback CcRoadDepot;
|
||||
|
||||
/* roadveh_gui.cpp */
|
||||
/* roadveh_gui.c */
|
||||
CommandCallback CcBuildRoadVeh;
|
||||
CommandCallback CcCloneRoadVeh;
|
||||
|
||||
/* ship_gui.cpp */
|
||||
/* ship_gui.c */
|
||||
CommandCallback CcBuildShip;
|
||||
CommandCallback CcCloneShip;
|
||||
|
||||
/* train_gui.cpp */
|
||||
/* train_gui.c */
|
||||
CommandCallback CcBuildWagon;
|
||||
CommandCallback CcBuildLoco;
|
||||
CommandCallback CcCloneTrain;
|
||||
|
||||
CommandCallback CcAI;
|
||||
|
||||
@@ -78,9 +77,11 @@ CommandCallback *_callback_table[] = {
|
||||
/* 0x12 */ CcPlaySound1E,
|
||||
/* 0x13 */ CcStation,
|
||||
/* 0x14 */ CcTerraform,
|
||||
/* 0x15 */ CcAI,
|
||||
/* 0x16 */ CcCloneVehicle,
|
||||
/* 0x17 */ CcGiveMoney,
|
||||
/* 0x15 */ CcCloneAircraft,
|
||||
/* 0x16 */ CcCloneRoadVeh,
|
||||
/* 0x17 */ CcCloneShip,
|
||||
/* 0x18 */ CcCloneTrain,
|
||||
/* 0x19 */ CcAI
|
||||
};
|
||||
|
||||
const int _callback_table_count = lengthof(_callback_table);
|
||||
@@ -1,11 +1,9 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file callback_table.h */
|
||||
|
||||
#ifndef CALLBACK_TABLE_H
|
||||
#define CALLBACK_TABLE_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern CommandCallback *_callback_table[];
|
||||
extern const int _callback_table_count;
|
||||
+6
-1118
File diff suppressed because it is too large
Load Diff
+864
@@ -0,0 +1,864 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "tunnel_map.h"
|
||||
#include "variables.h"
|
||||
#include "table/sprites.h"
|
||||
|
||||
typedef struct TerraformerHeightMod {
|
||||
TileIndex tile;
|
||||
byte height;
|
||||
} TerraformerHeightMod;
|
||||
|
||||
typedef struct TerraformerState {
|
||||
int height[4];
|
||||
uint32 flags;
|
||||
|
||||
int direction;
|
||||
int modheight_count;
|
||||
int tile_table_count;
|
||||
|
||||
int32 cost;
|
||||
|
||||
TileIndex *tile_table;
|
||||
TerraformerHeightMod *modheight;
|
||||
|
||||
} TerraformerState;
|
||||
|
||||
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TileIndex *t;
|
||||
int count;
|
||||
|
||||
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) return -1;
|
||||
|
||||
t = ts->tile_table;
|
||||
for (count = ts->tile_table_count; count != 0; count--, t++) {
|
||||
if (*t == tile) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformerHeightMod *mod = ts->modheight;
|
||||
int count;
|
||||
|
||||
for (count = ts->modheight_count; count != 0; count--, mod++) {
|
||||
if (mod->tile == tile) return mod->height;
|
||||
}
|
||||
|
||||
return TileHeight(tile);
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
int count;
|
||||
TileIndex *t;
|
||||
|
||||
count = ts->tile_table_count;
|
||||
|
||||
if (count >= 625) return;
|
||||
|
||||
for(t = ts->tile_table; count != 0; count--,t++) {
|
||||
if (*t == tile) return;
|
||||
}
|
||||
|
||||
ts->tile_table[ts->tile_table_count++] = tile;
|
||||
}
|
||||
|
||||
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
|
||||
{
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
|
||||
TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, 0));
|
||||
TerraformAddDirtyTile(ts, tile);
|
||||
}
|
||||
|
||||
static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
|
||||
{
|
||||
int r;
|
||||
int32 ret;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
r = TerraformAllowTileProcess(ts, tile);
|
||||
if (r <= 0) return r;
|
||||
|
||||
if (IsTileType(tile, MP_RAILWAY)) {
|
||||
static const TrackBits safe_track[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
|
||||
static const Slope unsafe_slope[] = { SLOPE_S, SLOPE_W, SLOPE_N, SLOPE_E };
|
||||
|
||||
Slope tileh;
|
||||
uint z;
|
||||
|
||||
// Nothing could be built at the steep slope - this avoids a bug
|
||||
// when you have a single diagonal track in one corner on a
|
||||
// basement and then you raise/lower the other corner.
|
||||
tileh = GetTileSlope(tile, &z);
|
||||
if (tileh == unsafe_slope[mode] ||
|
||||
tileh == ComplementSlope(unsafe_slope[mode])) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If we have a single diagonal track there, the other side of
|
||||
// tile can be terraformed.
|
||||
if (IsPlainRailTile(tile) && GetTrackBits(tile) == safe_track[mode]) {
|
||||
/* If terraforming downwards prevent damaging a potential tunnel below.
|
||||
* This check is only necessary for flat tiles, because if the tile is
|
||||
* non-flat, then the corner opposing the rail is raised. Only this corner
|
||||
* can be lowered and this is a safe action
|
||||
*/
|
||||
if (tileh == SLOPE_FLAT &&
|
||||
ts->direction == -1 &&
|
||||
IsTunnelInWay(tile, z - TILE_HEIGHT)) {
|
||||
_terraform_err_tile = tile;
|
||||
_error_message = STR_1002_EXCAVATION_WOULD_DAMAGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 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, TileIndex tile, int height)
|
||||
{
|
||||
int nh;
|
||||
TerraformerHeightMod *mod;
|
||||
int count;
|
||||
|
||||
assert(tile < MapSize());
|
||||
|
||||
if (height < 0) {
|
||||
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
|
||||
return false;
|
||||
}
|
||||
|
||||
_error_message = STR_1004_TOO_HIGH;
|
||||
|
||||
if (height > 15) return false;
|
||||
|
||||
nh = TerraformGetHeightOfTile(ts, tile);
|
||||
if (nh < 0 || height == nh) return false;
|
||||
|
||||
if (TerraformProc(ts, tile, 0) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
|
||||
if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
|
||||
|
||||
mod = ts->modheight;
|
||||
count = ts->modheight_count;
|
||||
|
||||
for (;;) {
|
||||
if (count == 0) {
|
||||
if (ts->modheight_count >= 576)
|
||||
return false;
|
||||
ts->modheight_count++;
|
||||
break;
|
||||
}
|
||||
if (mod->tile == tile) break;
|
||||
mod++;
|
||||
count--;
|
||||
}
|
||||
|
||||
mod->tile = tile;
|
||||
mod->height = (byte)height;
|
||||
|
||||
ts->cost += _price.terraform;
|
||||
|
||||
{
|
||||
int direction = ts->direction, r;
|
||||
const TileIndexDiffC *ttm;
|
||||
|
||||
static const TileIndexDiffC _terraform_tilepos[] = {
|
||||
{ 1, 0},
|
||||
{-2, 0},
|
||||
{ 1, 1},
|
||||
{ 0, -2}
|
||||
};
|
||||
|
||||
for(ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
|
||||
tile += ToTileIndexDiff(*ttm);
|
||||
|
||||
r = TerraformGetHeightOfTile(ts, tile);
|
||||
if (r != height && r-direction != height && r+direction != height) {
|
||||
if (!TerraformTileHeight(ts, tile, r+direction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Terraform land
|
||||
* @param x,y coordinates to terraform
|
||||
* @param p1 corners to terraform.
|
||||
* @param p2 direction; eg up or down
|
||||
*/
|
||||
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TerraformerState ts;
|
||||
TileIndex tile;
|
||||
int direction;
|
||||
|
||||
TerraformerHeightMod modheight_data[576];
|
||||
TileIndex tile_table_data[625];
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_terraform_err_tile = 0;
|
||||
|
||||
ts.direction = direction = p2 ? 1 : -1;
|
||||
ts.flags = flags;
|
||||
ts.modheight_count = ts.tile_table_count = 0;
|
||||
ts.cost = 0;
|
||||
ts.modheight = modheight_data;
|
||||
ts.tile_table = tile_table_data;
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
/* Make an extra check for map-bounds cause we add tiles to the originating tile */
|
||||
if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
|
||||
|
||||
if (p1 & 1) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(1, 0),
|
||||
TileHeight(tile + TileDiffXY(1, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 2) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(1, 1),
|
||||
TileHeight(tile + TileDiffXY(1, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 4) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(0, 1),
|
||||
TileHeight(tile + TileDiffXY(0, 1)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (p1 & 8) {
|
||||
if (!TerraformTileHeight(&ts, tile + TileDiffXY(0, 0),
|
||||
TileHeight(tile + TileDiffXY(0, 0)) + direction))
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (direction == -1) {
|
||||
/* Check if tunnel would take damage */
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
uint z, t;
|
||||
TileIndex tile = *ti;
|
||||
|
||||
z = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
|
||||
if (t <= z) z = t;
|
||||
t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
|
||||
if (t <= z) z = t;
|
||||
|
||||
if (IsTunnelInWay(tile, z * TILE_HEIGHT)) {
|
||||
return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Clear the landscape at the tiles */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* change the height */
|
||||
{
|
||||
int count;
|
||||
TerraformerHeightMod *mod;
|
||||
|
||||
mod = ts.modheight;
|
||||
for (count = ts.modheight_count; count != 0; count--, mod++) {
|
||||
TileIndex til = mod->tile;
|
||||
|
||||
SetTileHeight(til, mod->height);
|
||||
TerraformAddDirtyTileAround(&ts, til);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally mark the dirty tiles dirty */
|
||||
{
|
||||
int count;
|
||||
TileIndex *ti = ts.tile_table;
|
||||
for (count = ts.tile_table_count; count != 0; count--, ti++) {
|
||||
MarkTileDirtyByTile(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ts.cost;
|
||||
}
|
||||
|
||||
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param x,y end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
TileIndex tile;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 >= MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
h = TileHeight(p1);
|
||||
|
||||
ex >>= 4; ey >>= 4;
|
||||
|
||||
// make sure sx,sy are smaller than ex,ey
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
if (ex < sx) intswap(ex, sx);
|
||||
if (ey < sy) intswap(ey, sy);
|
||||
tile = TileXY(sx, sy);
|
||||
|
||||
size_x = ex-sx+1;
|
||||
size_y = ey-sy+1;
|
||||
|
||||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((money -= ret) < 0) {
|
||||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is purchasing
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
int32 cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (IsTileType(tile, MP_UNMOVABLE) && _m[tile].m5 == 3 &&
|
||||
IsTileOwner(tile, _current_player))
|
||||
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
|
||||
|
||||
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
ModifyTile(tile,
|
||||
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
|
||||
3 /* map5 */
|
||||
);
|
||||
}
|
||||
|
||||
return cost + _price.purchase_land * 10;
|
||||
}
|
||||
|
||||
|
||||
static int32 ClearTile_Clear(TileIndex tile, byte flags)
|
||||
{
|
||||
static const int32 null = 0;
|
||||
static const int32* clear_price_table[] = {
|
||||
&null,
|
||||
&_price.clear_1,
|
||||
&_price.clear_1,
|
||||
&_price.clear_1,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.clear_3,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.purchase_land,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
&_price.clear_2,
|
||||
};
|
||||
const int32 *price = clear_price_table[GB(_m[tile].m5, 0, 5)];
|
||||
|
||||
if (flags & DC_EXEC) DoClearSquare(tile);
|
||||
|
||||
return *price;
|
||||
}
|
||||
|
||||
/** Sell a land area. Actually you only sell one tile, so
|
||||
* the name is a bit confusing ;p
|
||||
* @param x,y the tile the player is selling
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
|
||||
if (!IsTileType(tile, MP_UNMOVABLE) || _m[tile].m5 != 3) return CMD_ERROR;
|
||||
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) return CMD_ERROR;
|
||||
|
||||
|
||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC)
|
||||
DoClearSquare(tile);
|
||||
|
||||
return - _price.purchase_land * 2;
|
||||
}
|
||||
|
||||
|
||||
#include "table/clear_land.h"
|
||||
|
||||
|
||||
void DrawClearLandTile(const TileInfo *ti, byte set)
|
||||
{
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19);
|
||||
}
|
||||
|
||||
void DrawHillyLandTile(const TileInfo *ti)
|
||||
{
|
||||
if (ti->tileh != 0) {
|
||||
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh]);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawClearLandFence(const TileInfo *ti)
|
||||
{
|
||||
byte m4 = _m[ti->tile].m4;
|
||||
byte z = ti->z;
|
||||
|
||||
if (ti->tileh & 2) {
|
||||
z += 8;
|
||||
if (ti->tileh == 0x17) z += 8;
|
||||
}
|
||||
|
||||
if (GB(m4, 5, 3) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GB(m4, 5, 3) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
|
||||
if (GB(m4, 2, 3) != 0) {
|
||||
DrawGroundSpriteAt(_clear_land_fence_sprites_1[GB(m4, 2, 3) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawTile_Clear(TileInfo *ti)
|
||||
{
|
||||
switch (GB(ti->map5, 2, 3)) {
|
||||
case 0:
|
||||
DrawClearLandTile(ti, GB(ti->map5, 0, 2));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
DrawHillyLandTile(ti);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
DrawGroundSprite(_clear_land_sprites_1[GB(_m[ti->tile].m3, 0, 4)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DrawGroundSprite(_clear_land_sprites_2[GB(ti->map5, 0, 2)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
DrawGroundSprite(_clear_land_sprites_3[GB(ti->map5, 0, 2)] + _tileh_to_sprite[ti->tileh]);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawClearLandFence(ti);
|
||||
}
|
||||
|
||||
static uint GetSlopeZ_Clear(const TileInfo* ti)
|
||||
{
|
||||
return GetPartialZ(ti->x & 0xF, ti->y & 0xF, ti->tileh) + ti->z;
|
||||
}
|
||||
|
||||
static uint GetSlopeTileh_Clear(const TileInfo *ti)
|
||||
{
|
||||
return ti->tileh;
|
||||
}
|
||||
|
||||
static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static void AnimateTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
void TileLoopClearHelper(TileIndex tile)
|
||||
{
|
||||
byte self;
|
||||
byte neighbour;
|
||||
TileIndex dirty = INVALID_TILE;
|
||||
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_CLEAR:
|
||||
self = (GB(_m[tile].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
self = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
|
||||
case MP_CLEAR:
|
||||
neighbour = (GB(_m[TILE_ADDXY(tile, 1, 0)].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
neighbour = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GB(_m[tile].m4, 5, 3) == 0) {
|
||||
if (self != neighbour) {
|
||||
SB(_m[tile].m4, 5, 3, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SB(_m[tile].m4, 5, 3, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
|
||||
case MP_CLEAR:
|
||||
neighbour = (GB(_m[TILE_ADDXY(tile, 0, 1)].m5, 0, 5) == 15);
|
||||
break;
|
||||
|
||||
default:
|
||||
neighbour = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GB(_m[tile].m4, 2, 3) == 0) {
|
||||
if (self != neighbour) {
|
||||
SB(_m[tile].m4, 2, 3, 3);
|
||||
dirty = tile;
|
||||
}
|
||||
} else {
|
||||
if (self == 0 && neighbour == 0) {
|
||||
SB(_m[tile].m4, 2, 3, 0);
|
||||
dirty = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
|
||||
}
|
||||
|
||||
|
||||
/* convert into snowy tiles */
|
||||
static void TileLoopClearAlps(TileIndex tile)
|
||||
{
|
||||
int k;
|
||||
byte m5,tmp;
|
||||
|
||||
/* distance from snow line, in steps of 8 */
|
||||
k = GetTileZ(tile) - _opt.snow_line;
|
||||
|
||||
m5 = _m[tile].m5 & 0x1C;
|
||||
tmp = _m[tile].m5 & 3;
|
||||
|
||||
if (k < -8) {
|
||||
/* snow_m2_down */
|
||||
if (m5 != 0x10)
|
||||
return;
|
||||
if (tmp == 0)
|
||||
m5 = 3;
|
||||
} else if (k == -8) {
|
||||
/* snow_m1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 0) {
|
||||
m5 = (tmp - 1) + 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k < 8) {
|
||||
/* snow_0 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 1) {
|
||||
m5 = 1;
|
||||
if (tmp != 0)
|
||||
m5 = tmp - 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else if (k == 8) {
|
||||
/* snow_p1 */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 2) {
|
||||
m5 = 2;
|
||||
if (tmp <= 2)
|
||||
m5 = tmp + 1;
|
||||
m5 += 0x10;
|
||||
} else
|
||||
return;
|
||||
} else {
|
||||
/* snow_p2_up */
|
||||
if (m5 != 0x10) {
|
||||
m5 = 0x10;
|
||||
} else if (tmp != 3) {
|
||||
m5 = tmp + 1 + 0x10;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
_m[tile].m5 = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoopClearDesert(TileIndex tile)
|
||||
{
|
||||
if ((_m[tile].m5 & 0x1C) == 0x14) return;
|
||||
|
||||
if (GetMapExtraBits(tile) == 1) {
|
||||
_m[tile].m5 = 0x17;
|
||||
} else {
|
||||
if (GetMapExtraBits(tile + TileDiffXY( 1, 0)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY(-1, 0)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY( 0, 1)) != 1 &&
|
||||
GetMapExtraBits(tile + TileDiffXY( 0, -1)) != 1)
|
||||
return;
|
||||
_m[tile].m5 = 0x15;
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
static void TileLoop_Clear(TileIndex tile)
|
||||
{
|
||||
byte m5,m3;
|
||||
|
||||
TileLoopClearHelper(tile);
|
||||
|
||||
if (_opt.landscape == LT_DESERT) {
|
||||
TileLoopClearDesert(tile);
|
||||
} else if (_opt.landscape == LT_HILLY) {
|
||||
TileLoopClearAlps(tile);
|
||||
}
|
||||
|
||||
m5 = _m[tile].m5;
|
||||
if ((m5 & 0x1C) == 0x10 || (m5 & 0x1C) == 0x14) return;
|
||||
|
||||
if ((m5 & 0x1C) != 0xC) {
|
||||
if ((m5 & 3) == 3) return;
|
||||
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_m[tile].m5 = m5;
|
||||
return;
|
||||
}
|
||||
/* did overflow, so continue */
|
||||
} else {
|
||||
m5 = (GB(Random(), 0, 8) > 21) ? 2 : 6;
|
||||
}
|
||||
m5++;
|
||||
} else if (_game_mode != GM_EDITOR) {
|
||||
/* handle farm field */
|
||||
m5 += 0x20;
|
||||
if (m5 >= 0x20) {
|
||||
// Didn't overflow
|
||||
_m[tile].m5 = m5;
|
||||
return;
|
||||
}
|
||||
/* overflowed */
|
||||
m3 = _m[tile].m3 + 1;
|
||||
assert( (m3 & 0xF) != 0);
|
||||
if ( (m3 & 0xF) >= 9) /* NOTE: will not work properly if m3&0xF == 0xF */
|
||||
m3 &= ~0xF;
|
||||
_m[tile].m3 = m3;
|
||||
}
|
||||
|
||||
_m[tile].m5 = m5;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
void GenerateClearTile(void)
|
||||
{
|
||||
uint i;
|
||||
TileIndex tile;
|
||||
|
||||
/* add hills */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
|
||||
do {
|
||||
tile = RandomTile();
|
||||
if (IsTileType(tile, MP_CLEAR)) SB(_m[tile].m5, 2, 2, 1);
|
||||
} while (--i);
|
||||
|
||||
/* add grey squares */
|
||||
i = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
|
||||
do {
|
||||
uint32 r = Random();
|
||||
tile = RandomTileSeed(r);
|
||||
if (IsTileType(tile, MP_CLEAR)) {
|
||||
uint j = GB(r, 16, 4) + 5;
|
||||
for(;;) {
|
||||
TileIndex tile_new;
|
||||
|
||||
SB(_m[tile].m5, 2, 2, 2);
|
||||
do {
|
||||
if (--j == 0) goto get_out;
|
||||
tile_new = tile + TileOffsByDir(GB(Random(), 0, 2));
|
||||
} while (!IsTileType(tile_new, MP_CLEAR));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
static void ClickTile_Clear(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const StringID _clear_land_str[] = {
|
||||
STR_080B_ROUGH_LAND,
|
||||
STR_080A_ROCKS,
|
||||
STR_080E_FIELDS,
|
||||
STR_080F_SNOW_COVERED_LAND,
|
||||
STR_0810_DESERT,
|
||||
0,
|
||||
0,
|
||||
STR_080C_BARE_LAND,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
STR_080D_GRASS,
|
||||
};
|
||||
|
||||
static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
uint i = GB(_m[tile].m5, 2, 3);
|
||||
if (i == 0) i = GB(_m[tile].m5, 0, 2) + 8;
|
||||
td->str = _clear_land_str[i - 1];
|
||||
td->owner = GetTileOwner(tile);
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void InitializeClearLand(void)
|
||||
{
|
||||
_opt.snow_line = _patches.snow_line_height * 8;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, /* draw_tile_proc */
|
||||
GetSlopeZ_Clear, /* get_slope_z_proc */
|
||||
ClearTile_Clear, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Clear, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
|
||||
ClickTile_Clear, /* click_tile_proc */
|
||||
AnimateTile_Clear, /* animate_tile_proc */
|
||||
TileLoop_Clear, /* tile_loop_clear */
|
||||
ChangeTileOwner_Clear, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
NULL, /* vehicle_leave_tile_proc */
|
||||
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
|
||||
};
|
||||
@@ -0,0 +1,549 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "gui.h"
|
||||
#include "command.h"
|
||||
#include "player.h"
|
||||
#include "network.h"
|
||||
#include "variables.h"
|
||||
|
||||
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(CmdChangeServiceInt);
|
||||
DEF_COMMAND(CmdRestoreOrderIndex);
|
||||
|
||||
DEF_COMMAND(CmdBuildIndustry);
|
||||
|
||||
DEF_COMMAND(CmdBuildCompanyHQ);
|
||||
DEF_COMMAND(CmdSetPlayerFace);
|
||||
DEF_COMMAND(CmdSetPlayerColor);
|
||||
|
||||
DEF_COMMAND(CmdIncreaseLoan);
|
||||
DEF_COMMAND(CmdDecreaseLoan);
|
||||
|
||||
DEF_COMMAND(CmdWantEnginePreview);
|
||||
|
||||
DEF_COMMAND(CmdNameVehicle);
|
||||
DEF_COMMAND(CmdRenameEngine);
|
||||
|
||||
DEF_COMMAND(CmdChangeCompanyName);
|
||||
DEF_COMMAND(CmdChangePresidentName);
|
||||
|
||||
DEF_COMMAND(CmdRenameStation);
|
||||
|
||||
DEF_COMMAND(CmdSellAircraft);
|
||||
DEF_COMMAND(CmdStartStopAircraft);
|
||||
DEF_COMMAND(CmdBuildAircraft);
|
||||
DEF_COMMAND(CmdSendAircraftToHangar);
|
||||
DEF_COMMAND(CmdRefitAircraft);
|
||||
|
||||
DEF_COMMAND(CmdPlaceSign);
|
||||
DEF_COMMAND(CmdRenameSign);
|
||||
|
||||
DEF_COMMAND(CmdBuildRoadVeh);
|
||||
DEF_COMMAND(CmdStartStopRoadVeh);
|
||||
DEF_COMMAND(CmdSellRoadVeh);
|
||||
DEF_COMMAND(CmdSendRoadVehToDepot);
|
||||
DEF_COMMAND(CmdTurnRoadVeh);
|
||||
|
||||
DEF_COMMAND(CmdPause);
|
||||
|
||||
DEF_COMMAND(CmdBuyShareInCompany);
|
||||
DEF_COMMAND(CmdSellShareInCompany);
|
||||
DEF_COMMAND(CmdBuyCompany);
|
||||
|
||||
DEF_COMMAND(CmdBuildTown);
|
||||
|
||||
DEF_COMMAND(CmdRenameTown);
|
||||
DEF_COMMAND(CmdDoTownAction);
|
||||
|
||||
DEF_COMMAND(CmdSetRoadDriveSide);
|
||||
|
||||
DEF_COMMAND(CmdChangeDifficultyLevel);
|
||||
DEF_COMMAND(CmdChangePatchSetting);
|
||||
|
||||
DEF_COMMAND(CmdStartStopShip);
|
||||
DEF_COMMAND(CmdSellShip);
|
||||
DEF_COMMAND(CmdBuildShip);
|
||||
DEF_COMMAND(CmdSendShipToDepot);
|
||||
DEF_COMMAND(CmdRefitShip);
|
||||
|
||||
DEF_COMMAND(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);
|
||||
|
||||
DEF_COMMAND(CmdCloneVehicle);
|
||||
|
||||
|
||||
/* The master command table */
|
||||
static const Command _command_proc_table[] = {
|
||||
{CmdBuildRailroadTrack, 0}, /* 0 */
|
||||
{CmdRemoveRailroadTrack, 0}, /* 1 */
|
||||
{CmdBuildSingleRail, 0}, /* 2 */
|
||||
{CmdRemoveSingleRail, 0}, /* 3 */
|
||||
{CmdLandscapeClear, 0}, /* 4 */
|
||||
{CmdBuildBridge, 0}, /* 5 */
|
||||
{CmdBuildRailroadStation, 0}, /* 6 */
|
||||
{CmdBuildTrainDepot, 0}, /* 7 */
|
||||
{CmdBuildSingleSignal, 0}, /* 8 */
|
||||
{CmdRemoveSingleSignal, 0}, /* 9 */
|
||||
{CmdTerraformLand, 0}, /* 10 */
|
||||
{CmdPurchaseLandArea, 0}, /* 11 */
|
||||
{CmdSellLandArea, 0}, /* 12 */
|
||||
{CmdBuildTunnel, 0}, /* 13 */
|
||||
{CmdRemoveFromRailroadStation, 0}, /* 14 */
|
||||
{CmdConvertRail, 0}, /* 15 */
|
||||
{CmdBuildTrainWaypoint, 0}, /* 16 */
|
||||
{CmdRenameWaypoint, 0}, /* 17 */
|
||||
{CmdRemoveTrainWaypoint, 0}, /* 18 */
|
||||
{NULL, 0}, /* 19 */
|
||||
{NULL, 0}, /* 20 */
|
||||
{CmdBuildRoadStop, 0}, /* 21 */
|
||||
{NULL, 0}, /* 22 */
|
||||
{CmdBuildLongRoad, 0}, /* 23 */
|
||||
{CmdRemoveLongRoad, 0}, /* 24 */
|
||||
{CmdBuildRoad, 0}, /* 25 */
|
||||
{CmdRemoveRoad, 0}, /* 26 */
|
||||
{CmdBuildRoadDepot, 0}, /* 27 */
|
||||
{NULL, 0}, /* 28 */
|
||||
{CmdBuildAirport, 0}, /* 29 */
|
||||
{CmdBuildDock, 0}, /* 30 */
|
||||
{CmdBuildShipDepot, 0}, /* 31 */
|
||||
{CmdBuildBuoy, 0}, /* 32 */
|
||||
{CmdPlantTree, 0}, /* 33 */
|
||||
{CmdBuildRailVehicle, 0}, /* 34 */
|
||||
{CmdMoveRailVehicle, 0}, /* 35 */
|
||||
{CmdStartStopTrain, 0}, /* 36 */
|
||||
{NULL, 0}, /* 37 */
|
||||
{CmdSellRailWagon, 0}, /* 38 */
|
||||
{CmdSendTrainToDepot, 0}, /* 39 */
|
||||
{CmdForceTrainProceed, 0}, /* 40 */
|
||||
{CmdReverseTrainDirection, 0}, /* 41 */
|
||||
|
||||
{CmdModifyOrder, 0}, /* 42 */
|
||||
{CmdSkipOrder, 0}, /* 43 */
|
||||
{CmdDeleteOrder, 0}, /* 44 */
|
||||
{CmdInsertOrder, 0}, /* 45 */
|
||||
|
||||
{CmdChangeServiceInt, 0}, /* 46 */
|
||||
|
||||
{CmdBuildIndustry, 0}, /* 47 */
|
||||
{CmdBuildCompanyHQ, 0}, /* 48 */
|
||||
{CmdSetPlayerFace, 0}, /* 49 */
|
||||
{CmdSetPlayerColor, 0}, /* 50 */
|
||||
|
||||
{CmdIncreaseLoan, 0}, /* 51 */
|
||||
{CmdDecreaseLoan, 0}, /* 52 */
|
||||
|
||||
{CmdWantEnginePreview, 0}, /* 53 */
|
||||
|
||||
{CmdNameVehicle, 0}, /* 54 */
|
||||
{CmdRenameEngine, 0}, /* 55 */
|
||||
|
||||
{CmdChangeCompanyName, 0}, /* 56 */
|
||||
{CmdChangePresidentName, 0}, /* 57 */
|
||||
|
||||
{CmdRenameStation, 0}, /* 58 */
|
||||
|
||||
{CmdSellAircraft, 0}, /* 59 */
|
||||
{CmdStartStopAircraft, 0}, /* 60 */
|
||||
|
||||
{CmdBuildAircraft, 0}, /* 61 */
|
||||
{CmdSendAircraftToHangar, 0}, /* 62 */
|
||||
{NULL, 0}, /* 63 */
|
||||
{CmdRefitAircraft, 0}, /* 64 */
|
||||
|
||||
{CmdPlaceSign, 0}, /* 65 */
|
||||
{CmdRenameSign, 0}, /* 66 */
|
||||
|
||||
{CmdBuildRoadVeh, 0}, /* 67 */
|
||||
{CmdStartStopRoadVeh, 0}, /* 68 */
|
||||
{CmdSellRoadVeh, 0}, /* 69 */
|
||||
{CmdSendRoadVehToDepot, 0}, /* 70 */
|
||||
{CmdTurnRoadVeh, 0}, /* 71 */
|
||||
{NULL, 0}, /* 72 */
|
||||
|
||||
{CmdPause, CMD_SERVER}, /* 73 */
|
||||
|
||||
{CmdBuyShareInCompany, 0}, /* 74 */
|
||||
{CmdSellShareInCompany, 0}, /* 75 */
|
||||
{CmdBuyCompany, 0}, /* 76 */
|
||||
|
||||
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
|
||||
{NULL, 0}, /* 78 */
|
||||
{NULL, 0}, /* 79 */
|
||||
{CmdRenameTown, CMD_SERVER}, /* 80 */
|
||||
{CmdDoTownAction, 0}, /* 81 */
|
||||
|
||||
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
|
||||
{NULL, 0}, /* 83 */
|
||||
{NULL, 0}, /* 84 */
|
||||
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
|
||||
|
||||
{CmdStartStopShip, 0}, /* 86 */
|
||||
{CmdSellShip, 0}, /* 87 */
|
||||
{CmdBuildShip, 0}, /* 88 */
|
||||
{CmdSendShipToDepot, 0}, /* 89 */
|
||||
{NULL, 0}, /* 90 */
|
||||
{CmdRefitShip, 0}, /* 91 */
|
||||
|
||||
{NULL, 0}, /* 92 */
|
||||
{NULL, 0}, /* 93 */
|
||||
{NULL, 0}, /* 94 */
|
||||
{NULL, 0}, /* 95 */
|
||||
{NULL, 0}, /* 96 */
|
||||
{NULL, 0}, /* 97 */
|
||||
{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 */
|
||||
{CmdCloneVehicle, 0}, /* 116 */
|
||||
};
|
||||
|
||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||
bool IsValidCommand(uint cmd)
|
||||
{
|
||||
cmd &= 0xFF;
|
||||
|
||||
return
|
||||
cmd < lengthof(_command_proc_table) &&
|
||||
_command_proc_table[cmd].proc != NULL;
|
||||
}
|
||||
|
||||
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
|
||||
|
||||
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
|
||||
{
|
||||
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
|
||||
}
|
||||
|
||||
|
||||
static int _docommand_recursive;
|
||||
|
||||
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 (TileVirtXY(x, y) >= MapSize()) {
|
||||
_cmd_text = NULL;
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
proc = _command_proc_table[procc].proc;
|
||||
|
||||
if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
|
||||
|
||||
_docommand_recursive++;
|
||||
|
||||
// only execute the test call if it's toplevel, or we're not execing.
|
||||
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
|
||||
res = proc(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);
|
||||
// XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player
|
||||
if ( (x|y) != 0 && _current_player < MAX_PLAYERS) {
|
||||
GetPlayer(_current_player)->last_build_coordinate = TileVirtXY(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
_cmd_text = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32 GetAvailableMoneyForCommand(void)
|
||||
{
|
||||
PlayerID pid = _current_player;
|
||||
if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
|
||||
return GetPlayer(pid)->player_money;
|
||||
}
|
||||
|
||||
// toplevel network safe docommand function for the current player. must not be called recursively.
|
||||
// the callback is called when the command succeeded or failed.
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
|
||||
{
|
||||
int32 res = 0,res2;
|
||||
CommandProc *proc;
|
||||
uint32 flags;
|
||||
bool notest;
|
||||
|
||||
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 except for the dedicated server which
|
||||
* is a spectator but is the server, so can do anything */
|
||||
if (_current_player == OWNER_SPECTATOR && !_network_dedicated) {
|
||||
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;
|
||||
if (proc == NULL) {
|
||||
_cmd_text = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some commands have a different output in dryrun than the realrun
|
||||
// e.g.: if you demolish a whole town, the dryrun would say okay.
|
||||
// but by really destroying, your rating drops and at a certain point
|
||||
// it will fail. so res and res2 are different
|
||||
// CMD_REMOVE_ROAD: This command has special local authority
|
||||
// restrictions which may cause the test run to fail (the previous
|
||||
// road fragments still stay there and the town won't let you
|
||||
// disconnect the road system), but the exec will succeed and this
|
||||
// fact will trigger an assertion failure. --pasky
|
||||
notest =
|
||||
(cmd & 0xFF) == CMD_CLEAR_AREA ||
|
||||
(cmd & 0xFF) == CMD_CONVERT_RAIL ||
|
||||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
|
||||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
|
||||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
|
||||
|
||||
_docommand_recursive = 1;
|
||||
|
||||
// cost estimation only?
|
||||
if (_shift_pressed && IsLocalPlayer() && !(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 we are a dedicated server temporarily switch local player, otherwise
|
||||
* the other parties won't be able to execute our command and will desync.
|
||||
* @todo Rewrite dedicated server to something more than a dirty hack!
|
||||
*/
|
||||
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
|
||||
if (_network_dedicated) _local_player = 0;
|
||||
NetworkSend_Command(tile, p1, p2, cmd, callback);
|
||||
if (_network_dedicated) _local_player = OWNER_SPECTATOR;
|
||||
_docommand_recursive = 0;
|
||||
_cmd_text = NULL;
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
// update last build coordinate of player.
|
||||
if ( tile != 0 && _current_player < MAX_PLAYERS) GetPlayer(_current_player)->last_build_coordinate = tile;
|
||||
|
||||
/* Actually try and execute the command. If no cost-type is given
|
||||
* use the construction one */
|
||||
_yearly_expenses_type = EXPENSES_CONSTRUCTION;
|
||||
res2 = proc(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 (IsLocalPlayer() && _game_mode != GM_EDITOR) {
|
||||
if (res2 != 0)
|
||||
ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
|
||||
if (_additional_cash_required) {
|
||||
SetDParam(0, _additional_cash_required);
|
||||
ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, _error_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 (IsLocalPlayer() && _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;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
enum {
|
||||
CMD_BUILD_RAILROAD_TRACK = 0,
|
||||
CMD_REMOVE_RAILROAD_TRACK = 1,
|
||||
CMD_BUILD_SINGLE_RAIL = 2,
|
||||
CMD_REMOVE_SINGLE_RAIL = 3,
|
||||
CMD_LANDSCAPE_CLEAR = 4,
|
||||
CMD_BUILD_BRIDGE = 5,
|
||||
CMD_BUILD_RAILROAD_STATION = 6,
|
||||
CMD_BUILD_TRAIN_DEPOT = 7,
|
||||
CMD_BUILD_SIGNALS = 8,
|
||||
CMD_REMOVE_SIGNALS = 9,
|
||||
CMD_TERRAFORM_LAND = 10,
|
||||
CMD_PURCHASE_LAND_AREA = 11,
|
||||
CMD_SELL_LAND_AREA = 12,
|
||||
CMD_BUILD_TUNNEL = 13,
|
||||
|
||||
CMD_REMOVE_FROM_RAILROAD_STATION = 14,
|
||||
CMD_CONVERT_RAIL = 15,
|
||||
|
||||
CMD_BUILD_TRAIN_WAYPOINT = 16,
|
||||
CMD_RENAME_WAYPOINT = 17,
|
||||
CMD_REMOVE_TRAIN_WAYPOINT = 18,
|
||||
|
||||
CMD_BUILD_ROAD_STOP = 21,
|
||||
CMD_BUILD_LONG_ROAD = 23,
|
||||
CMD_REMOVE_LONG_ROAD = 24,
|
||||
CMD_BUILD_ROAD = 25,
|
||||
CMD_REMOVE_ROAD = 26,
|
||||
CMD_BUILD_ROAD_DEPOT = 27,
|
||||
|
||||
CMD_BUILD_AIRPORT = 29,
|
||||
|
||||
CMD_BUILD_DOCK = 30,
|
||||
|
||||
CMD_BUILD_SHIP_DEPOT = 31,
|
||||
CMD_BUILD_BUOY = 32,
|
||||
|
||||
CMD_PLANT_TREE = 33,
|
||||
|
||||
CMD_BUILD_RAIL_VEHICLE = 34,
|
||||
CMD_MOVE_RAIL_VEHICLE = 35,
|
||||
|
||||
CMD_START_STOP_TRAIN = 36,
|
||||
|
||||
CMD_SELL_RAIL_WAGON = 38,
|
||||
|
||||
CMD_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_SERVICE_INT = 46,
|
||||
|
||||
CMD_BUILD_INDUSTRY = 47,
|
||||
|
||||
CMD_BUILD_COMPANY_HQ = 48,
|
||||
CMD_SET_PLAYER_FACE = 49,
|
||||
CMD_SET_PLAYER_COLOR = 50,
|
||||
|
||||
CMD_INCREASE_LOAN = 51,
|
||||
CMD_DECREASE_LOAN = 52,
|
||||
|
||||
CMD_WANT_ENGINE_PREVIEW = 53,
|
||||
|
||||
CMD_NAME_VEHICLE = 54,
|
||||
CMD_RENAME_ENGINE = 55,
|
||||
CMD_CHANGE_COMPANY_NAME = 56,
|
||||
CMD_CHANGE_PRESIDENT_NAME = 57,
|
||||
CMD_RENAME_STATION = 58,
|
||||
|
||||
CMD_SELL_AIRCRAFT = 59,
|
||||
CMD_START_STOP_AIRCRAFT = 60,
|
||||
CMD_BUILD_AIRCRAFT = 61,
|
||||
CMD_SEND_AIRCRAFT_TO_HANGAR = 62,
|
||||
CMD_REFIT_AIRCRAFT = 64,
|
||||
|
||||
CMD_PLACE_SIGN = 65,
|
||||
CMD_RENAME_SIGN = 66,
|
||||
|
||||
CMD_BUILD_ROAD_VEH = 67,
|
||||
CMD_START_STOP_ROADVEH = 68,
|
||||
CMD_SELL_ROAD_VEH = 69,
|
||||
CMD_SEND_ROADVEH_TO_DEPOT = 70,
|
||||
CMD_TURN_ROADVEH = 71,
|
||||
|
||||
CMD_PAUSE = 73,
|
||||
|
||||
CMD_BUY_SHARE_IN_COMPANY = 74,
|
||||
CMD_SELL_SHARE_IN_COMPANY = 75,
|
||||
CMD_BUY_COMPANY = 76,
|
||||
|
||||
CMD_BUILD_TOWN = 77,
|
||||
|
||||
CMD_RENAME_TOWN = 80,
|
||||
CMD_DO_TOWN_ACTION = 81,
|
||||
|
||||
CMD_SET_ROAD_DRIVE_SIDE = 82,
|
||||
|
||||
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
|
||||
|
||||
CMD_START_STOP_SHIP = 86,
|
||||
CMD_SELL_SHIP = 87,
|
||||
CMD_BUILD_SHIP = 88,
|
||||
CMD_SEND_SHIP_TO_DEPOT = 89,
|
||||
CMD_REFIT_SHIP = 91,
|
||||
|
||||
CMD_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,
|
||||
|
||||
CMD_CLONE_VEHICLE = 116,
|
||||
|
||||
};
|
||||
|
||||
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 */
|
||||
-2562
File diff suppressed because it is too large
Load Diff
@@ -1,134 +1,276 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONFIGURE_EXECUTABLE="$_"
|
||||
# On *nix systems those two are equal when ./configure is done
|
||||
if [ "$0" != "$CONFIGURE_EXECUTABLE" ]; then
|
||||
# On some systems, when ./configure is triggered from 'make'
|
||||
# the $_ is filled with 'make'. So if that is true, skip 'make'
|
||||
# and use $0 (and hope that is correct ;))
|
||||
if [ -n "`echo $CONFIGURE_EXECUTABLE | grep make`" ]; then
|
||||
CONFIGURE_EXECUTABLE="$0"
|
||||
else
|
||||
CONFIGURE_EXECUTABLE="$CONFIGURE_EXECUTABLE $0"
|
||||
# This 'configure' script is a very easy wrapper around 'make updateconf'
|
||||
# It allows cross-compilers to do their job much more easy.
|
||||
|
||||
function showhelp() {
|
||||
echo "Configure for OpenTTD"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $0 --your_options"
|
||||
echo ""
|
||||
echo "Params:"
|
||||
echo " --debug Create debug-release [no]"
|
||||
echo " --profile Create profile-release [no]"
|
||||
echo " --dedicated Make a dedicated build [no]"
|
||||
echo " --revision Set the revision of the compilation [detected]"
|
||||
echo " --target-cc Sets the target-compiler [\$CC]"
|
||||
echo " --target-cxx Sets the C++ target-compiler []"
|
||||
echo " --host-cc Sets the host-compiler [\$CC]"
|
||||
echo " --os Sets the OS. Listens to: [detected]"
|
||||
echo " UNIX, OSX, FREEBSD, MORPHOS"
|
||||
echo " BEOS, SUNOS, CYGWIN, MINGW"
|
||||
echo " --windres Sets the windres (Windows) [windres]"
|
||||
echo " --force-le Force LE platform [no]"
|
||||
echo " --force-be Force BE platform [no]"
|
||||
echo ""
|
||||
echo "Params that can be used with --with or --without"
|
||||
echo " (e.g.: --without-static disables static (default))"
|
||||
echo " static Do you want a static build? [no]"
|
||||
echo " directmusic Do you want direct-music? [no]"
|
||||
echo " zlib Do you want zlib-support? [yes]"
|
||||
echo " sdl Do you want SDL-support? [yes]"
|
||||
echo " png Do you want PNG-support? [yes]"
|
||||
echo " cocoa Do you want cocoa-support? (MacOSX) [no]"
|
||||
echo ""
|
||||
echo "Params used to configure external libs:"
|
||||
echo " --static-zlib-path Set the path to your static zlib []"
|
||||
echo " --sdl-config Where is your sdl-config [sdl-config]"
|
||||
echo " --libpng-config Where is your libpng-config [libpng-config]"
|
||||
echo " "
|
||||
}
|
||||
|
||||
function handle() {
|
||||
PARAM="$PARAM \"$1=`awk 'BEGIN { FS="="; $0="'"$2"'"; print $2;}'`\""
|
||||
}
|
||||
|
||||
# The things you can use inside this case:
|
||||
# handle NAME VALUE - Sets the value to give the 'make upgradeconf'
|
||||
# Value is in form: tag=REAL_VALUE
|
||||
# ITEM="NAME" - Will set the value as above, only with the next param
|
||||
# SITEM="NAME" - Will set the var $NAME to the next param
|
||||
for n in "$@"
|
||||
do
|
||||
case "$n" in
|
||||
--help | -h)
|
||||
showhelp
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--debug)
|
||||
DEBUG_SET=1
|
||||
ITEM="DEBUG"
|
||||
;;
|
||||
--debug=*)
|
||||
handle "DEBUG" "$n"
|
||||
;;
|
||||
--profile)
|
||||
PARAM="$PARAM PROFILE=1"
|
||||
;;
|
||||
--dedicated)
|
||||
PARAM="$PARAM DEDICATED=1"
|
||||
;;
|
||||
--revision=*)
|
||||
RELEASE=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--revision)
|
||||
SITEM="RELEASE"
|
||||
;;
|
||||
--target-cc=*)
|
||||
handle "CC_TARGET" "$n"
|
||||
;;
|
||||
--target-cc)
|
||||
ITEM="CC_TARGET"
|
||||
;;
|
||||
--target-cxx=*)
|
||||
TARGET_CXX=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--target-cxx)
|
||||
SITEM="TARGET_CXX"
|
||||
;;
|
||||
--host-cc=*)
|
||||
handle CC_HOST "$n"
|
||||
;;
|
||||
--host-cc)
|
||||
ITEM="CC_HOST"
|
||||
;;
|
||||
--host-cflags=*)
|
||||
handle CFLAGS_HOST "$n"
|
||||
;;
|
||||
--host-cflags)
|
||||
ITEM="CFLAGS_HOST"
|
||||
;;
|
||||
--os=*)
|
||||
TARGET_OS=`awk 'BEGIN { FS="="; $0="'"$n"'"; print $2;}'`
|
||||
;;
|
||||
--os)
|
||||
SITEM="TARGET_OS"
|
||||
;;
|
||||
--windres=*)
|
||||
handle WINDRES "$n"
|
||||
;;
|
||||
--windres)
|
||||
ITEM="WINDRES"
|
||||
;;
|
||||
--force-le)
|
||||
PARAM="$PARAM ENDIAN_FORCE=LE"
|
||||
;;
|
||||
--force-be)
|
||||
PARAM="$PARAM ENDIAN_FORCE=BE"
|
||||
;;
|
||||
|
||||
--with-static)
|
||||
PARAM="$PARAM STATIC=1"
|
||||
;;
|
||||
--without-static)
|
||||
PARAM="$PARAM STATIC="
|
||||
;;
|
||||
--with-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC=1"
|
||||
;;
|
||||
--without-directmusic)
|
||||
PARAM="$PARAM WITH_DIRECTMUSIC="
|
||||
;;
|
||||
--with-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB=1"
|
||||
;;
|
||||
--without-zlib)
|
||||
PARAM="$PARAM WITH_ZLIB="
|
||||
;;
|
||||
--with-sdl)
|
||||
PARAM="$PARAM WITH_SDL=1"
|
||||
;;
|
||||
--without-sdl)
|
||||
PARAM="$PARAM WITH_SDL="
|
||||
;;
|
||||
--with-png)
|
||||
PARAM="$PARAM WITH_PNG=1"
|
||||
;;
|
||||
--without-png)
|
||||
PARAM="$PARAM WITH_PNG="
|
||||
;;
|
||||
--with-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA=1"
|
||||
;;
|
||||
--without-cocoa)
|
||||
PARAM="$PARAM WITH_COCOA="
|
||||
;;
|
||||
--static-zlib-path=*)
|
||||
handle STATIC_ZLIB_PATH "$n"
|
||||
;;
|
||||
--static-zlib-path)
|
||||
ITEM="STATIC_ZLIB_PATH"
|
||||
;;
|
||||
--sdl-config=*)
|
||||
handle SDL_CONFIG "$n"
|
||||
;;
|
||||
--sdl-config)
|
||||
ITEM="SDL_CONFIG"
|
||||
;;
|
||||
--libpng-config=*)
|
||||
handle LIBPNG_CONFIG "$n"
|
||||
;;
|
||||
--lib-png-config)
|
||||
ITEM="LIBPNG_CONFIG"
|
||||
;;
|
||||
|
||||
--*=*)
|
||||
echo -n "Unknown switch "
|
||||
echo `awk 'BEGIN { FS="="; $0="'"$n"'"; print $1;}'`
|
||||
exit 1
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
if ! test -z "$ITEM"
|
||||
then
|
||||
PARAM="$PARAM $ITEM=\"$n\""
|
||||
ITEM="";
|
||||
elif ! test -z "$SITEM"
|
||||
then
|
||||
export $SITEM="$n"
|
||||
SITEM=""
|
||||
else
|
||||
echo "Unknown switch $n"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! test -z "$TARGET_OS"
|
||||
then
|
||||
TARGET_OS=`echo $TARGET_OS | tr '[:lower:]' '[:upper:]'`
|
||||
case "$TARGET_OS" in
|
||||
WIN32)
|
||||
PARAM="$PARAM WIN32=1"
|
||||
;;
|
||||
UNIX)
|
||||
PARAM="$PARAM UNIX=1"
|
||||
;;
|
||||
OSX)
|
||||
PARAM="$PARAM OSX=1 UNIX=1"
|
||||
;;
|
||||
FREEBSD)
|
||||
PARAM="$PARAM FREEBSD=1"
|
||||
;;
|
||||
MORPHOS)
|
||||
PARAM="$PARAM MORPHOS=1 UNIX=1"
|
||||
;;
|
||||
BEOS)
|
||||
PARAM="$PARAM BEOS=1 UNIX=1"
|
||||
;;
|
||||
SUNOS)
|
||||
PARAM="$PARAM SUNOS=1 UNIX=1"
|
||||
;;
|
||||
CYGWIN)
|
||||
PARAM="$PARAM CYGWIN=1 WIN32=1"
|
||||
;;
|
||||
MINGW)
|
||||
PARAM="$PARAM MINGW=1 WIN32=1"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OS: $TARGET_OS"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
PARAM="$PARAM BYPASS_OS_DETECT=1"
|
||||
fi
|
||||
|
||||
if ! test -z "$DEBUG_SET"
|
||||
then
|
||||
if test -z "`echo $PARAM | grep "DEBUG="`"
|
||||
then
|
||||
# Someone did --debug, without assigning a value, assume 1
|
||||
PARAM="$PARAM DEBUG=1"
|
||||
fi
|
||||
fi
|
||||
# Find out where configure is (in what dir)
|
||||
ROOT_DIR="`dirname $0`"
|
||||
ROOT_DIR="`cd $ROOT_DIR && pwd`"
|
||||
|
||||
PWD="`pwd`"
|
||||
PREFIX="$PWD/bin"
|
||||
|
||||
. $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 $?
|
||||
# First remove the Makefile.config, else you can have double entries
|
||||
if test -e "Makefile.config"
|
||||
then
|
||||
rm -f Makefile.config
|
||||
fi
|
||||
|
||||
set_default
|
||||
detect_params "$@"
|
||||
check_params
|
||||
save_params
|
||||
make_cflags_and_ldflags
|
||||
echo "make upgradeconf $PARAM" > Makefile.run
|
||||
. Makefile.run
|
||||
rm -f Makefile.run
|
||||
|
||||
EXE=""
|
||||
if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "WINCE" ]; then
|
||||
EXE=".exe"
|
||||
# Makefile.config currently doesn't support custom CXX, so, we add the line
|
||||
# ourself!
|
||||
|
||||
if ! test -z "$TARGET_CXX"
|
||||
then
|
||||
echo "CXX=$TARGET_CXX" >> Makefile.config
|
||||
fi
|
||||
|
||||
TTD="openttd$EXE"
|
||||
STRGEN="strgen$EXE"
|
||||
ENDIAN_CHECK="endian_check$EXE"
|
||||
# Same for RELEASE (read: REVISION)
|
||||
|
||||
if [ -z "$sort" ]; then
|
||||
PIPE_SORT="sed s/a/a/"
|
||||
else
|
||||
PIPE_SORT="$sort"
|
||||
if ! test -z "$RELEASE"
|
||||
then
|
||||
echo "RELEASE=$RELEASE" >> Makefile.config
|
||||
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 == "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 == "BEOS" && "'$os'" != "BEOS") { next; }
|
||||
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
|
||||
"'$os'" != "CYGWIN" && "'$os'" != "MSVC" ) { 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 == "NO_THREADS" && "'$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"
|
||||
|
||||
generate_main
|
||||
generate_lang
|
||||
generate_src
|
||||
|
||||
+194
-225
@@ -1,25 +1,21 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file console.cpp */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "window_gui.h"
|
||||
#include "gfx.h"
|
||||
#include "player.h"
|
||||
#include "variables.h"
|
||||
#include "string.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "console.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_data.h"
|
||||
#include "network/network_server.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "window_func.h"
|
||||
#include "string_func.h"
|
||||
#include "gfx_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "network.h"
|
||||
#include "network_data.h"
|
||||
#include "network_server.h"
|
||||
|
||||
#define ICON_BUFFER 79
|
||||
#define ICON_HISTORY_SIZE 20
|
||||
@@ -29,67 +25,55 @@
|
||||
#define ICON_MAX_ALIAS_LINES 40
|
||||
#define ICON_TOKEN_COUNT 20
|
||||
|
||||
/* console parser */
|
||||
IConsoleCmd *_iconsole_cmds; ///< list of registred commands
|
||||
IConsoleVar *_iconsole_vars; ///< list of registred vars
|
||||
IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
|
||||
|
||||
/* console colors/modes */
|
||||
byte _icolour_def;
|
||||
byte _icolour_err;
|
||||
byte _icolour_warn;
|
||||
byte _icolour_dbg;
|
||||
byte _icolour_cmd;
|
||||
IConsoleModes _iconsole_mode;
|
||||
|
||||
/* ** main console ** */
|
||||
// ** main console ** //
|
||||
static Window *_iconsole_win; // Pointer to console window
|
||||
static bool _iconsole_inited;
|
||||
static char *_iconsole_buffer[ICON_BUFFER + 1];
|
||||
static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
|
||||
static Textbuf _iconsole_cmdline;
|
||||
static byte _iconsole_scroll;
|
||||
|
||||
/* ** stdlib ** */
|
||||
// ** stdlib ** //
|
||||
byte _stdlib_developer = 1;
|
||||
bool _stdlib_con_developer = false;
|
||||
FILE *_iconsole_output_file;
|
||||
|
||||
/* ** main console cmd buffer ** */
|
||||
// ** main console cmd buffer
|
||||
static char *_iconsole_history[ICON_HISTORY_SIZE];
|
||||
static byte _iconsole_historypos;
|
||||
|
||||
/* *************** *
|
||||
* end of header *
|
||||
* *************** */
|
||||
/* *************** */
|
||||
/* end of header */
|
||||
/* *************** */
|
||||
|
||||
static void IConsoleClearCommand()
|
||||
static void IConsoleClearCommand(void)
|
||||
{
|
||||
memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
|
||||
_iconsole_cmdline.length = 0;
|
||||
_iconsole_cmdline.width = 0;
|
||||
_iconsole_cmdline.caretpos = 0;
|
||||
_iconsole_cmdline.caretxoffs = 0;
|
||||
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
|
||||
SetWindowDirty(_iconsole_win);
|
||||
}
|
||||
|
||||
static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
|
||||
static inline void IConsoleResetHistoryPos(void) {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
|
||||
|
||||
|
||||
static void IConsoleHistoryAdd(const char *cmd);
|
||||
static void IConsoleHistoryAdd(const char* cmd);
|
||||
static void IConsoleHistoryNavigate(int direction);
|
||||
|
||||
/* ** console window ** */
|
||||
static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
// ** console window ** //
|
||||
static void IConsoleWndProc(Window* w, WindowEvent* e)
|
||||
{
|
||||
static byte iconsole_scroll = ICON_BUFFER;
|
||||
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int i = iconsole_scroll;
|
||||
int i = _iconsole_scroll;
|
||||
int max = (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
int delta = 0;
|
||||
GfxFillRect(w->left, w->top, w->width, w->height - 1, 0);
|
||||
while ((i > 0) && (i > iconsole_scroll - max) && (_iconsole_buffer[i] != NULL)) {
|
||||
while ((i > 0) && (i > _iconsole_scroll - max) && (_iconsole_buffer[i] != NULL)) {
|
||||
DoDrawString(_iconsole_buffer[i], 5,
|
||||
w->height - (iconsole_scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
|
||||
w->height - (_iconsole_scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
|
||||
i--;
|
||||
}
|
||||
/* If the text is longer than the window, don't show the starting ']' */
|
||||
@@ -102,7 +86,7 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
DoDrawString(_iconsole_cmdline.buf, 10 + delta, w->height - ICON_LINE_HEIGHT, _icolour_cmd);
|
||||
|
||||
if (_iconsole_cmdline.caret)
|
||||
DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, TC_WHITE);
|
||||
DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, 12);
|
||||
break;
|
||||
}
|
||||
case WE_MOUSELOOP:
|
||||
@@ -110,11 +94,12 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WE_DESTROY:
|
||||
_iconsole_win = NULL;
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
break;
|
||||
case WE_KEYPRESS:
|
||||
e->we.keypress.cont = false;
|
||||
switch (e->we.keypress.keycode) {
|
||||
e->keypress.cont = false;
|
||||
switch (e->keypress.keycode) {
|
||||
case WKC_UP:
|
||||
IConsoleHistoryNavigate(+1);
|
||||
SetWindowDirty(w);
|
||||
@@ -124,35 +109,31 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_PAGEUP:
|
||||
if (iconsole_scroll - (w->height / ICON_LINE_HEIGHT) - 1 < 0) {
|
||||
iconsole_scroll = 0;
|
||||
} else {
|
||||
iconsole_scroll -= (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
}
|
||||
if (_iconsole_scroll - (w->height / ICON_LINE_HEIGHT) - 1 < 0)
|
||||
_iconsole_scroll = 0;
|
||||
else
|
||||
_iconsole_scroll -= (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_PAGEDOWN:
|
||||
if (iconsole_scroll + (w->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
} else {
|
||||
iconsole_scroll += (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
}
|
||||
if (_iconsole_scroll + (w->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER)
|
||||
_iconsole_scroll = ICON_BUFFER;
|
||||
else
|
||||
_iconsole_scroll += (w->height / ICON_LINE_HEIGHT) - 1;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_UP:
|
||||
if (iconsole_scroll <= 0) {
|
||||
iconsole_scroll = 0;
|
||||
} else {
|
||||
--iconsole_scroll;
|
||||
}
|
||||
if (_iconsole_scroll <= 0)
|
||||
_iconsole_scroll = 0;
|
||||
else
|
||||
--_iconsole_scroll;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_SHIFT | WKC_DOWN:
|
||||
if (iconsole_scroll >= ICON_BUFFER) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
} else {
|
||||
++iconsole_scroll;
|
||||
}
|
||||
if (_iconsole_scroll >= ICON_BUFFER)
|
||||
_iconsole_scroll = ICON_BUFFER;
|
||||
else
|
||||
++_iconsole_scroll;
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_BACKQUOTE:
|
||||
@@ -167,7 +148,7 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
break;
|
||||
case WKC_CTRL | WKC_RETURN:
|
||||
_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
|
||||
IConsoleResize(w);
|
||||
IConsoleResize();
|
||||
MarkWholeScreenDirty();
|
||||
break;
|
||||
case (WKC_CTRL | 'V'):
|
||||
@@ -184,26 +165,25 @@ static void IConsoleWndProc(Window *w, WindowEvent *e)
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case WKC_BACKSPACE: case WKC_DELETE:
|
||||
if (DeleteTextBufferChar(&_iconsole_cmdline, e->we.keypress.keycode)) {
|
||||
if (DeleteTextBufferChar(&_iconsole_cmdline, e->keypress.keycode)) {
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
break;
|
||||
case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
|
||||
if (MoveTextBufferPos(&_iconsole_cmdline, e->we.keypress.keycode)) {
|
||||
if (MoveTextBufferPos(&_iconsole_cmdline, e->keypress.keycode)) {
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (IsValidChar(e->we.keypress.key, CS_ALPHANUMERAL)) {
|
||||
iconsole_scroll = ICON_BUFFER;
|
||||
InsertTextBufferChar(&_iconsole_cmdline, e->we.keypress.key);
|
||||
if (IsValidAsciiChar(e->keypress.ascii)) {
|
||||
_iconsole_scroll = ICON_BUFFER;
|
||||
InsertTextBufferChar(&_iconsole_cmdline, e->keypress.ascii);
|
||||
IConsoleResetHistoryPos();
|
||||
SetWindowDirty(w);
|
||||
} else {
|
||||
e->we.keypress.cont = true;
|
||||
}
|
||||
} else
|
||||
e->keypress.cont = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -214,14 +194,14 @@ static const Widget _iconsole_window_widgets[] = {
|
||||
};
|
||||
|
||||
static const WindowDesc _iconsole_window_desc = {
|
||||
0, 0, 2, 2, 2, 2,
|
||||
WC_CONSOLE, WC_NONE,
|
||||
0, 0, 2, 2,
|
||||
WC_CONSOLE, 0,
|
||||
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
_iconsole_window_widgets,
|
||||
IConsoleWndProc,
|
||||
};
|
||||
|
||||
void IConsoleInit()
|
||||
void IConsoleInit(void)
|
||||
{
|
||||
extern const char _openttd_revision[];
|
||||
_iconsole_output_file = NULL;
|
||||
@@ -229,9 +209,12 @@ void IConsoleInit()
|
||||
_icolour_err = 3;
|
||||
_icolour_warn = 13;
|
||||
_icolour_dbg = 5;
|
||||
_icolour_cmd = TC_GOLD;
|
||||
_icolour_cmd = 2;
|
||||
_iconsole_scroll = ICON_BUFFER;
|
||||
_iconsole_historypos = ICON_HISTORY_SIZE - 1;
|
||||
_iconsole_inited = true;
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
_iconsole_win = NULL;
|
||||
|
||||
#ifdef ENABLE_NETWORK /* Initialize network only variables */
|
||||
_redirect_console_to_client = 0;
|
||||
@@ -240,7 +223,7 @@ void IConsoleInit()
|
||||
memset(_iconsole_history, 0, sizeof(_iconsole_history));
|
||||
memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
|
||||
memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
|
||||
_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
|
||||
_iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it
|
||||
_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
|
||||
|
||||
IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
|
||||
@@ -252,7 +235,7 @@ void IConsoleInit()
|
||||
IConsoleHistoryAdd("");
|
||||
}
|
||||
|
||||
void IConsoleClearBuffer()
|
||||
void IConsoleClearBuffer(void)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i <= ICON_BUFFER; i++) {
|
||||
@@ -261,22 +244,22 @@ void IConsoleClearBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
static void IConsoleClear()
|
||||
static void IConsoleClear(void)
|
||||
{
|
||||
free(_iconsole_cmdline.buf);
|
||||
IConsoleClearBuffer();
|
||||
}
|
||||
|
||||
static void IConsoleWriteToLogFile(const char *string)
|
||||
static void IConsoleWriteToLogFile(const char* string)
|
||||
{
|
||||
if (_iconsole_output_file != NULL) {
|
||||
/* if there is an console output file ... also print it there */
|
||||
// if there is an console output file ... also print it there
|
||||
fwrite(string, strlen(string), 1, _iconsole_output_file);
|
||||
fwrite("\n", 1, 1, _iconsole_output_file);
|
||||
}
|
||||
}
|
||||
|
||||
bool CloseConsoleLogIfActive()
|
||||
bool CloseConsoleLogIfActive(void)
|
||||
{
|
||||
if (_iconsole_output_file != NULL) {
|
||||
IConsolePrintF(_icolour_def, "file output complete");
|
||||
@@ -288,58 +271,62 @@ bool CloseConsoleLogIfActive()
|
||||
return false;
|
||||
}
|
||||
|
||||
void IConsoleFree()
|
||||
void IConsoleFree(void)
|
||||
{
|
||||
_iconsole_inited = false;
|
||||
IConsoleClear();
|
||||
CloseConsoleLogIfActive();
|
||||
}
|
||||
|
||||
void IConsoleResize(Window *w)
|
||||
void IConsoleResize(void)
|
||||
{
|
||||
_iconsole_win = FindWindowById(WC_CONSOLE, 0);
|
||||
|
||||
switch (_iconsole_mode) {
|
||||
case ICONSOLE_OPENED:
|
||||
w->height = _screen.height / 3;
|
||||
w->width = _screen.width;
|
||||
_iconsole_win->height = _screen.height / 3;
|
||||
_iconsole_win->width = _screen.width;
|
||||
break;
|
||||
case ICONSOLE_FULL:
|
||||
w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
|
||||
w->width = _screen.width;
|
||||
_iconsole_win->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
|
||||
_iconsole_win->width = _screen.width;
|
||||
break;
|
||||
default: return;
|
||||
default: break;
|
||||
}
|
||||
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
void IConsoleSwitch()
|
||||
void IConsoleSwitch(void)
|
||||
{
|
||||
switch (_iconsole_mode) {
|
||||
case ICONSOLE_CLOSED: {
|
||||
Window *w = AllocateWindowDesc(&_iconsole_window_desc);
|
||||
w->height = _screen.height / 3;
|
||||
w->width = _screen.width;
|
||||
case ICONSOLE_CLOSED:
|
||||
_iconsole_win = AllocateWindowDesc(&_iconsole_window_desc);
|
||||
_iconsole_win->height = _screen.height / 3;
|
||||
_iconsole_win->width = _screen.width;
|
||||
_iconsole_mode = ICONSOLE_OPENED;
|
||||
SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
|
||||
} break;
|
||||
SETBIT(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
|
||||
break;
|
||||
case ICONSOLE_OPENED: case ICONSOLE_FULL:
|
||||
DeleteWindowById(WC_CONSOLE, 0);
|
||||
_iconsole_win = NULL;
|
||||
_iconsole_mode = ICONSOLE_CLOSED;
|
||||
ClrBit(_no_scroll, SCROLL_CON);
|
||||
CLRBIT(_no_scroll, SCROLL_CON);
|
||||
break;
|
||||
}
|
||||
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
|
||||
void IConsoleOpen() {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
|
||||
void IConsoleClose(void) {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
|
||||
void IConsoleOpen(void) {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
|
||||
|
||||
/**
|
||||
* Add the entered line into the history so you can look it back
|
||||
* scroll, etc. Put it to the beginning as it is the latest text
|
||||
* @param cmd Text to be entered into the 'history'
|
||||
*/
|
||||
static void IConsoleHistoryAdd(const char *cmd)
|
||||
static void IConsoleHistoryAdd(const char* cmd)
|
||||
{
|
||||
free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
|
||||
|
||||
@@ -356,7 +343,7 @@ static void IConsoleHistoryNavigate(int direction)
|
||||
{
|
||||
int i = _iconsole_historypos + direction;
|
||||
|
||||
/* watch out for overflows, just wrap around */
|
||||
// watch out for overflows, just wrap around
|
||||
if (i < 0) i = ICON_HISTORY_SIZE - 1;
|
||||
if (i >= ICON_HISTORY_SIZE) i = 0;
|
||||
|
||||
@@ -369,8 +356,8 @@ static void IConsoleHistoryNavigate(int direction)
|
||||
|
||||
_iconsole_historypos = i;
|
||||
IConsoleClearCommand();
|
||||
/* copy history to 'command prompt / bash' */
|
||||
assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
|
||||
// copy history to 'command prompt / bash'
|
||||
assert(_iconsole_history[i] != NULL && IS_INT_INSIDE(i, 0, ICON_HISTORY_SIZE));
|
||||
ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
|
||||
UpdateTextBufferSize(&_iconsole_cmdline);
|
||||
}
|
||||
@@ -384,9 +371,8 @@ static void IConsoleHistoryNavigate(int direction)
|
||||
* @param color_code the colour of the command. Red in case of errors, etc.
|
||||
* @param string the message entered or output on the console (notice, error, etc.)
|
||||
*/
|
||||
void IConsolePrint(uint16 color_code, const char *string)
|
||||
void IConsolePrint(uint16 color_code, const char* string)
|
||||
{
|
||||
char *str;
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (_redirect_console_to_client != 0) {
|
||||
/* Redirect the string to the client */
|
||||
@@ -395,38 +381,38 @@ void IConsolePrint(uint16 color_code, const char *string)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a copy of the string, strip if of colours and invalid
|
||||
* characters and (when applicable) assign it to the console buffer */
|
||||
str = strdup(string);
|
||||
str_strip_colours(str);
|
||||
str_validate(str);
|
||||
|
||||
if (_network_dedicated) {
|
||||
fprintf(stdout, "%s\n", str);
|
||||
fflush(stdout);
|
||||
IConsoleWriteToLogFile(str);
|
||||
free(str); // free duplicated string since it's not used anymore
|
||||
printf("%s\n", string);
|
||||
IConsoleWriteToLogFile(string);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_iconsole_inited) return;
|
||||
|
||||
/* move up all the strings in the buffer one place and do the same for colour
|
||||
* to accomodate for the new command/message */
|
||||
free(_iconsole_buffer[0]);
|
||||
memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
|
||||
_iconsole_buffer[ICON_BUFFER] = str;
|
||||
_iconsole_buffer[ICON_BUFFER] = strdup(string);
|
||||
|
||||
{ // filter out unprintable characters
|
||||
char *i;
|
||||
for (i = _iconsole_buffer[ICON_BUFFER]; *i != '\0'; i++)
|
||||
if (!IsValidAsciiChar((byte)*i)) *i = ' ';
|
||||
}
|
||||
|
||||
memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
|
||||
_iconsole_cbuffer[ICON_BUFFER] = color_code;
|
||||
|
||||
IConsoleWriteToLogFile(_iconsole_buffer[ICON_BUFFER]);
|
||||
IConsoleWriteToLogFile(string);
|
||||
|
||||
SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
|
||||
if (_iconsole_win != NULL) SetWindowDirty(_iconsole_win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the printing of text entered into the console or redirected there
|
||||
* by any other means. Uses printf() style format, for more information look
|
||||
* at IConsolePrint()
|
||||
* at @IConsolePrint()
|
||||
*/
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
|
||||
{
|
||||
@@ -443,15 +429,13 @@ void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
|
||||
/**
|
||||
* It is possible to print debugging information to the console,
|
||||
* which is achieved by using this function. Can only be used by
|
||||
* debug() in debug.cpp. You need at least a level 2 (developer) for debugging
|
||||
* @debug() in debug.c. You need at least a level 2 (developer) for debugging
|
||||
* messages to show up
|
||||
* @param dbg debugging category
|
||||
* @param string debugging message
|
||||
*/
|
||||
void IConsoleDebug(const char *dbg, const char *string)
|
||||
void IConsoleDebug(const char* string)
|
||||
{
|
||||
if (_stdlib_developer > 1)
|
||||
IConsolePrintF(_icolour_dbg, "dbg: [%s] %s", dbg, string);
|
||||
IConsolePrintF(_icolour_dbg, "dbg: %s", string);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,7 +443,7 @@ void IConsoleDebug(const char *dbg, const char *string)
|
||||
* errors or mishaps, but non-fatal. You need at least a level 1 (developer) for
|
||||
* debugging messages to show up
|
||||
*/
|
||||
void IConsoleWarning(const char *string)
|
||||
void IConsoleWarning(const char* string)
|
||||
{
|
||||
if (_stdlib_developer > 0)
|
||||
IConsolePrintF(_icolour_warn, "WARNING: %s", string);
|
||||
@@ -469,7 +453,7 @@ void IConsoleWarning(const char *string)
|
||||
* It is possible to print error information to the console. This can include
|
||||
* game errors, or errors in general you would want the user to notice
|
||||
*/
|
||||
void IConsoleError(const char *string)
|
||||
void IConsoleError(const char* string)
|
||||
{
|
||||
IConsolePrintF(_icolour_err, "ERROR: %s", string);
|
||||
}
|
||||
@@ -477,7 +461,7 @@ void IConsoleError(const char *string)
|
||||
/**
|
||||
* Change a string into its number representation. Supports
|
||||
* decimal and hexadecimal numbers as well as 'on'/'off' 'true'/'false'
|
||||
* @param *value the variable a successful conversion will be put in
|
||||
* @param *value the variable a successfull conversion will be put in
|
||||
* @param *arg the string to be converted
|
||||
* @return Return true on success or false on failure
|
||||
*/
|
||||
@@ -498,13 +482,12 @@ bool GetArgumentInteger(uint32 *value, const char *arg)
|
||||
return arg != endptr;
|
||||
}
|
||||
|
||||
/* * *************************
|
||||
* hooking code *
|
||||
* *************************/
|
||||
|
||||
// * ************************* * //
|
||||
// * hooking code * //
|
||||
// * ************************* * //
|
||||
/**
|
||||
* General internal hooking code that is the same for both commands and variables
|
||||
* @param hooks IConsoleHooks structure that will be set according to
|
||||
* @param hooks @IConsoleHooks structure that will be set according to
|
||||
* @param type type access trigger
|
||||
* @param proc function called when the hook criteria is met
|
||||
*/
|
||||
@@ -529,9 +512,9 @@ static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConso
|
||||
/**
|
||||
* Handle any special hook triggers. If the hook type is met check if
|
||||
* there is a function associated with that and if so, execute it
|
||||
* @param hooks IConsoleHooks structure that will be checked
|
||||
* @param hooks @IConsoleHooks structure that will be checked
|
||||
* @param type type of hook, trigger that needs to be activated
|
||||
* @return true on a successful execution of the hook command or if there
|
||||
* @return true on a successfull execution of the hook command or if there
|
||||
* is no hook/trigger present at all. False otherwise
|
||||
*/
|
||||
static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
|
||||
@@ -586,41 +569,40 @@ void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *
|
||||
* three types, just with different variables. Yes, templates would be handy. It was
|
||||
* either this define or an even more ugly void* magic function
|
||||
*/
|
||||
#define IConsoleAddSorted(_base, item_new, IConsoleType, type) \
|
||||
{ \
|
||||
IConsoleType *item, *item_before; \
|
||||
/* first command */ \
|
||||
if (_base == NULL) { \
|
||||
_base = item_new; \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
item_before = NULL; \
|
||||
item = _base; \
|
||||
\
|
||||
/* BEGIN - Alphabetically insert the commands into the linked list */ \
|
||||
while (item != NULL) { \
|
||||
int i = strcmp(item->name, item_new->name); \
|
||||
if (i == 0) { \
|
||||
IConsoleError(type " with this name already exists; insertion aborted"); \
|
||||
free(item_new); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
if (i > 0) break; /* insert at this position */ \
|
||||
\
|
||||
item_before = item; \
|
||||
item = item->next; \
|
||||
} \
|
||||
\
|
||||
if (item_before == NULL) { \
|
||||
_base = item_new; \
|
||||
} else { \
|
||||
item_before->next = item_new; \
|
||||
} \
|
||||
\
|
||||
item_new->next = item; \
|
||||
/* END - Alphabetical insert */ \
|
||||
#define IConsoleAddSorted(_base, item_new, IConsoleType, type) \
|
||||
{ \
|
||||
IConsoleType *item, *item_before; \
|
||||
/* first command */ \
|
||||
if (_base == NULL) { \
|
||||
_base = item_new; \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
item_before = NULL; \
|
||||
item = _base; \
|
||||
\
|
||||
/* BEGIN - Alphabetically insert the commands into the linked list */ \
|
||||
while (item != NULL) { \
|
||||
int i = strcmp(item->name, item_new->name); \
|
||||
if (i == 0) { \
|
||||
IConsoleError(type " with this name already exists; insertion aborted"); \
|
||||
free(item_new); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
if (i > 0) break; /* insert at this position */ \
|
||||
\
|
||||
item_before = item; \
|
||||
item = item->next; \
|
||||
} \
|
||||
\
|
||||
if (item_before == NULL) { \
|
||||
_base = item_new; \
|
||||
} else \
|
||||
item_before->next = item_new; \
|
||||
\
|
||||
item_new->next = item; \
|
||||
/* END - Alphabetical insert */ \
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,7 +613,7 @@ void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *
|
||||
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
|
||||
{
|
||||
char *new_cmd = strdup(name);
|
||||
IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
|
||||
IConsoleCmd *item_new = malloc(sizeof(IConsoleCmd));
|
||||
|
||||
item_new->next = NULL;
|
||||
item_new->proc = proc;
|
||||
@@ -668,7 +650,7 @@ void IConsoleAliasRegister(const char *name, const char *cmd)
|
||||
{
|
||||
char *new_alias = strdup(name);
|
||||
char *cmd_aliased = strdup(cmd);
|
||||
IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);
|
||||
IConsoleAlias *item_new = malloc(sizeof(IConsoleAlias));
|
||||
|
||||
item_new->next = NULL;
|
||||
item_new->cmdline = cmd_aliased;
|
||||
@@ -696,8 +678,8 @@ IConsoleAlias *IConsoleAliasGet(const char *name)
|
||||
/** copy in an argument into the aliasstream */
|
||||
static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
|
||||
{
|
||||
int len = min(ICON_MAX_STREAMSIZE - bufpos, (uint)strlen(src));
|
||||
strecpy(dst, src, dst + len - 1);
|
||||
int len = min(ICON_MAX_STREAMSIZE - bufpos, strlen(src));
|
||||
strncpy(dst, src, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -709,11 +691,11 @@ static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
|
||||
* @param tokencount the number of parameters passed
|
||||
* @param *tokens are the parameters given to the original command (0 is the first param)
|
||||
*/
|
||||
static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT])
|
||||
static void IConsoleAliasExec(const IConsoleAlias* alias, byte tokencount, char* tokens[ICON_TOKEN_COUNT])
|
||||
{
|
||||
const char *cmdptr;
|
||||
char *aliases[ICON_MAX_ALIAS_LINES], aliasstream[ICON_MAX_STREAMSIZE];
|
||||
uint i;
|
||||
int i;
|
||||
uint a_index, astream_i;
|
||||
|
||||
memset(&aliases, 0, sizeof(aliases));
|
||||
@@ -727,18 +709,18 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
|
||||
|
||||
switch (*cmdptr) {
|
||||
case '\'': // ' will double for ""
|
||||
case '\'': /* ' will double for "" */
|
||||
aliasstream[astream_i++] = '"';
|
||||
break;
|
||||
case ';': // Cmd seperator, start new command
|
||||
case ';': /* Cmd seperator, start new command */
|
||||
aliasstream[astream_i] = '\0';
|
||||
aliases[++a_index] = &aliasstream[++astream_i];
|
||||
cmdptr++;
|
||||
break;
|
||||
case '%': // Some or all parameters
|
||||
case '%': /* Some or all parameters */
|
||||
cmdptr++;
|
||||
switch (*cmdptr) {
|
||||
case '+': { // All parameters seperated: "[param 1]" "[param 2]"
|
||||
case '+': { /* All parameters seperated: "[param 1]" "[param 2]" */
|
||||
for (i = 0; i != tokencount; i++) {
|
||||
aliasstream[astream_i++] = '"';
|
||||
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
|
||||
@@ -746,7 +728,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
aliasstream[astream_i++] = ' ';
|
||||
}
|
||||
} break;
|
||||
case '!': { // Merge the parameters to one: "[param 1] [param 2] [param 3...]"
|
||||
case '!': { /* Merge the parameters to one: "[param 1] [param 2] [param 3...]" */
|
||||
aliasstream[astream_i++] = '"';
|
||||
for (i = 0; i != tokencount; i++) {
|
||||
astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
|
||||
@@ -755,7 +737,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
aliasstream[astream_i++] = '"';
|
||||
|
||||
} break;
|
||||
default: { // One specific parameter: %A = [param 1] %B = [param 2] ...
|
||||
default: { /* One specific parameter: %A = [param 1] %B = [param 2] ... */
|
||||
int param = *cmdptr - 'A';
|
||||
|
||||
if (param < 0 || param >= tokencount) {
|
||||
@@ -776,17 +758,14 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= a_index; i++) IConsoleCmdExec(aliases[i]); // execute each alias in turn
|
||||
for (i = 0; i <= (int)a_index; i++) IConsoleCmdExec(aliases[i]); // execute each alias in turn
|
||||
}
|
||||
|
||||
/**
|
||||
* Special function for adding string-type variables. They in addition
|
||||
* also need a 'size' value saying how long their string buffer is.
|
||||
* @param name name of the variable that will be used
|
||||
* @param addr memory location the variable will point to
|
||||
* @param size the length of the string buffer
|
||||
* @param help the help string shown for the variable
|
||||
* For more information see IConsoleVarRegister()
|
||||
* For more information see @IConsoleVarRegister()
|
||||
*/
|
||||
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
|
||||
{
|
||||
@@ -806,7 +785,7 @@ void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const
|
||||
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
|
||||
{
|
||||
char *new_cmd = strdup(name);
|
||||
IConsoleVar *item_new = MallocT<IConsoleVar>(1);
|
||||
IConsoleVar *item_new = malloc(sizeof(IConsoleVar));
|
||||
|
||||
item_new->help = (help != NULL) ? strdup(help) : NULL;
|
||||
|
||||
@@ -878,12 +857,12 @@ static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
|
||||
* @param *var the variable in question
|
||||
* @param *value the new value
|
||||
*/
|
||||
static void IConsoleVarSetStringvalue(const IConsoleVar *var, const char *value)
|
||||
static void IConsoleVarSetStringvalue(const IConsoleVar *var, char *value)
|
||||
{
|
||||
if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
|
||||
|
||||
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
|
||||
ttd_strlcpy((char*)var->addr, value, var->size);
|
||||
ttd_strlcpy((char*)var->addr, (char*)value, var->size);
|
||||
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
|
||||
IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
|
||||
return;
|
||||
@@ -1075,7 +1054,7 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
if (cmdstr[0] == '#') return; // comments
|
||||
|
||||
for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
|
||||
if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
|
||||
if (!IsValidAsciiChar(*cmdptr)) {
|
||||
IConsoleError("command contains malformed characters, aborting");
|
||||
IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr);
|
||||
return;
|
||||
@@ -1107,16 +1086,10 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
|
||||
tstream_i++;
|
||||
break;
|
||||
case '"': // Tokens enclosed in "" are one token
|
||||
case '"': /* Tokens enclosed in "" are one token */
|
||||
longtoken = !longtoken;
|
||||
break;
|
||||
case '\\': // Escape character for ""
|
||||
if (cmdptr[1] == '"' && tstream_i + 1 < lengthof(tokenstream)) {
|
||||
tokenstream[tstream_i++] = *++cmdptr;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
default: // Normal character
|
||||
default: /* Normal character */
|
||||
tokenstream[tstream_i++] = *cmdptr;
|
||||
|
||||
if (!foundtoken) {
|
||||
@@ -1129,10 +1102,8 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
|
||||
if (_stdlib_con_developer) {
|
||||
uint i;
|
||||
|
||||
for (i = 0; tokens[i] != NULL; i++) {
|
||||
for (i = 0; tokens[i] != NULL; i++)
|
||||
IConsolePrintF(_icolour_dbg, "condbg: token %d is: '%s'", i, tokens[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens[0] == '\0') return; // don't execute empty commands
|
||||
@@ -1140,33 +1111,31 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
* First try commands, then aliases, and finally variables. Execute
|
||||
* the found action taking into account its hooking code
|
||||
*/
|
||||
cmd = IConsoleCmdGet(tokens[0]);
|
||||
if (cmd != NULL) {
|
||||
cmd = IConsoleCmdGet(tokens[0]);
|
||||
if (cmd != NULL) {
|
||||
if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) {
|
||||
IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION);
|
||||
if (cmd->proc(t_index, tokens)) { // index started with 0
|
||||
IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
|
||||
} else {
|
||||
cmd->proc(0, NULL); // if command failed, give help
|
||||
}
|
||||
} else cmd->proc(0, NULL); // if command failed, give help
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
t_index--; // ignore the variable-name for comfort for both aliases and variaables
|
||||
alias = IConsoleAliasGet(tokens[0]);
|
||||
if (alias != NULL) {
|
||||
IConsoleAliasExec(alias, t_index, &tokens[1]);
|
||||
return;
|
||||
}
|
||||
t_index--; // ignore the variable-name for comfort for both aliases and variaables
|
||||
alias = IConsoleAliasGet(tokens[0]);
|
||||
if (alias != NULL) {
|
||||
IConsoleAliasExec(alias, t_index, &tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
var = IConsoleVarGet(tokens[0]);
|
||||
if (var != NULL) {
|
||||
if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS)) {
|
||||
IConsoleVarExec(var, t_index, &tokens[1]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var = IConsoleVarGet(tokens[0]);
|
||||
if (var != NULL) {
|
||||
if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS))
|
||||
IConsoleVarExec(var, t_index, &tokens[1]);
|
||||
|
||||
IConsoleError("command or variable not found");
|
||||
return;
|
||||
}
|
||||
|
||||
IConsoleError("command or variable not found");
|
||||
}
|
||||
+66
-67
@@ -1,18 +1,14 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file console.h */
|
||||
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#include "window_type.h"
|
||||
|
||||
/* maximum length of a typed in command */
|
||||
// maximum length of a typed in command
|
||||
#define ICON_CMDLN_SIZE 255
|
||||
/* maximum length of a totally expanded command */
|
||||
// maximum length of a totally expanded command
|
||||
#define ICON_MAX_STREAMSIZE 1024
|
||||
|
||||
enum IConsoleVarTypes {
|
||||
typedef enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_BOOLEAN,
|
||||
ICONSOLE_VAR_BYTE,
|
||||
ICONSOLE_VAR_UINT16,
|
||||
@@ -20,31 +16,31 @@ enum IConsoleVarTypes {
|
||||
ICONSOLE_VAR_INT16,
|
||||
ICONSOLE_VAR_INT32,
|
||||
ICONSOLE_VAR_STRING
|
||||
};
|
||||
} IConsoleVarTypes;
|
||||
|
||||
enum IConsoleModes {
|
||||
typedef enum IConsoleModes {
|
||||
ICONSOLE_FULL,
|
||||
ICONSOLE_OPENED,
|
||||
ICONSOLE_CLOSED
|
||||
};
|
||||
} IConsoleModes;
|
||||
|
||||
enum IConsoleHookTypes {
|
||||
typedef enum IConsoleHookTypes {
|
||||
ICONSOLE_HOOK_ACCESS,
|
||||
ICONSOLE_HOOK_PRE_ACTION,
|
||||
ICONSOLE_HOOK_POST_ACTION
|
||||
};
|
||||
} IConsoleHookTypes;
|
||||
|
||||
/** --Hooks--
|
||||
* Hooks are certain triggers get get accessed/executed on either
|
||||
* access, before execution/change or after execution/change. This allows
|
||||
* for general flow of permissions or special action needed in some cases
|
||||
*/
|
||||
typedef bool IConsoleHook();
|
||||
struct IConsoleHooks{
|
||||
IConsoleHook *access; ///< trigger when accessing the variable/command
|
||||
IConsoleHook *pre; ///< trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; ///< trigger after the variable/command is changed/executed
|
||||
};
|
||||
typedef bool IConsoleHook(void);
|
||||
typedef struct IConsoleHooks{
|
||||
IConsoleHook *access; // trigger when accessing the variable/command
|
||||
IConsoleHook *pre; // trigger before the variable/command is changed/executed
|
||||
IConsoleHook *post; // trigger after the variable/command is changed/executed
|
||||
} IConsoleHooks;
|
||||
|
||||
/** --Commands--
|
||||
* Commands are commands, or functions. They get executed once and any
|
||||
@@ -55,13 +51,14 @@ struct IConsoleHooks{
|
||||
*/
|
||||
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
|
||||
|
||||
struct IConsoleCmd {
|
||||
char *name; ///< name of command
|
||||
IConsoleCmd *next; ///< next command in list
|
||||
struct IConsoleCmd;
|
||||
typedef struct IConsoleCmd {
|
||||
char *name; // name of command
|
||||
struct IConsoleCmd *next; // next command in list
|
||||
|
||||
IConsoleCmdProc *proc; ///< process executed when command is typed
|
||||
IConsoleHooks hook; ///< any special trigger action that needs executing
|
||||
};
|
||||
IConsoleCmdProc *proc; // process executed when command is typed
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleCmd;
|
||||
|
||||
/** --Variables--
|
||||
* Variables are pointers to real ingame variables which allow for
|
||||
@@ -72,17 +69,18 @@ struct IConsoleCmd {
|
||||
* - '++' to increase value by one
|
||||
* - '--' to decrease value by one
|
||||
*/
|
||||
struct IConsoleVar {
|
||||
char *name; ///< name of the variable
|
||||
IConsoleVar *next; ///< next variable in list
|
||||
struct IConsoleVar;
|
||||
typedef struct IConsoleVar {
|
||||
char *name; // name of the variable
|
||||
struct IConsoleVar *next; // next variable in list
|
||||
|
||||
void *addr; ///< the address where the variable is pointing at
|
||||
uint32 size; ///< size of the variable, used for strings
|
||||
char *help; ///< the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; ///< type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; ///< some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; ///< any special trigger action that needs executing
|
||||
};
|
||||
void *addr; // the address where the variable is pointing at
|
||||
uint32 size; // size of the variable, used for strings
|
||||
char *help; // the optional help string shown when requesting information
|
||||
IConsoleVarTypes type; // type of variable (for correct assignment/output)
|
||||
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
|
||||
IConsoleHooks hook; // any special trigger action that needs executing
|
||||
} IConsoleVar;
|
||||
|
||||
/** --Aliases--
|
||||
* Aliases are like shortcuts for complex functions, variable assignments,
|
||||
@@ -95,67 +93,68 @@ struct IConsoleVar {
|
||||
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
|
||||
* - ";" allows for combining commands (see example 'ng')
|
||||
*/
|
||||
struct IConsoleAlias {
|
||||
char *name; ///< name of the alias
|
||||
IConsoleAlias *next; ///< next alias in list
|
||||
struct IConsoleAlias;
|
||||
typedef struct IConsoleAlias {
|
||||
char *name; // name of the alias
|
||||
struct IConsoleAlias *next; // next alias in list
|
||||
|
||||
char *cmdline; ///< command(s) that is/are being aliased
|
||||
};
|
||||
char *cmdline; // command(s) that is/are being aliased
|
||||
} IConsoleAlias;
|
||||
|
||||
/* console parser */
|
||||
extern IConsoleCmd *_iconsole_cmds; ///< list of registred commands
|
||||
extern IConsoleVar *_iconsole_vars; ///< list of registred vars
|
||||
extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
|
||||
// ** 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 */
|
||||
extern byte _icolour_def;
|
||||
extern byte _icolour_err;
|
||||
extern byte _icolour_warn;
|
||||
extern byte _icolour_dbg;
|
||||
extern byte _icolour_cmd;
|
||||
extern IConsoleModes _iconsole_mode;
|
||||
// ** 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 IConsoleFree();
|
||||
void IConsoleClearBuffer();
|
||||
void IConsoleResize(Window *w);
|
||||
void IConsoleSwitch();
|
||||
void IConsoleClose();
|
||||
void IConsoleOpen();
|
||||
// ** console functions ** //
|
||||
void IConsoleInit(void);
|
||||
void IConsoleFree(void);
|
||||
void IConsoleClearBuffer(void);
|
||||
void IConsoleResize(void);
|
||||
void IConsoleSwitch(void);
|
||||
void IConsoleClose(void);
|
||||
void IConsoleOpen(void);
|
||||
|
||||
/* console output */
|
||||
// ** console output ** //
|
||||
void IConsolePrint(uint16 color_code, const char *string);
|
||||
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
|
||||
void IConsoleDebug(const char *dbg, const char *string);
|
||||
void IConsoleDebug(const char *string);
|
||||
void IConsoleWarning(const char *string);
|
||||
void IConsoleError(const char *string);
|
||||
|
||||
/* Commands */
|
||||
// *** 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 */
|
||||
// *** 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 */
|
||||
// *** Parser *** //
|
||||
void IConsoleCmdExec(const char *cmdstr);
|
||||
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
|
||||
|
||||
/* console std lib (register ingame commands/aliases/variables) */
|
||||
void IConsoleStdLibRegister();
|
||||
// ** console std lib (register ingame commands/aliases/variables) ** //
|
||||
void IConsoleStdLibRegister(void);
|
||||
|
||||
/* Hooking code */
|
||||
// ** 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 */
|
||||
// ** Supporting functions **//
|
||||
bool GetArgumentInteger(uint32 *value, const char *arg);
|
||||
#endif /* CONSOLE_H */
|
||||
@@ -1,42 +1,22 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file console_cmds.cpp */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "engine.h"
|
||||
#include "landscape.h"
|
||||
#include "saveload.h"
|
||||
#include "variables.h"
|
||||
#include "network/network_data.h"
|
||||
#include "network/network_client.h"
|
||||
#include "network/network_server.h"
|
||||
#include "network/network_udp.h"
|
||||
#include "command_func.h"
|
||||
#include "settings_func.h"
|
||||
#include "fios.h"
|
||||
#include "fileio.h"
|
||||
#include "station.h"
|
||||
#include "screenshot.h"
|
||||
#include "genworld.h"
|
||||
#include "network/network.h"
|
||||
#include "strings_func.h"
|
||||
#include "viewport_func.h"
|
||||
#include "window_func.h"
|
||||
#include "functions.h"
|
||||
#include "map_func.h"
|
||||
#include "date_func.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "string_func.h"
|
||||
#include "player_func.h"
|
||||
#include "player_base.h"
|
||||
#include "settings_type.h"
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
#include "table/strings.h"
|
||||
#endif /* ENABLE_NETWORK */
|
||||
#include "saveload.h"
|
||||
#include "string.h"
|
||||
#include "variables.h"
|
||||
#include "network_data.h"
|
||||
#include "network_client.h"
|
||||
#include "network_server.h"
|
||||
#include "network_udp.h"
|
||||
#include "command.h"
|
||||
#include "settings.h"
|
||||
#include "hal.h" /* for file list */
|
||||
#include "vehicle.h"
|
||||
|
||||
// ** scriptfile handling ** //
|
||||
static FILE *_script_file;
|
||||
@@ -44,7 +24,7 @@ static bool _script_running;
|
||||
|
||||
// ** console command / variable defines ** //
|
||||
#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
|
||||
#define DEF_CONSOLE_HOOK(function) static bool function()
|
||||
#define DEF_CONSOLE_HOOK(function) static bool function(void)
|
||||
|
||||
|
||||
/* **************************** */
|
||||
@@ -53,7 +33,7 @@ static bool _script_running;
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
||||
static inline bool NetworkAvailable()
|
||||
static inline bool NetworkAvailable(void)
|
||||
{
|
||||
if (!_network_available) {
|
||||
IConsoleError("You cannot use this command because there is no network available.");
|
||||
@@ -144,12 +124,23 @@ DEF_CONSOLE_CMD(ConResetTile)
|
||||
|
||||
DEF_CONSOLE_CMD(ConStopAllVehicles)
|
||||
{
|
||||
Vehicle* v;
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Stops all vehicles in the game. For debugging only! Use at your own risk... Usage: 'stopall'");
|
||||
return true;
|
||||
}
|
||||
|
||||
StopAllVehicles();
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (IsValidVehicle(v)) {
|
||||
/* Code ripped from CmdStartStopTrain. Can't call it, because of
|
||||
* ownership problems, so we'll duplicate some code, for now */
|
||||
if (v->type == VEH_Train)
|
||||
v->u.rail.days_since_order_progr = 0;
|
||||
v->vehstatus |= VS_STOPPED;
|
||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
|
||||
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
@@ -165,10 +156,6 @@ DEF_CONSOLE_CMD(ConScrollToTile)
|
||||
if (argc == 2) {
|
||||
uint32 result;
|
||||
if (GetArgumentInteger(&result, argv[1])) {
|
||||
if (result >= MapSize()) {
|
||||
IConsolePrint(_icolour_err, "Tile does not exist");
|
||||
return true;
|
||||
}
|
||||
ScrollMainWindowToTile((TileIndex)result);
|
||||
return true;
|
||||
}
|
||||
@@ -177,7 +164,8 @@ DEF_CONSOLE_CMD(ConScrollToTile)
|
||||
return false;
|
||||
}
|
||||
|
||||
extern void BuildFileList();
|
||||
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
|
||||
extern void BuildFileList(void);
|
||||
extern void SetFiosType(const byte fiostype);
|
||||
|
||||
/* Save the map to a file */
|
||||
@@ -189,34 +177,21 @@ DEF_CONSOLE_CMD(ConSave)
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
char *filename = str_fmt("%s.sav", argv[1]);
|
||||
char buf[200];
|
||||
|
||||
snprintf(buf, lengthof(buf), "%s%s%s.sav", _path.save_dir, PATHSEP, argv[1]);
|
||||
IConsolePrint(_icolour_def, "Saving map...");
|
||||
|
||||
if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
|
||||
IConsolePrint(_icolour_err, "Saving map failed");
|
||||
} else {
|
||||
IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", filename);
|
||||
}
|
||||
free(filename);
|
||||
if (SaveOrLoad(buf, SL_SAVE) != SL_OK) {
|
||||
IConsolePrint(_icolour_err, "SaveMap failed");
|
||||
} else
|
||||
IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Explicitly save the configuration */
|
||||
DEF_CONSOLE_CMD(ConSaveConfig)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Saves the current config, typically to 'openttd.cfg'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
SaveToConfig();
|
||||
IConsolePrint(_icolour_def, "Saved config.");
|
||||
return true;
|
||||
}
|
||||
|
||||
static const FiosItem* GetFiosItem(const char* file)
|
||||
{
|
||||
int i;
|
||||
@@ -229,14 +204,14 @@ static const FiosItem* GetFiosItem(const char* file)
|
||||
if (strcmp(file, _fios_list[i].title) == 0) break;
|
||||
}
|
||||
|
||||
if (i == _fios_num) { // If no name matches, try to parse it as number
|
||||
if (i == _fios_num) { /* If no name matches, try to parse it as number */
|
||||
char* endptr;
|
||||
|
||||
i = strtol(file, &endptr, 10);
|
||||
if (file == endptr || *endptr != '\0') i = -1;
|
||||
}
|
||||
|
||||
return IsInsideMM(i, 0, _fios_num) ? &_fios_list[i] : NULL;
|
||||
return IS_INT_INSIDE(i, 0, _fios_num) ? &_fios_list[i] : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,9 +240,8 @@ DEF_CONSOLE_CMD(ConLoad)
|
||||
} break;
|
||||
default: IConsolePrintF(_icolour_err, "%s: Not a savegame.", file);
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
|
||||
}
|
||||
|
||||
FiosFreeSavegameList();
|
||||
return true;
|
||||
@@ -291,9 +265,8 @@ DEF_CONSOLE_CMD(ConRemove)
|
||||
if (item != NULL) {
|
||||
if (!FiosDelete(item->name))
|
||||
IConsolePrintF(_icolour_err, "%s: Failed to delete file", file);
|
||||
} else {
|
||||
} else
|
||||
IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
|
||||
}
|
||||
|
||||
FiosFreeSavegameList();
|
||||
return true;
|
||||
@@ -343,9 +316,8 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
|
||||
break;
|
||||
default: IConsolePrintF(_icolour_err, "%s: Not a directory.", file);
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
|
||||
}
|
||||
|
||||
FiosFreeSavegameList();
|
||||
return true;
|
||||
@@ -361,7 +333,7 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
|
||||
}
|
||||
|
||||
// XXX - Workaround for broken file handling
|
||||
FiosGetSavegameList(SLD_LOAD_GAME);
|
||||
FiosGetSavegameList(&_fios_num, SLD_LOAD_GAME);
|
||||
FiosFreeSavegameList();
|
||||
|
||||
FiosGetDescText(&path, NULL);
|
||||
@@ -426,12 +398,11 @@ DEF_CONSOLE_CMD(ConBan)
|
||||
}
|
||||
|
||||
if (ci != NULL) {
|
||||
IConsolePrint(_icolour_def, "Client banned");
|
||||
banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
|
||||
SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
|
||||
} else {
|
||||
IConsolePrint(_icolour_def, "Client banned");
|
||||
} else
|
||||
IConsolePrint(_icolour_def, "Client not online, banned IP");
|
||||
}
|
||||
|
||||
/* Add user to ban-list */
|
||||
for (index = 0; index < lengthof(_network_ban_list); index++) {
|
||||
@@ -500,12 +471,11 @@ DEF_CONSOLE_CMD(ConPauseGame)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_pause_game == 0) {
|
||||
if (_pause == 0) {
|
||||
DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
|
||||
IConsolePrint(_icolour_def, "Game paused.");
|
||||
} else {
|
||||
} else
|
||||
IConsolePrint(_icolour_def, "Game is already paused.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -517,12 +487,11 @@ DEF_CONSOLE_CMD(ConUnPauseGame)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_pause_game != 0) {
|
||||
if (_pause != 0) {
|
||||
DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
|
||||
IConsolePrint(_icolour_def, "Game unpaused.");
|
||||
} else {
|
||||
} else
|
||||
IConsolePrint(_icolour_def, "Game is already unpaused.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -537,28 +506,15 @@ DEF_CONSOLE_CMD(ConRcon)
|
||||
|
||||
if (argc < 3) return false;
|
||||
|
||||
if (_network_server) {
|
||||
IConsoleCmdExec(argv[2]);
|
||||
} else {
|
||||
SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
|
||||
}
|
||||
SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConStatus)
|
||||
{
|
||||
static const char* const stat_str[] = {
|
||||
"inactive",
|
||||
"authorizing",
|
||||
"authorized",
|
||||
"waiting",
|
||||
"loading map",
|
||||
"map done",
|
||||
"ready",
|
||||
"active"
|
||||
};
|
||||
|
||||
NetworkTCPSocketHandler *cs;
|
||||
static const char *stat_str[] = {"inactive", "authorized", "waiting", "loading map", "map done", "ready", "active"};
|
||||
const char *status;
|
||||
const NetworkClientState *cs;
|
||||
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
|
||||
@@ -568,13 +524,10 @@ DEF_CONSOLE_CMD(ConStatus)
|
||||
FOR_ALL_CLIENTS(cs) {
|
||||
int lag = NetworkCalculateLag(cs);
|
||||
const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
|
||||
const char* status;
|
||||
|
||||
status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
|
||||
status = (cs->status <= STATUS_ACTIVE) ? stat_str[cs->status] : "unknown";
|
||||
IConsolePrintF(8, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'",
|
||||
cs->index, ci->client_name, status, lag,
|
||||
ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
|
||||
GetPlayerIP(ci), ci->unique_id);
|
||||
cs->index, ci->client_name, status, lag, ci->client_playas, GetPlayerIP(ci), ci->unique_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -598,18 +551,18 @@ DEF_CONSOLE_CMD(ConServerInfo)
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount)
|
||||
{
|
||||
if (_network_game_info.clients_max > MAX_CLIENTS) {
|
||||
_network_game_info.clients_max = MAX_CLIENTS;
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount) {
|
||||
/* XXX - hardcoded, string limiation -- TrueLight
|
||||
* XXX - also see network.c:NetworkStartup ~1356 */
|
||||
if (_network_game_info.clients_max > 10) {
|
||||
_network_game_info.clients_max = 10;
|
||||
IConsoleError("Maximum clients out of bounds, truncating to limit.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
|
||||
{
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount) {
|
||||
if (_network_game_info.companies_max > MAX_PLAYERS) {
|
||||
_network_game_info.companies_max = MAX_PLAYERS;
|
||||
IConsoleError("Maximum companies out of bounds, truncating to limit.");
|
||||
@@ -618,9 +571,8 @@ DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
|
||||
{
|
||||
/* XXX see ConHookValidateMaxClientsCount */
|
||||
DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount) {
|
||||
/* XXX @see ConHookValidateMaxClientsCount */
|
||||
if (_network_game_info.spectators_max > 10) {
|
||||
_network_game_info.spectators_max = 10;
|
||||
IConsoleError("Maximum spectators out of bounds, truncating to limit.");
|
||||
@@ -629,12 +581,6 @@ DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookCheckMinPlayers)
|
||||
{
|
||||
CheckMinPlayers();
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConKick)
|
||||
{
|
||||
NetworkClientInfo *ci;
|
||||
@@ -668,19 +614,18 @@ DEF_CONSOLE_CMD(ConKick)
|
||||
|
||||
if (ci != NULL) {
|
||||
SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
|
||||
} else {
|
||||
} else
|
||||
IConsoleError("Client not found");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConResetCompany)
|
||||
{
|
||||
const Player *p;
|
||||
NetworkTCPSocketHandler *cs;
|
||||
const NetworkClientInfo *ci;
|
||||
PlayerID index;
|
||||
Player *p;
|
||||
NetworkClientState *cs;
|
||||
NetworkClientInfo *ci;
|
||||
byte index;
|
||||
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Remove an idle company from the game. Usage: 'reset_company <company-id>'");
|
||||
@@ -690,15 +635,16 @@ DEF_CONSOLE_CMD(ConResetCompany)
|
||||
|
||||
if (argc != 2) return false;
|
||||
|
||||
index = (PlayerID)(atoi(argv[1]) - 1);
|
||||
index = atoi(argv[1]);
|
||||
|
||||
/* Check valid range */
|
||||
if (!IsValidPlayer(index)) {
|
||||
if (index < 1 || index > MAX_PLAYERS) {
|
||||
IConsolePrintF(_icolour_err, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check if company does exist */
|
||||
index--;
|
||||
p = GetPlayer(index);
|
||||
if (!p->is_active) {
|
||||
IConsoleError("Company does not exist.");
|
||||
@@ -713,13 +659,13 @@ DEF_CONSOLE_CMD(ConResetCompany)
|
||||
/* Check if the company has active players */
|
||||
FOR_ALL_CLIENTS(cs) {
|
||||
ci = DEREF_CLIENT_INFO(cs);
|
||||
if (ci->client_playas == index) {
|
||||
if (ci->client_playas - 1 == index) {
|
||||
IConsoleError("Cannot remove company: a client is connected to that company.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
|
||||
if (ci->client_playas == index) {
|
||||
if (ci->client_playas - 1 == index) {
|
||||
IConsoleError("Cannot remove company: the server is connected to that company.");
|
||||
return true;
|
||||
}
|
||||
@@ -740,11 +686,11 @@ DEF_CONSOLE_CMD(ConNetworkClients)
|
||||
return true;
|
||||
}
|
||||
|
||||
FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
|
||||
IConsolePrintF(8, "Client #%1d name: '%s' company: %1d IP: %s",
|
||||
ci->client_index, ci->client_name,
|
||||
ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
|
||||
GetPlayerIP(ci));
|
||||
for (ci = _network_client_info; ci != &_network_client_info[MAX_CLIENT_INFO]; ci++) {
|
||||
if (ci->client_index != NETWORK_EMPTY_INDEX) {
|
||||
IConsolePrintF(8, "Client #%1d name: '%s' company: %1d IP: %s",
|
||||
ci->client_index, ci->client_name, ci->client_playas, GetPlayerIP(ci));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -759,32 +705,24 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
|
||||
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
|
||||
IConsoleHelp("IP can contain port and player: 'IP[[#Player]:Port]', eg: 'server.ottd.org#2:443'");
|
||||
IConsoleHelp("Player #255 is spectator all others are a certain company with Company 1 being #1");
|
||||
IConsoleHelp("IP can contain port and player: 'IP#Player:Port', eg: 'server.ottd.org#2:443'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc < 2) return false;
|
||||
if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
|
||||
|
||||
if (_networking) // We are in network-mode, first close it!
|
||||
NetworkDisconnect();
|
||||
|
||||
ip = argv[1];
|
||||
/* Default settings: default port and new company */
|
||||
rport = NETWORK_DEFAULT_PORT;
|
||||
_network_playas = PLAYER_NEW_COMPANY;
|
||||
|
||||
ParseConnectionString(&player, &port, ip);
|
||||
|
||||
IConsolePrintF(_icolour_def, "Connecting to %s...", ip);
|
||||
if (player != NULL) {
|
||||
_network_playas = (PlayerID)atoi(player);
|
||||
IConsolePrintF(_icolour_def, " player-no: %d", _network_playas);
|
||||
|
||||
/* From a user pov 0 is a new player, internally it's different and all
|
||||
* players are offset by one to ease up on users (eg players 1-8 not 0-7) */
|
||||
if (_network_playas != PLAYER_SPECTATOR) {
|
||||
_network_playas--;
|
||||
if (!IsValidPlayer(_network_playas)) return false;
|
||||
}
|
||||
_network_playas = atoi(player);
|
||||
IConsolePrintF(_icolour_def, " player-no: %s", player);
|
||||
}
|
||||
if (port != NULL) {
|
||||
rport = atoi(port);
|
||||
@@ -814,7 +752,7 @@ DEF_CONSOLE_CMD(ConExec)
|
||||
|
||||
if (argc < 2) return false;
|
||||
|
||||
_script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
|
||||
_script_file = fopen(argv[1], "r");
|
||||
|
||||
if (_script_file == NULL) {
|
||||
if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
|
||||
@@ -838,7 +776,7 @@ DEF_CONSOLE_CMD(ConExec)
|
||||
IConsoleError("Encountered errror while trying to read from script file");
|
||||
|
||||
_script_running = false;
|
||||
FioFCloseFile(_script_file);
|
||||
fclose(_script_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -856,7 +794,7 @@ DEF_CONSOLE_CMD(ConReturn)
|
||||
/* **************************** */
|
||||
/* default console commands */
|
||||
/* **************************** */
|
||||
extern bool CloseConsoleLogIfActive();
|
||||
extern bool CloseConsoleLogIfActive(void);
|
||||
|
||||
DEF_CONSOLE_CMD(ConScript)
|
||||
{
|
||||
@@ -904,61 +842,20 @@ DEF_CONSOLE_CMD(ConEchoC)
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void SwitchMode(int new_mode);
|
||||
|
||||
DEF_CONSOLE_CMD(ConNewGame)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Start a new game. Usage: 'newgame [seed]'");
|
||||
IConsoleHelp("The server can force a new game using 'newgame'; any client joined will rejoin after the server is done generating the new game.");
|
||||
IConsoleHelp("Start a new game. Usage: 'newgame'");
|
||||
IConsoleHelp("The server can force a new game using 'newgame', any client using it will part and start a single-player game");
|
||||
return true;
|
||||
}
|
||||
|
||||
StartNewGameWithoutGUI((argc == 2) ? (uint)atoi(argv[1]) : GENERATE_NEW_SEED);
|
||||
GenRandomNewGame(Random(), InteractiveRandom());
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void SwitchMode(int new_mode);
|
||||
|
||||
DEF_CONSOLE_CMD(ConRestart)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Restart game. Usage: 'restart'");
|
||||
IConsoleHelp("Restarts a game. It tries to reproduce the exact same map as the game started with.");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Don't copy the _newgame pointers to the real pointers, so call SwitchMode directly */
|
||||
_patches.map_x = MapLogX();
|
||||
_patches.map_y = FindFirstBit(MapSizeY());
|
||||
SwitchMode(SM_NEWGAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConGetSeed)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
|
||||
IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
|
||||
return true;
|
||||
}
|
||||
|
||||
IConsolePrintF(_icolour_def, "Generation Seed: %u", _patches.generation_seed);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConGetDate)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
|
||||
return true;
|
||||
}
|
||||
|
||||
YearMonthDay ymd;
|
||||
ConvertDateToYMD(_date, &ymd);
|
||||
IConsolePrintF(_icolour_def, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DEF_CONSOLE_CMD(ConAlias)
|
||||
{
|
||||
IConsoleAlias *alias;
|
||||
@@ -990,10 +887,10 @@ DEF_CONSOLE_CMD(ConScreenShot)
|
||||
|
||||
if (argc > 3) return false;
|
||||
|
||||
SetScreenshotType(SC_VIEWPORT);
|
||||
_make_screenshot = 1;
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "big") == 0 || (argc == 3 && strcmp(argv[2], "big") == 0))
|
||||
SetScreenshotType(SC_WORLD);
|
||||
_make_screenshot = 2;
|
||||
|
||||
if (strcmp(argv[1], "no_con") == 0 || (argc == 3 && strcmp(argv[2], "no_con") == 0))
|
||||
IConsoleClose();
|
||||
@@ -1070,9 +967,7 @@ DEF_CONSOLE_CMD(ConDebugLevel)
|
||||
|
||||
if (argc == 1) {
|
||||
IConsolePrintF(_icolour_def, "Current debug-level: '%s'", GetDebugString());
|
||||
} else {
|
||||
SetDebugString(argv[1]);
|
||||
}
|
||||
} else SetDebugString(argv[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1084,8 +979,6 @@ DEF_CONSOLE_CMD(ConExit)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_game_mode == GM_NORMAL && _patches.autosave_on_exit) DoExitSave();
|
||||
|
||||
_exit_game = true;
|
||||
return true;
|
||||
}
|
||||
@@ -1226,39 +1119,8 @@ DEF_CONSOLE_CMD(ConSay)
|
||||
|
||||
if (!_network_server) {
|
||||
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
|
||||
} else {
|
||||
} else
|
||||
NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConPlayers)
|
||||
{
|
||||
Player *p;
|
||||
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("List the in-game details of all clients connected to the server. Usage 'players'");
|
||||
return true;
|
||||
}
|
||||
NetworkPopulateCompanyInfo();
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
char buffer[512];
|
||||
|
||||
if (!p->is_active) continue;
|
||||
|
||||
const NetworkPlayerInfo *npi = &_network_player_info[p->index];
|
||||
|
||||
GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer));
|
||||
IConsolePrintF(8, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %" OTTD_PRINTF64 "d Loan: %" OTTD_PRINTF64 "d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected",
|
||||
p->index + 1, buffer, npi->company_name, p->inaugurated_year, (int64)p->player_money, (int64)p->current_loan, (int64)CalculateCompanyValue(p),
|
||||
/* trains */ npi->num_vehicle[0],
|
||||
/* lorry + bus */ npi->num_vehicle[1] + npi->num_vehicle[2],
|
||||
/* planes */ npi->num_vehicle[3],
|
||||
/* ships */ npi->num_vehicle[4],
|
||||
/* protected */ StrEmpty(npi->password) ? "un" : "");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1279,10 +1141,9 @@ DEF_CONSOLE_CMD(ConSayPlayer)
|
||||
}
|
||||
|
||||
if (!_network_server) {
|
||||
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
|
||||
} else {
|
||||
NetworkServer_HandleChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
|
||||
}
|
||||
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2]);
|
||||
} else
|
||||
NetworkServer_HandleChat(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1299,16 +1160,15 @@ DEF_CONSOLE_CMD(ConSayClient)
|
||||
|
||||
if (!_network_server) {
|
||||
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
|
||||
} else {
|
||||
} else
|
||||
NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookServerPW)
|
||||
{
|
||||
if (strcmp(_network_server_password, "*") == 0) {
|
||||
if (strncmp(_network_server_password, "*", NETWORK_PASSWORD_LENGTH) == 0) {
|
||||
_network_server_password[0] = '\0';
|
||||
_network_game_info.use_password = 0;
|
||||
} else {
|
||||
@@ -1321,7 +1181,7 @@ DEF_CONSOLE_HOOK(ConHookServerPW)
|
||||
|
||||
DEF_CONSOLE_HOOK(ConHookRconPW)
|
||||
{
|
||||
if (strcmp(_network_rcon_password, "*") == 0)
|
||||
if (strncmp(_network_rcon_password, "*", NETWORK_PASSWORD_LENGTH) == 0)
|
||||
_network_rcon_password[0] = '\0';
|
||||
|
||||
ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
|
||||
@@ -1329,33 +1189,29 @@ DEF_CONSOLE_HOOK(ConHookRconPW)
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void HashCurrentCompanyPassword();
|
||||
|
||||
/* Also use from within player_gui to change the password graphically */
|
||||
bool NetworkChangeCompanyPassword(byte argc, char *argv[])
|
||||
{
|
||||
if (argc == 0) {
|
||||
if (!IsValidPlayer(_local_player)) return true; // dedicated server
|
||||
if (_local_player >= MAX_PLAYERS) return true; // dedicated server
|
||||
IConsolePrintF(_icolour_warn, "Current value for 'company_pw': %s", _network_player_info[_local_player].password);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsValidPlayer(_local_player)) {
|
||||
if (_local_player >= MAX_PLAYERS) {
|
||||
IConsoleError("You have to own a company to make use of this command.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argc != 1) return false;
|
||||
|
||||
if (strcmp(argv[0], "*") == 0) argv[0][0] = '\0';
|
||||
if (strncmp(argv[0], "*", sizeof(_network_player_info[_local_player].password)) == 0)
|
||||
argv[0][0] = '\0';
|
||||
|
||||
ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
|
||||
|
||||
if (!_network_server) {
|
||||
if (!_network_server)
|
||||
SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
|
||||
} else {
|
||||
HashCurrentCompanyPassword();
|
||||
}
|
||||
|
||||
IConsolePrintF(_icolour_warn, "'company_pw' changed to: %s", _network_player_info[_local_player].password);
|
||||
|
||||
@@ -1368,7 +1224,7 @@ DEF_CONSOLE_HOOK(ConProcPlayerName)
|
||||
|
||||
if (ci == NULL) return false;
|
||||
|
||||
/* Don't change the name if it is the same as the old name */
|
||||
// Don't change the name if it is the same as the old name
|
||||
if (strcmp(ci->client_name, _network_player_name) != 0) {
|
||||
if (!_network_server) {
|
||||
SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
|
||||
@@ -1412,7 +1268,6 @@ DEF_CONSOLE_CMD(ConProcServerIP)
|
||||
IConsolePrintF(_icolour_warn, "'server_ip' changed to: %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
DEF_CONSOLE_CMD(ConPatch)
|
||||
{
|
||||
@@ -1426,35 +1281,12 @@ DEF_CONSOLE_CMD(ConPatch)
|
||||
|
||||
if (argc == 2) {
|
||||
IConsoleGetPatchSetting(argv[1]);
|
||||
} else {
|
||||
uint32 val;
|
||||
|
||||
if (GetArgumentInteger(&val, argv[2])) {
|
||||
if (!IConsoleSetPatchSetting(argv[1], val)) {
|
||||
if (_network_server) {
|
||||
IConsoleError("This command/variable is not available during network games.");
|
||||
} else {
|
||||
IConsoleError("This command/variable is only available to a network server.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
IConsoleSetPatchSetting(argv[1], argv[2]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_CONSOLE_CMD(ConListPatches)
|
||||
{
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("List patch options. Usage: 'list_patches'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc != 1) return false;
|
||||
|
||||
IConsoleListPatches();
|
||||
return true;
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
DEF_CONSOLE_CMD(ConListDumpVariables)
|
||||
{
|
||||
@@ -1482,10 +1314,10 @@ DEF_CONSOLE_CMD(ConListDumpVariables)
|
||||
/* debug commands and variables */
|
||||
/* ****************************************** */
|
||||
|
||||
static void IConsoleDebugLibRegister()
|
||||
static void IConsoleDebugLibRegister(void)
|
||||
{
|
||||
/* debugging variables and functions */
|
||||
extern bool _stdlib_con_developer; // XXX extern in .cpp
|
||||
// debugging variables and functions
|
||||
extern bool _stdlib_con_developer; /* XXX extern in .c */
|
||||
|
||||
IConsoleVarRegister("con_developer", &_stdlib_con_developer, ICONSOLE_VAR_BOOLEAN, "Enable/disable console debugging information (internal)");
|
||||
IConsoleCmdRegister("resettile", ConResetTile);
|
||||
@@ -1499,12 +1331,12 @@ static void IConsoleDebugLibRegister()
|
||||
/* console command and variable registration */
|
||||
/* ****************************************** */
|
||||
|
||||
void IConsoleStdLibRegister()
|
||||
void IConsoleStdLibRegister(void)
|
||||
{
|
||||
/* stdlib */
|
||||
extern byte _stdlib_developer; // XXX extern in .cpp
|
||||
// stdlib
|
||||
extern byte _stdlib_developer; /* XXX extern in .c */
|
||||
|
||||
/* default variables and functions */
|
||||
// default variables and functions
|
||||
IConsoleCmdRegister("debug_level", ConDebugLevel);
|
||||
IConsoleCmdRegister("dump_vars", ConListDumpVariables);
|
||||
IConsoleCmdRegister("echo", ConEcho);
|
||||
@@ -1519,9 +1351,6 @@ void IConsoleStdLibRegister()
|
||||
IConsoleCmdRegister("list_vars", ConListVariables);
|
||||
IConsoleCmdRegister("list_aliases", ConListAliases);
|
||||
IConsoleCmdRegister("newgame", ConNewGame);
|
||||
IConsoleCmdRegister("restart", ConRestart);
|
||||
IConsoleCmdRegister("getseed", ConGetSeed);
|
||||
IConsoleCmdRegister("getdate", ConGetDate);
|
||||
IConsoleCmdRegister("quit", ConExit);
|
||||
IConsoleCmdRegister("resetengines", ConResetEngines);
|
||||
IConsoleCmdRegister("return", ConReturn);
|
||||
@@ -1532,13 +1361,10 @@ void IConsoleStdLibRegister()
|
||||
IConsoleCmdRegister("load", ConLoad);
|
||||
IConsoleCmdRegister("rm", ConRemove);
|
||||
IConsoleCmdRegister("save", ConSave);
|
||||
IConsoleCmdRegister("saveconfig", ConSaveConfig);
|
||||
IConsoleCmdRegister("ls", ConListFiles);
|
||||
IConsoleCmdRegister("cd", ConChangeDirectory);
|
||||
IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
|
||||
IConsoleCmdRegister("clear", ConClearBuffer);
|
||||
IConsoleCmdRegister("patch", ConPatch);
|
||||
IConsoleCmdRegister("list_patches", ConListPatches);
|
||||
|
||||
IConsoleAliasRegister("dir", "ls");
|
||||
IConsoleAliasRegister("del", "rm %+");
|
||||
@@ -1557,8 +1383,6 @@ void IConsoleStdLibRegister()
|
||||
/*** Networking commands ***/
|
||||
IConsoleCmdRegister("say", ConSay);
|
||||
IConsoleCmdHookAdd("say", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
|
||||
IConsoleCmdRegister("players", ConPlayers);
|
||||
IConsoleCmdHookAdd("players", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
IConsoleCmdRegister("say_player", ConSayPlayer);
|
||||
IConsoleCmdHookAdd("say_player", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
|
||||
IConsoleCmdRegister("say_client", ConSayClient);
|
||||
@@ -1594,6 +1418,9 @@ void IConsoleStdLibRegister()
|
||||
IConsoleCmdRegister("unpause", ConUnPauseGame);
|
||||
IConsoleCmdHookAdd("unpause", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
|
||||
IConsoleCmdRegister("patch", ConPatch);
|
||||
IConsoleCmdHookAdd("patch", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
|
||||
/*** Networking variables ***/
|
||||
IConsoleVarRegister("net_frame_freq", &_network_frame_freq, ICONSOLE_VAR_BYTE, "The amount of frames before a command will be (visibly) executed. Default value: 1");
|
||||
IConsoleVarHookAdd("net_frame_freq", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
@@ -1651,14 +1478,8 @@ void IConsoleStdLibRegister()
|
||||
IConsoleVarHookAdd("autoclean_protected", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
IConsoleVarRegister("autoclean_unprotected", &_network_autoclean_unprotected, ICONSOLE_VAR_BYTE, "Automatically shut down inactive companies after the given amount of months");
|
||||
IConsoleVarHookAdd("autoclean_unprotected", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
IConsoleVarRegister("restart_game_year", &_network_restart_game_year, ICONSOLE_VAR_UINT16, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
|
||||
IConsoleVarHookAdd("restart_game_year", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
|
||||
IConsoleVarRegister("min_players", &_network_min_players, ICONSOLE_VAR_BYTE, "Automatically pause the game when the number of active players passes below the given amount");
|
||||
IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
IConsoleVarHookAdd("min_players", ICONSOLE_HOOK_POST_ACTION, ConHookCheckMinPlayers);
|
||||
IConsoleVarRegister("reload_cfg", &_network_reload_cfg, ICONSOLE_VAR_BOOLEAN, "reload the entire config file between the end of this game, and starting the next new game - dedicated servers");
|
||||
IConsoleVarHookAdd("reload_cfg", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
IConsoleVarRegister("restart_game_date", &_network_restart_game_date, ICONSOLE_VAR_UINT16, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
|
||||
IConsoleVarHookAdd("restart_game_date", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "currency.h"
|
||||
#include "news.h"
|
||||
#include "variables.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
// exchange rate prefix
|
||||
// | separator | postfix
|
||||
// | | Euro year | |
|
||||
// | | | | |
|
||||
CurrencySpec _currency_specs[] = {
|
||||
{ 1, ',', CF_NOEURO, "\xA3", "" }, // british pounds
|
||||
{ 2, ',', CF_NOEURO, "$", "" }, // us dollars
|
||||
{ 2, ',', CF_ISEURO, "¤", "" }, // Euro
|
||||
{ 200, ',', CF_NOEURO, "\xA5", "" }, // yen
|
||||
{ 19, ',', 2002, "", " S." }, // austrian schilling
|
||||
{ 57, ',', 2002, "BEF ", "" }, // belgian franc
|
||||
{ 2, ',', CF_NOEURO, "CHF ", "" }, // swiss franc
|
||||
{ 50, ',', CF_NOEURO, "", " Kc" }, // czech koruna // TODO: Should use the "c" with an upside down "^"
|
||||
{ 4, '.', 2002, "DM ", "" }, // deutsche mark
|
||||
{ 10, '.', CF_NOEURO, "", " kr" }, // danish krone
|
||||
{ 200, '.', 2002, "Pts ", "" }, // spanish pesetas
|
||||
{ 8, ',', 2002, "", " mk" }, // finnish markka
|
||||
{ 10, '.', 2002, "FF ", "" }, // french francs
|
||||
{ 480, ',', 2002, "", "Dr." }, // greek drachma
|
||||
{ 376, ',', 2002, "", " Ft" }, // hungarian forint
|
||||
{ 130, '.', CF_NOEURO, "", " Kr" }, // icelandic krona
|
||||
{ 2730, ',', 2002, "", " L." }, // italian lira
|
||||
{ 3, ',', 2002, "NLG ", "" }, // dutch gulden
|
||||
{ 11, '.', CF_NOEURO, "", " Kr" }, // norwegian krone
|
||||
{ 6, ' ', CF_NOEURO, "", " zl" }, // polish zloty
|
||||
{ 6, '.', CF_NOEURO, "", " Lei" }, // romanian Lei
|
||||
{ 5, ' ', CF_NOEURO, "", " p" }, // russian rouble
|
||||
{ 13, '.', CF_NOEURO, "", " Kr" }, // swedish krona
|
||||
{ 1, ' ', CF_NOEURO, "", "" }, // custom currency
|
||||
};
|
||||
|
||||
const StringID _currency_string_list[] = {
|
||||
STR_CURR_GBP,
|
||||
STR_CURR_USD,
|
||||
STR_CURR_EUR,
|
||||
STR_CURR_YEN,
|
||||
STR_CURR_ATS,
|
||||
STR_CURR_BEF,
|
||||
STR_CURR_CHF,
|
||||
STR_CURR_CZK,
|
||||
STR_CURR_DEM,
|
||||
STR_CURR_DKK,
|
||||
STR_CURR_ESP,
|
||||
STR_CURR_FIM,
|
||||
STR_CURR_FRF,
|
||||
STR_CURR_GRD,
|
||||
STR_CURR_HUF,
|
||||
STR_CURR_ISK,
|
||||
STR_CURR_ITL,
|
||||
STR_CURR_NLG,
|
||||
STR_CURR_NOK,
|
||||
STR_CURR_PLN,
|
||||
STR_CURR_ROL,
|
||||
STR_CURR_RUR,
|
||||
STR_CURR_SEK,
|
||||
STR_CURR_CUSTOM,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
|
||||
// NOTE: Make sure both lists are in the same order
|
||||
// + 1 string list terminator
|
||||
assert_compile(lengthof(_currency_specs) + 1 == lengthof(_currency_string_list));
|
||||
|
||||
|
||||
// get a mask of the allowed currencies depending on the year
|
||||
uint GetMaskOfAllowedCurrencies(void)
|
||||
{
|
||||
uint mask = 0;
|
||||
uint i;
|
||||
|
||||
for (i = 0; i != lengthof(_currency_specs); i++) {
|
||||
uint16 to_euro = _currency_specs[i].to_euro;
|
||||
|
||||
if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro - MAX_YEAR_BEGIN_REAL) continue;
|
||||
if (to_euro == CF_ISEURO && _cur_year < 2000 - MAX_YEAR_BEGIN_REAL) continue;
|
||||
mask |= (1 << i);
|
||||
}
|
||||
mask |= (1 << 23); // always allow custom currency
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
void CheckSwitchToEuro(void)
|
||||
{
|
||||
if (_currency_specs[_opt.currency].to_euro != CF_NOEURO &&
|
||||
_currency_specs[_opt.currency].to_euro != CF_ISEURO &&
|
||||
MAX_YEAR_BEGIN_REAL + _cur_year >= _currency_specs[_opt.currency].to_euro) {
|
||||
_opt.currency = 2; // this is the index of euro above.
|
||||
AddNewsItem(STR_EURO_INTRODUCE, NEWS_FLAGS(NM_NORMAL, 0, NT_ECONOMY, 0), 0, 0);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef CURRENCY_H
|
||||
#define CURRENCY_H
|
||||
|
||||
enum {
|
||||
CF_NOEURO = 0,
|
||||
CF_ISEURO = 1,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 rate;
|
||||
char separator;
|
||||
uint16 to_euro;
|
||||
char prefix[16];
|
||||
char suffix[16];
|
||||
} CurrencySpec;
|
||||
|
||||
extern CurrencySpec _currency_specs[];
|
||||
extern const StringID _currency_string_list[];
|
||||
|
||||
// XXX small hack, but makes the rest of the code a bit nicer to read
|
||||
#define _custom_currency (_currency_specs[23])
|
||||
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
|
||||
|
||||
uint GetMaskOfAllowedCurrencies(void);
|
||||
void CheckSwitchToEuro(void);
|
||||
|
||||
#endif /* CURRENCY_H */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25
-78
@@ -1,19 +1,13 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file debug.cpp */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "openttd.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "string_func.h"
|
||||
#include "network/core/core.h"
|
||||
|
||||
#if defined(ENABLE_NETWORK)
|
||||
SOCKET _debug_socket = INVALID_SOCKET;
|
||||
#endif /* ENABLE_NETWORK */
|
||||
#include "functions.h"
|
||||
#include "string.h"
|
||||
|
||||
int _debug_ai_level;
|
||||
int _debug_driver_level;
|
||||
@@ -22,20 +16,28 @@ int _debug_map_level;
|
||||
int _debug_misc_level;
|
||||
int _debug_ms_level;
|
||||
int _debug_net_level;
|
||||
int _debug_sprite_level;
|
||||
int _debug_spritecache_level;
|
||||
int _debug_oldloader_level;
|
||||
int _debug_ntp_level;
|
||||
int _debug_npf_level;
|
||||
int _debug_yapf_level;
|
||||
int _debug_freetype_level;
|
||||
int _debug_sl_level;
|
||||
int _debug_station_level;
|
||||
|
||||
|
||||
struct DebugLevel {
|
||||
void CDECL debug(const char *s, ...)
|
||||
{
|
||||
va_list va;
|
||||
char buf[1024];
|
||||
|
||||
va_start(va, s);
|
||||
vsnprintf(buf, lengthof(buf), s, va);
|
||||
va_end(va);
|
||||
fprintf(stderr, "dbg: %s\n", buf);
|
||||
IConsoleDebug(buf);
|
||||
}
|
||||
|
||||
typedef struct DebugLevel {
|
||||
const char *name;
|
||||
int *level;
|
||||
};
|
||||
} DebugLevel;
|
||||
|
||||
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
|
||||
static const DebugLevel debug_level[] = {
|
||||
@@ -46,58 +48,20 @@ struct DebugLevel {
|
||||
DEBUG_LEVEL(misc),
|
||||
DEBUG_LEVEL(ms),
|
||||
DEBUG_LEVEL(net),
|
||||
DEBUG_LEVEL(sprite),
|
||||
DEBUG_LEVEL(spritecache),
|
||||
DEBUG_LEVEL(oldloader),
|
||||
DEBUG_LEVEL(ntp),
|
||||
DEBUG_LEVEL(npf),
|
||||
DEBUG_LEVEL(yapf),
|
||||
DEBUG_LEVEL(freetype),
|
||||
DEBUG_LEVEL(sl),
|
||||
DEBUG_LEVEL(station),
|
||||
DEBUG_LEVEL(npf)
|
||||
};
|
||||
#undef DEBUG_LEVEL
|
||||
|
||||
#if !defined(NO_DEBUG_MESSAGES)
|
||||
|
||||
void CDECL debug(const char *dbg, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, dbg);
|
||||
const char *s;
|
||||
char buf[1024];
|
||||
|
||||
s = va_arg(va, const char*);
|
||||
vsnprintf(buf, lengthof(buf), s, va);
|
||||
va_end(va);
|
||||
#if defined(ENABLE_NETWORK)
|
||||
if (_debug_socket != INVALID_SOCKET) {
|
||||
char buf2[lengthof(buf) + 32];
|
||||
|
||||
snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
|
||||
send(_debug_socket, buf2, strlen(buf2), 0);
|
||||
} else
|
||||
#endif /* ENABLE_NETWORK */
|
||||
{
|
||||
#if defined(WINCE)
|
||||
/* We need to do OTTD2FS twice, but as it uses a static buffer, we need to store one temporary */
|
||||
TCHAR tbuf[512];
|
||||
_sntprintf(tbuf, sizeof(tbuf), _T("%s"), OTTD2FS(dbg));
|
||||
NKDbgPrintfW(_T("dbg: [%s] %s\n"), tbuf, OTTD2FS(buf));
|
||||
#else
|
||||
fprintf(stderr, "dbg: [%s] %s\n", dbg, buf);
|
||||
#endif
|
||||
IConsoleDebug(dbg, buf);
|
||||
}
|
||||
}
|
||||
#endif /* NO_DEBUG_MESSAGES */
|
||||
|
||||
void SetDebugString(const char *s)
|
||||
{
|
||||
int v;
|
||||
char *end;
|
||||
const char *t;
|
||||
|
||||
/* global debugging level? */
|
||||
// global debugging level?
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
const DebugLevel *i;
|
||||
|
||||
@@ -107,19 +71,19 @@ void SetDebugString(const char *s)
|
||||
for (i = debug_level; i != endof(debug_level); ++i) *i->level = v;
|
||||
}
|
||||
|
||||
/* individual levels */
|
||||
// individual levels
|
||||
for (;;) {
|
||||
const DebugLevel *i;
|
||||
int *p;
|
||||
|
||||
/* skip delimiters */
|
||||
// skip delimiters
|
||||
while (*s == ' ' || *s == ',' || *s == '\t') s++;
|
||||
if (*s == '\0') break;
|
||||
|
||||
t = s;
|
||||
while (*s >= 'a' && *s <= 'z') s++;
|
||||
|
||||
/* check debugging levels */
|
||||
// check debugging levels
|
||||
p = NULL;
|
||||
for (i = debug_level; i != endof(debug_level); ++i)
|
||||
if (s == t + strlen(i->name) && strncmp(t, i->name, s - t) == 0) {
|
||||
@@ -143,10 +107,10 @@ void SetDebugString(const char *s)
|
||||
* Just return a string with the values of all the debug categorites
|
||||
* @return string with debug-levels
|
||||
*/
|
||||
const char *GetDebugString()
|
||||
const char *GetDebugString(void)
|
||||
{
|
||||
const DebugLevel *i;
|
||||
static char dbgstr[150];
|
||||
static char dbgstr[100];
|
||||
char dbgval[20];
|
||||
|
||||
memset(dbgstr, 0, sizeof(dbgstr));
|
||||
@@ -160,20 +124,3 @@ const char *GetDebugString()
|
||||
|
||||
return dbgstr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DUMP_COMMANDS
|
||||
#include "fileio.h"
|
||||
|
||||
void CDECL DebugDumpCommands(const char *s, ...)
|
||||
{
|
||||
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
|
||||
if (f == NULL) return;
|
||||
|
||||
va_list va;
|
||||
va_start(va, s);
|
||||
vfprintf(f, s, va);
|
||||
va_end(va);
|
||||
|
||||
fflush(f);
|
||||
}
|
||||
#endif /* DEBUG_DUMP_COMMANDS */
|
||||
@@ -0,0 +1,29 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#ifdef NO_DEBUG_MESSAGES
|
||||
#define DEBUG(name, level)
|
||||
#else
|
||||
#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug
|
||||
|
||||
extern int _debug_ai_level;
|
||||
extern int _debug_driver_level;
|
||||
extern int _debug_grf_level;
|
||||
extern int _debug_map_level;
|
||||
extern int _debug_misc_level;
|
||||
extern int _debug_ms_level;
|
||||
extern int _debug_net_level;
|
||||
extern int _debug_spritecache_level;
|
||||
extern int _debug_oldloader_level;
|
||||
extern int _debug_ntp_level;
|
||||
extern int _debug_npf_level;
|
||||
#endif
|
||||
|
||||
void CDECL debug(const char *s, ...);
|
||||
|
||||
void SetDebugString(const char *s);
|
||||
const char *GetDebugString(void);
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
@@ -1,7 +1,5 @@
|
||||
/* $Id$ */
|
||||
|
||||
/** @file dedicated.cpp */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
@@ -14,15 +12,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(SUNOS) && !defined(_LP64) && !defined(_I32LPx)
|
||||
/* Solaris has, in certain situation, pid_t defined as long, while in other
|
||||
* cases it has it defined as int... this handles all cases nicely. */
|
||||
# define PRINTF_PID_T "%ld"
|
||||
#else
|
||||
# define PRINTF_PID_T "%d"
|
||||
#endif
|
||||
|
||||
void DedicatedFork()
|
||||
void DedicatedFork(void)
|
||||
{
|
||||
/* Fork the program */
|
||||
pid_t pid = fork();
|
||||
@@ -53,9 +43,9 @@ void DedicatedFork()
|
||||
}
|
||||
|
||||
default:
|
||||
/* We're the parent */
|
||||
// We're the parent
|
||||
printf("Loading dedicated server...\n");
|
||||
printf(" - Forked to background with pid " PRINTF_PID_T "\n", pid);
|
||||
printf(" - Forked to background with pid %d\n", pid);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -63,7 +53,6 @@ void DedicatedFork()
|
||||
|
||||
#else
|
||||
|
||||
/** Empty helper function call for NOT(UNIX and not MORPHOS) systems */
|
||||
void DedicatedFork() {}
|
||||
void DedicatedFork(void) {}
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
@@ -0,0 +1,145 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "depot.h"
|
||||
#include "functions.h"
|
||||
#include "tile.h"
|
||||
#include "map.h"
|
||||
#include "table/strings.h"
|
||||
#include "saveload.h"
|
||||
#include "order.h"
|
||||
|
||||
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(TileIndex 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(TileIndex 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 SaveLoad _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},
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DEPOT_H
|
||||
#define DEPOT_H
|
||||
|
||||
/** @file depot.h Header files for depots (not hangars)
|
||||
* @see depot.c */
|
||||
|
||||
#include "pool.h"
|
||||
#include "tile.h"
|
||||
#include "variables.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) && (_m[tile].m5 & 0xFC) == 0xC0;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
return IsTileType(tile, MP_STREET) && (_m[tile].m5 & 0xF0) == 0x20;
|
||||
|
||||
case TRANSPORT_WATER:
|
||||
return IsTileType(tile, MP_WATER) && (_m[tile].m5 & ~3) == 0x80;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direction the exit of the depot on the given tile is facing.
|
||||
*/
|
||||
static inline DiagDirection 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 (DiagDirection)GB(_m[tile].m5, 0, 2);
|
||||
case TRANSPORT_WATER:
|
||||
/* Water is stubborn, it stores the directions in a different order. */
|
||||
switch (GB(_m[tile].m5, 0, 2)) {
|
||||
case 0: return DIAGDIR_NE;
|
||||
case 1: return DIAGDIR_SW;
|
||||
case 2: return DIAGDIR_NW;
|
||||
case 3: return DIAGDIR_SE;
|
||||
}
|
||||
default:
|
||||
return INVALID_DIAGDIR; /* Not reached */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Find out if the slope of the tile is suitable to build a depot of given direction
|
||||
@param direction The direction in which the depot's exit points. Starts with 0 as NE and goes Clockwise
|
||||
@param tileh The slope of the tile in question
|
||||
@return true if the construction is possible
|
||||
|
||||
|
||||
This is checked by the ugly 0x4C >> direction magic, which does the following:
|
||||
0x4C is 0100 1100 and tileh has only bits 0..3 set (steep tiles are ruled out)
|
||||
So: for direction (only the significant bits are shown)<p>
|
||||
00 (exit towards NE) we need either bit 2 or 3 set in tileh: 0x4C >> 0 = 1100<p>
|
||||
01 (exit towards SE) we need either bit 1 or 2 set in tileh: 0x4C >> 1 = 0110<p>
|
||||
02 (exit towards SW) we need either bit 0 or 1 set in tileh: 0x4C >> 2 = 0011<p>
|
||||
03 (exit towards NW) we need either bit 0 or 4 set in tileh: 0x4C >> 3 = 1001<p>
|
||||
So ((0x4C >> p2) & tileh) determines whether the depot can be built on the current tileh
|
||||
*/
|
||||
static inline bool CanBuildDepotByTileh(uint32 direction, uint tileh)
|
||||
{
|
||||
return (0x4C >> direction) & tileh;
|
||||
}
|
||||
|
||||
|
||||
Depot *GetDepotByTile(TileIndex tile);
|
||||
void InitializeDepot(void);
|
||||
Depot *AllocateDepot(void);
|
||||
void DoDeleteDepot(TileIndex tile);
|
||||
|
||||
#endif /* DEPOT_H */
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DIRECTION_H
|
||||
#define DIRECTION_H
|
||||
|
||||
|
||||
/* the 2 axis */
|
||||
typedef enum Axis {
|
||||
AXIS_X = 0,
|
||||
AXIS_Y = 1,
|
||||
AXIS_END
|
||||
} Axis;
|
||||
|
||||
|
||||
static inline Axis DiagDirToAxis(uint d)
|
||||
{
|
||||
return (Axis)(d & 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Converts an Axis to a DiagDirection
|
||||
* Points always in the positive direction, i.e. S[EW]
|
||||
*/
|
||||
static inline uint AxisToDiagDir(Axis a)
|
||||
{
|
||||
return (uint)(2 - a);
|
||||
}
|
||||
|
||||
#endif
|
||||
+992
@@ -0,0 +1,992 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "vehicle.h"
|
||||
#include "command.h"
|
||||
#include "news.h"
|
||||
#include "station.h"
|
||||
#include "waypoint.h"
|
||||
#include "town.h"
|
||||
#include "industry.h"
|
||||
#include "player.h"
|
||||
#include "airport_movement.h"
|
||||
#include "sound.h"
|
||||
#include "variables.h"
|
||||
#include "table/sprites.h"
|
||||
|
||||
static void DisasterClearSquare(TileIndex tile)
|
||||
{
|
||||
if (!EnsureNoVehicle(tile)) return;
|
||||
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_RAILWAY:
|
||||
if (IS_HUMAN_PLAYER(GetTileOwner(tile)) && !IsRailWaypoint(tile)) DoClearSquare(tile);
|
||||
break;
|
||||
|
||||
case MP_HOUSE: {
|
||||
PlayerID p = _current_player;
|
||||
_current_player = OWNER_NONE;
|
||||
DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
|
||||
_current_player = p;
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_TREES:
|
||||
case MP_CLEAR:
|
||||
DoClearSquare(tile);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const SpriteID _disaster_images_1[] = {0xF41,0xF41,0xF41,0xF41,0xF41,0xF41,0xF41,0xF41};
|
||||
static const SpriteID _disaster_images_2[] = {0xF44,0xF44,0xF44,0xF44,0xF44,0xF44,0xF44,0xF44};
|
||||
static const SpriteID _disaster_images_3[] = {0xF4E,0xF4E,0xF4E,0xF4E,0xF4E,0xF4E,0xF4E,0xF4E};
|
||||
static const SpriteID _disaster_images_4[] = {0xF46,0xF46,0xF47,0xF47,0xF48,0xF48,0xF49,0xF49};
|
||||
static const SpriteID _disaster_images_5[] = {0xF4A,0xF4A,0xF4B,0xF4B,0xF4C,0xF4C,0xF4D,0xF4D};
|
||||
static const SpriteID _disaster_images_6[] = {0xF50,0xF50,0xF50,0xF50,0xF50,0xF50,0xF50,0xF50};
|
||||
static const SpriteID _disaster_images_7[] = {0xF51,0xF51,0xF51,0xF51,0xF51,0xF51,0xF51,0xF51};
|
||||
static const SpriteID _disaster_images_8[] = {0xF52,0xF52,0xF52,0xF52,0xF52,0xF52,0xF52,0xF52};
|
||||
static const SpriteID _disaster_images_9[] = {0xF3E,0xF3E,0xF3E,0xF3E,0xF3E,0xF3E,0xF3E,0xF3E};
|
||||
|
||||
static const SpriteID * const _disaster_images[] = {
|
||||
_disaster_images_1,_disaster_images_1,
|
||||
_disaster_images_2,_disaster_images_2,
|
||||
_disaster_images_3,_disaster_images_3,
|
||||
_disaster_images_8,_disaster_images_8,_disaster_images_9,
|
||||
_disaster_images_6,_disaster_images_6,
|
||||
_disaster_images_7,_disaster_images_7,
|
||||
_disaster_images_4,_disaster_images_5,
|
||||
};
|
||||
|
||||
static void DisasterVehicleUpdateImage(Vehicle *v)
|
||||
{
|
||||
int img = v->u.disaster.image_override;
|
||||
if (img == 0)
|
||||
img = _disaster_images[v->subtype][v->direction];
|
||||
v->cur_image = img;
|
||||
}
|
||||
|
||||
static void InitializeDisasterVehicle(Vehicle *v, int x, int y, byte z, byte direction, byte subtype)
|
||||
{
|
||||
v->type = VEH_Disaster;
|
||||
v->x_pos = x;
|
||||
v->y_pos = y;
|
||||
v->z_pos = z;
|
||||
v->tile = TileVirtXY(x, y);
|
||||
v->direction = direction;
|
||||
v->subtype = subtype;
|
||||
v->x_offs = -1;
|
||||
v->y_offs = -1;
|
||||
v->sprite_width = 2;
|
||||
v->sprite_height = 2;
|
||||
v->z_height = 5;
|
||||
v->owner = OWNER_NONE;
|
||||
v->vehstatus = VS_UNCLICKABLE;
|
||||
v->u.disaster.image_override = 0;
|
||||
v->current_order.type = OT_NOTHING;
|
||||
v->current_order.flags = 0;
|
||||
v->current_order.station = 0;
|
||||
|
||||
DisasterVehicleUpdateImage(v);
|
||||
VehiclePositionChanged(v);
|
||||
BeginVehicleMove(v);
|
||||
EndVehicleMove(v);
|
||||
}
|
||||
|
||||
static void DeleteDisasterVeh(Vehicle *v)
|
||||
{
|
||||
DeleteVehicleChain(v);
|
||||
}
|
||||
|
||||
static void SetDisasterVehiclePos(Vehicle *v, int x, int y, byte z)
|
||||
{
|
||||
Vehicle *u;
|
||||
int yt;
|
||||
|
||||
BeginVehicleMove(v);
|
||||
v->x_pos = x;
|
||||
v->y_pos = y;
|
||||
v->z_pos = z;
|
||||
v->tile = TileVirtXY(x, y);
|
||||
|
||||
DisasterVehicleUpdateImage(v);
|
||||
VehiclePositionChanged(v);
|
||||
EndVehicleMove(v);
|
||||
|
||||
if ( (u=v->next) != NULL) {
|
||||
BeginVehicleMove(u);
|
||||
|
||||
u->x_pos = x;
|
||||
u->y_pos = yt = y - 1 - (max(z - GetSlopeZ(x, y-1), 0) >> 3);
|
||||
u->z_pos = GetSlopeZ(x,yt);
|
||||
u->direction = v->direction;
|
||||
|
||||
DisasterVehicleUpdateImage(u);
|
||||
VehiclePositionChanged(u);
|
||||
EndVehicleMove(u);
|
||||
|
||||
if ( (u=u->next) != NULL) {
|
||||
BeginVehicleMove(u);
|
||||
u->x_pos = x;
|
||||
u->y_pos = y;
|
||||
u->z_pos = z + 5;
|
||||
VehiclePositionChanged(u);
|
||||
EndVehicleMove(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DisasterTick_Zeppeliner(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
Station *st;
|
||||
int x,y;
|
||||
byte z;
|
||||
TileIndex tile;
|
||||
|
||||
++v->tick_counter;
|
||||
|
||||
if (v->current_order.station < 2) {
|
||||
if (v->tick_counter&1)
|
||||
return;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (v->current_order.station == 1) {
|
||||
if (++v->age == 38) {
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
if ((v->tick_counter&7)==0) {
|
||||
CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE);
|
||||
}
|
||||
} else if (v->current_order.station == 0) {
|
||||
tile = v->tile; /**/
|
||||
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_m[tile].m5, 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(GetTileOwner(tile))) {
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
|
||||
SetDParam(0, _m[tile].m2);
|
||||
AddNewsItem(STR_B000_ZEPPELIN_DISASTER_AT,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0),
|
||||
v->index,
|
||||
0);
|
||||
}
|
||||
}
|
||||
if (v->y_pos >= ((int)MapSizeY() + 9) * 16 - 1)
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->current_order.station > 2) {
|
||||
if (++v->age <= 13320)
|
||||
return;
|
||||
|
||||
tile = v->tile; /**/
|
||||
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_m[tile].m5, 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(GetTileOwner(tile))) {
|
||||
st = GetStation(_m[tile].m2);
|
||||
CLRBITS(st->airport_flags, RUNWAY_IN_block);
|
||||
}
|
||||
|
||||
SetDisasterVehiclePos(v, v->x_pos, v->y_pos, v->z_pos);
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
x = v->x_pos;
|
||||
y = v->y_pos;
|
||||
z = GetSlopeZ(x,y);
|
||||
if (z < v->z_pos)
|
||||
z = v->z_pos - 1;
|
||||
SetDisasterVehiclePos(v, x, y, z);
|
||||
|
||||
if (++v->age == 1) {
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||
v->u.disaster.image_override = SPR_BLIMP_CRASHING;
|
||||
} else if (v->age == 70) {
|
||||
v->u.disaster.image_override = SPR_BLIMP_CRASHED;
|
||||
} else if (v->age <= 300) {
|
||||
if (!(v->tick_counter&7)) {
|
||||
uint32 r = Random();
|
||||
|
||||
CreateEffectVehicleRel(v,
|
||||
GB(r, 0, 4) - 7,
|
||||
GB(r, 4, 4) - 7,
|
||||
GB(r, 8, 3) + 5,
|
||||
EV_EXPLOSION_SMALL);
|
||||
}
|
||||
} else if (v->age == 350) {
|
||||
v->current_order.station = 3;
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
tile = v->tile;/**/
|
||||
if (IsValidTile(tile) &&
|
||||
IsTileType(tile, MP_STATION) &&
|
||||
IS_BYTE_INSIDE(_m[tile].m5, 8, 0x43) &&
|
||||
IS_HUMAN_PLAYER(GetTileOwner(tile))) {
|
||||
|
||||
st = GetStation(_m[tile].m2);
|
||||
SETBITS(st->airport_flags, RUNWAY_IN_block);
|
||||
}
|
||||
}
|
||||
|
||||
// UFO starts in the middle, and flies around a bit until it locates
|
||||
// a road vehicle which it targets.
|
||||
static void DisasterTick_UFO(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
Vehicle *u;
|
||||
uint dist;
|
||||
byte z;
|
||||
|
||||
v->u.disaster.image_override = (++v->tick_counter & 8) ? SPR_UFO_SMALL_SCOUT_DARKER : SPR_UFO_SMALL_SCOUT;
|
||||
|
||||
if (v->current_order.station == 0) {
|
||||
// fly around randomly
|
||||
int x = TileX(v->dest_tile) * 16;
|
||||
int y = TileY(v->dest_tile) * 16;
|
||||
if (abs(x - v->x_pos) + abs(y - v->y_pos) >= 16) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
return;
|
||||
}
|
||||
if (++v->age < 6) {
|
||||
v->dest_tile = RandomTile();
|
||||
return;
|
||||
}
|
||||
v->current_order.station = 1;
|
||||
|
||||
FOR_ALL_VEHICLES(u) {
|
||||
if (u->type == VEH_Road && IS_HUMAN_PLAYER(u->owner)) {
|
||||
v->dest_tile = u->index;
|
||||
v->age = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteDisasterVeh(v);
|
||||
} else {
|
||||
// target a vehicle
|
||||
u = GetVehicle(v->dest_tile);
|
||||
if (u->type != VEH_Road) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
dist = abs(v->x_pos - u->x_pos) + abs(v->y_pos - u->y_pos);
|
||||
|
||||
if (dist < 16 && !(u->vehstatus&VS_HIDDEN) && u->breakdown_ctr==0) {
|
||||
u->breakdown_ctr = 3;
|
||||
u->breakdown_delay = 140;
|
||||
}
|
||||
|
||||
v->direction = GetDirectionTowards(v, u->x_pos, u->y_pos);
|
||||
GetNewVehiclePos(v, &gp);
|
||||
|
||||
z = v->z_pos;
|
||||
if (dist <= 16 && z > u->z_pos) z--;
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, z);
|
||||
|
||||
if (z <= u->z_pos && (u->vehstatus&VS_HIDDEN)==0) {
|
||||
v->age++;
|
||||
if (u->u.road.crashed_ctr == 0) {
|
||||
u->u.road.crashed_ctr++;
|
||||
u->vehstatus |= VS_CRASHED;
|
||||
|
||||
AddNewsItem(STR_B001_ROAD_VEHICLE_DESTROYED,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0),
|
||||
u->index,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
// destroy?
|
||||
if (v->age > 50) {
|
||||
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||
DeleteDisasterVeh(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DestructIndustry(Industry *i)
|
||||
{
|
||||
TileIndex tile;
|
||||
|
||||
for (tile = 0; tile != MapSize(); tile++) {
|
||||
if (IsTileType(tile, MP_INDUSTRY) && _m[tile].m2 == i->index) {
|
||||
_m[tile].m1 = 0;
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Airplane which destroys an oil refinery
|
||||
static void DisasterTick_2(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
v->tick_counter++;
|
||||
v->u.disaster.image_override =
|
||||
(v->current_order.station == 1 && v->tick_counter & 4) ? SPR_F_15_FIRING : 0;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (gp.x < -160) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->current_order.station == 2) {
|
||||
if (!(v->tick_counter&3)) {
|
||||
Industry *i = GetIndustry(v->dest_tile);
|
||||
int x = TileX(i->xy) * 16;
|
||||
int y = TileY(i->xy) * 16;
|
||||
uint32 r = Random();
|
||||
|
||||
CreateEffectVehicleAbove(
|
||||
GB(r, 0, 6) + x,
|
||||
GB(r, 6, 6) + y,
|
||||
GB(r, 12, 4),
|
||||
EV_EXPLOSION_SMALL);
|
||||
|
||||
if (++v->age >= 55)
|
||||
v->current_order.station = 3;
|
||||
}
|
||||
} else if (v->current_order.station == 1) {
|
||||
if (++v->age == 112) {
|
||||
Industry *i;
|
||||
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
|
||||
i = GetIndustry(v->dest_tile);
|
||||
DestructIndustry(i);
|
||||
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B002_OIL_REFINERY_EXPLOSION, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0);
|
||||
SndPlayTileFx(SND_12_EXPLOSION, i->xy);
|
||||
}
|
||||
} else if (v->current_order.station == 0) {
|
||||
int x,y;
|
||||
TileIndex tile;
|
||||
int ind;
|
||||
|
||||
x = v->x_pos - 15*16;
|
||||
y = v->y_pos;
|
||||
|
||||
if ( (uint)x > MapMaxX() * 16-1)
|
||||
return;
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
if (!IsTileType(tile, MP_INDUSTRY))
|
||||
return;
|
||||
|
||||
v->dest_tile = ind = _m[tile].m2;
|
||||
|
||||
if (GetIndustry(ind)->type == IT_OIL_REFINERY) {
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helicopter which destroys a factory
|
||||
static void DisasterTick_3(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
v->tick_counter++;
|
||||
v->u.disaster.image_override =
|
||||
(v->current_order.station == 1 && v->tick_counter & 4) ? SPR_AH_64A_FIRING : 0;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (gp.x > (int)MapSizeX() * 16 + 9*16 - 1) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->current_order.station == 2) {
|
||||
if (!(v->tick_counter&3)) {
|
||||
Industry *i = GetIndustry(v->dest_tile);
|
||||
int x = TileX(i->xy) * 16;
|
||||
int y = TileY(i->xy) * 16;
|
||||
uint32 r = Random();
|
||||
|
||||
CreateEffectVehicleAbove(
|
||||
GB(r, 0, 6) + x,
|
||||
GB(r, 6, 6) + y,
|
||||
GB(r, 12, 4),
|
||||
EV_EXPLOSION_SMALL);
|
||||
|
||||
if (++v->age >= 55)
|
||||
v->current_order.station = 3;
|
||||
}
|
||||
} else if (v->current_order.station == 1) {
|
||||
if (++v->age == 112) {
|
||||
Industry *i;
|
||||
|
||||
v->current_order.station = 2;
|
||||
v->age = 0;
|
||||
|
||||
i = GetIndustry(v->dest_tile);
|
||||
DestructIndustry(i);
|
||||
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS, NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy, 0);
|
||||
SndPlayTileFx(SND_12_EXPLOSION, i->xy);
|
||||
}
|
||||
} else if (v->current_order.station == 0) {
|
||||
int x,y;
|
||||
TileIndex tile;
|
||||
int ind;
|
||||
|
||||
x = v->x_pos - 15*16;
|
||||
y = v->y_pos;
|
||||
|
||||
if ( (uint)x > MapMaxX() * 16-1)
|
||||
return;
|
||||
|
||||
tile = TileVirtXY(x, y);
|
||||
if (!IsTileType(tile, MP_INDUSTRY))
|
||||
return;
|
||||
|
||||
v->dest_tile = ind = _m[tile].m2;
|
||||
|
||||
if (GetIndustry(ind)->type == IT_FACTORY) {
|
||||
v->current_order.station = 1;
|
||||
v->age = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helicopter rotor blades
|
||||
static void DisasterTick_3b(Vehicle *v)
|
||||
{
|
||||
if (++v->tick_counter & 1)
|
||||
return;
|
||||
|
||||
if (++v->cur_image > SPR_ROTOR_MOVING_3) v->cur_image = SPR_ROTOR_MOVING_1;
|
||||
|
||||
VehiclePositionChanged(v);
|
||||
BeginVehicleMove(v);
|
||||
EndVehicleMove(v);
|
||||
}
|
||||
|
||||
// Big UFO which lands on a piece of rail.
|
||||
// Will be shot down by a plane
|
||||
static void DisasterTick_4(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
byte z;
|
||||
Vehicle *u,*w;
|
||||
Town *t;
|
||||
TileIndex tile;
|
||||
TileIndex tile_org;
|
||||
|
||||
v->tick_counter++;
|
||||
|
||||
if (v->current_order.station == 1) {
|
||||
int x = TileX(v->dest_tile) * 16 + 8;
|
||||
int y = TileY(v->dest_tile) * 16 + 8;
|
||||
if (abs(v->x_pos - x) + abs(v->y_pos - y) >= 8) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
return;
|
||||
}
|
||||
|
||||
z = GetSlopeZ(v->x_pos, v->y_pos);
|
||||
if (z < v->z_pos) {
|
||||
SetDisasterVehiclePos(v, v->x_pos, v->y_pos, v->z_pos - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
v->current_order.station = 2;
|
||||
|
||||
FOR_ALL_VEHICLES(u) {
|
||||
if (u->type == VEH_Train || u->type == VEH_Road) {
|
||||
if (abs(u->x_pos - v->x_pos) + abs(u->y_pos - v->y_pos) <= 12*16) {
|
||||
u->breakdown_ctr = 5;
|
||||
u->breakdown_delay = 0xF0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t = ClosestTownFromTile(v->dest_tile, (uint)-1);
|
||||
SetDParam(0, t->index);
|
||||
AddNewsItem(STR_B004_UFO_LANDS_NEAR,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ACCIDENT, 0),
|
||||
v->tile,
|
||||
0);
|
||||
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u == NULL) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeDisasterVehicle(u, -6*16, v->y_pos, 135, 5, 11);
|
||||
u->u.disaster.unk2 = v->index;
|
||||
|
||||
w = ForceAllocateSpecialVehicle();
|
||||
if (w == NULL)
|
||||
return;
|
||||
|
||||
u->next = w;
|
||||
InitializeDisasterVehicle(w, -6*16, v->y_pos, 0, 5, 12);
|
||||
w->vehstatus |= VS_DISASTER;
|
||||
} else if (v->current_order.station < 1) {
|
||||
|
||||
int x = TileX(v->dest_tile) * 16;
|
||||
int y = TileY(v->dest_tile) * 16;
|
||||
if (abs(x - v->x_pos) + abs(y - v->y_pos) >= 16) {
|
||||
v->direction = GetDirectionTowards(v, x, y);
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
return;
|
||||
}
|
||||
|
||||
if (++v->age < 6) {
|
||||
v->dest_tile = RandomTile();
|
||||
return;
|
||||
}
|
||||
v->current_order.station = 1;
|
||||
|
||||
tile_org = tile = RandomTile();
|
||||
do {
|
||||
if (IsTileType(tile, MP_RAILWAY) &&
|
||||
(_m[tile].m5 & ~3) != 0xC0 && IS_HUMAN_PLAYER(GetTileOwner(tile)))
|
||||
break;
|
||||
tile = TILE_MASK(tile+1);
|
||||
} while (tile != tile_org);
|
||||
v->dest_tile = tile;
|
||||
v->age = 0;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
// The plane which will shoot down the UFO
|
||||
static void DisasterTick_4b(Vehicle *v)
|
||||
{
|
||||
GetNewVehiclePosResult gp;
|
||||
Vehicle *u;
|
||||
int i;
|
||||
|
||||
v->tick_counter++;
|
||||
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
|
||||
if (gp.x > (int)MapSizeX() * 16 + 9*16 - 1) {
|
||||
DeleteDisasterVeh(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v->current_order.station == 0) {
|
||||
u = GetVehicle(v->u.disaster.unk2);
|
||||
if (abs(v->x_pos - u->x_pos) > 16)
|
||||
return;
|
||||
v->current_order.station = 1;
|
||||
|
||||
CreateEffectVehicleRel(u, 0, 7, 8, EV_EXPLOSION_LARGE);
|
||||
SndPlayVehicleFx(SND_12_EXPLOSION, u);
|
||||
|
||||
DeleteDisasterVeh(u);
|
||||
|
||||
for(i=0; i!=80; i++) {
|
||||
uint32 r = Random();
|
||||
CreateEffectVehicleAbove(
|
||||
GB(r, 0, 6) + v->x_pos - 32,
|
||||
GB(r, 5, 6) + v->y_pos - 32,
|
||||
0,
|
||||
EV_EXPLOSION_SMALL);
|
||||
}
|
||||
|
||||
BEGIN_TILE_LOOP(tile, 6, 6, v->tile - TileDiffXY(3, 3))
|
||||
tile = TILE_MASK(tile);
|
||||
DisasterClearSquare(tile);
|
||||
END_TILE_LOOP(tile, 6, 6, v->tile - TileDiffXY(3, 3))
|
||||
}
|
||||
}
|
||||
|
||||
// Submarine handler
|
||||
static void DisasterTick_5_and_6(Vehicle *v)
|
||||
{
|
||||
uint32 r;
|
||||
GetNewVehiclePosResult gp;
|
||||
TileIndex tile;
|
||||
|
||||
v->tick_counter++;
|
||||
|
||||
if (++v->age > 8880) {
|
||||
VehiclePositionChanged(v);
|
||||
BeginVehicleMove(v);
|
||||
EndVehicleMove(v);
|
||||
DeleteVehicle(v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(v->tick_counter&1))
|
||||
return;
|
||||
|
||||
tile = v->tile + TileOffsByDir(v->direction >> 1);
|
||||
if (IsValidTile(tile) &&
|
||||
(r=GetTileTrackStatus(tile,TRANSPORT_WATER),(byte)(r+(r >> 8)) == 0x3F) &&
|
||||
!CHANCE16(1,90)) {
|
||||
GetNewVehiclePos(v, &gp);
|
||||
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
|
||||
return;
|
||||
}
|
||||
|
||||
v->direction = (v->direction + (GB(Random(), 0, 1) ? 2 : -2)) & 7;
|
||||
}
|
||||
|
||||
|
||||
static void DisasterTick_NULL(Vehicle *v) {}
|
||||
typedef void DisasterVehicleTickProc(Vehicle *v);
|
||||
|
||||
static DisasterVehicleTickProc * const _disastervehicle_tick_procs[] = {
|
||||
DisasterTick_Zeppeliner,DisasterTick_NULL,
|
||||
DisasterTick_UFO,DisasterTick_NULL,
|
||||
DisasterTick_2,DisasterTick_NULL,
|
||||
DisasterTick_3,DisasterTick_NULL,DisasterTick_3b,
|
||||
DisasterTick_4,DisasterTick_NULL,
|
||||
DisasterTick_4b,DisasterTick_NULL,
|
||||
DisasterTick_5_and_6,
|
||||
DisasterTick_5_and_6,
|
||||
};
|
||||
|
||||
|
||||
void DisasterVehicle_Tick(Vehicle *v)
|
||||
{
|
||||
_disastervehicle_tick_procs[v->subtype](v);
|
||||
}
|
||||
|
||||
|
||||
void OnNewDay_DisasterVehicle(Vehicle *v)
|
||||
{
|
||||
// not used
|
||||
}
|
||||
|
||||
typedef void DisasterInitProc(void);
|
||||
|
||||
// Zeppeliner which crashes on a small airport
|
||||
static void Disaster0_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
Station *st;
|
||||
int x;
|
||||
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
/* Pick a random place, unless we find
|
||||
a small airport */
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
FOR_ALL_STATIONS(st) {
|
||||
if (st->xy && st->airport_tile != 0 &&
|
||||
st->airport_type <= 1 &&
|
||||
IS_HUMAN_PLAYER(st->owner)) {
|
||||
x = (TileX(st->xy) + 2) * 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InitializeDisasterVehicle(v, x, 0, 135, 3, 0);
|
||||
|
||||
// Allocate shadow too?
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u, x, 0, 0, 3, 1);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster1_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
int x;
|
||||
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
InitializeDisasterVehicle(v, x, 0, 135, 3, 2);
|
||||
v->dest_tile = TileXY(MapSizeX() / 2, MapSizeY() / 2);
|
||||
v->age = 0;
|
||||
|
||||
// Allocate shadow too?
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u,x,0,0,3,3);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster2_Init(void)
|
||||
{
|
||||
Industry *i, *found;
|
||||
Vehicle *v,*u;
|
||||
int x,y;
|
||||
|
||||
found = NULL;
|
||||
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 &&
|
||||
i->type == IT_OIL_REFINERY &&
|
||||
(found==NULL || CHANCE16(1,2))) {
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == NULL)
|
||||
return;
|
||||
|
||||
v = ForceAllocateSpecialVehicle();
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = (MapSizeX() + 9) * 16 - 1;
|
||||
y = TileY(found->xy) * 16 + 37;
|
||||
|
||||
InitializeDisasterVehicle(v,x,y, 135,1,4);
|
||||
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u,x,y,0,3,5);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster3_Init(void)
|
||||
{
|
||||
Industry *i, *found;
|
||||
Vehicle *v,*u,*w;
|
||||
int x,y;
|
||||
|
||||
found = NULL;
|
||||
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 &&
|
||||
i->type == IT_FACTORY &&
|
||||
(found==NULL || CHANCE16(1,2))) {
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == NULL)
|
||||
return;
|
||||
|
||||
v = ForceAllocateSpecialVehicle();
|
||||
if (v == NULL)
|
||||
return;
|
||||
|
||||
x = -16 * 16;
|
||||
y = TileY(found->xy) * 16 + 37;
|
||||
|
||||
InitializeDisasterVehicle(v,x,y, 135,5,6);
|
||||
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u,x,y,0,5,7);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
|
||||
w = ForceAllocateSpecialVehicle();
|
||||
if (w != NULL) {
|
||||
u->next = w;
|
||||
InitializeDisasterVehicle(w,x,y,140,5,8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Disaster4_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle(), *u;
|
||||
int x,y;
|
||||
|
||||
if (v == NULL) return;
|
||||
|
||||
x = TileX(Random()) * 16 + 8;
|
||||
|
||||
y = MapMaxX() * 16 - 1;
|
||||
InitializeDisasterVehicle(v, x, y, 135, 7, 9);
|
||||
v->dest_tile = TileXY(MapSizeX() / 2, MapSizeY() / 2);
|
||||
v->age = 0;
|
||||
|
||||
// Allocate shadow too?
|
||||
u = ForceAllocateSpecialVehicle();
|
||||
if (u != NULL) {
|
||||
v->next = u;
|
||||
InitializeDisasterVehicle(u,x,y,0,7,10);
|
||||
u->vehstatus |= VS_DISASTER;
|
||||
}
|
||||
}
|
||||
|
||||
// Submarine type 1
|
||||
static void Disaster5_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle();
|
||||
int x,y;
|
||||
byte dir;
|
||||
uint32 r;
|
||||
|
||||
if (v == NULL) return;
|
||||
|
||||
r = Random();
|
||||
x = TileX(r) * 16 + 8;
|
||||
|
||||
y = 8;
|
||||
dir = 3;
|
||||
if (r & 0x80000000) { y = MapMaxX() * 16 - 8 - 1; dir = 7; }
|
||||
InitializeDisasterVehicle(v, x, y, 0, dir,13);
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
// Submarine type 2
|
||||
static void Disaster6_Init(void)
|
||||
{
|
||||
Vehicle *v = ForceAllocateSpecialVehicle();
|
||||
int x,y;
|
||||
byte dir;
|
||||
uint32 r;
|
||||
|
||||
if (v == NULL) return;
|
||||
|
||||
r = Random();
|
||||
x = TileX(r) * 16 + 8;
|
||||
|
||||
y = 8;
|
||||
dir = 3;
|
||||
if (r & 0x80000000) { y = MapMaxX() * 16 - 8 - 1; dir = 7; }
|
||||
InitializeDisasterVehicle(v, x, y, 0, dir,14);
|
||||
v->age = 0;
|
||||
}
|
||||
|
||||
static void Disaster7_Init(void)
|
||||
{
|
||||
int index = GB(Random(), 0, 4);
|
||||
Industry *i;
|
||||
uint m;
|
||||
|
||||
for (m = 0; m < 15; m++) {
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->xy != 0 && i->type == IT_COAL_MINE && --index < 0) {
|
||||
|
||||
SetDParam(0, i->town->index);
|
||||
AddNewsItem(STR_B005_COAL_MINE_SUBSIDENCE_LEAVES,
|
||||
NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy + TileDiffXY(1, 1), 0);
|
||||
|
||||
{
|
||||
TileIndex tile = i->xy;
|
||||
TileIndexDiff step = TileOffsByDir(GB(Random(), 0, 2));
|
||||
uint n;
|
||||
|
||||
for (n = 0; n < 30; n++) {
|
||||
DisasterClearSquare(tile);
|
||||
tile = TILE_MASK(tile + step);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DisasterInitProc * const _disaster_initprocs[] = {
|
||||
Disaster0_Init,
|
||||
Disaster1_Init,
|
||||
Disaster2_Init,
|
||||
Disaster3_Init,
|
||||
Disaster4_Init,
|
||||
Disaster5_Init,
|
||||
Disaster6_Init,
|
||||
Disaster7_Init,
|
||||
};
|
||||
|
||||
#define MK(a, b) { (a) - MAX_YEAR_BEGIN_REAL, (b) - MAX_YEAR_BEGIN_REAL }
|
||||
static const struct {
|
||||
byte min;
|
||||
byte max;
|
||||
} _dis_years[] = {
|
||||
MK(1930, 1955),
|
||||
MK(1940, 1970),
|
||||
MK(1960, 1990),
|
||||
MK(1970, 2000),
|
||||
MK(2000, 2100),
|
||||
MK(1940, 1965),
|
||||
MK(1975, 2010),
|
||||
MK(1950, 1985)
|
||||
};
|
||||
#undef MK
|
||||
|
||||
|
||||
static void DoDisaster(void)
|
||||
{
|
||||
byte buf[lengthof(_dis_years)];
|
||||
byte year = _cur_year;
|
||||
uint i;
|
||||
uint j;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i != lengthof(_dis_years); i++) {
|
||||
if (year >= _dis_years[i].min && year < _dis_years[i].max) buf[j++] = i;
|
||||
}
|
||||
|
||||
if (j == 0) return;
|
||||
|
||||
_disaster_initprocs[buf[RandomRange(j)]]();
|
||||
}
|
||||
|
||||
|
||||
static void ResetDisasterDelay(void)
|
||||
{
|
||||
_disaster_delay = GB(Random(), 0, 9) + 730;
|
||||
}
|
||||
|
||||
void DisasterDailyLoop(void)
|
||||
{
|
||||
if (--_disaster_delay != 0) return;
|
||||
|
||||
ResetDisasterDelay();
|
||||
|
||||
if (_opt.diff.disasters != 0) DoDisaster();
|
||||
}
|
||||
|
||||
void StartupDisasters(void)
|
||||
{
|
||||
ResetDisasterDelay();
|
||||
}
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "map.h"
|
||||
#include "window.h"
|
||||
#include "station.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "variables.h"
|
||||
|
||||
static void ShowBuildDockStationPicker(void);
|
||||
static void ShowBuildDocksDepotPicker(void);
|
||||
|
||||
static byte _ship_depot_direction;
|
||||
|
||||
void CcBuildDocks(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
}
|
||||
}
|
||||
|
||||
void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
|
||||
}
|
||||
|
||||
|
||||
static void PlaceDocks_Dock(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_Depot(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_AUTO | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT));
|
||||
}
|
||||
|
||||
static void PlaceDocks_Buoy(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
|
||||
}
|
||||
|
||||
static void PlaceDocks_DemolishArea(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildCanal(TileIndex tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_X_OR_Y);
|
||||
}
|
||||
|
||||
static void PlaceDocks_BuildLock(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
|
||||
}
|
||||
|
||||
|
||||
static void BuildDocksClick_Canal(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 3, SPR_CURSOR_CANAL, 1, PlaceDocks_BuildCanal);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Lock(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 4, SPR_CURSOR_LOCK, 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, SPR_CURSOR_SHIP_DEPOT, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Dock(Window *w)
|
||||
{
|
||||
|
||||
if (HandlePlacePushButton(w, 8, SPR_CURSOR_DOCK, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Buoy(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 9, SPR_CURSOR_BOUY, 1, PlaceDocks_Buoy);
|
||||
}
|
||||
|
||||
static void BuildDocksClick_Landscaping(Window *w)
|
||||
{
|
||||
ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
typedef void OnButtonClick(Window *w);
|
||||
static OnButtonClick * const _build_docks_button_proc[] = {
|
||||
BuildDocksClick_Canal,
|
||||
BuildDocksClick_Lock,
|
||||
NULL,
|
||||
BuildDocksClick_Demolish,
|
||||
BuildDocksClick_Depot,
|
||||
BuildDocksClick_Dock,
|
||||
BuildDocksClick_Buoy,
|
||||
BuildDocksClick_Landscaping,
|
||||
};
|
||||
|
||||
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch(e->event) {
|
||||
case WE_PAINT:
|
||||
DrawWindowWidgets(w);
|
||||
break;
|
||||
|
||||
case WE_CLICK:
|
||||
if (e->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: {
|
||||
TileIndex tile_from;
|
||||
TileIndex tile_to;
|
||||
|
||||
tile_from = tile_to = e->place.tile;
|
||||
switch (GetTileSlope(tile_from, NULL)) {
|
||||
case 3: tile_to += TileDiffXY(-1, 0); break;
|
||||
case 6: tile_to += TileDiffXY( 0, -1); break;
|
||||
case 9: tile_to += TileDiffXY( 0, 1); break;
|
||||
case 12: tile_to += TileDiffXY( 1, 0); break;
|
||||
}
|
||||
VpSetPresizeRange(tile_from, tile_to);
|
||||
} break;
|
||||
|
||||
case WE_DESTROY:
|
||||
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const Widget _build_docks_toolb_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, 0x0, STR_STICKY_BUTTON},
|
||||
{ WWT_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);
|
||||
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
|
||||
}
|
||||
|
||||
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
int rad;
|
||||
|
||||
if (WP(w,def_d).close) return;
|
||||
w->click_state = (1<<3) << _station_show_coverage;
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
rad = (_patches.modified_catchment) ? CA_DOCK : 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_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ 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,59 +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 also download a precompiled binary from a release,
|
||||
nightly, etc.
|
||||
strgen takes as argument a txt file and translates it to a lng file, allowing
|
||||
it to be used inside OpenTTD. strgen needs the master language file
|
||||
english.txt to work. Below are some examples of strgen usage.
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
+13
-11
@@ -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.
|
||||
@@ -20,4 +20,4 @@ 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
|
||||
The game adds some items by itself when it runs, like a save folder and a setting file
|
||||
@@ -0,0 +1,10 @@
|
||||
There are currently two different downloads for OSX, one is named osx, while the other one is named osx-jaguar
|
||||
|
||||
The reason for this is that Apple added more functionality to 10.3 and to make use of that, it will no longer run on OSX 10.2 (codenamed Jaguar). To make the game useable on Jaguar, then a special download is available, but it will miss the bugfixes/features, that relies on newer functionality.
|
||||
|
||||
The general download is a universal binary and should work great on all macs using 10.3.9 or newer, no matter what processor it got. You should at all time avoid the Jaguar Build if possible.
|
||||
|
||||
Technically the universal binary is a triple binary because it contains code for 3 CPUs and the CPUs in question are PPC (G3+G4), G5 and Intel. The Jaguar build is only optimised for PPC and other (newer) CPUs will not benefit so much from their advanced features. This is another reason to avoid the Jaguar build. It's generally slower on modern CPUs.
|
||||
|
||||
Current list of missing features in the Jaguar build:
|
||||
-Can't save screenshots or savegames if certain chars are in the filename. This mainly applies to European chars and hits German hard as the month Mär (Mar) can't be saved
|
||||
@@ -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 $
|
||||
+37
-43
@@ -50,10 +50,6 @@ To enable music, start OpenTTD with the command line:
|
||||
If I hear enough responses that both music and sound work together (it might
|
||||
just be my system), I'll have the defaults changed.
|
||||
|
||||
Please note also that the GCC version does not currently support the MCI MIDI
|
||||
system.
|
||||
|
||||
|
||||
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
|
||||
------------------------------------------
|
||||
|
||||
@@ -64,8 +60,6 @@ directly will result in the console not being displayed. You may
|
||||
still pass any other parameters ('-D' is already passed) to
|
||||
dedicated.cmd.
|
||||
|
||||
You can find the dedicated.cmd file in the os/os2 directory.
|
||||
|
||||
=========================
|
||||
BUILDING THE OS/2 VERSION
|
||||
=========================
|
||||
@@ -73,33 +67,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,23 +87,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
|
||||
|
||||
- Freetype
|
||||
http://freetype.sourceforge.net/
|
||||
|
||||
Currently, there are no pre-built libraries available for GCC. If you manage to get
|
||||
OpenTTD working on Watcom though (do let us know if this is the case!), pre-built
|
||||
versions can be downloaded from the Files section at
|
||||
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-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 +130,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://sf.net/project/showfiles.php?group_id=103924&package_id=114307)
|
||||
* DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft)
|
||||
* MS Windows Platform SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en)
|
||||
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
|
||||
|
||||
...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/servlets/ProjectDocumentList?folderID=91)
|
||||
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
|
||||
|
||||
|
||||
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
|
||||
@@ -0,0 +1,104 @@
|
||||
Compiling OpenTTD using Microsoft Visual C++ 6.0
|
||||
|
||||
|
||||
Step 1: Ingredients
|
||||
|
||||
Download the following files:
|
||||
|
||||
* Openttd-useful.zip (http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633)
|
||||
* DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft)
|
||||
* The February 2003 Microsoft Platform SDK (http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm) (newer SDK's do not work with MSVC6)
|
||||
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H) (maybe you not need this)
|
||||
|
||||
...and of course the newest source from svn://svn.openttd.org/trunk
|
||||
|
||||
You have to have a SVN-client to download the source:
|
||||
|
||||
* Command line version (Subversion 1.2.3 Win32 binaries) (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
|
||||
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
|
||||
|
||||
Step 2: Includes and Libraries
|
||||
|
||||
Put the newly downloaded files in the VC lib and include directories (Where "C:\Program Files\Microsoft Visual Studio\VC98" 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]
|
||||
* 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.)
|
||||
|
||||
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, which is recommended so you don't overwrite VS6 files, 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 8.1 SDK\include )
|
||||
|
||||
b) library files (the lib dir, C:\Program Files\Microsoft Visual Studio\VC98\DirectX 8.1 SDK\lib )
|
||||
|
||||
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!!
|
||||
|
||||
Step 4: TTD Graphics files
|
||||
|
||||
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: Compiling
|
||||
|
||||
Open trunk/openttd.dsw
|
||||
|
||||
Build menu > Set active configuration > Select: "openttd - Win32 Release"
|
||||
|
||||
Compile...
|
||||
|
||||
|
||||
Now it should work, it worked for me :)
|
||||
|
||||
From r1319 you can compile branch/map in Debug mode (by Bociusz)
|
||||
|
||||
For compiling branch/cargo-packets you have to add cargo.c and .h to this tree's openttd.dsp
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
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 |
+617
-1555
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>
|
||||
+102
-206
@@ -6,7 +6,6 @@
|
||||
<title>OpenTTD Landscape Internals - #2</title>
|
||||
<style type="text/css">
|
||||
span.abuse { font-family: "Courier New", Courier, mono; background-color: rgb(255, 58, 31); }
|
||||
span.option{ font-family: "Courier New", Courier, mono; background-color: rgb(255,255, 30); }
|
||||
span.free { font-family: "Courier New", Courier, mono; background-color: rgb(30, 178, 54); }
|
||||
span.used { font-family: "Courier New", Courier, mono; }
|
||||
td.bits { white-space: nowrap; text-align: center; font-family: "Courier New", Courier, mono; }
|
||||
@@ -17,14 +16,13 @@
|
||||
</head>
|
||||
<body style="direction: ltr;">
|
||||
<h3 style="font-weight: bold;">Landscape</h3>
|
||||
<span style="font-weight: bold;"></span>Six attributes hold the information about a tile.
|
||||
<span style="font-weight: bold;"></span>Five attributes hold the information about a tile.
|
||||
This can be seen in the <a href="landscape.html">Landscape</a> document. This page tries to give an overview of used and free bits of
|
||||
the array so you can quickly see what is used and what is not.
|
||||
<ul>
|
||||
<li><span style="font-weight: bold;"><span class="free">O</span></span> - bit is free</li>
|
||||
<li><span style="font-weight: bold;"><span class="used">X</span></span> - bit is used</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of attribute is abused for different purposes, i.e. other bits define the actual meaning.</li>
|
||||
<li><span style="font-weight: bold;"><span class="option">~</span></span> - bit is accessed, but does not really have a meaning (e.g. owner of clear land is always OWNER_NONE)</li>
|
||||
<li><span style="font-weight: bold;"><span class="abuse"> </span></span> - bit of attribute is abused for different purposes</li>
|
||||
</ul>
|
||||
<p>
|
||||
<ul>
|
||||
@@ -34,110 +32,72 @@ the array so you can quickly see what is used and what is not.
|
||||
<li><span style="font-weight: bold;">m3</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m4</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m5</span> - 8 bits in size, is used for general storage</li>
|
||||
<li><span style="font-weight: bold;">m6</span> - 8 bits in size, special meaning : lower 2 bits only valid in tropic climate, upper 2 bits for bridges</li>
|
||||
<li><span style="font-weight: bold;">m7</span> - 8 bits in size, is used for general storage</li>
|
||||
</ul>
|
||||
|
||||
<table align=center border="1" cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=2>class</th>
|
||||
<th>type_height (8)</th>
|
||||
<th>m1 (8)</th>
|
||||
<th>m2 (16)</th>
|
||||
<th>m3 (8)</th>
|
||||
<th>m4 (8)</th>
|
||||
<th>type_height (8)</th>
|
||||
<th>m5 (8)</th>
|
||||
<th>m6 (8)</th>
|
||||
<th>m7 (8)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 class="caption">bits</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">FEDC BA98 7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
<td class="bits">7654 3210</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">0</td>
|
||||
<td>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"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">farmland</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=4>1</td>
|
||||
<td rowspan=3>1</td>
|
||||
<td class="caption">rail</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO 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"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO O</span>XXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">rail with signals</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO O</span>XXX <span class="free">O</span>XXX</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">depot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">waypoint</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OOO</span>X</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>2</td>
|
||||
<td class="caption">road</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
@@ -146,207 +106,143 @@ the array so you can quickly see what is used and what is not.
|
||||
<td class="caption">level crossing</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">O</span>XXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO</span> XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road depot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits">XXX<span class="free">O OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td class="caption">house</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="caption">town</td>
|
||||
<td class="bits"><span class="abuse">XXXX XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="option">~ ~~</span>XX</td>
|
||||
<td class="bits">XX<span class="free">OO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXX<span class="abuse">X XXXX</span></td>
|
||||
<td class="bits"><span class="abuse">XXXX XX</span>XX</td>
|
||||
<td class="bits">XXXX <span class="abuse">XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">O</span>XX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td class="caption">trees</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~</span>XX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XX<span class="free">OO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO O</span>XXX</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=6>5</td>
|
||||
<td class="caption">rail station</td>
|
||||
<td>5</td>
|
||||
<td class="caption">station</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX <span class="option">~~</span>XX</td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road stop</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO O</span>XXX</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"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">dock</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">airport</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">buoy</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">oilrig</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="option">~~~~ ~~~~</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>6</td>
|
||||
<td class="caption">sea, shore</td>
|
||||
<td>6</td>
|
||||
<td class="caption">water</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">X<span class="option">~~</span>X XXXX</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">canal, river</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">shipdepot</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td rowspan=6>8</td>
|
||||
<td class="caption">industry</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO</span> <span class="abuse">
|
||||
XXXX</span></td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bubble/sugar/toffee</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>toy factory</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gold/copper/coal</td>
|
||||
<td class="bits"><span class="abuse">XX</span><span class="free">OO OO</span><span class="abuse">XX</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>oil wells</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">OOO OO</span><span class="abuse">XX</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>power station</td>
|
||||
<td class="bits"><span class="abuse">X</span><span class="free">O</span><span class="abuse">XX XX</span><span class="free">OO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=2>9</td>
|
||||
<td class="caption">tunnel entrance</td>
|
||||
<td class="caption">tunnel</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</span> <span class="option">~</span><span class="abuse">XXX</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OOO</span> <span class="option">~</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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bridge ramp</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> XXXX <span class="free">OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO</span> <span class="option">~</span><span class="abuse">XXX</span></td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">X<span class="free">OOO</span> <span class="option">~</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>
|
||||
</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">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bridge</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX XXXX</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">X<span class="free">OOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A</td>
|
||||
<td class="caption">various (HQ)</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">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">company statue</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
+3
-12
@@ -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.
|
||||
|
||||
+9
-21
@@ -1,37 +1,28 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.Dd Jul 20, 2008
|
||||
.Dd August 12, 2006
|
||||
.Dt OPENTTD 6
|
||||
.Sh NAME
|
||||
.Nm openttd
|
||||
.Nd An open source clone of the Microprose game "Transport Tycoon Deluxe"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl Defhix
|
||||
.Op Fl Defhi
|
||||
.Op Fl G Ar seed
|
||||
.Op Fl b Ar blitter
|
||||
.Op Fl d Ar [level | cat=lvl[, ...]]
|
||||
.Op Fl c Ar config_file
|
||||
.Op Fl g Ar [savegame]
|
||||
.Op Fl l Ar host[:port]
|
||||
.Op Fl n Ar host[:port][#player]
|
||||
.Op Fl n Ar [host[#player][:port]]
|
||||
.Op Fl r Ar widthxheight
|
||||
.Op Fl t Ar date
|
||||
.Op Fl m Ar driver
|
||||
.Op Fl s Ar driver
|
||||
.Op Fl v Ar driver
|
||||
.Op Fl b Ar blitter
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width ".Fl n Ar host[:port][#player]"
|
||||
.It Fl D Ar [host][:port]
|
||||
.Bl -tag -width ".Fl n Ar host[#player][:port]"
|
||||
.It Fl D
|
||||
Start a dedicated server
|
||||
.It Fl G Ar seed
|
||||
Seed the pseudo random number generator
|
||||
.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
|
||||
@@ -51,13 +42,12 @@ at start or start a new game if omitted
|
||||
Display a summary of all options and available drivers
|
||||
.It Fl i
|
||||
Force to use the DOS palette (use this if you see a lot of magenta)
|
||||
.It Fl 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]
|
||||
.It Fl n
|
||||
Start a network server
|
||||
.It Fl n Ar host[#player][:port]
|
||||
Join a network game, optionally specify player to play as and port to connect to
|
||||
.It Fl r Ar widthxheight
|
||||
Set the resolution
|
||||
@@ -69,11 +59,9 @@ Set the starting date
|
||||
.It Fl v Ar driver
|
||||
Set the video driver, see
|
||||
.Fl h
|
||||
.It Fl x
|
||||
Do not automatically save to config file on exit
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
http://wiki.openttd.org/, http://www.openttd.org
|
||||
http://wiki.openttd.org/
|
||||
.Sh HISTORY
|
||||
Transport Tycoon Deluxe was written by Chris Sawyer and published by Microprose.
|
||||
.Nm
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "debug.h"
|
||||
#include "driver.h"
|
||||
#include "functions.h"
|
||||
#include "hal.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "music/bemidi.h"
|
||||
#include "music/dmusic.h"
|
||||
#include "music/extmidi.h"
|
||||
#include "music/null_m.h"
|
||||
#include "music/os2_m.h"
|
||||
#include "music/win32_m.h"
|
||||
#include "music/qtmidi.h"
|
||||
|
||||
#include "sound/null_s.h"
|
||||
#include "sound/sdl_s.h"
|
||||
#include "sound/cocoa_s.h"
|
||||
#include "sound/win32_s.h"
|
||||
|
||||
#include "video/dedicated_v.h"
|
||||
#include "video/null_v.h"
|
||||
#include "video/sdl_v.h"
|
||||
#include "video/cocoa_v.h"
|
||||
#include "video/win32_v.h"
|
||||
|
||||
typedef struct DriverDesc {
|
||||
const char* name;
|
||||
const char* longname;
|
||||
const HalCommonDriver* drv;
|
||||
} DriverDesc;
|
||||
|
||||
typedef struct DriverClass {
|
||||
const DriverDesc *descs;
|
||||
const char *name;
|
||||
const HalCommonDriver** drv;
|
||||
} DriverClass;
|
||||
|
||||
|
||||
#define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z }
|
||||
static const DriverDesc _music_driver_descs[] = {
|
||||
#ifdef __BEOS__
|
||||
M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver),
|
||||
#endif
|
||||
#ifdef __OS2__
|
||||
M("os2", "OS/2 Music Driver", &_os2_music_driver),
|
||||
#endif
|
||||
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
|
||||
M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver),
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 MIDI Driver", &_win32_music_driver),
|
||||
#endif
|
||||
#if defined(__APPLE__) && !defined(DEDICATED)
|
||||
M("qt", "QuickTime MIDI Driver", &_qtime_music_driver),
|
||||
#endif
|
||||
#ifdef UNIX
|
||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
||||
M("extmidi", "External MIDI Driver", &_extmidi_music_driver),
|
||||
#endif
|
||||
#endif
|
||||
M("null", "Null Music Driver", &_null_music_driver),
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
|
||||
static const DriverDesc _sound_driver_descs[] = {
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 WaveOut Driver", &_win32_sound_driver),
|
||||
#endif
|
||||
#ifdef WITH_SDL
|
||||
M("sdl", "SDL Sound Driver", &_sdl_sound_driver),
|
||||
#endif
|
||||
#ifdef WITH_COCOA
|
||||
M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver),
|
||||
#endif
|
||||
M("null", "Null Sound Driver", &_null_sound_driver),
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
|
||||
static const DriverDesc _video_driver_descs[] = {
|
||||
#ifdef WIN32
|
||||
M("win32", "Win32 GDI Video Driver", &_win32_video_driver),
|
||||
#endif
|
||||
#ifdef WITH_SDL
|
||||
M("sdl", "SDL Video Driver", &_sdl_video_driver),
|
||||
#endif
|
||||
#ifdef WITH_COCOA
|
||||
M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver),
|
||||
#endif
|
||||
M("null", "Null Video Driver", &_null_video_driver),
|
||||
#ifdef ENABLE_NETWORK
|
||||
M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver),
|
||||
#endif
|
||||
M(NULL, NULL, NULL)
|
||||
};
|
||||
#undef M
|
||||
|
||||
|
||||
#define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z }
|
||||
static const DriverClass _driver_classes[] = {
|
||||
M(_video_driver_descs, "video", &_video_driver),
|
||||
M(_sound_driver_descs, "sound", &_sound_driver),
|
||||
M(_music_driver_descs, "music", &_music_driver)
|
||||
};
|
||||
#undef M
|
||||
|
||||
static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name)
|
||||
{
|
||||
for (; dd->name != NULL; dd++) {
|
||||
if (strcmp(dd->name, name) == 0) return dd;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LoadDriver(int driver, const char *name)
|
||||
{
|
||||
const DriverClass *dc = &_driver_classes[driver];
|
||||
const DriverDesc *dd;
|
||||
const char *err;
|
||||
|
||||
if (*name == '\0') {
|
||||
for (dd = dc->descs; dd->name != NULL; dd++) {
|
||||
err = dd->drv->start(NULL);
|
||||
if (err == NULL) break;
|
||||
DEBUG(driver, 1) ("Probing %s driver \"%s\" failed with error: %s",
|
||||
dc->name, dd->name, err
|
||||
);
|
||||
}
|
||||
if (dd->name == NULL) {
|
||||
error("Couldn't find any suitable %s driver", dc->name);
|
||||
}
|
||||
|
||||
DEBUG(driver, 1)
|
||||
("Successfully probed %s driver \"%s\"", dc->name, dd->name);
|
||||
|
||||
*dc->drv = dd->drv;
|
||||
} else {
|
||||
char* parm;
|
||||
char buffer[256];
|
||||
const char* parms[32];
|
||||
|
||||
// Extract the driver name and put parameter list in parm
|
||||
ttd_strlcpy(buffer, name, sizeof(buffer));
|
||||
parm = strchr(buffer, ':');
|
||||
parms[0] = NULL;
|
||||
if (parm != NULL) {
|
||||
uint np = 0;
|
||||
// Tokenize the parm.
|
||||
do {
|
||||
*parm++ = '\0';
|
||||
if (np < lengthof(parms) - 1)
|
||||
parms[np++] = parm;
|
||||
while (*parm != '\0' && *parm != ',')
|
||||
parm++;
|
||||
} while (*parm == ',');
|
||||
parms[np] = NULL;
|
||||
}
|
||||
dd = GetDriverByName(dc->descs, buffer);
|
||||
if (dd == NULL)
|
||||
error("No such %s driver: %s\n", dc->name, buffer);
|
||||
|
||||
if (*dc->drv != NULL) (*dc->drv)->stop();
|
||||
*dc->drv = NULL;
|
||||
|
||||
err = dd->drv->start(parms);
|
||||
if (err != NULL) {
|
||||
error("Unable to load driver %s(%s). The error was: %s\n",
|
||||
dd->name, dd->longname, err
|
||||
);
|
||||
}
|
||||
*dc->drv = dd->drv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char* GetDriverParam(const char* const* parm, const char* name)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (parm == NULL) return NULL;
|
||||
|
||||
len = strlen(name);
|
||||
for (; *parm != NULL; parm++) {
|
||||
const char* p = *parm;
|
||||
|
||||
if (strncmp(p, name, len) == 0) {
|
||||
if (p[len] == '=') return p + len + 1;
|
||||
if (p[len] == '\0') return p + len;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool GetDriverParamBool(const char* const* parm, const char* name)
|
||||
{
|
||||
return GetDriverParam(parm, name) != NULL;
|
||||
}
|
||||
|
||||
int GetDriverParamInt(const char* const* parm, const char* name, int def)
|
||||
{
|
||||
const char* p = GetDriverParam(parm, name);
|
||||
return p != NULL ? atoi(p) : def;
|
||||
}
|
||||
|
||||
|
||||
char *GetDriverList(char* p)
|
||||
{
|
||||
const DriverClass* dc;
|
||||
|
||||
for (dc = _driver_classes; dc != endof(_driver_classes); dc++) {
|
||||
const DriverDesc* dd;
|
||||
|
||||
p += sprintf(p, "List of %s drivers:\n", dc->name);
|
||||
for (dd = dc->descs; dd->name != NULL; dd++) {
|
||||
p += sprintf(p, "%10s: %s\n", dd->name, dd->longname);
|
||||
}
|
||||
p += sprintf(p, "\n");
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
void LoadDriver(int driver, const char *name);
|
||||
|
||||
bool GetDriverParamBool(const char* const* parm, const char* name);
|
||||
int GetDriverParamInt(const char* const* parm, const char* name, int def);
|
||||
|
||||
char *GetDriverList(char* p);
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
@@ -0,0 +1,84 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "functions.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
#include "table/sprites.h"
|
||||
|
||||
static void DrawTile_Dummy(TileInfo *ti)
|
||||
{
|
||||
DrawGroundSpriteAt(SPR_SHADOW_CELL, ti->x, ti->y, ti->z);
|
||||
}
|
||||
|
||||
|
||||
static uint GetSlopeZ_Dummy(const TileInfo* ti)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint GetSlopeTileh_Dummy(const TileInfo* ti)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 ClearTile_Dummy(TileIndex tile, byte flags)
|
||||
{
|
||||
return_cmd_error(STR_0001_OFF_EDGE_OF_MAP);
|
||||
}
|
||||
|
||||
|
||||
static void GetAcceptedCargo_Dummy(TileIndex tile, AcceptedCargo ac)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void GetTileDesc_Dummy(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
td->str = STR_EMPTY;
|
||||
td->owner = OWNER_NONE;
|
||||
}
|
||||
|
||||
static void AnimateTile_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void TileLoop_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ClickTile_Dummy(TileIndex tile)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static void ChangeTileOwner_Dummy(TileIndex tile, PlayerID old_player, PlayerID new_player)
|
||||
{
|
||||
/* not used */
|
||||
}
|
||||
|
||||
static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TileTypeProcs _tile_type_dummy_procs = {
|
||||
DrawTile_Dummy, /* draw_tile_proc */
|
||||
GetSlopeZ_Dummy, /* get_slope_z_proc */
|
||||
ClearTile_Dummy, /* clear_tile_proc */
|
||||
GetAcceptedCargo_Dummy, /* get_accepted_cargo_proc */
|
||||
GetTileDesc_Dummy, /* get_tile_desc_proc */
|
||||
GetTileTrackStatus_Dummy, /* get_tile_track_status_proc */
|
||||
ClickTile_Dummy, /* click_tile_proc */
|
||||
AnimateTile_Dummy, /* animate_tile_proc */
|
||||
TileLoop_Dummy, /* tile_loop_clear */
|
||||
ChangeTileOwner_Dummy, /* change_tile_owner_clear */
|
||||
NULL, /* get_produced_cargo_proc */
|
||||
NULL, /* vehicle_enter_tile_proc */
|
||||
NULL, /* vehicle_leave_tile_proc */
|
||||
GetSlopeTileh_Dummy, /* get_slope_tileh_proc */
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef ECONOMY_H
|
||||
#define ECONOMY_H
|
||||
|
||||
void ResetPriceBaseMultipliers(void);
|
||||
void SetPriceBaseMultiplier(uint price, byte factor);
|
||||
|
||||
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;
|
||||
|
||||
extern const ScoreInfo _score_info[];
|
||||
extern 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(const Subsidy* s, bool mode);
|
||||
void DeleteSubsidyWithIndustry(uint16 index);
|
||||
void DeleteSubsidyWithStation(uint16 index);
|
||||
|
||||
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type);
|
||||
uint MoveGoodsToStation(TileIndex tile, int w, int h, int type, uint amount);
|
||||
|
||||
#endif /* ECONOMY_H */
|
||||
@@ -0,0 +1,52 @@
|
||||
/* $Id$ */
|
||||
|
||||
#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, force_PREPROCESSOR = 0;
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "BE") == 0)
|
||||
force_BE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "LE") == 0)
|
||||
force_LE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "PREPROCESSOR") == 0)
|
||||
force_PREPROCESSOR = 1;
|
||||
|
||||
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
|
||||
|
||||
if (force_LE == 1) {
|
||||
printf("#define TTD_LITTLE_ENDIAN\n");
|
||||
} else {
|
||||
if (force_BE == 1) {
|
||||
printf("#define TTD_BIG_ENDIAN\n");
|
||||
} else {
|
||||
if (force_PREPROCESSOR == 1) {
|
||||
// adding support for universal binaries on OSX
|
||||
// Universal binaries supports both PPC and x86
|
||||
// If a compiler for OSX gets this setting, it will always pick the correct endian and no test is needed
|
||||
printf("#ifdef __BIG_ENDIAN__\n");
|
||||
printf("#define TTD_BIG_ENDIAN\n");
|
||||
printf("#else\n");
|
||||
printf("#define TTD_LITTLE_ENDIAN\n");
|
||||
printf("#endif\n");
|
||||
} else {
|
||||
if ( *(short *) EndianTest == 1 )
|
||||
printf("#define TTD_LITTLE_ENDIAN\n");
|
||||
else
|
||||
printf("#define TTD_BIG_ENDIAN\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("#endif\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
/** @file engine.h
|
||||
*/
|
||||
|
||||
#include "sprite.h"
|
||||
#include "pool.h"
|
||||
|
||||
typedef struct RailVehicleInfo {
|
||||
byte image_index;
|
||||
byte flags; /* 1=multihead engine, 2=wagon */
|
||||
byte base_cost;
|
||||
uint16 max_speed;
|
||||
uint16 power;
|
||||
uint16 weight;
|
||||
byte running_cost_base;
|
||||
byte running_cost_class;
|
||||
byte engclass; // 0: steam, 1: diesel, 2: electric
|
||||
byte capacity;
|
||||
byte cargo_type;
|
||||
byte callbackmask; // see CallbackMask enum
|
||||
uint16 pow_wag_power;
|
||||
byte pow_wag_weight;
|
||||
byte visual_effect; // NOTE: this is not 100% implemented yet, at the moment it is only used as a 'fallback' value
|
||||
// for when the 'powered wagon' callback fails. But it should really also determine what
|
||||
// kind of visual effect to generate for a vehicle (default, steam, diesel, electric).
|
||||
// Same goes for the callback result, which atm is only used to check if a wagon is powered.
|
||||
byte shorten_factor; // length on main map for this type is 8 - shorten_factor
|
||||
} 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;
|
||||
|
||||
/** Information about a vehicle
|
||||
* @see table/engines.h
|
||||
*/
|
||||
typedef struct EngineInfo {
|
||||
uint16 base_intro;
|
||||
byte unk2; ///< Carriages have the highest bit set in this one
|
||||
byte lifelength;
|
||||
byte base_life;
|
||||
byte railtype:4;
|
||||
byte climates:4;
|
||||
uint32 refit_mask;
|
||||
} 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;
|
||||
byte preview_player;
|
||||
byte preview_wait;
|
||||
byte railtype;
|
||||
byte 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
|
||||
};
|
||||
|
||||
enum {
|
||||
INVALID_ENGINE = 0xFFFF,
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// This enum lists the implemented callbacks
|
||||
// Use as argument for the GetCallBackResult function (see comments there)
|
||||
enum CallbackID {
|
||||
// Powered wagons, if the result is lower as 0x40 then the wagon is powered
|
||||
// TODO: interpret the rest of the result, aka "visual effects"
|
||||
CBID_WAGON_POWER = 0x10,
|
||||
|
||||
// Vehicle length, returns the amount of 1/8's the vehicle is shorter
|
||||
// only for train vehicles
|
||||
CBID_VEH_LENGTH = 0x11,
|
||||
|
||||
// Refit capacity, the passed vehicle needs to have its ->cargo_type set to
|
||||
// the cargo we are refitting to, returns the new cargo capacity
|
||||
CBID_REFIT_CAP = 0x15,
|
||||
|
||||
CBID_ARTIC_ENGINE = 0x16,
|
||||
};
|
||||
|
||||
// bit positions for rvi->callbackmask, indicates which callbacks are used by an engine
|
||||
// (some callbacks are always used, and dont appear here)
|
||||
enum CallbackMask {
|
||||
CBM_WAGON_POWER = 0,
|
||||
CBM_VEH_LENGTH = 1,
|
||||
CBM_REFIT_CAP = 3,
|
||||
CBM_ARTIC_ENGINE = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
CALLBACK_FAILED = 0xFFFF
|
||||
};
|
||||
|
||||
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 const uint32 cargo_classes[16];
|
||||
|
||||
void SetWagonOverrideSprites(EngineID engine, struct SpriteGroup *group, byte *train_id, int trains);
|
||||
void SetCustomEngineSprites(EngineID engine, byte cargo, struct SpriteGroup *group);
|
||||
// loaded is in percents, overriding_engine 0xffff is none
|
||||
int GetCustomEngineSprite(EngineID engine, const Vehicle *v, byte direction);
|
||||
uint16 GetCallBackResult(uint16 callback_info, EngineID engine, const Vehicle *v);
|
||||
bool UsesWagonOverride(const Vehicle *v);
|
||||
#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(EngineID engine, const char *name);
|
||||
StringID GetCustomEngineName(EngineID engine);
|
||||
|
||||
|
||||
void DrawTrainEngine(int x, int y, EngineID engine, uint32 image_ormod);
|
||||
void DrawRoadVehEngine(int x, int y, EngineID engine, uint32 image_ormod);
|
||||
void DrawShipEngine(int x, int y, EngineID engine, uint32 image_ormod);
|
||||
void DrawAircraftEngine(int x, int y, EngineID engine, uint32 image_ormod);
|
||||
|
||||
void LoadCustomEngineNames(void);
|
||||
void DeleteCustomEngineNames(void);
|
||||
|
||||
bool IsEngineBuildable(uint engine, byte type);
|
||||
|
||||
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++)
|
||||
|
||||
static inline Engine* GetEngine(EngineID 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 const EngineInfo orig_engine_info[TOTAL_NUM_ENGINES];
|
||||
extern const RailVehicleInfo orig_rail_vehicle_info[NUM_TRAIN_ENGINES];
|
||||
extern const ShipVehicleInfo orig_ship_vehicle_info[NUM_SHIP_ENGINES];
|
||||
extern const AircraftVehicleInfo orig_aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
|
||||
extern const RoadVehicleInfo orig_road_vehicle_info[NUM_ROAD_ENGINES];
|
||||
|
||||
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 const RailVehicleInfo* RailVehInfo(EngineID e)
|
||||
{
|
||||
assert(e < lengthof(_rail_vehicle_info));
|
||||
return &_rail_vehicle_info[e];
|
||||
}
|
||||
|
||||
static inline const ShipVehicleInfo* ShipVehInfo(EngineID e)
|
||||
{
|
||||
assert(e >= SHIP_ENGINES_INDEX && e < SHIP_ENGINES_INDEX + lengthof(_ship_vehicle_info));
|
||||
return &_ship_vehicle_info[e - SHIP_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline const AircraftVehicleInfo* AircraftVehInfo(EngineID e)
|
||||
{
|
||||
assert(e >= AIRCRAFT_ENGINES_INDEX && e < AIRCRAFT_ENGINES_INDEX + lengthof(_aircraft_vehicle_info));
|
||||
return &_aircraft_vehicle_info[e - AIRCRAFT_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
static inline const RoadVehicleInfo* RoadVehInfo(EngineID e)
|
||||
{
|
||||
assert(e >= ROAD_ENGINES_INDEX && e < ROAD_ENGINES_INDEX + lengthof(_road_vehicle_info));
|
||||
return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
void UnloadWagonOverrides(void);
|
||||
void UnloadCustomEngineSprites(void);
|
||||
void UnloadCustomEngineNames(void);
|
||||
|
||||
/************************************************************************
|
||||
* Engine Replacement stuff
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Struct to store engine replacements. DO NOT USE outside of engine.c. Is
|
||||
* placed here so the only exception to this rule, the saveload code, can use
|
||||
* it.
|
||||
*/
|
||||
struct EngineRenew {
|
||||
uint16 index;
|
||||
EngineID from;
|
||||
EngineID to;
|
||||
struct EngineRenew *next;
|
||||
};
|
||||
|
||||
typedef struct EngineRenew EngineRenew;
|
||||
|
||||
/**
|
||||
* Memory pool for engine renew elements. DO NOT USE outside of engine.c. Is
|
||||
* placed here so the only exception to this rule, the saveload code, can use
|
||||
* it.
|
||||
*/
|
||||
extern MemoryPool _engine_renew_pool;
|
||||
|
||||
/**
|
||||
* DO NOT USE outside of engine.c. Is
|
||||
* placed here so the only exception to this rule, the saveload code, can use
|
||||
* it.
|
||||
*/
|
||||
static inline EngineRenew *GetEngineRenew(uint16 index)
|
||||
{
|
||||
return (EngineRenew*)GetItemFromPool(&_engine_renew_pool, index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A list to group EngineRenew directives together (such as per-player).
|
||||
*/
|
||||
typedef EngineRenew* EngineRenewList;
|
||||
|
||||
/**
|
||||
* Remove all engine replacement settings for the player.
|
||||
* @param er The renewlist for a given player.
|
||||
* @return The new renewlist for the player.
|
||||
*/
|
||||
void RemoveAllEngineReplacement(EngineRenewList* erl);
|
||||
|
||||
/**
|
||||
* Retrieve the engine replacement in a given renewlist for an original engine type.
|
||||
* @param erl The renewlist to search in.
|
||||
* @param engine Engine type to be replaced.
|
||||
* @return The engine type to replace with, or INVALID_ENGINE if no
|
||||
* replacement is in the list.
|
||||
*/
|
||||
EngineID EngineReplacement(EngineRenewList erl, EngineID engine);
|
||||
|
||||
/**
|
||||
* Add an engine replacement to the given renewlist.
|
||||
* @param erl The renewlist to add to.
|
||||
* @param old_engine The original engine type.
|
||||
* @param new_engine The replacement engine type.
|
||||
* @param flags The calling command flags.
|
||||
* @return 0 on success, CMD_ERROR on failure.
|
||||
*/
|
||||
int32 AddEngineReplacement(EngineRenewList* erl, EngineID old_engine, EngineID new_engine, uint32 flags);
|
||||
|
||||
/**
|
||||
* Remove an engine replacement from a given renewlist.
|
||||
* @param erl The renewlist from which to remove the replacement
|
||||
* @param engine The original engine type.
|
||||
* @param flags The calling command flags.
|
||||
* @return 0 on success, CMD_ERROR on failure.
|
||||
*/
|
||||
int32 RemoveEngineReplacement(EngineRenewList* erl, EngineID engine, uint32 flags);
|
||||
|
||||
#endif /* ENGINE_H */
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "table/strings.h"
|
||||
#include "table/sprites.h"
|
||||
#include "functions.h"
|
||||
#include "window.h"
|
||||
#include "gui.h"
|
||||
#include "viewport.h"
|
||||
#include "gfx.h"
|
||||
#include "engine.h"
|
||||
#include "command.h"
|
||||
#include "news.h"
|
||||
#include "variables.h"
|
||||
|
||||
|
||||
static StringID GetEngineCategoryName(EngineID engine)
|
||||
{
|
||||
if (engine < NUM_TRAIN_ENGINES) {
|
||||
switch (GetEngine(engine)->railtype) {
|
||||
case RAILTYPE_RAIL: return STR_8102_RAILROAD_LOCOMOTIVE;
|
||||
case RAILTYPE_MONO: return STR_8106_MONORAIL_LOCOMOTIVE;
|
||||
case RAILTYPE_MAGLEV: 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_CLOSEBOX, 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, EngineID engine, uint32 image_ormod);
|
||||
typedef void DrawEngineInfoProc(EngineID, int x, int y, int maxw);
|
||||
|
||||
typedef struct DrawEngineInfo {
|
||||
DrawEngineProc *engine_proc;
|
||||
DrawEngineInfoProc *info_proc;
|
||||
} DrawEngineInfo;
|
||||
|
||||
static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw);
|
||||
static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw);
|
||||
static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw);
|
||||
static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw);
|
||||
|
||||
static const DrawEngineInfo _draw_engine_list[4] = {
|
||||
{DrawTrainEngine,DrawTrainEngineInfo},
|
||||
{DrawRoadVehEngine,DrawRoadVehEngineInfo},
|
||||
{DrawShipEngine,DrawShipEngineInfo},
|
||||
{DrawAircraftEngine,DrawAircraftEngineInfo},
|
||||
};
|
||||
|
||||
static void EnginePreviewWndProc(Window *w, WindowEvent *e)
|
||||
{
|
||||
switch (e->event) {
|
||||
case WE_PAINT: {
|
||||
EngineID engine = w->window_number;
|
||||
const DrawEngineInfo* dei;
|
||||
int width;
|
||||
|
||||
DrawWindowWidgets(w);
|
||||
|
||||
SetDParam(0, GetEngineCategoryName(engine));
|
||||
DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
|
||||
|
||||
DrawStringCentered(w->width >> 1, 80, GetCustomEngineName(engine), 0x10);
|
||||
|
||||
(dei = _draw_engine_list,engine < NUM_TRAIN_ENGINES) ||
|
||||
(dei++,engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES) ||
|
||||
(dei++,engine < 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(EngineID engine)
|
||||
{
|
||||
Window *w;
|
||||
|
||||
w = AllocateWindowDesc(&_engine_preview_desc);
|
||||
w->window_number = engine;
|
||||
}
|
||||
|
||||
static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw)
|
||||
{
|
||||
const RailVehicleInfo *rvi = RailVehInfo(engine);
|
||||
uint multihead = (rvi->flags & RVI_MULTIHEAD) ? 1 : 0;
|
||||
|
||||
SetDParam(0, (_price.build_railvehicle >> 3) * rvi->base_cost >> 5);
|
||||
SetDParam(2, rvi->max_speed * 10 >> 4);
|
||||
SetDParam(3, rvi->power << multihead);
|
||||
SetDParam(1, rvi->weight << multihead);
|
||||
|
||||
SetDParam(4, rvi->running_cost_base * _price.running_rail[rvi->running_cost_class] >> 8 << multihead);
|
||||
|
||||
if (rvi->capacity != 0) {
|
||||
SetDParam(5, _cargoc.names_long[rvi->cargo_type]);
|
||||
SetDParam(6, rvi->capacity << multihead);
|
||||
} else {
|
||||
SetDParam(5, STR_8838_N_A);
|
||||
}
|
||||
DrawStringMultiCenter(x, y, STR_885B_COST_WEIGHT_T_SPEED_POWER, maxw);
|
||||
}
|
||||
|
||||
void DrawNewsNewTrainAvail(Window *w)
|
||||
{
|
||||
EngineID 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, 0x323 | USE_COLORTABLE);
|
||||
DrawTrainEngineInfo(engine, w->width >> 1, 129, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewTrainAvail(const NewsItem *ni)
|
||||
{
|
||||
EngineID engine = ni->string_id;
|
||||
SetDParam(0, STR_8859_NEW_NOW_AVAILABLE);
|
||||
SetDParam(1, GetEngineCategoryName(engine));
|
||||
SetDParam(2, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw)
|
||||
{
|
||||
const AircraftVehicleInfo *avi = AircraftVehInfo(engine);
|
||||
SetDParam(0, (_price.aircraft_base >> 3) * avi->base_cost >> 5);
|
||||
SetDParam(1, avi->max_speed << 3);
|
||||
SetDParam(2, avi->passenger_capacity);
|
||||
SetDParam(3, avi->mail_capacity);
|
||||
SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
|
||||
|
||||
DrawStringMultiCenter(x, y, STR_A02E_COST_MAX_SPEED_CAPACITY, maxw);
|
||||
}
|
||||
|
||||
void DrawNewsNewAircraftAvail(Window *w)
|
||||
{
|
||||
EngineID 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, 0x323 | USE_COLORTABLE);
|
||||
DrawAircraftEngineInfo(engine, w->width >> 1, 131, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewAircraftAvail(const NewsItem *ni)
|
||||
{
|
||||
EngineID engine = ni->string_id;
|
||||
SetDParam(0, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw)
|
||||
{
|
||||
const RoadVehicleInfo *rvi = RoadVehInfo(engine);
|
||||
|
||||
SetDParam(0, (_price.roadveh_base >> 3) * rvi->base_cost >> 5);
|
||||
SetDParam(1, rvi->max_speed * 10 >> 5);
|
||||
SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
|
||||
|
||||
SetDParam(4, rvi->capacity);
|
||||
SetDParam(3, _cargoc.names_long[rvi->cargo_type]);
|
||||
|
||||
DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw);
|
||||
}
|
||||
|
||||
void DrawNewsNewRoadVehAvail(Window *w)
|
||||
{
|
||||
EngineID 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, 0x323 | USE_COLORTABLE);
|
||||
DrawRoadVehEngineInfo(engine, w->width >> 1, 129, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewRoadVehAvail(const NewsItem *ni)
|
||||
{
|
||||
EngineID engine = ni->string_id;
|
||||
SetDParam(0, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
|
||||
static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw)
|
||||
{
|
||||
const ShipVehicleInfo *svi = ShipVehInfo(engine);
|
||||
SetDParam(0, svi->base_cost * (_price.ship_base >> 3) >> 5);
|
||||
SetDParam(1, svi->max_speed * 10 >> 5);
|
||||
SetDParam(2, _cargoc.names_long[svi->cargo_type]);
|
||||
SetDParam(3, svi->capacity);
|
||||
SetDParam(4, svi->running_cost * _price.ship_running >> 8);
|
||||
DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw);
|
||||
}
|
||||
|
||||
void DrawNewsNewShipAvail(Window *w)
|
||||
{
|
||||
EngineID 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, 0x323 | USE_COLORTABLE);
|
||||
DrawShipEngineInfo(engine, w->width >> 1, 131, w->width - 52);
|
||||
}
|
||||
|
||||
StringID GetNewsStringNewShipAvail(const NewsItem *ni)
|
||||
{
|
||||
EngineID engine = ni->string_id;
|
||||
SetDParam(0, STR_982C_NEW_SHIP_NOW_AVAILABLE);
|
||||
SetDParam(1, GetCustomEngineName(engine));
|
||||
return STR_02B6;
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "fileio.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
#if defined(UNIX) || defined(__OS2__)
|
||||
#include <ctype.h> // required for tolower()
|
||||
#endif
|
||||
|
||||
/*************************************************/
|
||||
/* FILE IO ROUTINES ******************************/
|
||||
/*************************************************/
|
||||
|
||||
#define FIO_BUFFER_SIZE 512
|
||||
|
||||
typedef struct {
|
||||
byte *buffer, *buffer_end;
|
||||
uint32 pos;
|
||||
FILE *cur_fh;
|
||||
FILE *handles[32];
|
||||
byte buffer_start[512];
|
||||
} Fio;
|
||||
|
||||
static Fio _fio;
|
||||
|
||||
// Get current position in file
|
||||
uint32 FioGetPos(void)
|
||||
{
|
||||
return _fio.pos + (_fio.buffer - _fio.buffer_start) - FIO_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
void FioSeekTo(uint32 pos, int mode)
|
||||
{
|
||||
if (mode == SEEK_CUR) pos += FioGetPos();
|
||||
_fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE;
|
||||
fseek(_fio.cur_fh, (_fio.pos=pos), SEEK_SET);
|
||||
}
|
||||
|
||||
// Seek to a file and a position
|
||||
void FioSeekToFile(uint32 pos)
|
||||
{
|
||||
FILE *f = _fio.handles[pos >> 24];
|
||||
assert(f != NULL);
|
||||
_fio.cur_fh = f;
|
||||
FioSeekTo(pos & 0xFFFFFF, SEEK_SET);
|
||||
}
|
||||
|
||||
byte FioReadByte(void)
|
||||
{
|
||||
if (_fio.buffer == _fio.buffer_end) {
|
||||
_fio.pos += FIO_BUFFER_SIZE;
|
||||
fread(_fio.buffer = _fio.buffer_start, 1, FIO_BUFFER_SIZE, _fio.cur_fh);
|
||||
}
|
||||
return *_fio.buffer++;
|
||||
}
|
||||
|
||||
void FioSkipBytes(int n)
|
||||
{
|
||||
for(;;) {
|
||||
int m = min(_fio.buffer_end - _fio.buffer, n);
|
||||
_fio.buffer += m;
|
||||
n -= m;
|
||||
if (n == 0) break;
|
||||
FioReadByte();
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16 FioReadWord(void)
|
||||
{
|
||||
byte b = FioReadByte();
|
||||
return (FioReadByte() << 8) | b;
|
||||
}
|
||||
|
||||
uint32 FioReadDword(void)
|
||||
{
|
||||
uint b = FioReadWord();
|
||||
return (FioReadWord() << 16) | b;
|
||||
}
|
||||
|
||||
void FioReadBlock(void *ptr, uint size)
|
||||
{
|
||||
FioSeekTo(FioGetPos(), SEEK_SET);
|
||||
_fio.pos += size;
|
||||
fread(ptr, 1, size, _fio.cur_fh);
|
||||
}
|
||||
|
||||
static inline void FioCloseFile(int slot)
|
||||
{
|
||||
if (_fio.handles[slot] != NULL) {
|
||||
fclose(_fio.handles[slot]);
|
||||
_fio.handles[slot] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FioCloseAll(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i != lengthof(_fio.handles); i++)
|
||||
FioCloseFile(i);
|
||||
}
|
||||
|
||||
bool FiosCheckFileExists(const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
sprintf(buf, "%s%s", _path.data_dir, filename);
|
||||
|
||||
f = fopen(buf, "rb");
|
||||
#if !defined(WIN32)
|
||||
if (f == NULL) {
|
||||
char *s;
|
||||
// Make lower case and try again
|
||||
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
|
||||
#if defined SECOND_DATA_DIR
|
||||
// tries in the 2nd data directory
|
||||
if (f == NULL) {
|
||||
sprintf(buf, "%s%s", _path.second_data_dir, filename);
|
||||
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f == NULL)
|
||||
return false;
|
||||
else {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *FioFOpenFile(const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
sprintf(buf, "%s%s", _path.data_dir, filename);
|
||||
|
||||
f = fopen(buf, "rb");
|
||||
#if !defined(WIN32)
|
||||
if (f == NULL) {
|
||||
char *s;
|
||||
// Make lower case and try again
|
||||
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
|
||||
#if defined SECOND_DATA_DIR
|
||||
// tries in the 2nd data directory
|
||||
if (f == NULL) {
|
||||
sprintf(buf, "%s%s", _path.second_data_dir, filename);
|
||||
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void FioOpenFile(int slot, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
sprintf(buf, "%s%s", _path.data_dir, filename);
|
||||
|
||||
f = fopen(buf, "rb");
|
||||
#if !defined(WIN32)
|
||||
if (f == NULL) {
|
||||
char *s;
|
||||
// Make lower case and try again
|
||||
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
|
||||
#if defined SECOND_DATA_DIR
|
||||
// tries in the 2nd data directory
|
||||
if (f == NULL) {
|
||||
sprintf(buf, "%s%s", _path.second_data_dir, filename);
|
||||
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
|
||||
*s = tolower(*s);
|
||||
f = fopen(buf, "rb");
|
||||
}
|
||||
|
||||
if (f == NULL)
|
||||
sprintf(buf, "%s%s", _path.data_dir, filename); //makes it print the primary datadir path instead of the secundary one
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f == NULL)
|
||||
error("Cannot open file '%s'", buf);
|
||||
|
||||
FioCloseFile(slot); // if file was opened before, close it
|
||||
_fio.handles[slot] = f;
|
||||
FioSeekToFile(slot << 24);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef FILEIO_H
|
||||
#define FILEIO_H
|
||||
|
||||
void FioSeekTo(uint32 pos, int mode);
|
||||
void FioSeekToFile(uint32 pos);
|
||||
uint32 FioGetPos(void);
|
||||
byte FioReadByte(void);
|
||||
uint16 FioReadWord(void);
|
||||
uint32 FioReadDword(void);
|
||||
void FioCloseAll(void);
|
||||
FILE *FioFOpenFile(const char *filename);
|
||||
void FioOpenFile(int slot, const char *filename);
|
||||
void FioReadBlock(void *ptr, uint size);
|
||||
void FioSkipBytes(int n);
|
||||
bool FiosCheckFileExists(const char *filename);
|
||||
|
||||
#endif /* FILEIO_H */
|
||||
-116
@@ -1,116 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Arguments given? Show help text.
|
||||
if [ "$#" != "0" ]; then
|
||||
cat <<EOF
|
||||
Usage: ./findversion.sh
|
||||
Finds the current revision and if the code is modified.
|
||||
|
||||
Output: <REV>\t<REV_NR>\t<MODIFIED>\t<CLEAN_REV>
|
||||
REV
|
||||
a string describing what version of the code the current checkout is
|
||||
based on. The exact format of this string depends on the version
|
||||
control system in use, but it tries to identify the revision used as
|
||||
close as possible (using the svn revision number or hg/git hash).
|
||||
This also includes an indication of whether the checkout was
|
||||
modified and which branch was checked out. This value is not
|
||||
guaranteed to be sortable, but is mainly meant for identifying the
|
||||
revision and user display.
|
||||
|
||||
If no revision identifier could be found, this is left empty.
|
||||
REV_NR
|
||||
the revision number of the svn revision this checkout is based on.
|
||||
This can be used to determine which functionality is present in this
|
||||
checkout. For trunk svn checkouts and hg/git branches based upon it,
|
||||
this number should be accurate. For svn branch checkouts, this
|
||||
number is mostly meaningless, at least when comparing with the
|
||||
REV_NR from other branches or trunk.
|
||||
|
||||
This number should be sortable. Within a given branch or trunk, a
|
||||
higher number means a newer version. However, when using git or hg,
|
||||
this number will not increase on new commits.
|
||||
|
||||
If no revision number could be found, this is left empty.
|
||||
MODIFIED
|
||||
Whether (the src directory of) this checkout is modified or not. A
|
||||
value of 0 means not modified, a value of 2 means it was modified.
|
||||
Modification is determined in relation to the commit identified by
|
||||
REV, so not in relation to the svn revision identified by REV_NR.
|
||||
|
||||
A value of 1 means that the modified status is unknown, because this
|
||||
is not an svn/git/hg checkout for example.
|
||||
|
||||
CLEAN_REV
|
||||
the same as REV but without branch name
|
||||
|
||||
By setting the AWK environment variable, a caller can determine which
|
||||
version of "awk" is used. If nothing is set, this script defaults to
|
||||
"awk".
|
||||
EOF
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Allow awk to be provided by the caller.
|
||||
if [ -z "$AWK" ]; then
|
||||
AWK=awk
|
||||
fi
|
||||
|
||||
# Find out some dirs
|
||||
cd `dirname "$0"`
|
||||
ROOT_DIR=`pwd`
|
||||
SRC_DIR=src
|
||||
|
||||
# Determine if we are using a modified version
|
||||
# Assume the dir is not modified
|
||||
MODIFIED="0"
|
||||
if [ -d "$ROOT_DIR/.svn" ]; then
|
||||
# We are an svn checkout
|
||||
if [ -n "`svnversion \"$SRC_DIR\" | grep 'M'`" ]; then
|
||||
MODIFIED="2"
|
||||
fi
|
||||
# Find the revision like: rXXXXM-branch
|
||||
BRANCH=`LC_ALL=C svn info "$SRC_DIR" | "$AWK" '/^URL:.*branches/ { split($2, a, "/"); for(i in a) if (a[i]=="branches") { print a[i+1]; break } }'`
|
||||
TAG=`LC_ALL=C svn info "$SRC_DIR" | "$AWK" '/^URL:.*tags/ { split($2, a, "/"); for(i in a) if (a[i]=="tags") { print a[i+1]; break } }'`
|
||||
REV_NR=`LC_ALL=C svn info "$SRC_DIR" | "$AWK" '/^Last Changed Rev:/ { print $4 }'`
|
||||
if [ -n "$TAG" ]; then
|
||||
REV=$TAG
|
||||
else
|
||||
REV="r$REV_NR"
|
||||
fi
|
||||
elif [ -d "$ROOT_DIR/.git" ]; then
|
||||
# We are a git checkout
|
||||
if [ -n "`git diff-index HEAD \"$SRC_DIR\"`" ]; then
|
||||
MODIFIED="2"
|
||||
fi
|
||||
HASH=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null | cut -c1-8`
|
||||
REV="g$HASH"
|
||||
BRANCH=`git branch|grep '[*]' | sed 's/\* //;s/^master$//'`
|
||||
REV_NR=`LC_ALL=C git log --pretty=format:%s "$SRC_DIR" | grep "^(svn r[0-9]*)" | head -n 1 | sed "s/.*(svn r\([0-9]*\)).*/\1/"`
|
||||
elif [ -d "$ROOT_DIR/.hg" ]; then
|
||||
# We are a hg checkout
|
||||
if [ -n "`hg status \"$SRC_DIR\" | grep -v '^?'`" ]; then
|
||||
MODIFIED="2"
|
||||
fi
|
||||
HASH=`LC_ALL=C hg parents 2>/dev/null | head -n 1 | cut -d: -f3 | cut -c1-8`
|
||||
REV="h$HASH"
|
||||
BRANCH=`hg branch | sed 's/^default$//'`
|
||||
REV_NR=`LC_ALL=C hg log -r $HASH:0 -k "svn" -l 1 --template "{desc}\n" "$SRC_DIR" | grep "^(svn r[0-9]*)" | head -n 1 | sed "s/.*(svn r\([0-9]*\)).*/\1/"`
|
||||
else
|
||||
# We don't know
|
||||
MODIFIED="1"
|
||||
BRANCH=""
|
||||
REV=""
|
||||
REV_NR=""
|
||||
fi
|
||||
|
||||
if [ "$MODIFIED" -eq "2" ]; then
|
||||
REV="${REV}M"
|
||||
fi
|
||||
|
||||
CLEAN_REV=${REV}
|
||||
|
||||
if [ -n "$BRANCH" ]; then
|
||||
REV="${REV}-$BRANCH"
|
||||
fi
|
||||
|
||||
echo "$REV $REV_NR $MODIFIED $CLEAN_REV"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user