diff --git a/COPYING b/COPYING new file mode 100644 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + 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 + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU 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 +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +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 +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +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 +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +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 +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +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 + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with 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. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Jamfile.next b/Jamfile.next new file mode 100644 --- /dev/null +++ b/Jamfile.next @@ -0,0 +1,163 @@ +CFILES = ai.c aircraft_cmd.c aircraft_gui.c airport_gui.c + bridge_gui.c clear_cmd.c command.c disaster_cmd.c + dock_gui.c dummy_land.c economy.c engine.c engine_gui.c + fileio.c gfx.c graph_gui.c industry_cmd.c industry_gui.c + intro_gui.c landscape.c main_gui.c minilzo.c misc.c + misc_cmd.c misc_gui.c music_gui.c namegen.c network.c + news_gui.c oldloader.c order_cmd.c order_gui.c pathfind.c + player_gui.c players.c rail_cmd.c rail_gui.c road_cmd.c + road_gui.c roadveh_cmd.c roadveh_gui.c saveload.c sdl.c + settings.c settings_gui.c ship_cmd.c ship_gui.c smallmap_gui.c + sound.c spritecache.c station_cmd.c station_gui.c + strings.c subsidy_gui.c texteff.c town_cmd.c town_gui.c + train_cmd.c train_gui.c tree_cmd.c ttd.c + tunnelbridge_cmd.c unmovable_cmd.c vehicle.c + viewport.c water_cmd.c widget.c window.c screenshot.c + airport.c grfspecial.c terraform_gui.c ; + + +LANGFILES = english.txt swedish.txt french.txt german.txt italian.txt slovak.txt hungarian.txt norwegian.txt danish.txt czech.txt galician.txt polish.txt; + +#################### +# On UNIX we use gcc +#################### +if $(UNIX) { + SDL_CONFIG_CFLAGS = `XX_SDL_CONFIG_PLACEHOLDER_XX --cflags` ; + SDL_CONFIG_LIBS = `XX_SDL_CONFIG_PLACEHOLDER_XX --libs` ; + + LINKFLAGS += $(SDL_CONFIG_LIBS) ; + CC = gcc ; + CCFLAGS += -Wall -Wno-multichar -DUNIX -DWITH_SDL ; + + OPTIMFLAGS = -O2 -fomit-frame-pointer ; + DEBUGFLAGS = -g ; + +# also include extmidi + CFILES += extmidi.c unix.c ; + +# compile in PNG support? + if $(WITH_PNG) { + CCFLAGS += -DWITH_PNG -I$(WITH_PNG) ; + LINKFLAGS += -lpng ; + } + +# compile in zlib support? + if $(WITH_ZLIB) { + CCFLAGS += -DWITH_ZLIB ; + LINKFLAGS += -lz ; + } +# compile for BeOS 5.1 and higher + if $(WITH_BONE_NETWORKING) { + CCFLAGS += -DENABLE_NETWORK ; + LINKFLAGS += -lsocket -lbind ; + } +# link in BeOS MIDI and Be API libraries + if $(BEOS_MIDI) { + CCFLAGS += -DBEOS_MIDI ; + LINKFLAGS += -lbe -lmidi ; + CFILES += bemidi.cpp ; + } +} + +#################### +# MSVC on Win32 +#################### + +actions ActWin32Res { + $(VISUALC)\\..\\common\\msdev98\\bin\\rc /r /i $(STDHDRS) /fo $(<) $(>) +} + +rule Win32Res { ActWin32Res $(<) : $(>) ; DEPENDS $(<) : $(>) ; } + +if $(TOOLSET) = VISUALC { + OPTIMFLAGS = /Oa /Os /Ow /Oy /Oi /Og /Ox /Gr /Gf /Gy /Zp4 /J /WX /W3 -DNDEBUG ; + + CCFLAGS += -DWIN32 -DWIN32_EXCEPTION_TRACKER ; + CFILES += win32.c ; + LINKFLAGS += /opt:nowin98 /LIBPATH:$(VISUALC)\\lib ; + + LINKLIBS = ws2_32.lib winmm.lib user32.lib gdi32.lib ; + +# compile resources too + EOBJ = ttd.res ; + Win32Res ttd.res : ttd.rc ; + +# png screenshots? + if $(WITH_PNG) { + CCFLAGS += -DWITH_PNG -I$(WITH_PNG) ; + LINKLIBS += libpng.lib ; + } + +# zlib savegames? + if $(WITH_ZLIB) { + CCFLAGS += -DWITH_ZLIB ; + LINKLIBS += zlibstat.lib ; + } + +# build release by default + RELEASE = 1 ; +} + + +#################### +# Common +#################### +rule MyObjects { + local _i _t _s ; + + _t = $(OUTDIR)/$(>:S=$(SUFOBJ)) ; + OPTIM on $(_t) = $(3) ; + + MkDir $(OUTDIR) ; + Depends $(_t) : $(OUTDIR) ; + + for _i in $(>) { + _s = $(OUTDIR)/$(_i:S=$(SUFOBJ)) ; + Object $(_s) : $(_i) ; + +# special handling for sdl.c and unix.c + if $(_i) = sdl.c || $(_i) = unix.c { CCFLAGS on $(_s) += $(SDL_CONFIG_CFLAGS) ; } + } + MainFromObjects $(OUTDIR)/$(<) : $(_t) $(EOBJ) ; +} + +rule MyMain { + if $(RELEASE) { + OUTDIR = release ; + MyObjects ttd : $(>) : $(OPTIMFLAGS) ; + } else { + OUTDIR = debug ; + MyObjects ttd : $(>) : -D_DEBUG $(DEBUGFLAGS) ; + } +} + +actions CompileLang { + strgen$(SLASH)strgen $(>) +} + +rule LangFile { + if $(>) = lang/english.txt { + CompileLang $(<) table/strings.h : ; + DEPENDS table/string.h : $(>) ; + } else { + CompileLang $(<) : $(>) ; + } + + Clean clean : $(<) ; + DEPENDS $(<) : $(>) ; + DEPENDS all : $(<) ; + DEPENDS $(<) : strgen/strgen ; +} + +rule LangFiles { + local _i ; + for _i in $(<) { LangFile $(_i:S=.lng) : $(_i) ; } + Clean clean : table/strings.h ; +} + +LangFiles lang/$(LANGFILES) ; + +Main strgen/strgen : strgen/strgen.c ; + +MyMain ttd : $(CFILES) ; + diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,615 @@ +# This Makefile is partially based on "a completely generic Makefile", +# originally created by Justin Husted +# +# Rewrite and sane dependencies support by Petr Baudis +# Cygwin support and configuration by Jaen Saul +# A lot of modifications by Bjarni Corfitzen +# +# Last modified by: $Author: strigeus $ +# On: $Date: 2004/03/11 19:15:06 $ + + +############################################################################## +# +# 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 + +# 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 +# +# Summary of library choice defines +# WITH_ZLIB: savegames using zlib +# WITH_PNG: screenshots using PNG +# WITH_SDL: SDL video driver support +# +# Summary of other defines: +# MANUAL_CONFIG: do not use Makefile.config, config options set manually +# DEBUG: build in debug mode +# PROFILE: build in profile mode, disables -s and -fomit-frame-pointer +# DISPLAY_WARNINGS: when off, some errors are not displayed while compiling +# TRANSLATOR: build in translator mode (untranslated strings are prepended by +# a 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 +# +# DATA_DIR_PREFIX: This sets the dir OpenTTD looks for the needed files. +# MUST END WITH / if defined +# +# STATIC: link statically +# CYGWIN: build in Cygwin environment +# MINGW: build with MingW compiler, link with MingW libraries +# +# Experimental (does not work properly): +# WITH_NETWORK: enable networking +# WITH_DIRECTMUSIC: enable DirectMusic MIDI support + + +############################################################################## +# +# Configuration +# + +# CONFIG_WRITER have to be found even for manual configuration +CONFIG_WRITER=makefiledir/Makefile.config_writer + +ifndef MANUAL_CONFIG +# 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) +else +CONFIG_INCLUDED:=1 +endif + +# tests if makefile.config contains the new needed SDL-CONFIG +# it updates makefile.config if needed. Flags like ENABLE_NETWORK are remembered +ifndef SDL-CONFIG +ifdef WITH_SDL +ifndef MANUAL_CONFIG +#network is enabled by default +ENABLE_NETWORK:=1 +UPDATECONFIG:=upgradeconf +CONFIG_INCLUDED:= +else +# this should define SDL-CONFIG for manual configuration +ifeq ($(shell uname),FreeBSD) +SDL-CONFIG:=sdl11-config +else +SDL-CONFIG:=sdl-config +endif +endif +endif +endif + +ifndef CONFIG_INCLUDED +-include $(LIB_DETECTION) +endif + +ifdef DISPLAY_WARNINGS +WARNING_DISPLAY:=-fstrict-aliasing +else +WARNING_DISPLAY:=-fno-strict-aliasing +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 + + +# Force SDL on UNIX platforms +ifndef WITH_SDL +ifdef UNIX +$(error You need to have SDL installed in order to run OpenTTD on UNIX.) +endif +endif + + + +############################################################################## +# +# Compiler configuration +# + +CC=gcc +CXX=g++ + +ifdef MORPHOS +CC += -noixemul -pipe +CXX += -noixemul -pipe +endif + +# Executable file extension +ifdef WIN32 +EXE=.exe +else +EXE= +endif + +# Set output executable names +TTD=ttd$(EXE) +STRGEN=strgen/strgen$(EXE) +OSXAPP="OpenTTD.app" + +# What revision are we compiling, if we have an idea? +REV_NUMBER := $(shell if test -d .svn; then svnversion . | tr -dc 0-9; fi) + +ifdef RELEASE +REV:=$(RELEASE) +else +REV := $(shell if test -d .svn; then echo -n r; svnversion .; fi) +tmp_test:=$(shell echo "$(REV)" | grep "M" ) +ifdef tmp_test +REV_NUMBER:=1 +endif +endif + +ifndef REV_NUMBER +REV_NUMBER:=0 +endif + +# MorphOS needs builddate +BUILDDATE=`date +%d.%m.%y` + +# AMD64 needs a little more settings to work +ifeq ($(shell uname -m), x86_64) +endwarnings:=endwarnings +64_bit_warnings:=64_bit_warnings +BASECFLAGS += -m64 -D_LITTLE_ENDIAN +endif + + +# When calling the compiler, use these flags +# -g debugging symbols +# -Wall all warnings +# -s automatic strip +# +# You may also want: +# -O optimize or -O2 fully optimize (O's above 2 are not recommended) +# -pg profile - generate profiling data. See "man gprof" to use this. + +CFLAGS=-Wall -Wno-multichar +CDEFS=-DWITH_REV +LDFLAGS= +LIBS= + +ifdef DEBUG +# Debug mode +CDEFS += -D_DEBUG +BASECFLAGS += -g +else +ifdef PROFILE +BASECFLAGS += -pg +else +# Release mode +ifndef MORPHOS +# automatical strip breaks under morphos +BASECFLAGS += -s +LDFLAGS += -s +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 -mpowerpc-gpopt -force_cpusubtype_ALL $(WARNING_DISPLAY) +else +ifdef MORPHOS +BASECFLAGS += -O2 -funroll-loops -fexpensive-optimizations -mstring -mmultiple $(WARNING_DISPLAY) +else +BASECFLAGS += -O2 $(WARNING_DISPLAY) +endif +ifndef PROFILE +BASECFLAGS += -fomit-frame-pointer +endif +endif +endif + +ifdef STATIC +ifndef OSX # OSX can't build static if -static flag is used +LDFLAGS += -static +endif +endif + +# If building on Cygwin/MingW don't link with Cygwin libs +ifdef WIN32 +ifdef MINGW +ifdef CYGWIN +BASECFLAGS += -mno-cygwin +LDFLAGS += -mno-cygwin +endif +endif +endif + +CFLAGS += $(BASECFLAGS) + +ifdef UNIX +CDEFS += -DUNIX +endif + +# SDL config +ifdef WITH_SDL +CDEFS += -DWITH_SDL +CFLAGS += `$(SDL-CONFIG) --cflags` +ifdef STATIC +LIBS += `$(SDL-CONFIG) --static-libs` +else +LIBS += `$(SDL-CONFIG) --libs` +endif +endif + + +# zlib config +ifdef WITH_ZLIB + CDEFS += -DWITH_ZLIB + ifdef STATIC + ifdef OSX +# zlib is default on OSX, so everybody have it. No need for static linking + LIBS += -lz + else + ifndef STATIC_ZLIB_PATH + ifndef MANUAL_CONFIG + # updates makefile.config with the zlib path + UPDATECONFIG:=upgradeconf + endif + TEMP:=$(shell ls /lib 2>/dev/null | grep "zlib.a")$(shell ls /lib 2>/dev/null | grep "libz.a") + ifdef TEMP + STATIC_ZLIB_PATH:=/lib/$(TEMP) + else + TEMP:=$(shell ls /usr/lib 2>/dev/null | grep "zlib.a")$(shell ls /usr/lib 2>/dev/null | grep "libz.a") + ifdef TEMP + STATIC_ZLIB_PATH:=/usr/lib/$(TEMP) + else + TEMP:=$(shell ls /usr/local/lib 2>/dev/null | grep "zlib.a")$(shell ls /usr/local/lib 2>/dev/null | grep "libz.a") + ifdef TEMP + STATIC_ZLIB_PATH:=/usr/local/lib/$(TEMP) + endif + endif + endif + endif + LIBS += $(STATIC_ZLIB_PATH) + endif + else + LIBS += -lz + endif +endif + +# libpng config +ifdef WITH_PNG +CDEFS += -DWITH_PNG +# FreeBSD doesn't use libpng-config +ifdef FREEBSD +LIBS += -lpng +else +CFLAGS += `libpng-config --cflags` +ifdef OSX +ifdef STATIC +# Seems like we need a tiny hack for OSX static to work +LIBS += `libpng-config --prefix`/lib/libpng.a +else +LIBS += `libpng-config --libs` +endif +else +# seems like older libpng versions are broken and need this +PNGCONFIG_FLAGS = --ldflags --libs +ifdef STATIC +LIBS += `libpng-config --static $(PNGCONFIG_FLAGS)` +else +LIBS += `libpng-config $(PNGCONFIG_FLAGS)` +endif +endif +endif +endif + + +ifdef TRANSLATOR +STRGEN_FLAGS=-t +else +STRGEN_FLAGS= +endif + +# file paths setup +ifdef GAME_DATA_DIR +CDEFS += -DGAME_DATA_DIR=\"$(GAME_DATA_DIR)\" +endif + +ifdef PERSONAL_DIR +CDEFS += -DPERSONAL_DIR=\"$(PERSONAL_DIR)\" +endif + +ifdef USE_HOMEDIR +CDEFS += -DUSE_HOMEDIR +endif + +# MIDI setup +ifdef OSX +ifndef MIDI +MIDI:=$(OSXAPP)/contents/macos/track_starter +endif +endif + +ifdef MIDI +CDEFS += -DEXTERNAL_PLAYER=\"$(MIDI)\" +ifdef MIDI_ARG +CDEFS += -DMIDI_ARG=\"$(MIDI_ARG)\" +endif +endif + +# Experimental +ifdef WITH_NETWORK +CDEFS += -DENABLE_NETWORK +ifdef UNIX +ifndef OSX +ifndef MORPHOS +# this have caused problems on many platforms and disabling it didn't break anything +# now we test if disabling it as a general breaks it for anybody +#LIBS += -lresolv +endif +endif +endif +endif + +ifdef WITH_DIRECTMUSIC +CDEFS += -DWIN32_ENABLE_DIRECTMUSIC_SUPPORT +endif + +ifdef WIN32 +LIBS += -lws2_32 -lwinmm -lgdi32 -ldxguid -lole32 -lstdc++ +TTDLDFLAGS += -Wl,--subsystem,windows +endif + +# sets up the paths for use for make install +ifdef BINARY_DIR +BINARY_INSTALL:=$(BINARY_DIR)$(TTD) +else +BINARY_INSTALL:=$(INSTALL_DIR)$(TTD) +endif +ifdef DATA_DIR_PREFIX +DATA_DIR:=$(DATA_DIR_PREFIX) +else +DATA_DIR:=$(INSTALL_DIR) +endif + +############################################################################## +# +# What to compile +# (users do not want to modify anything below) +# + + +### Sources + +ttd_SOURCES = \ + ai.c aircraft_cmd.c aircraft_gui.c airport.c airport_gui.c bridge_gui.c \ + clear_cmd.c command.c disaster_cmd.c dock_gui.c dummy_land.c economy.c \ + engine.c engine_gui.c fileio.c gfx.c graph_gui.c industry_cmd.c \ + industry_gui.c intro_gui.c landscape.c main_gui.c misc.c misc_cmd.c \ + misc_gui.c music_gui.c namegen.c network.c news_gui.c oldloader.c \ + order_cmd.c order_gui.c pathfind.c player_gui.c players.c rail_cmd.c \ + rail_gui.c road_cmd.c road_gui.c roadveh_cmd.c roadveh_gui.c saveload.c \ + settings_gui.c ship_cmd.c ship_gui.c smallmap_gui.c sound.c \ + spritecache.c station_cmd.c station_gui.c strings.c subsidy_gui.c \ + texteff.c town_cmd.c town_gui.c train_cmd.c train_gui.c tree_cmd.c \ + ttd.c tunnelbridge_cmd.c unmovable_cmd.c vehicle.c viewport.c \ + water_cmd.c widget.c window.c minilzo.c screenshot.c settings.c rev.c \ + grfspecial.c terraform_gui.c network_gui.c + +ifdef WITH_SDL +ttd_SOURCES += sdl.c +endif + +ifdef WIN32 +ttd_SOURCES += win32.c w32dm.c +else +ttd_SOURCES += extmidi.c unix.c +endif + +ttd_OBJS = $(ttd_SOURCES:%.c=%.o) + +ifdef WIN32 +# Resource file +ttd_OBJS += winres.o +endif + +ifdef WITH_DIRECTMUSIC +ttd_SOURCES += w32dm2.cpp +ttd_OBJS += w32dm2.o +endif + +ttd_DEPS1 = $(foreach obj,$(ttd_OBJS),.deps/$(obj)) +ttd_DEPS = $(ttd_DEPS1:%.o=%.P) + +LANG_TXT = $(filter-out %.unfinished.txt,$(wildcard lang/*.txt)) +LANGS = $(LANG_TXT:%.txt=%.lng) + +C_COMPILE = $(CC) $(CFLAGS) $(CDEFS) +CXX_COMPILE = $(CXX) $(CFLAGS) $(CDEFS) + +C_BUILD = $(C_COMPILE) -c +CXX_BUILD = $(CXX_COMPILE) -c + +C_LINK = $(CC) $(LDFLAGS) -o + + +############################################################################## +# +# Targets +# + + +### Normal build rules + + +ifdef OSX +OSX:=OSX +endif + + +all: $(UPDATECONFIG) $(TTD) $(OSX) $(endwarnings) + + +$(TTD): table/strings.h $(ttd_OBJS) $(LANGS) $(MAKE_CONFIG) + $(C_LINK) $@ $(TTDLDFLAGS) $(ttd_OBJS) $(LIBS) + +$(OSX): + @mkdir -p $(OSXAPP)/Contents/MacOS + @mkdir -p $(OSXAPP)/Contents/Resources + @echo "APPL????" > $(OSXAPP)/Contents/PkgInfo + @cp os/macos/ttd.icns $(OSXAPP)/Contents/Resources/ + @os/macos/plistgen.sh $(OSXAPP) $(REV) + @cp os/macos/track_starter $(OSXAPP)/contents/macos + @ls os/macos | grep -q "\.class" || \ + javac os/macos/OpenTTDMidi.java + @cp os/macos/OpenTTDMidi.class $(OSXAPP)/contents/macos + @cp $(TTD) $(OSXAPP)/Contents/MacOS/ttd + +$(endwarnings): $(64_bit_warnings) + +$(64_bit_warnings): + $(warning 64 bit CPUs will get some 64 bit specific bugs!) + $(warning If you see any bugs, include in your bug report that you use a 64 bit CPU) + +$(STRGEN): strgen/strgen.c rev.o + $(CC) $(BASECFLAGS) $(CDEFS) -o $@ $^ + +lang/english.lng: lang/english.txt $(STRGEN) + $(STRGEN) + +table/strings.h: lang/english.lng + +lang/%.lng: lang/%.txt $(STRGEN) + $(STRGEN) $(STRGEN_FLAGS) $< + +winres.o: ttd.rc + windres -o $@ $< + + +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 + @echo 'const int _revision_number = $(REV_NUMBER);' >>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: + rm -rf .deps *~ $(TTD) $(STRGEN) core table/strings.h $(LANGS) $(ttd_OBJS) + +mrproper: clean + rm -rf $(MAKE_CONFIG) + +ifndef OSX +ifndef MORPHOS +install: + @if [ "$(INSTALL)" == "" ]; then $(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\") + @if [ "$(DATA_DIR)" == "" ]; then $(error no install path set - check makefile.config) + mkdir -p $(DATA_DIR)/lang + mkdir -p $(DATA_DIR)/data + cp $(TTD) $(BINARY_INSTALL) + cp lang/*.lng $(DATA_DIR)/lang + cp data/*.grf $(DATA_DIR)/data +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 $(64_bit_warnings) $(endwarnings) love + + +### Automatic configuration +-include $(CONFIG_WRITER) + + +# Export all variables set to subprocesses (a bit dirty) +.EXPORT_ALL_VARIABLES: +upgradeconf: $(MAKE_CONFIG) + rm $(MAKE_CONFIG) + $(MAKE) $(MAKE_CONFIG) + +.PHONY: upgradeconf + + +### Internal build rules + +# This makes sure the .deps dir is always around. +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +# Introduce the dependencies +-include $(ttd_DEPS) + +# This compiles the object file as well as silently updating its dependencies +# list at the same time. It is not an issue that they aren't around during the +# first compilation round as we just build everything at that time anyway, +# therefore we do not need to watch deps. +%.o: %.c $(MAKE_CONFIG) + @echo '$(C_BUILD) $<'; \ + $(C_BUILD) $< -Wp,-MD,.deps/$(*F).pp + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +# For DirectMusic build +%.o: %.cpp $(MAKE_CONFIG) + $(CXX_BUILD) $< diff --git a/StdAfx.c b/StdAfx.c new file mode 100644 --- /dev/null +++ b/StdAfx.c @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ttd.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/ai.c b/ai.c new file mode 100644 --- /dev/null +++ b/ai.c @@ -0,0 +1,3943 @@ +#include "stdafx.h" +#include "ttd.h" +#include "player.h" +#include "vehicle.h" +#include "engine.h" +#include "command.h" +#include "town.h" +#include "industry.h" +#include "station.h" +#include "pathfind.h" +#include "economy.h" +#include "airport.h" + +// remove some day perhaps? +static Player *_cur_ai_player; + +typedef void AiStateAction(Player *p); + +enum { + AIS_0 = 0, + AIS_1 = 1, + AIS_VEH_LOOP = 2, + AIS_VEH_CHECK_REPLACE_VEHICLE = 3, + AIS_VEH_DO_REPLACE_VEHICLE = 4, + AIS_WANT_NEW_ROUTE = 5, + AIS_BUILD_DEFAULT_RAIL_BLOCKS = 6, + AIS_BUILD_RAIL = 7, + AIS_BUILD_RAIL_VEH = 8, + AIS_DELETE_RAIL_BLOCKS = 9, + AIS_BUILD_DEFAULT_ROAD_BLOCKS = 10, + AIS_BUILD_ROAD = 11, + AIS_BUILD_ROAD_VEHICLES = 12, + AIS_DELETE_ROAD_BLOCKS = 13, + AIS_AIRPORT_STUFF = 14, + AIS_BUILD_DEFAULT_AIRPORT_BLOCKS = 15, + AIS_BUILD_AIRCRAFT_VEHICLES = 16, + AIS_CHECK_SHIP_STUFF = 17, + AIS_BUILD_DEFAULT_SHIP_BLOCKS = 18, + AIS_DO_SHIP_STUFF = 19, + AIS_SELL_VEHICLE = 20, + AIS_REMOVE_STATION = 21, + AIS_REMOVE_TRACK = 22, + AIS_REMOVE_SINGLE_RAIL_TILE = 23 +}; + + +#include "table/ai_rail.h" + +static byte GetRailTrackStatus(TileIndex tile) { + uint32 r = GetTileTrackStatus(tile, 0); + return (byte) (r | r >> 8); +} + + +static void AiCase0(Player *p) +{ + p->ai.state = AIS_REMOVE_TRACK; + p->ai.state_counter = 0; +} + +static void AiCase1(Player *p) +{ + p->ai.cur_veh = NULL; + p->ai.state = AIS_VEH_LOOP; +} + +static void AiStateVehLoop(Player *p) +{ + Vehicle *v; + + v = p->ai.cur_veh == NULL ? _vehicles : p->ai.cur_veh+1; + + for (;v != endof(_vehicles); v++) { + if (v->type == 0 || v->owner != _current_player) + continue; + + if ((v->type == VEH_Train && v->subtype==0) || + v->type == VEH_Road || + (v->type == VEH_Aircraft && v->subtype <= 2) || + v->type == VEH_Ship) { + + /* replace engine? */ + if (v->type == VEH_Train && v->engine_type < 3 && + (_price.build_railvehicle >> 3) < p->player_money) { + p->ai.state = AIS_VEH_CHECK_REPLACE_VEHICLE; + p->ai.cur_veh = v; + return; + } + + /* not profitable? */ + if (v->age >= 730 && + v->profit_last_year < _price.station_value*5 && + v->profit_this_year < _price.station_value*5) { + p->ai.state_counter = 0; + p->ai.state = AIS_SELL_VEHICLE; + p->ai.cur_veh = v; + return; + } + + /* not reliable? */ + if ((v->age != 0 && + _engines[v->engine_type].reliability < 35389) || + v->age >= v->max_age) { + p->ai.state = AIS_VEH_CHECK_REPLACE_VEHICLE; + p->ai.cur_veh = v; + return; + } + } + } + + p->ai.state = AIS_WANT_NEW_ROUTE; + p->ai.state_counter = 0; +} + +// XXX +static const byte _rail_locos_count[3] = { + 27, 3, 5 +}; +extern const byte _rail_engines_start[3]; + +static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag) +{ + int best_veh_index = -1; + byte best_veh_score = 0; + int32 r; + + int i = _rail_engines_start[railtype]; + int end = i + _rail_locos_count[railtype]; + Engine *e = &_engines[i]; + do { + assert(!(_rail_vehicle_info[i].flags & RVI_WAGON)); + + if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) + continue; + + r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_RAIL_VEHICLE); + if (r != CMD_ERROR && + (!(_cmd_build_rail_veh_var1&1) || !(flag&1)) && + r <= money && + _cmd_build_rail_veh_score >= best_veh_score) { + best_veh_score = _cmd_build_rail_veh_score; + best_veh_index = i; + } + } while (++e, ++i != end); + + return best_veh_index; +} + +static int AiChooseRoadVehToBuild(byte cargo, int32 money) +{ + int best_veh_index = -1; + int32 best_veh_cost = 0; + int32 r; + + int i = _cargoc.ai_roadveh_start[cargo]; + int end = i + _cargoc.ai_roadveh_count[cargo]; + Engine *e = &_engines[i]; + do { + if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) + continue; + + r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_ROAD_VEH); + if (r != CMD_ERROR && r <= money && r >= best_veh_cost) { + best_veh_cost = r; + best_veh_index = i; + } + } while (++e, ++i != end); + + return best_veh_index; +} + +static int AiChooseAircraftToBuild(int32 money, byte flag) +{ + int best_veh_index = -1; + int32 best_veh_cost = 0; + int32 r; + + int i = AIRCRAFT_ENGINES_INDEX; + int end = i + NUM_AIRCRAFT_ENGINES; + Engine *e = &_engines[i]; + do { + if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) + continue; + + if (flag&1) { + if (i<253) continue; + } else { + if (i>=253) continue; + } + + r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_AIRCRAFT); + if (r != CMD_ERROR && r <= money && r >= best_veh_cost) { + best_veh_cost = r; + best_veh_index = i; + } + } while (++e, ++i != end); + + return best_veh_index; +} + +static int32 AiGetBasePrice(Player *p) +{ + int32 base = _price.station_value; + + // adjust base price when more expensive vehicles are available + if (p->ai.railtype_to_use == 1) base = (base * 3) >> 1; + else if (p->ai.railtype_to_use == 2) base *= 2; + + return base; +} + +#if 0 +static int AiChooseShipToBuild(byte cargo, int32 money) +{ + // XXX: not done + return 0; +} +#endif + +static int AiChooseRoadVehToReplaceWith(Player *p, Vehicle *v) +{ + int32 avail_money = p->player_money + v->value; + return AiChooseRoadVehToBuild(v->cargo_type, avail_money); +} + +static int AiChooseAircraftToReplaceWith(Player *p, Vehicle *v) +{ + int32 avail_money = p->player_money + v->value; + return AiChooseAircraftToBuild(avail_money, v->engine_type>=253?1:0); +} + +static int AiChooseTrainToReplaceWith(Player *p, Vehicle *v) +{ + int32 avail_money = p->player_money + v->value; + int num=0; + Vehicle *u = v; + + while (++num, u->next != NULL) { + u = u->next; + } + + // XXX: check if a wagon + return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0); +} + +static int AiChooseShipToReplaceWith(Player *p, Vehicle *v) +{ + error("!AiChooseShipToReplaceWith"); + + /* maybe useless, but avoids compiler warning this way */ + return 0; +} + +static void AiHandleGotoDepot(Player *p, int cmd) +{ + if ((p->ai.cur_veh->next_order & OT_MASK) != OT_GOTO_DEPOT) + DoCommandByTile(0, p->ai.cur_veh->index, 0, DC_EXEC, cmd); + + if (++p->ai.state_counter <= 1387) { + p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE; + return; + } + + if ((p->ai.cur_veh->next_order&OT_MASK) == OT_GOTO_DEPOT) { + p->ai.cur_veh->next_order = OT_DUMMY; + InvalidateWindow(WC_VEHICLE_VIEW, p->ai.cur_veh->index); + } +} + +static void AiRestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) +{ + uint16 *os = bak->order, ord; + int ind = 0; + while ((ord = *os++) != 0) { + if (DoCommandByTile(0, v->index + (ind << 16), ord, DC_EXEC, CMD_INSERT_ORDER) == CMD_ERROR) + break; + ind++; + } +} + +static void AiHandleReplaceTrain(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + BackuppedOrders orderbak[1]; + int veh; + uint tile; + + // wait until the vehicle reaches the depot. + if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { + AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT); + return; + } + + veh = AiChooseTrainToReplaceWith(p, v); + if (veh != -1) { + BackupVehicleOrders(v, orderbak); + tile = v->tile; + + if (DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON) != CMD_ERROR && + DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE) != CMD_ERROR) { + veh = _new_train_id; + AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN); + } + } +} + +static void AiHandleReplaceRoadVeh(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + BackuppedOrders orderbak[1]; + int veh; + uint tile; + + if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { + AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT); + return; + } + + veh = AiChooseRoadVehToReplaceWith(p, v); + if (veh != -1) { + BackupVehicleOrders(v, orderbak); + tile = v->tile; + + if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH) != CMD_ERROR && + DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH) != CMD_ERROR) { + veh = _new_roadveh_id; + AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH); + } + } +} + +static void AiHandleReplaceAircraft(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + int veh; + BackuppedOrders orderbak[1]; + uint tile; + + if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) { + AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR); + return; + } + + veh = AiChooseAircraftToReplaceWith(p, v); + if (veh != -1) { + BackupVehicleOrders(v, orderbak); + tile = v->tile; + + if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT) != CMD_ERROR && + DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT) != CMD_ERROR) { + veh = _new_aircraft_id; + AiRestoreVehicleOrders(&_vehicles[veh], orderbak); + DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); + } + } +} + +static void AiHandleReplaceShip(Player *p) +{ + error("!AiHandleReplaceShip"); +} + +typedef int CheckReplaceProc(Player *p, Vehicle *v); + +static CheckReplaceProc * const _veh_check_replace_proc[] = { + AiChooseTrainToReplaceWith, + AiChooseRoadVehToReplaceWith, + AiChooseShipToReplaceWith, + AiChooseAircraftToReplaceWith, +}; + +typedef void DoReplaceProc(Player *p); +static DoReplaceProc * const _veh_do_replace_proc[] = { + AiHandleReplaceTrain, + AiHandleReplaceRoadVeh, + AiHandleReplaceShip, + AiHandleReplaceAircraft +}; + +static void AiStateCheckReplaceVehicle(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + + if (v->type == 0 || v->owner != _current_player || v->type > VEH_Ship || _veh_check_replace_proc[v->type - VEH_Train](p, v) == -1) { + p->ai.state = AIS_VEH_LOOP; + } else { + p->ai.state_counter = 0; + p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE; + } +} + +static void AiStateDoReplaceVehicle(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + p->ai.state = AIS_VEH_LOOP; + // vehicle is not owned by the player anymore, something went very wrong. + if (v->type == 0 || v->owner != _current_player) + return; + _veh_do_replace_proc[v->type - VEH_Train](p); +} + +typedef struct FoundRoute { + int distance; + byte cargo; + void *from; + void *to; +} FoundRoute; + +static Town *AiFindRandomTown() { + Town *t = DEREF_TOWN(RandomRange(_total_towns)); + return (t->xy != 0) ? t : NULL; +} + +static Industry *AiFindRandomIndustry() { + Industry *i = DEREF_INDUSTRY(RandomRange(_total_industries)); + return (i->xy != 0) ? i : NULL; +} + +static void AiFindSubsidyIndustryRoute(FoundRoute *fr) +{ + int i; + byte cargo; + Subsidy *s; + Industry *from, *to_ind; + Town *to_tow; + TileIndex to_xy; + + // initially error + fr->distance = -1; + + // Randomize subsidy index.. + i = RandomRange(lengthof(_subsidies) * 3); + if (i >= lengthof(_subsidies)) + return; + + s = &_subsidies[i]; + + // Don't want passengers or mail + cargo = s->cargo_type; + if (cargo == 0xFF || cargo == CT_PASSENGERS || cargo == CT_MAIL || s->age > 7) + return; + fr->cargo = cargo; + + fr->from = from = DEREF_INDUSTRY(s->from); + + if (cargo == CT_GOODS || cargo == CT_FOOD) { + to_tow = DEREF_TOWN(s->to); + if (to_tow->population < (uint32)(cargo == CT_FOOD ? 200 : 900)) + return; // error + fr->to = to_tow; + to_xy = to_tow->xy; + } else { + to_ind = DEREF_INDUSTRY(s->to); + fr->to = to_ind; + to_xy = to_ind->xy; + } + + fr->distance = GetTileDist(from->xy, to_xy); +} + +static void AiFindSubsidyPassengerRoute(FoundRoute *fr) +{ + uint i; + Subsidy *s; + Town *from,*to; + + // initially error + fr->distance = -1; + + // Randomize subsidy index.. + i = RandomRange(lengthof(_subsidies) * 3); + if (i >= lengthof(_subsidies)) + return; + + s = &_subsidies[i]; + + // Only want passengers + if (s->cargo_type != CT_PASSENGERS || s->age > 7) + return; + fr->cargo = s->cargo_type; + + fr->from = from = DEREF_TOWN(s->from); + fr->to = to = DEREF_TOWN(s->to); + + // They must be big enough + if (from->population < 400 || to->population < 400) + return; + + fr->distance = GetTileDist(from->xy, to->xy); +} + +static void AiFindRandomIndustryRoute(FoundRoute *fr) +{ + Industry *i,*i2; + Town *t; + uint32 r; + byte cargo; + + // initially error + fr->distance = -1; + + r = Random(); + + // pick a source + fr->from = i = AiFindRandomIndustry(); + if (i == NULL) + return; + + // pick a random produced cargo + cargo = i->produced_cargo[0]; + if (r&1 && i->produced_cargo[1] != 0xFF) + cargo = i->produced_cargo[1]; + + fr->cargo = cargo; + + // don't allow passengers + if (cargo == 0xFF || cargo == CT_PASSENGERS) + return; + + if (cargo != CT_GOODS && cargo != CT_FOOD) { + // pick a dest, and see if it can receive + i2 = AiFindRandomIndustry(); + if (i2 == NULL || i == i2 || !(i2->accepts_cargo[0] == cargo || i2->accepts_cargo[1] == cargo || i2->accepts_cargo[2] == cargo)) + return; + + fr->to = i2; + fr->distance = GetTileDist(i->xy, i2->xy); + } else { + // pick a dest town, and see if it's big enough + t = AiFindRandomTown(); + if (t == NULL || t->population < (uint32)(cargo == CT_FOOD ? 200 : 900)) + return; + + fr->to = t; + fr->distance = GetTileDist(i->xy, t->xy); + } +} + +static void AiFindRandomPassengerRoute(FoundRoute *fr) +{ + uint32 r; + Town *source, *dest; + + // initially error + fr->distance = -1; + + r = Random(); + + fr->from = source = AiFindRandomTown(); + if (source == NULL || source->population < 400) + return; + + fr->to = dest = AiFindRandomTown(); + if (dest == NULL || source == dest || dest->population < 400) + return; + + fr->distance = GetTileDist(source->xy, dest->xy); +} + +// Warn: depends on 'xy' being the first element in both Town and Industry +#define GET_TOWN_OR_INDUSTRY_TILE(p) (((Town*)(p))->xy) + +static bool AiCheckIfRouteIsGood(Player *p, FoundRoute *fr, byte bitmask) +{ + TileIndex from_tile, to_tile; + Station *st; + int dist, cur; + uint same_station = 0; + + // Make sure distance to closest station is < 37 pixels. + from_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->from); + to_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->to); + + dist = 0xFFFF; + FOR_ALL_STATIONS(st) if (st->xy != 0 && st->owner == _current_player) { + cur = GetTileDist1D(from_tile, st->xy); + if (cur < dist) dist = cur; + cur = GetTileDist1D(to_tile, st->xy); + if (cur < dist) dist = cur; + if (to_tile == from_tile && st->xy == to_tile) + same_station++; + } + + // To prevent the AI from building ten busstations in the same town, do some calculations + // For each road or airport station, we want 350 of population! + if ((bitmask == 2 || bitmask == 4) && same_station > 2 && ((Town *)(fr->from))->population < same_station * 350) + return false; + + if (dist != 0xFFFF && dist > 37) + return false; + + if (p->ai.route_type_mask != 0 && !(p->ai.route_type_mask&bitmask) && !CHANCE16(1,5)) + return false; + + if (fr->cargo == CT_PASSENGERS || fr->cargo == CT_MAIL) { + if (((Town*)fr->from)->pct_pass_transported > 0x99 || + ((Town*)fr->to)->pct_pass_transported > 0x99) + return false; + + // Make sure it has a reasonably good rating + if ( ((Town*)fr->from)->ratings[_current_player] < -100 || + ((Town*)fr->to)->ratings[_current_player] < -100) + return false; + } else { + Industry *i = (Industry*)fr->from; + + if (i->pct_transported[fr->cargo != i->produced_cargo[0]] > 0x99 || + i->total_production[fr->cargo != i->produced_cargo[0]] == 0) + return false; + } + + p->ai.route_type_mask |= bitmask; + return true; +} + +static byte AiGetDirectionBetweenTiles(TileIndex a, TileIndex b) +{ + byte i = (GET_TILE_X(a) < GET_TILE_X(b)) ? 1 : 0; + if (GET_TILE_Y(a) >= GET_TILE_Y(b)) i ^= 3; + return i; +} + +static TileIndex AiGetPctTileBetween(TileIndex a, TileIndex b, byte pct) +{ + return TILE_XY( + GET_TILE_X(a) + ((GET_TILE_X(b) - GET_TILE_X(a)) * pct >> 8), + GET_TILE_Y(a) + ((GET_TILE_Y(b) - GET_TILE_Y(a)) * pct >> 8) + ); +} + +static void AiWantLongIndustryRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + // look for one from the subsidy list + AiFindSubsidyIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 60, 90+1)) + break; + + // try a random one + AiFindRandomIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 60, 90+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + if (!AiCheckIfRouteIsGood(p, &fr, 1)) + return; + + // Fill the source field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 9; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.unk6 = 1; + p->ai.src.unk7 = 0; + p->ai.src.buildcmd_a = 0x24; + p->ai.src.buildcmd_b = 0xFF; + p->ai.src.direction = AiGetDirectionBetweenTiles( + p->ai.src.spec_tile, + p->ai.dst.spec_tile + ); + p->ai.src.cargo = fr.cargo | 0x80; + + // Fill the dest field + + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 9; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.unk6 = 1; + p->ai.dst.unk7 = 0; + p->ai.dst.buildcmd_a = 0x34; + p->ai.dst.buildcmd_b = 0xFF; + p->ai.dst.direction = AiGetDirectionBetweenTiles( + p->ai.dst.spec_tile, + p->ai.src.spec_tile + ); + p->ai.dst.cargo = fr.cargo; + + // Fill middle field 1 + p->ai.mid1.spec_tile = AiGetPctTileBetween( + p->ai.src.spec_tile, + p->ai.dst.spec_tile, + 0x55 + ); + p->ai.mid1.use_tile = 0; + p->ai.mid1.rand_rng = 6; + p->ai.mid1.cur_building_rule = 0xFF; + p->ai.mid1.unk6 = 2; + p->ai.mid1.unk7 = 1; + p->ai.mid1.buildcmd_a = 0x30; + p->ai.mid1.buildcmd_b = 0xFF; + p->ai.mid1.direction = p->ai.src.direction; + p->ai.mid1.cargo = fr.cargo; + + // Fill middle field 2 + p->ai.mid2.spec_tile = AiGetPctTileBetween( + p->ai.src.spec_tile, + p->ai.dst.spec_tile, + 0xAA + ); + p->ai.mid2.use_tile = 0; + p->ai.mid2.rand_rng = 6; + p->ai.mid2.cur_building_rule = 0xFF; + p->ai.mid2.unk6 = 2; + p->ai.mid2.unk7 = 1; + p->ai.mid2.buildcmd_a = 0xFF; + p->ai.mid2.buildcmd_b = 0xFF; + p->ai.mid2.direction = p->ai.dst.direction; + p->ai.mid2.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_wagons = 3; + p->ai.build_kind = 2; + p->ai.num_build_rec = 4; + p->ai.num_loco_to_build = 2; + p->ai.num_want_fullload = 2; + p->ai.wagon_list[0] = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantMediumIndustryRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 40, 60+1)) + break; + + // try a random one + AiFindRandomIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 40, 60+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + if (!AiCheckIfRouteIsGood(p, &fr, 1)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 9; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.unk6 = 1; + p->ai.src.unk7 = 0; + p->ai.src.buildcmd_a = 0x10; + p->ai.src.buildcmd_b = 0xFF; + p->ai.src.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to) + ); + p->ai.src.cargo = fr.cargo | 0x80; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 9; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.unk6 = 1; + p->ai.dst.unk7 = 0; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.buildcmd_b = 0xFF; + p->ai.dst.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + GET_TOWN_OR_INDUSTRY_TILE(fr.from) + ); + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_wagons = 3; + p->ai.build_kind = 1; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 1; + p->ai.num_want_fullload = 1; + p->ai.wagon_list[0] = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantShortIndustryRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 15, 40+1)) + break; + + // try a random one + AiFindRandomIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 15, 40+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + if (!AiCheckIfRouteIsGood(p, &fr, 1)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 9; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.unk6 = 1; + p->ai.src.unk7 = 0; + p->ai.src.buildcmd_a = 0x10; + p->ai.src.buildcmd_b = 0xFF; + p->ai.src.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to) + ); + p->ai.src.cargo = fr.cargo | 0x80; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 9; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.unk6 = 1; + p->ai.dst.unk7 = 0; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.buildcmd_b = 0xFF; + p->ai.dst.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + GET_TOWN_OR_INDUSTRY_TILE(fr.from) + ); + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_wagons = 2; + p->ai.build_kind = 1; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 1; + p->ai.num_want_fullload = 1; + p->ai.wagon_list[0] = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantMailRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 60, 110+1)) + break; + + // try a random one + AiFindRandomPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 60, 110+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_MAIL; + if (!AiCheckIfRouteIsGood(p, &fr, 1)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 7; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.unk6 = 1; + p->ai.src.unk7 = 0; + p->ai.src.buildcmd_a = 0x24; + p->ai.src.buildcmd_b = 0xFF; + p->ai.src.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to) + ); + p->ai.src.cargo = fr.cargo; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 7; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.unk6 = 1; + p->ai.dst.unk7 = 0; + p->ai.dst.buildcmd_a = 0x34; + p->ai.dst.buildcmd_b = 0xFF; + p->ai.dst.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + GET_TOWN_OR_INDUSTRY_TILE(fr.from) + ); + p->ai.dst.cargo = fr.cargo; + + // Fill middle field 1 + p->ai.mid1.spec_tile = AiGetPctTileBetween( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + 0x55 + ); + p->ai.mid1.use_tile = 0; + p->ai.mid1.rand_rng = 6; + p->ai.mid1.cur_building_rule = 0xFF; + p->ai.mid1.unk6 = 2; + p->ai.mid1.unk7 = 1; + p->ai.mid1.buildcmd_a = 0x30; + p->ai.mid1.buildcmd_b = 0xFF; + p->ai.mid1.direction = p->ai.src.direction; + p->ai.mid1.cargo = fr.cargo; + + // Fill middle field 2 + p->ai.mid2.spec_tile = AiGetPctTileBetween( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + 0xAA + ); + p->ai.mid2.use_tile = 0; + p->ai.mid2.rand_rng = 6; + p->ai.mid2.cur_building_rule = 0xFF; + p->ai.mid2.unk6 = 2; + p->ai.mid2.unk7 = 1; + p->ai.mid2.buildcmd_a = 0xFF; + p->ai.mid2.buildcmd_b = 0xFF; + p->ai.mid2.direction = p->ai.dst.direction; + p->ai.mid2.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_wagons = 3; + p->ai.build_kind = 2; + p->ai.num_build_rec = 4; + p->ai.num_loco_to_build = 2; + p->ai.num_want_fullload = 0; + p->ai.wagon_list[0] = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantPassengerRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 0, 55+1)) + break; + + // try a random one + AiFindRandomPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 0, 55+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_PASSENGERS; + if (!AiCheckIfRouteIsGood(p, &fr, 1)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 7; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.unk6 = 1; + p->ai.src.unk7 = 0; + p->ai.src.buildcmd_a = 0x10; + p->ai.src.buildcmd_b = 0xFF; + p->ai.src.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.from), + GET_TOWN_OR_INDUSTRY_TILE(fr.to) + ); + p->ai.src.cargo = fr.cargo; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 7; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.unk6 = 1; + p->ai.dst.unk7 = 0; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.buildcmd_b = 0xFF; + p->ai.dst.direction = AiGetDirectionBetweenTiles( + GET_TOWN_OR_INDUSTRY_TILE(fr.to), + GET_TOWN_OR_INDUSTRY_TILE(fr.from) + ); + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_wagons = 2; + p->ai.build_kind = 1; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 1; + p->ai.num_want_fullload = 0; + p->ai.wagon_list[0] = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantTrainRoute(Player *p) +{ + uint16 r; + p->ai.railtype_to_use = p->max_railtype - 1; + r = (uint16)Random(); + + if (r > 0xD000) { + AiWantLongIndustryRoute(p); + } else if (r > 0x6000) { + AiWantMediumIndustryRoute(p); + } else if (r > 0x1000) { + AiWantShortIndustryRoute(p); + } else if (r > 0x800) { + AiWantPassengerRoute(p); + } else { + AiWantMailRoute(p); + } +} + +static void AiWantLongRoadIndustryRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 35, 55+1)) + break; + + // try a random one + AiFindRandomIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 35, 55+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + if (!AiCheckIfRouteIsGood(p, &fr, 2)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 9; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.buildcmd_a = 1; + p->ai.src.direction = 0; + p->ai.src.cargo = fr.cargo | 0x80; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 9; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.direction = 0; + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 5; + p->ai.num_want_fullload = 5; + +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantMediumRoadIndustryRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 15, 40+1)) + break; + + // try a random one + AiFindRandomIndustryRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 15, 40+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + if (!AiCheckIfRouteIsGood(p, &fr, 2)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 9; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.buildcmd_a = 1; + p->ai.src.direction = 0; + p->ai.src.cargo = fr.cargo | 0x80; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 9; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.direction = 0; + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 3; + p->ai.num_want_fullload = 3; + +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantLongRoadPassengerRoute(Player *p) +{ + int i; + FoundRoute fr; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 55, 180+1)) + break; + + // try a random one + AiFindRandomPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance, 55, 180+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_PASSENGERS; + + if (!AiCheckIfRouteIsGood(p, &fr, 2)) + return; + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 10; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.buildcmd_a = 1; + p->ai.src.direction = 0; + p->ai.src.cargo = CT_PASSENGERS; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 10; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.direction = 0; + p->ai.dst.cargo = CT_PASSENGERS; + + // Fill common fields + p->ai.cargo_type = CT_PASSENGERS; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 4; + p->ai.num_want_fullload = 0; + +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantPassengerRouteInsideTown(Player *p) +{ + int i; + FoundRoute fr; + Town *t; + + i = 60; + for(;;) { + // Find a town big enough + t = AiFindRandomTown(); + if (t != NULL && t->population >= 700) + break; + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_PASSENGERS; + fr.from = fr.to = t; + + if (!AiCheckIfRouteIsGood(p, &fr, 2)) + return; + + // Fill the source field + p->ai.src.spec_tile = t->xy; + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 10; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.buildcmd_a = 1; + p->ai.src.direction = 0; + p->ai.src.cargo = CT_PASSENGERS; + + // Fill the dest field + p->ai.dst.spec_tile = t->xy; + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 10; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.buildcmd_a = 0xFF; + p->ai.dst.direction = 0; + p->ai.dst.cargo = CT_PASSENGERS; + + // Fill common fields + p->ai.cargo_type = CT_PASSENGERS; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 2; + p->ai.num_want_fullload = 0; + +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS; + p->ai.state_mode = -1; + p->ai.state_counter = 0; + p->ai.timeout_counter = 0; +} + +static void AiWantRoadRoute(Player *p) +{ + uint16 r = (uint16)Random(); + + if (r > 0x4000) { + AiWantLongRoadIndustryRoute(p); + } else if (r > 0x2000) { + AiWantMediumRoadIndustryRoute(p); + } else if (r > 0x1000) { + AiWantLongRoadPassengerRoute(p); + } else { + AiWantPassengerRouteInsideTown(p); + } + +} + +static void AiWantPassengerAircraftRoute(Player *p) +{ + FoundRoute fr; + int i; + + i = 60; + for(;;) { + + // look for one from the subsidy list + AiFindSubsidyPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance,0,95+1)) + break; + + // try a random one + AiFindRandomPassengerRoute(&fr); + if (IS_INT_INSIDE(fr.distance,0,95+1)) + break; + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_PASSENGERS; + if (!AiCheckIfRouteIsGood(p, &fr, 4)) + return; + + + // Fill the source field + p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to); + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 12; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.cargo = fr.cargo; + + // Fill the dest field + p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from); + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 12; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.cargo = fr.cargo; + + // Fill common fields + p->ai.cargo_type = fr.cargo; + p->ai.build_kind = 0; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 1; + p->ai.num_want_fullload = 1; +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_AIRPORT_STUFF; + p->ai.timeout_counter = 0; +} + +static void AiWantOilRigAircraftRoute(Player *p) +{ + int i; + FoundRoute fr; + Town *t; + Industry *in; + + i = 60; + for(;;) { + // Find a town + t = AiFindRandomTown(); + if (t != NULL) { + // Find a random oil rig industry + in = DEREF_INDUSTRY(RandomRange(lengthof(_industries))); + if (in != NULL && in->type == IT_OIL_RIG) { + if (GetTileDist(t->xy, in->xy) < 60) + break; + } + } + + // only test 60 times + if (--i == 0) + return; + } + + fr.cargo = CT_PASSENGERS; + fr.from = fr.to = t; + + if (!AiCheckIfRouteIsGood(p, &fr, 4)) + return; + + // Fill the source field + p->ai.src.spec_tile = t->xy; + p->ai.src.use_tile = 0; + p->ai.src.rand_rng = 12; + p->ai.src.cur_building_rule = 0xFF; + p->ai.src.cargo = CT_PASSENGERS; + + // Fill the dest field + p->ai.dst.spec_tile = in->xy; + p->ai.dst.use_tile = 0; + p->ai.dst.rand_rng = 5; + p->ai.dst.cur_building_rule = 0xFF; + p->ai.dst.cargo = CT_PASSENGERS; + + // Fill common fields + p->ai.cargo_type = CT_PASSENGERS; + p->ai.build_kind = 1; + p->ai.num_build_rec = 2; + p->ai.num_loco_to_build = 1; + p->ai.num_want_fullload = 0; +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.order_list_blocks[0] = 0; + p->ai.order_list_blocks[1] = 1; + p->ai.order_list_blocks[2] = 255; + + p->ai.state = AIS_AIRPORT_STUFF; + p->ai.timeout_counter = 0; +} + +static void AiWantAircraftRoute(Player *p) +{ + uint16 r = (uint16)Random(); + + if (r >= 0x2AAA || _date < 0x3912) { + AiWantPassengerAircraftRoute(p); + } else { + AiWantOilRigAircraftRoute(p); + } +} + +static void AiWantShipRoute(Player *p) +{ + // XXX +// error("AiWaitShipRoute"); +} + + + +static void AiStateWantNewRoute(Player *p) +{ + uint16 r; + int i; + + if (p->player_money < AiGetBasePrice(p) * 500) { + p->ai.state = AIS_0; + return; + } + + i = 200; + for(;;) { + byte dis; + + r = (uint16)Random(); + + dis = _patches.ai_disable_veh; + if ((dis & 0xF) == 0xF) return; // no available vehicles at all? + + if (r < 0x7626) { + if (dis&DISABLE_TRAINS) continue; + AiWantTrainRoute(p); + } else if (r < 0xC4EA) { + if (dis&DISABLE_ROADVEH) continue; + AiWantRoadRoute(p); + } else if (r < 0xD89B) { + if (dis&DISABLE_AIRCRAFT) continue; + AiWantAircraftRoute(p); + } else { + if (dis&DISABLE_SHIPS) continue; + AiWantShipRoute(p); + } + + // got a route? + if (p->ai.state != AIS_WANT_NEW_ROUTE) + break; + + // time out? + if (--i == 0) { + if (++p->ai.state_counter == 556) p->ai.state = AIS_0; + break; + } + } +} + +static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo) +{ + uint values[NUM_CARGO]; + int w,h; + uint tile2; + + for(;p->mode != 4;p++) if (p->mode == 1) { + tile2 = TILE_ADD(tile, p->tileoffs); + + w = ((p->attr>>1) & 7); + h = ((p->attr>>4) & 7); + if (p->attr&1) intswap(w, h); + + if (cargo & 0x80) { + GetProductionAroundTiles(values, tile2, w, h); + return values[cargo & 0x7F] != 0; + } else { + GetAcceptanceAroundTiles(values, tile2, w, h); + if (!(values[cargo] & ~7)) + return false; + if (cargo != CT_MAIL) + return true; + return !!((values[cargo]>>1) & ~7); + } + } + + return true; +} + +static int32 AiDoBuildDefaultRailTrack(TileIndex tile, const AiDefaultBlockData *p, byte flag) +{ + int32 r; + int32 total_cost = 0; + Town *t = NULL; + int rating = 0; + int i,j,k; + + for(;;) { + // This will seldomly overflow for valid reasons. Mask it to be on the safe side. + uint c = TILE_MASK(tile + p->tileoffs); + + _cleared_town = NULL; + + if (p->mode < 2) { + if (p->mode == 0) { + // Depot + r = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, p->attr, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRAIN_DEPOT); + } else { + // Station + r = DoCommandByTile(c, (p->attr&1) | (p->attr>>4)<<8 | (p->attr>>1&7)<<16, _cur_ai_player->ai.railtype_to_use, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_RAILROAD_STATION); + } + + if (r == CMD_ERROR) return CMD_ERROR; + total_cost += r; + +clear_town_stuff:; + if (_cleared_town != NULL) { + if (t != NULL && t != _cleared_town) + return CMD_ERROR; + t = _cleared_town; + rating += _cleared_town_rating; + } + } else if (p->mode == 2) { + // Rail + if (IS_TILETYPE(c, MP_RAILWAY)) + return CMD_ERROR; + + j = p->attr; + k = 0; + + // Build the rail + for(i=0; i!=6; i++,j>>=1) { + if (j&1) { + k = i; + r = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, i, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL); + if (r == CMD_ERROR) return CMD_ERROR; + total_cost += r; + } + } + + /* signals too? */ + if (j&3) { + // Can't build signals on a road. + if (IS_TILETYPE(c, MP_STREET)) + return CMD_ERROR; + + if (flag & DC_EXEC) { + j = 4 - j; + do { + r = DoCommandByTile(c, k, 0, flag, CMD_BUILD_SIGNALS); + } while (--j); + } else { + r = _price.build_signals; + } + if (r == CMD_ERROR) return CMD_ERROR; + total_cost += r; + } + } else if (p->mode == 3) { + //Clear stuff and then build single rail. + if (GetTileSlope(c,NULL) != 0) + return CMD_ERROR; + r = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR); + if (r == CMD_ERROR) return CMD_ERROR; + total_cost += r + _price.build_rail; + + if (flag & DC_EXEC) { + DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, p->attr&1, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_SINGLE_RAIL); + } + + goto clear_town_stuff; + } else { + // Unk + break; + } + + p++; + } + + if (!(flag & DC_EXEC)) { + if (t != NULL && rating > t->ratings[_current_player]) { + return CMD_ERROR; + } + } + + return total_cost; +} + +// Returns rule and cost +static int AiBuildDefaultRailTrack(TileIndex tile, byte p0, byte p1, byte p2, byte p3, byte dir, byte cargo, int32 *cost) +{ + int i; + const AiDefaultRailBlock *p; + + for(i=0; (p = _default_rail_track_data[i]) != NULL; i++) { + if (p->p0 == p0 && p->p1 == p1 && p->p2 == p2 && p->p3 == p3 && + (p->dir == 0xFF || p->dir == dir || ((p->dir-1)&3) == dir)) { + *cost = AiDoBuildDefaultRailTrack(tile, p->data, DC_NO_TOWN_RATING); + if (*cost != CMD_ERROR && AiCheckTrackResources(tile, p->data, cargo)) + return i; + } + } + + return -1; +} + +static const byte _terraform_up_flags[] = { + 14, 13, 12, 11, + 10, 9, 8, 7, + 6, 5, 4, 3, + 2, 1, 0, 1, + 2, 1, 4, 1, + 2, 1, 8, 1, + 2, 1, 4, 2, + 2, 1 +}; + +static const byte _terraform_down_flags[] = { + 1, 2, 3, 4, + 5, 6, 1, 8, + 9, 10, 8, 12, + 4, 2, 0, 0, + 1, 2, 3, 4, + 5, 6, 2, 8, + 9, 10, 1, 12, + 8, 4 +}; + +static void AiDoTerraformLand(TileIndex tile, int dir, int unk, int mode) +{ + byte old_player; + uint32 r; + uint slope; + int h; + + old_player = _current_player; + _current_player = OWNER_NONE; + + r = Random(); + + unk &= (int)r; + + do { + tile = TILE_MASK(tile + _tileoffs_by_dir[dir]); + + r >>= 2; + if (r&2) { + dir++; + if (r&1) + dir -= 2; + } + dir &= 3; + } while (--unk >= 0); + + slope = GetTileSlope(tile, &h); + + if (slope != 0) { + if (mode > 0 || (mode == 0 && !(r&0xC))) { + // Terraform up + DoCommandByTile(tile, _terraform_up_flags[slope-1], 1, + DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); + } else if (h != 0) { + // Terraform down + DoCommandByTile(tile, _terraform_down_flags[slope-1], 0, + DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); + } + } + + _current_player = old_player; +} + +static void AiStateBuildDefaultRailBlocks(Player *p) +{ + int i, j; + AiBuildRec *aib; + int rule; + int32 cost; + + // time out? + if (++p->ai.timeout_counter == 1388) { + p->ai.state = AIS_DELETE_RAIL_BLOCKS; + return; + } + + // do the following 8 times + i = 8; + do { + // check if we can build the default track + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + // this item has already been built? + if (aib->cur_building_rule != 255) + continue; + + // adjust the coordinate randomly, + // to make sure that we find a position. + aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng); + + // check if the track can be build there. + rule = AiBuildDefaultRailTrack(aib->use_tile, + p->ai.build_kind, p->ai.num_wagons, + aib->unk6, aib->unk7, + aib->direction, aib->cargo, &cost); + + if (rule == -1) { + // cannot build, terraform after a while + if (p->ai.state_counter >= 600) { + AiDoTerraformLand(aib->use_tile, Random()&3, 3, (int8)p->ai.state_mode); + } + // also try the other terraform direction + if (++p->ai.state_counter >= 1000) { + p->ai.state_counter = 0; + p->ai.state_mode = -p->ai.state_mode; + } + } else if (CheckPlayerHasMoney(cost)) { + int32 r; + // player has money, build it. + aib->cur_building_rule = rule; + + r = AiDoBuildDefaultRailTrack( + aib->use_tile, + _default_rail_track_data[rule]->data, + DC_EXEC | DC_NO_TOWN_RATING + ); + assert(r != CMD_ERROR); + } + } while (++aib,--j); + } while (--i); + + // check if we're done with all of them + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + if (aib->cur_building_rule == 255) + return; + } while (++aib,--j); + + // yep, all are done. switch state to the rail building state. + p->ai.state = AIS_BUILD_RAIL; + p->ai.state_mode = 255; +} + +static TileIndex AiGetEdgeOfDefaultRailBlock(byte rule, TileIndex tile, byte cmd, int *dir) +{ + const AiDefaultBlockData *p = _default_rail_track_data[rule]->data; + + while (p->mode != 3 || !((--cmd) & 0x80)) p++; + + return tile + p->tileoffs - _tileoffs_by_dir[*dir = p->attr]; +} + +typedef struct AiRailPathFindData { + TileIndex tile; + TileIndex tile2; + int count; + bool flag; +} AiRailPathFindData; + +static bool AiEnumFollowTrack(uint tile, AiRailPathFindData *a, int track, uint length, byte *state) +{ + if (a->flag) + return true; + + if (length > 20 || tile == a->tile) { + a->flag = true; + return true; + } + + if (GetTileDist1D(tile, a->tile2) < 4) + a->count++; + + return false; +} + +static bool AiDoFollowTrack(Player *p) +{ + AiRailPathFindData arpfd; + arpfd.tile = p->ai.start_tile_a; + arpfd.tile2 = p->ai.cur_tile_a; + arpfd.flag = false; + arpfd.count = 0; + FollowTrack(p->ai.cur_tile_a + _tileoffs_by_dir[p->ai.cur_dir_a], 0x2000, p->ai.cur_dir_a^2, + (TPFEnumProc*)AiEnumFollowTrack, NULL, &arpfd); + return arpfd.count > 8; +} + +typedef struct AiRailFinder { + TileIndex final_tile; + byte final_dir; + byte depth; + byte recursive_mode; + byte cur_best_dir; + byte best_dir; + byte cur_best_depth; + byte best_depth; + uint cur_best_dist; + const byte *best_ptr; + uint best_dist; + TileIndex cur_best_tile, best_tile; + TileIndex bridge_end_tile; + Player *player; + TileInfo ti; +} AiRailFinder; + +static const byte _ai_table_15[4][8] = { + {0, 0, 4, 3, 3, 1, 128+0, 64}, + {1, 1, 2, 0, 4, 2, 128+1, 65}, + {0, 2, 2, 3, 5, 1, 128+2, 66}, + {1, 3, 5, 0, 3, 2, 128+3, 67} +}; + +static const byte _dir_table_1[] = {3, 9, 12, 6}; +static const byte _dir_table_2[] = {12, 6, 3, 9}; + + +static bool AiIsTileBanned(Player *p, TileIndex tile, byte val) { + int i; + + for(i=0; i!=p->ai.banned_tile_count; i++) + if (p->ai.banned_tiles[i] == tile && + p->ai.banned_val[i] == val) + return true; + return false; +} + +static void AiBanTile(Player *p, TileIndex tile, byte val) { + int i; + + for(i=lengthof(p->ai.banned_tiles)-1; i!=0; i--) { + p->ai.banned_tiles[i] = p->ai.banned_tiles[i-1]; + p->ai.banned_val[i] = p->ai.banned_val[i-1]; + } + + p->ai.banned_tiles[0] = tile; + p->ai.banned_val[0] = val; + + if (p->ai.banned_tile_count != lengthof(p->ai.banned_tiles)) + p->ai.banned_tile_count++; +} + +static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, int dir); + +static bool AiCheckRailPathBetter(AiRailFinder *arf, const byte *p) +{ + bool better = false; + + if (arf->recursive_mode < 1) { + // Mode is 0. This means destination has not been found yet. + // If the found path is shorter than the current one, remember it. + if (arf->cur_best_dist < arf->best_dist) { + arf->best_dir = arf->cur_best_dir; + arf->best_dist = arf->cur_best_dist; + arf->best_ptr = p; + arf->best_tile = arf->cur_best_tile; + better = true; + } + } else if (arf->recursive_mode > 1) { + // Mode is 2. + if (arf->best_dist != 0 || arf->cur_best_depth < arf->best_depth) { + arf->best_depth = arf->cur_best_depth; + arf->best_dist = 0; + arf->best_ptr = p; + arf->best_tile = 0; + better = true; + } + } + arf->recursive_mode = 0; + arf->cur_best_dist = (uint)-1; + arf->cur_best_depth = 0xff; + + return better; +} + +static void FORCEINLINE AiCheckBuildRailBridgeHere(AiRailFinder *arf, TileIndex tile, const byte *p) +{ + TileIndex tile_new; + bool flag; + + int dir2 = p[0] & 3; + + FindLandscapeHeightByTile(&arf->ti, tile); + + if (arf->ti.tileh == _dir_table_1[dir2] || (arf->ti.tileh==0 && arf->ti.z!=0)) { + tile_new = tile; + // Allow bridges directly over bottom tiles + flag = arf->ti.z == 0; + for(;;) { + if (tile_new < -_tileoffs_by_dir[dir2]) return; // Wraping around map, no bridge possible! + tile_new = TILE_MASK(tile_new + _tileoffs_by_dir[dir2]); + FindLandscapeHeightByTile(&arf->ti, tile_new); + if (arf->ti.tileh != 0 || arf->ti.type == MP_CLEAR || arf->ti.type == MP_TREES) { + if (!flag) return; + break; + } + if (arf->ti.type != MP_WATER && arf->ti.type != MP_RAILWAY && arf->ti.type != MP_STREET) + return; + flag = true; + } + + // Is building a (rail)bridge possible at this place (type doesn't matter)? + if (DoCommandByTile(tile_new, tile, arf->player->ai.railtype_to_use<<8, + DC_AUTO, CMD_BUILD_BRIDGE) == CMD_ERROR) + return; + AiBuildRailRecursive(arf, tile_new, dir2); + + // At the bottom depth, check if the new path is better than the old one. + if (arf->depth == 1) { + if (AiCheckRailPathBetter(arf, p)) + arf->bridge_end_tile = tile_new; + } + } +} + +static void FORCEINLINE AiCheckBuildRailTunnelHere(AiRailFinder *arf, TileIndex tile, const byte *p) +{ + FindLandscapeHeightByTile(&arf->ti, tile); + + if (arf->ti.tileh == _dir_table_2[p[0]&3] && arf->ti.z!=0) { + int32 cost = DoCommandByTile(tile, arf->player->ai.railtype_to_use, 0, DC_AUTO, CMD_BUILD_TUNNEL); + + if (cost != CMD_ERROR && cost <= (arf->player->player_money>>4)) { + AiBuildRailRecursive(arf, _build_tunnel_endtile, p[0]&3); + if (arf->depth == 1) { + AiCheckRailPathBetter(arf, p); + } + } + } +} + + +static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, int dir) +{ + const byte *p; + + tile = TILE_MASK(tile + _tileoffs_by_dir[dir]); + + // Reached destination? + if (tile == arf->final_tile) { + if (arf->final_dir != (dir^2)) { + if (arf->recursive_mode != 2) + arf->recursive_mode = 1; + } else if (arf->recursive_mode != 2) { + arf->recursive_mode = 2; + arf->cur_best_depth = arf->depth; + } else { + if (arf->depth < arf->cur_best_depth) + arf->cur_best_depth = arf->depth; + } + return; + } + + // Depth too deep? + if (arf->depth >= 4) { + uint dist = GetTileDist1Db(tile, arf->final_tile); + if (dist < arf->cur_best_dist) { + // Store the tile that is closest to the final position. + arf->cur_best_depth = arf->depth; + arf->cur_best_dist = dist; + arf->cur_best_tile = tile; + arf->cur_best_dir = dir; + } + return; + } + + // Increase recursion depth + arf->depth++; + + // Grab pointer to list of stuff that is possible to build + p = _ai_table_15[dir]; + + // Try to build a single rail in all directions. + FindLandscapeHeightByTile(&arf->ti, tile); + if (arf->ti.z == 0) { + p += 6; + } else { + do { + // Make sure the tile is not in the list of banned tiles and that a rail can be built here. + if (!AiIsTileBanned(arf->player, tile, p[0]) && + DoCommandByTile(tile, arf->player->ai.railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL) != CMD_ERROR) { + AiBuildRailRecursive(arf, tile, p[1]); + } + + // At the bottom depth? + if (arf->depth == 1) { + AiCheckRailPathBetter(arf, p); + } + + p += 2; + } while (!(p[0]&0x80)); + } + + AiCheckBuildRailBridgeHere(arf, tile, p); + AiCheckBuildRailTunnelHere(arf, tile, p+1); + + arf->depth--; +} + + +static const byte _dir_table_3[]= {0x25, 0x2A, 0x19, 0x16}; + +static void AiBuildRailConstruct(Player *p) +{ + AiRailFinder arf; + int i; + + // Check too much lookahead? + if (AiDoFollowTrack(p)) { + p->ai.state_counter = (Random()&0xE)+6; // Destruct this amount of blocks + p->ai.state_mode = 1; // Start destruct + + // Ban this tile and don't reach it for a while. + AiBanTile(p, p->ai.cur_tile_a, FindFirstBit(GetRailTrackStatus(p->ai.cur_tile_a))); + return; + } + + // Setup recursive finder and call it. + arf.player = p; + arf.final_tile = p->ai.cur_tile_b; + arf.final_dir = p->ai.cur_dir_b; + arf.depth = 0; + arf.recursive_mode = 0; + arf.best_ptr = NULL; + arf.cur_best_dist = (uint)-1; + arf.cur_best_depth = 0xff; + arf.best_dist = (uint)-1; + arf.best_depth = 0xff; + arf.cur_best_tile = 0; + arf.best_tile = 0; + AiBuildRailRecursive(&arf, p->ai.cur_tile_a, p->ai.cur_dir_a); + + // Reached destination? + if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) { + p->ai.state_mode = 255; + return; + } + + // Didn't find anything to build? + if (arf.best_ptr == NULL) { + // Terraform some + for(i=0; i!=5; i++) + AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0); + + if (++p->ai.state_counter == 21) { + p->ai.state_counter = 40; + p->ai.state_mode = 1; + + // Ban this tile + AiBanTile(p, p->ai.cur_tile_a, FindFirstBit(GetRailTrackStatus(p->ai.cur_tile_a))); + } + return; + } + + p->ai.cur_tile_a += _tileoffs_by_dir[p->ai.cur_dir_a]; + + if (arf.best_ptr[0]&0x80) { + int i; + int32 bridge_len = GetBridgeLength(arf.bridge_end_tile, p->ai.cur_tile_a); + + /* Figure out what (rail)bridge type to build + start with best bridge, then go down to worse and worse bridges + unnecessary to check for worse bridge (i=0), since AI will always build that. + AI is so fucked up that fixing this small thing will probably not solve a thing + */ + for(i = 10 + (p->ai.railtype_to_use << 8); i != 0; i--) { + if (CheckBridge_Stuff(i, bridge_len)) { + int32 cost = DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i, DC_AUTO, CMD_BUILD_BRIDGE); + if (cost != CMD_ERROR && cost < (p->player_money >> 5)) + break; + } + } + + // Build it + DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i, DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE); + + p->ai.cur_tile_a = arf.bridge_end_tile; + p->ai.state_counter = 0; + } else if (arf.best_ptr[0]&0x40) { + // tunnel + DoCommandByTile(p->ai.cur_tile_a, p->ai.railtype_to_use, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL); + p->ai.cur_tile_a = _build_tunnel_endtile; + p->ai.state_counter = 0; + } else { + // rail + p->ai.cur_dir_a = arf.best_ptr[1]; + DoCommandByTile(p->ai.cur_tile_a, p->ai.railtype_to_use, arf.best_ptr[0], + DC_EXEC | DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL); + p->ai.state_counter = 0; + } + + if (arf.best_tile != 0) { + for(i=0; i!=2; i++) + AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0); + } +} + +static bool AiRemoveTileAndGoForward(Player *p) +{ + byte b; + int bit; + const byte *ptr; + uint tile = p->ai.cur_tile_a; + int offs; + TileIndex tilenew; + + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + if (!(_map5[tile] & 0x80)) { + // Clear the tunnel and continue at the other side of it. + if (DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return false; + p->ai.cur_tile_a = TILE_MASK(_build_tunnel_endtile - _tileoffs_by_dir[p->ai.cur_dir_a]); + return true; + } + + if (!(_map5[tile] & 0x40)) { + + // Check if the bridge points in the right direction. + // This is not really needed the first place AiRemoveTileAndGoForward is called. + if ((_map5[tile]&1) != (p->ai.cur_dir_a&1)) + return false; + + // Find other side of bridge. + offs = _tileoffs_by_dir[p->ai.cur_dir_a]; + do { + tile = TILE_MASK(tile - offs); + } while (_map5[tile] & 0x40); + + tilenew = TILE_MASK(tile - offs); + // And clear the bridge. + if (DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return false; + p->ai.cur_tile_a = tilenew; + return true; + } + } + + // Find the railtype at the position. Quit if no rail there. + b = GetRailTrackStatus(tile) & _dir_table_3[p->ai.cur_dir_a]; + if (b == 0) + return false; + + // Convert into a bit position that CMD_REMOVE_SINGLE_RAIL expects. + bit = FindFirstBit(b); + + // Then remove and signals if there are any. + if (IS_TILETYPE(tile, MP_RAILWAY) && + (_map5[tile]&0xC0) == 0x40) { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_REMOVE_SIGNALS); + } + + // And also remove the rail. + if (DoCommandByTile(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL) == CMD_ERROR) + return false; + + // Find the direction at the other edge of the rail. + ptr = _ai_table_15[p->ai.cur_dir_a^2]; + while (ptr[0] != bit) ptr+=2; + p->ai.cur_dir_a = ptr[1] ^ 2; + + // And then also switch tile. + p->ai.cur_tile_a = TILE_MASK(p->ai.cur_tile_a - _tileoffs_by_dir[p->ai.cur_dir_a]); + + return true; +} + + +static void AiBuildRailDestruct(Player *p) +{ + // Decrease timeout. + if (!--p->ai.state_counter) { + p->ai.state_mode = 2; + p->ai.state_counter = 0; + } + + // Don't do anything if the destination is already reached. + if (p->ai.cur_tile_a == p->ai.start_tile_a) + return; + + AiRemoveTileAndGoForward(p); +} + + +static void AiBuildRail(Player *p) +{ + int i; + + if (p->ai.state_mode < 1) { + // Construct mode, build new rail. + AiBuildRailConstruct(p); + } else if (p->ai.state_mode == 1) { + + // Destruct mode, destroy the rail currently built. + AiBuildRailDestruct(p); + } else if (p->ai.state_mode == 2) { + + // Terraform some and then try building again. + for(i=0; i!=4; i++) + AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0); + + if (++p->ai.state_counter == 4) { + p->ai.state_counter = 0; + p->ai.state_mode = 0; + } + } +} + +static void AiStateBuildRail(Player *p) +{ + int num; + AiBuildRec *aib; + byte cmd; + TileIndex tile; + int dir; + + // time out? + if (++p->ai.timeout_counter == 1388) { + p->ai.state = AIS_DELETE_RAIL_BLOCKS; + return; + } + + // Currently building a rail between two points? + if (p->ai.state_mode != 255) { + AiBuildRail(p); + + // Alternate between edges + swap_tile(&p->ai.start_tile_a, &p->ai.start_tile_b); + swap_tile(&p->ai.cur_tile_a, &p->ai.cur_tile_b); + swap_byte(&p->ai.start_dir_a, &p->ai.start_dir_b); + swap_byte(&p->ai.cur_dir_a, &p->ai.cur_dir_b); + return; + } + + // Now, find two new points to build between + num = p->ai.num_build_rec; + aib = &p->ai.src; + + for(;;) { + cmd = aib->buildcmd_a; + aib->buildcmd_a = 255; + if (cmd != 255) break; + + cmd = aib->buildcmd_b; + aib->buildcmd_b = 255; + if (cmd != 255) break; + + aib++; + if (--num == 0) { + p->ai.state = AIS_BUILD_RAIL_VEH; + p->ai.state_counter = 0; // timeout + return; + } + } + + // Find first edge to build from. + tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, cmd&3, &dir); + p->ai.start_tile_a = tile; + p->ai.cur_tile_a = tile; + p->ai.start_dir_a = dir; + p->ai.cur_dir_a = dir; + DoCommandByTile(TILE_MASK(tile + _tileoffs_by_dir[dir]), 0, (dir&1)?1:0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL); + + assert(TILE_MASK(tile) != 0xFF00); + + // Find second edge to build to + aib = (&p->ai.src) + ((cmd >> 4)&0xF); + tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, (cmd>>2)&3, &dir); + p->ai.start_tile_b = tile; + p->ai.cur_tile_b = tile; + p->ai.start_dir_b = dir; + p->ai.cur_dir_b = dir; + DoCommandByTile(TILE_MASK(tile + _tileoffs_by_dir[dir]), 0, (dir&1)?1:0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL); + + assert(TILE_MASK(tile) != 0xFF00); + + // And setup state. + p->ai.state_mode = 2; + p->ai.state_counter = 0; + p->ai.banned_tile_count = 0; +} + +static int AiGetStationIdByDef(TileIndex tile, int id) +{ + const AiDefaultBlockData *p = _default_rail_track_data[id]->data; + while (p->mode != 1) p++; + return _map2[TILE_ADD(tile,p->tileoffs)]; +} + +static void AiStateBuildRailVeh(Player *p) +{ + const AiDefaultBlockData *ptr; + TileIndex tile; + int i, veh; + int cargo; + int32 cost; + Vehicle *v; + uint loco_id; + + ptr = _default_rail_track_data[p->ai.src.cur_building_rule]->data; + while (ptr->mode != 0) { ptr++; } + + tile = TILE_ADD(p->ai.src.use_tile, ptr->tileoffs); + + cargo = p->ai.cargo_type; + for(i=0;;) { + if (p->ai.wagon_list[i] == INVALID_VEHICLE) { + veh = _cargoc.ai_railwagon[p->ai.railtype_to_use][cargo]; + cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE); + if (cost == CMD_ERROR) goto handle_nocash; + p->ai.wagon_list[i] = _new_wagon_id; + p->ai.wagon_list[i+1] = INVALID_VEHICLE; + return; + } + if (cargo == CT_MAIL) + cargo = CT_PASSENGERS; + if (++i == p->ai.num_wagons * 2 - 1) + break; + } + + // Which locomotive to build? + veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0); + if (veh == -1) { +handle_nocash: + // after a while, if AI still doesn't have cash, get out of this block by selling the wagons. + if (++p->ai.state_counter == 1000) { + for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) { + cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON); + assert(cost != CMD_ERROR); + } + p->ai.state = AIS_0; + } + return; + } + + // Try to build the locomotive + cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE); + assert(cost != CMD_ERROR); + loco_id = _new_train_id; + + // Sell a vehicle if the train is double headed. + v = &_vehicles[loco_id]; + if (v->next != NULL) { + i = p->ai.wagon_list[p->ai.num_wagons*2-2]; + p->ai.wagon_list[p->ai.num_wagons*2-2] = INVALID_VEHICLE; + DoCommandByTile(tile, i, 0, DC_EXEC, CMD_SELL_RAIL_WAGON); + } + + // Move the wagons onto the train + for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) { + DoCommandByTile(tile, p->ai.wagon_list[i] | (loco_id << 16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); + } + + for(i=0; p->ai.order_list_blocks[i] != 0xFF; i++) { + AiBuildRec *aib = (&p->ai.src) + p->ai.order_list_blocks[i]; + uint flags = (AiGetStationIdByDef(aib->use_tile, aib->cur_building_rule) << 8) + OT_GOTO_STATION; + bool is_pass = (p->ai.cargo_type == CT_PASSENGERS || + p->ai.cargo_type == CT_MAIL || + (_opt.landscape==LT_NORMAL && p->ai.cargo_type == CT_VALUABLES)); + + if (!is_pass && i == 1) flags |= OF_UNLOAD; + if (p->ai.num_want_fullload != 0 && (is_pass || i == 0)) flags |= OF_FULL_LOAD; + + DoCommandByTile(0, loco_id + (i << 16), flags, DC_EXEC, CMD_INSERT_ORDER); + } + + DoCommandByTile(0, loco_id, 0, DC_EXEC, CMD_START_STOP_TRAIN); + + if (p->ai.num_want_fullload != 0) + p->ai.num_want_fullload--; + + if (--p->ai.num_loco_to_build != 0) { +// p->ai.loco_id = INVALID_VEHICLE; + p->ai.wagon_list[0] = INVALID_VEHICLE; + } else { + p->ai.state = AIS_0; + } +} + +static void AiStateDeleteRailBlocks(Player *p) +{ + int num; + AiBuildRec *aib; + const AiDefaultBlockData *b; + + num = p->ai.num_build_rec; + aib = &p->ai.src; + do { + if (aib->cur_building_rule != 255) { + b = _default_rail_track_data[aib->cur_building_rule]->data; + while (b->mode != 4) { + DoCommandByTile(TILE_ADD(aib->use_tile, b->tileoffs), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + b++; + } + } + } while (++aib,--num); + + p->ai.state = AIS_0; +} + +static bool AiCheckRoadResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo) +{ + uint values[NUM_CARGO]; + for(;;p++) { + if (p->mode == 4) { + return true; + } else if (p->mode == 1) { + uint tile2 = TILE_ADD(tile, p->tileoffs); + if (cargo & 0x80) { + GetProductionAroundTiles(values, tile2, 1, 1); + return values[cargo & 0x7F] != 0; + } else { + GetAcceptanceAroundTiles(values, tile2, 1, 1); + return (values[cargo]&~7) != 0; + } + } + } +} + +static bool _want_road_truck_station; +static int32 AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag); + +// Returns rule and cost +static int AiFindBestDefaultRoadBlock(TileIndex tile, byte direction, byte cargo, int32 *cost) +{ + int i; + const AiDefaultRoadBlock *p; + + _want_road_truck_station = (cargo & 0x7F) != CT_PASSENGERS; + + for(i=0; (p = _road_default_block_data[i]) != NULL; i++) { + if (p->dir == direction) { + *cost = AiDoBuildDefaultRoadBlock(tile, p->data, 0); + if (*cost != CMD_ERROR && AiCheckRoadResources(tile, p->data, cargo)) + return i; + } + } + + return -1; +} + +static int32 AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag) +{ + int32 r; + int32 total_cost = 0; + Town *t = NULL; + int rating = 0; + int roadflag = 0; + + for(;p->mode != 4;p++) { + uint c = TILE_MASK(tile+ p->tileoffs); + + _cleared_town = NULL; + + if (p->mode == 2) { + if (IS_TILETYPE(c, MP_STREET) && + (_map5[c]&0xF0)==0 && + (_map5[c]&p->attr)!=0) { + roadflag |= 2; + + // all bits are already built? + if ((_map5[c]&p->attr)==p->attr) + continue; + } + + r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD); + if (r == CMD_ERROR) + return CMD_ERROR; + total_cost += r; + + continue; + } + + if (p->mode == 0) { + // Depot + r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_DEPOT); + goto clear_town_stuff; + } else if (p->mode == 1) { + if (_want_road_truck_station) { + // Truck station + r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRUCK_STATION); + } else { + // Bus station + r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_BUS_STATION); + } +clear_town_stuff:; + + if (r == CMD_ERROR) return CMD_ERROR; + total_cost += r; + + if (_cleared_town != NULL) { + if (t != NULL && t != _cleared_town) + return CMD_ERROR; + t = _cleared_town; + rating += _cleared_town_rating; + } + } else if (p->mode == 3) { + if (flag & DC_EXEC) + continue; + + if (GetTileSlope(c, NULL) != 0) + return CMD_ERROR; + + if (!(IS_TILETYPE(c, MP_STREET) && (_map5[c]&0xF0)==0)) { + r = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR); + if (r == CMD_ERROR) return CMD_ERROR; + } + + } + } + + if (!_want_road_truck_station && !(roadflag&2)) + return CMD_ERROR; + + if (!(flag & DC_EXEC)) { + if (t != NULL && rating > t->ratings[_current_player]) { + return CMD_ERROR; + } + } + return total_cost; +} + +// Make sure the blocks are not too close to each other +static bool AiCheckBlockDistances(Player *p, TileIndex tile) +{ + AiBuildRec *aib; + int num; + + num = p->ai.num_build_rec; + aib = &p->ai.src; + + do { + if (aib->cur_building_rule != 255) { + if (GetTileDist(aib->use_tile, tile) < 9) + return false; + } + } while (++aib, --num); + + return true; +} + + +static void AiStateBuildDefaultRoadBlocks(Player *p) +{ + int i, j; + AiBuildRec *aib; + int rule; + int32 cost; + + // time out? + if (++p->ai.timeout_counter == 1388) { + p->ai.state = AIS_DELETE_RAIL_BLOCKS; + return; + } + + // do the following 8 times + i = 8; + do { + // check if we can build the default track + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + // this item has already been built? + if (aib->cur_building_rule != 255) + continue; + + // adjust the coordinate randomly, + // to make sure that we find a position. + aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng); + + // check if the road can be built there. + rule = AiFindBestDefaultRoadBlock(aib->use_tile, + aib->direction, aib->cargo, &cost); + + if (rule == -1) { + // cannot build, terraform after a while + if (p->ai.state_counter >= 600) { + AiDoTerraformLand(aib->use_tile, Random()&3, 3, (int8)p->ai.state_mode); + } + // also try the other terraform direction + if (++p->ai.state_counter >= 1000) { + p->ai.state_counter = 0; + p->ai.state_mode = -p->ai.state_mode; + } + } else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p,aib->use_tile)) { + int32 r; + + // player has money, build it. + aib->cur_building_rule = rule; + + r = AiDoBuildDefaultRoadBlock( + aib->use_tile, + _road_default_block_data[rule]->data, + DC_EXEC | DC_NO_TOWN_RATING + ); + assert(r != CMD_ERROR); + } + } while (++aib,--j); + } while (--i); + + // check if we're done with all of them + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + if (aib->cur_building_rule == 255) + return; + } while (++aib,--j); + + // yep, all are done. switch state to the rail building state. + p->ai.state = AIS_BUILD_ROAD; + p->ai.state_mode = 255; +} + +typedef struct { + TileIndex final_tile; + byte final_dir; + byte depth; + byte recursive_mode; + byte cur_best_dir; + byte best_dir; + byte cur_best_depth; + byte best_depth; + uint cur_best_dist; + const byte *best_ptr; + uint best_dist; + TileIndex cur_best_tile, best_tile; + TileIndex bridge_end_tile; + Player *player; + TileInfo ti; +} AiRoadFinder; + +typedef struct AiRoadEnum { + TileIndex dest; + TileIndex best_tile; + int best_track; + uint best_dist; +} AiRoadEnum; + +static const byte _dir_by_track[] = { + 0,1,0,1,2,1, 0,0, + 2,3,3,2,3,0, +}; + +static void AiBuildRoadRecursive(AiRoadFinder *arf, TileIndex tile, int dir); + +static bool AiCheckRoadPathBetter(AiRoadFinder *arf, const byte *p) +{ + bool better = false; + + if (arf->recursive_mode < 1) { + // Mode is 0. This means destination has not been found yet. + // If the found path is shorter than the current one, remember it. + if (arf->cur_best_dist < arf->best_dist || + (arf->cur_best_dist == arf->best_dist && arf->cur_best_depth < arf->best_depth)) { + arf->best_depth = arf->cur_best_depth; + arf->best_dist = arf->cur_best_dist; + arf->best_dir = arf->cur_best_dir; + arf->best_ptr = p; + arf->best_tile = arf->cur_best_tile; + better = true; + } + } else if (arf->recursive_mode > 1) { + // Mode is 2. + if (arf->best_dist != 0 || arf->cur_best_depth < arf->best_depth) { + arf->best_depth = arf->cur_best_depth; + arf->best_dist = 0; + arf->best_ptr = p; + arf->best_tile = 0; + better = true; + } + } + arf->recursive_mode = 0; + arf->cur_best_dist = (uint)-1; + arf->cur_best_depth = 0xff; + + return better; +} + + +static bool AiEnumFollowRoad(uint tile, AiRoadEnum *a, int track, uint length, byte *state) +{ + uint dist = GetTileDist(tile, a->dest); + uint tile2; + + if (dist <= a->best_dist) { + tile2 = TILE_MASK(tile + _tileoffs_by_dir[_dir_by_track[track]]); + if (IS_TILETYPE(tile2, MP_STREET) && + (_map5[tile2]&0xF0) == 0) { + a->best_dist = dist; + a->best_tile = tile; + a->best_track = track; + } + } + + return false; +} + +static const uint16 _ai_road_table_and[4] = { + 0x1009, + 0x16, + 0x520, + 0x2A00, +}; + +bool AiCheckRoadFinished(Player *p) +{ + AiRoadEnum are; + uint tile; + int dir = p->ai.cur_dir_a; + uint32 bits; + int i; + + are.dest = p->ai.cur_tile_b; + tile = TILE_MASK(p->ai.cur_tile_a + _tileoffs_by_dir[dir]); + + bits = GetTileTrackStatus(tile, 2) & _ai_road_table_and[dir]; + if (bits == 0) { + return false; + } + + are.best_dist = (uint)-1; + + for_each_bit(i, bits) { + FollowTrack(tile, 0x3002, _dir_by_track[i], (TPFEnumProc*)AiEnumFollowRoad, NULL, &are); + } + + if (GetTileDist(tile, are.dest) <= are.best_dist) + return false; + + if (are.best_dist == 0) + return true; + + p->ai.cur_tile_a = are.best_tile; + p->ai.cur_dir_a = _dir_by_track[are.best_track]; + return false; +} + + +static bool AiBuildRoadHelper(uint tile, int flags, int type) +{ + static const byte _road_bits[] = { + 8+2, + 1+4, + 1+8, + 4+2, + 1+2, + 8+4, + }; + return DoCommandByTile(tile, _road_bits[type], 0, flags, CMD_BUILD_ROAD) != CMD_ERROR; +} + +static void FORCEINLINE AiCheckBuildRoadBridgeHere(AiRoadFinder *arf, TileIndex tile, const byte *p) +{ + TileIndex tile_new; + bool flag; + + int dir2 = p[0] & 3; + + FindLandscapeHeightByTile(&arf->ti, tile); + if (arf->ti.tileh == _dir_table_1[dir2] || (arf->ti.tileh==0 && arf->ti.z!=0)) { + tile_new = tile; + // Allow bridges directly over bottom tiles + flag = arf->ti.z == 0; + for(;;) { + if (tile_new < -_tileoffs_by_dir[dir2]) return; // Wraping around map, no bridge possible! + tile_new = TILE_MASK(tile_new + _tileoffs_by_dir[dir2]); + FindLandscapeHeightByTile(&arf->ti, tile_new); + if (arf->ti.tileh != 0 || arf->ti.type == MP_CLEAR || arf->ti.type == MP_TREES) { + // Allow a bridge if either we have a tile that's water, rail or street, + // or if we found an up tile. + if (!flag) return; + break; + } + if (arf->ti.type != MP_WATER && arf->ti.type != MP_RAILWAY && arf->ti.type != MP_STREET) + return; + flag = true; + } + + // Is building a (rail)bridge possible at this place (type doesn't matter)? + if (DoCommandByTile(tile_new, tile, 0x8000, DC_AUTO, CMD_BUILD_BRIDGE) == CMD_ERROR) + return; + AiBuildRoadRecursive(arf, tile_new, dir2); + + // At the bottom depth, check if the new path is better than the old one. + if (arf->depth == 1) { + if (AiCheckRoadPathBetter(arf, p)) + arf->bridge_end_tile = tile_new; + } + } +} + +static void FORCEINLINE AiCheckBuildRoadTunnelHere(AiRoadFinder *arf, TileIndex tile, const byte *p) +{ + FindLandscapeHeightByTile(&arf->ti, tile); + + if (arf->ti.tileh == _dir_table_2[p[0]&3] && arf->ti.z!=0) { + int32 cost = DoCommandByTile(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL); + + if (cost != CMD_ERROR && cost <= (arf->player->player_money>>4)) { + AiBuildRoadRecursive(arf, _build_tunnel_endtile, p[0]&3); + if (arf->depth == 1) { + AiCheckRoadPathBetter(arf, p); + } + } + } +} + + + +static void AiBuildRoadRecursive(AiRoadFinder *arf, TileIndex tile, int dir) +{ + const byte *p; + + tile = TILE_MASK(tile + _tileoffs_by_dir[dir]); + + // Reached destination? + if (tile == arf->final_tile) { + if ((arf->final_dir^2) == dir) { + arf->recursive_mode = 2; + arf->cur_best_depth = arf->depth; + } + return; + } + + // Depth too deep? + if (arf->depth >= 4) { + uint dist = GetTileDist1Db(tile, arf->final_tile); + if (dist < arf->cur_best_dist) { + // Store the tile that is closest to the final position. + arf->cur_best_dist = dist; + arf->cur_best_tile = tile; + arf->cur_best_dir = dir; + arf->cur_best_depth = arf->depth; + } + return; + } + + // Increase recursion depth + arf->depth++; + + // Grab pointer to list of stuff that is possible to build + p = _ai_table_15[dir]; + + // Try to build a single rail in all directions. + FindLandscapeHeightByTile(&arf->ti, tile); + if (arf->ti.z == 0) { + p += 6; + } else { + do { + // Make sure that a road can be built here. + if (AiBuildRoadHelper(tile, DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, p[0])) { + AiBuildRoadRecursive(arf, tile, p[1]); + } + + // At the bottom depth? + if (arf->depth == 1) { + AiCheckRoadPathBetter(arf, p); + } + + p += 2; + } while (!(p[0]&0x80)); + } + + AiCheckBuildRoadBridgeHere(arf, tile, p); + AiCheckBuildRoadTunnelHere(arf, tile, p+1); + + arf->depth--; +} + +int sw; + + +static void AiBuildRoadConstruct(Player *p) +{ + AiRoadFinder arf; + int i; + uint tile; + + // Reached destination? + if (AiCheckRoadFinished(p)) { + p->ai.state_mode = 255; + return; + } + + // Setup recursive finder and call it. + arf.player = p; + arf.final_tile = p->ai.cur_tile_b; + arf.final_dir = p->ai.cur_dir_b; + arf.depth = 0; + arf.recursive_mode = 0; + arf.best_ptr = NULL; + arf.cur_best_dist = (uint)-1; + arf.cur_best_depth = 0xff; + arf.best_dist = (uint)-1; + arf.best_depth = 0xff; + arf.cur_best_tile = 0; + arf.best_tile = 0; + AiBuildRoadRecursive(&arf, p->ai.cur_tile_a, p->ai.cur_dir_a); + + // Reached destination? + if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) { + p->ai.state_mode = 255; + return; + } + + // Didn't find anything to build? + if (arf.best_ptr == NULL) { + // Terraform some +do_some_terraform: + for(i=0; i!=5; i++) + AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0); + + if (++p->ai.state_counter == 21) { + p->ai.state_mode = 1; + + p->ai.cur_tile_a = TILE_MASK(p->ai.cur_tile_a + _tileoffs_by_dir[p->ai.cur_dir_a]); + p->ai.cur_dir_a ^= 2; + p->ai.state_counter = 0; + } + return; + } + + tile = TILE_MASK(p->ai.cur_tile_a + _tileoffs_by_dir[p->ai.cur_dir_a]); + + if (arf.best_ptr[0]&0x80) { + int i; + int32 bridge_len; + p->ai.cur_tile_a = arf.bridge_end_tile; + bridge_len = GetBridgeLength(tile, p->ai.cur_tile_a); // tile + + /* Figure out what (road)bridge type to build + start with best bridge, then go down to worse and worse bridges + unnecessary to check for worse bridge (i=0), since AI will always build that. + AI is so fucked up that fixing this small thing will probably not solve a thing + */ + for(i = 10; i != 0; i--) { + if (CheckBridge_Stuff(i, bridge_len)) { + int32 cost = DoCommandByTile(tile, p->ai.cur_tile_a, i + (0x80 << 8), DC_AUTO, CMD_BUILD_BRIDGE); + if (cost != CMD_ERROR && cost < (p->player_money >> 5)) + break; + } + } + + // Build it + DoCommandByTile(tile, p->ai.cur_tile_a, i + (0x80 << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE); + + p->ai.state_counter = 0; + } else if (arf.best_ptr[0]&0x40) { + // tunnel + DoCommandByTile(tile, 0x200, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL); + p->ai.cur_tile_a = _build_tunnel_endtile; + p->ai.state_counter = 0; + } else { + + // road + if (!AiBuildRoadHelper(tile, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, arf.best_ptr[0])) + goto do_some_terraform; + + p->ai.cur_dir_a = arf.best_ptr[1]; + p->ai.cur_tile_a = tile; + p->ai.state_counter = 0; + } + + if (arf.best_tile != 0) { + for(i=0; i!=2; i++) + AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0); + } +} + + +static void AiBuildRoad(Player *p) +{ + int i; + + if (p->ai.state_mode < 1) { + // Construct mode, build new road. + AiBuildRoadConstruct(p); + } else if (p->ai.state_mode == 1) { + // Destruct mode, not implemented for roads. + p->ai.state_mode = 2; + p->ai.state_counter = 0; + } else if (p->ai.state_mode == 2) { + + // Terraform some and then try building again. + for(i=0; i!=4; i++) + AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0); + + if (++p->ai.state_counter == 4) { + p->ai.state_counter = 0; + p->ai.state_mode = 0; + } + } +} + +static TileIndex AiGetRoadBlockEdge(byte rule, TileIndex tile, int *dir) +{ + const AiDefaultBlockData *p = _road_default_block_data[rule]->data; + while (p->mode != 1) p++; + *dir = p->attr; + return TILE_ADD(tile, p->tileoffs); +} + + +static void AiStateBuildRoad(Player *p) +{ + int num; + AiBuildRec *aib; + byte cmd; + TileIndex tile; + int dir; + + // time out? + if (++p->ai.timeout_counter == 1388) { + p->ai.state = AIS_DELETE_ROAD_BLOCKS; + return; + } + + // Currently building a road between two points? + if (p->ai.state_mode != 255) { + AiBuildRoad(p); + + // Alternate between edges + swap_tile(&p->ai.start_tile_a, &p->ai.start_tile_b); + swap_tile(&p->ai.cur_tile_a, &p->ai.cur_tile_b); + swap_byte(&p->ai.start_dir_a, &p->ai.start_dir_b); + swap_byte(&p->ai.cur_dir_a, &p->ai.cur_dir_b); + + sw ^= 1; + return; + } + + // Now, find two new points to build between + num = p->ai.num_build_rec; + aib = &p->ai.src; + + for(;;) { + cmd = aib->buildcmd_a; + aib->buildcmd_a = 255; + if (cmd != 255) break; + + aib++; + if (--num == 0) { + p->ai.state = AIS_BUILD_ROAD_VEHICLES; + return; + } + } + + // Find first edge to build from. + tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir); + p->ai.start_tile_a = tile; + p->ai.cur_tile_a = tile; + p->ai.start_dir_a = dir; + p->ai.cur_dir_a = dir; + + // Find second edge to build to + aib = (&p->ai.src) + (cmd&0xF); + tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir); + p->ai.start_tile_b = tile; + p->ai.cur_tile_b = tile; + p->ai.start_dir_b = dir; + p->ai.cur_dir_b = dir; + + // And setup state. + p->ai.state_mode = 2; + p->ai.state_counter = 0; + p->ai.banned_tile_count = 0; +} + +static int AiGetStationIdFromRoadBlock(TileIndex tile, int id) +{ + const AiDefaultBlockData *p = _road_default_block_data[id]->data; + while (p->mode != 1) p++; + return _map2[TILE_ADD(tile, p->tileoffs)]; +} + +static void AiStateBuildRoadVehicles(Player *p) +{ + const AiDefaultBlockData *ptr; + uint tile,loco_id; + int veh, i; + int32 cost; + + ptr = _road_default_block_data[p->ai.src.cur_building_rule]->data; + for(;ptr->mode != 0;ptr++) {} + tile = TILE_ADD(p->ai.src.use_tile, ptr->tileoffs); + + veh = AiChooseRoadVehToBuild(p->ai.cargo_type, p->player_money); + if (veh == -1) { + p->ai.state = AIS_0; + return; + } + + cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH); + if (cost == CMD_ERROR) + return; + + loco_id = _new_roadveh_id; + + for(i=0; p->ai.order_list_blocks[i] != 0xFF; i++) { + AiBuildRec *aib = (&p->ai.src) + p->ai.order_list_blocks[i]; + uint flags = (AiGetStationIdFromRoadBlock(aib->use_tile, aib->cur_building_rule) << 8) + OT_GOTO_STATION; + bool is_pass = (p->ai.cargo_type == CT_PASSENGERS || + p->ai.cargo_type == CT_MAIL || + (_opt.landscape==LT_NORMAL && p->ai.cargo_type == CT_VALUABLES)); + + if (!is_pass && i == 1) flags |= OF_UNLOAD; + if (p->ai.num_want_fullload != 0 && (is_pass || i == 0)) flags |= OF_FULL_LOAD; + + DoCommandByTile(0, loco_id + (i << 16), flags, DC_EXEC, CMD_INSERT_ORDER); + } + + DoCommandByTile(0, loco_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH); + + if (p->ai.num_want_fullload != 0) + p->ai.num_want_fullload--; + + if (--p->ai.num_loco_to_build == 0) { + p->ai.state = AIS_0; + } +} + +static void AiStateDeleteRoadBlocks(Player *p) +{ + int num; + AiBuildRec *aib; + const AiDefaultBlockData *b; + + num = p->ai.num_build_rec; + aib = &p->ai.src; + do { + if (aib->cur_building_rule != 255) { + b = _road_default_block_data[aib->cur_building_rule]->data; + while (b->mode != 4) { + if (b->mode <= 1) { + DoCommandByTile(TILE_ADD(aib->use_tile, b->tileoffs), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + b++; + } + } + } while (++aib,--num); + + p->ai.state = AIS_0; +} + +static bool AiCheckIfHangar(Station *st) +{ + uint tile = st->airport_tile; + // HANGAR of airports + // 0x20 - hangar large airport (32) + // 0x41 - hangar small airport (65) + return (_map5[tile] == 32 || _map5[tile] == 65); +} + +static void AiStateAirportStuff(Player *p) +{ + Station *st; + byte acc_planes; + int i; + AiBuildRec *aib; + byte rule; + + // Here we look for an airport we could use instead of building a new + // one. If we find such an aiport for any waypoint, + // AiStateBuildDefaultAirportBlocks() will kindly skip that one when + // building the waypoints. + + i = 0; + do { + // We do this all twice - once for the source (town in the case + // of oilrig route) and then for the destination (oilrig in the + // case of oilrig route). + aib = &p->ai.src + i; + + FOR_ALL_STATIONS(st) { + // Dismiss ghost stations. + if (st->xy == 0) + continue; + + // Is this an airport? + if (!(st->facilities & FACIL_AIRPORT)) + continue; + + // Do we own the airport? (Oilrigs aren't owned, though.) + if (st->owner != OWNER_NONE && st->owner != _current_player) + continue; + + acc_planes = GetAirport(st->airport_type)->acc_planes; + + // Dismiss heliports, unless we are checking an oilrig. + if (acc_planes == HELICOPTERS_ONLY && !(p->ai.build_kind == 1 && i == 1)) + continue; + + // Dismiss country airports if we are doing the other + // endpoint of an oilrig route. + if (acc_planes == AIRCRAFT_ONLY && (p->ai.build_kind == 1 && i == 0)) + continue; + + // Dismiss airports too far away. + if (GetTileDist1D(st->airport_tile, aib->spec_tile) > aib->rand_rng) + continue; + + // It's ideal airport, let's take it! + + /* XXX: This part is utterly broken - rule should + * contain number of the rule appropriate for the + * airport type (country, town, ...), see + * _airport_default_block_data (rule is just an index + * in this array). But the only difference between the + * currently existing two rules (rule 0 - town and rule + * 1 - country) is the attr field which is used only + * when building new airports - and that's irrelevant + * for us. So using just about any rule will suffice + * here for now (some of the new airport types would be + * broken because they will probably need different + * tileoff values etc), no matter that + * AiCheckIfHangar() makes no sense. --pasky */ + if (acc_planes == HELICOPTERS_ONLY) { + /* Heliports should have maybe own rulesets but + * OTOH we don't want AI to pick them up when + * looking for a suitable airport type to build. + * So any of rules 0 or 1 would do for now. The + * original rule number was 2 but that's a bug + * because we have no such rule. */ + rule = 1; + } else { + rule = AiCheckIfHangar(st); + } + + aib->cur_building_rule = rule; + aib->use_tile = st->airport_tile; + break; + } + } while (++i != p->ai.num_build_rec); + + p->ai.state = AIS_BUILD_DEFAULT_AIRPORT_BLOCKS; + p->ai.state_mode = 255; + p->ai.state_counter = 0; +} + +static int32 AiDoBuildDefaultAirportBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag) +{ + int32 total_cost = 0, r; + + for(;p->mode == 0;p++) { + if (!HASBIT(_avail_aircraft, p->attr)) + return CMD_ERROR; + r = DoCommandByTile(TILE_MASK(tile + p->tileoffs), p->attr,0,flag | DC_AUTO | DC_NO_WATER,CMD_BUILD_AIRPORT); + if (r == CMD_ERROR) + return CMD_ERROR; + total_cost += r; + } + + return total_cost; +} + +static bool AiCheckAirportResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo) +{ + uint values[NUM_CARGO]; + int w,h; + uint tile2; + + for(;p->mode==0;p++) { + tile2 = TILE_ADD(tile, p->tileoffs); + w = _airport_size_x[p->attr]; + h = _airport_size_y[p->attr]; + if (cargo & 0x80) { + GetProductionAroundTiles(values, tile2, w, h); + return values[cargo & 0x7F] != 0; + } else { + GetAcceptanceAroundTiles(values, tile2, w, h); + return values[cargo] >= 8; + } + } + return true; +} + +static int AiFindBestDefaultAirportBlock(TileIndex tile, byte cargo, byte heli, int32 *cost) +{ + int i; + const AiDefaultBlockData *p; + for(i=0; (p = _airport_default_block_data[i]) != NULL; i++) { + // If we are doing a helicopter service, avoid building + // airports where they can't land. + if (heli && GetAirport(p->attr)->acc_planes == AIRCRAFT_ONLY) + continue; + + *cost = AiDoBuildDefaultAirportBlock(tile, p, 0); + if (*cost != CMD_ERROR && AiCheckAirportResources(tile, p, cargo)) + return i; + } + return -1; +} + +static void AiStateBuildDefaultAirportBlocks(Player *p) +{ + int i, j; + AiBuildRec *aib; + int rule; + int32 cost; + + // time out? + if (++p->ai.timeout_counter == 1388) { + p->ai.state = AIS_0; + return; + } + + // do the following 8 times + i = 8; + do { + // check if we can build the default + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + // this item has already been built? + if (aib->cur_building_rule != 255) + continue; + + // adjust the coordinate randomly, + // to make sure that we find a position. + aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng); + + // check if the aircraft stuff can be built there. + rule = AiFindBestDefaultAirportBlock(aib->use_tile, aib->cargo, p->ai.build_kind, &cost); + +#if 0 + if (!IS_TILETYPE(aib->use_tile, MP_STREET) && + !IS_TILETYPE(aib->use_tile, MP_RAILWAY) && + !IS_TILETYPE(aib->use_tile, MP_STATION) + ) { + + _map_type_and_height[aib->use_tile] = 0xa1; + _map5[aib->use_tile] = 0x80; + MarkTileDirtyByTile(aib->use_tile); + } +#endif +// redsq_debug(aib->use_tile); + + if (rule == -1) { + // cannot build, terraform after a while + if (p->ai.state_counter >= 600) { + AiDoTerraformLand(aib->use_tile, Random()&3, 3, (int8)p->ai.state_mode); + } + // also try the other terraform direction + if (++p->ai.state_counter >= 1000) { + p->ai.state_counter = 0; + p->ai.state_mode = -p->ai.state_mode; + } + } else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p,aib->use_tile)) { + // player has money, build it. + int32 r; + + aib->cur_building_rule = rule; + + r = AiDoBuildDefaultAirportBlock( + aib->use_tile, + _airport_default_block_data[rule], + DC_EXEC | DC_NO_TOWN_RATING + ); + assert(r != CMD_ERROR); + } + } while (++aib,--j); + } while (--i); + + // check if we're done with all of them + aib = &p->ai.src; + j = p->ai.num_build_rec; + do { + if (aib->cur_building_rule == 255) + return; + } while (++aib,--j); + + // yep, all are done. switch state. + p->ai.state = AIS_BUILD_AIRCRAFT_VEHICLES; +} + +static int AiGetStationIdFromAircraftBlock(TileIndex tile, int id) +{ + const AiDefaultBlockData *p = _airport_default_block_data[id]; + while (p->mode != 1) p++; + return _map2[TILE_ADD(tile, p->tileoffs)]; +} + +static void AiStateBuildAircraftVehicles(Player *p) +{ + const AiDefaultBlockData *ptr; + uint tile; + int veh; + int32 cost; + int i; + uint loco_id; + + ptr = _airport_default_block_data[p->ai.src.cur_building_rule]; + for(;ptr->mode!=0;ptr++) {} + + tile = TILE_ADD(p->ai.src.use_tile, ptr->tileoffs); + + veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind!=0 ? 1 : 0); + if (veh == -1) { + return; + } + + cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT); + if (cost == CMD_ERROR) + return; + loco_id = _new_aircraft_id; + + for(i=0; p->ai.order_list_blocks[i] != 0xFF; i++) { + AiBuildRec *aib = (&p->ai.src) + p->ai.order_list_blocks[i]; + uint flags = (AiGetStationIdFromAircraftBlock(aib->use_tile, aib->cur_building_rule) << 8) + OT_GOTO_STATION; + bool is_pass = (p->ai.cargo_type == CT_PASSENGERS || p->ai.cargo_type == CT_MAIL); + + if (!is_pass && i == 1) flags |= OF_UNLOAD; + if (p->ai.num_want_fullload != 0 && (is_pass || i == 0)) flags |= OF_FULL_LOAD; + + DoCommandByTile(0, loco_id + (i << 16), flags, DC_EXEC, CMD_INSERT_ORDER); + } + + DoCommandByTile(0, loco_id, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); + + if (p->ai.num_want_fullload != 0) + p->ai.num_want_fullload--; + + if (--p->ai.num_loco_to_build == 0) { + p->ai.state = AIS_0; + } +} + +static void AiStateCheckShipStuff(Player *p) +{ + // XXX + error("!AiStateCheckShipStuff"); +} + +static void AiStateBuildDefaultShipBlocks(Player *p) +{ + // XXX + error("!AiStateBuildDefaultShipBlocks"); +} + +static void AiStateDoShipStuff(Player *p) +{ + // XXX + error("!AiStateDoShipStuff"); +} + +static void AiStateSellVeh(Player *p) +{ + Vehicle *v = p->ai.cur_veh; + + if (v->owner == _current_player) { + if (v->type == VEH_Train) { + + if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { + if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_TRAIN_GOTO_DEPOT); + goto going_to_depot; + } + + // Sell whole train + DoCommandByTile(v->tile, v->index, 1, DC_EXEC, CMD_SELL_RAIL_WAGON); + + } else if (v->type == VEH_Road) { + if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { + if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT); + goto going_to_depot; + } + + DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH); + } else if (v->type == VEH_Aircraft) { + if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) { + if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) + DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR); + goto going_to_depot; + } + + DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT); + } else if (v->type == VEH_Ship) { + // XXX: not implemented + error("!v->type == VEH_Ship"); + } + } + + goto return_to_loop; +going_to_depot:; + if (++p->ai.state_counter <= 832) + return; + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + v->next_order = OT_DUMMY; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + } +return_to_loop:; + p->ai.state = AIS_VEH_LOOP; +} + +static void AiStateRemoveStation(Player *p) +{ + // Remove stations that aren't in use by any vehicle + byte in_use[256], *used; + uint16 *ord; + Station *st; + uint tile; + + // Go to this state when we're done. + p->ai.state = AIS_1; + + // Get a list of all stations that are in use by a vehicle + memset(in_use, 0, sizeof(in_use)); + for(ord=_order_array; ord != _ptr_to_next_order; ord++) { + if ((*ord & OT_MASK) == OT_GOTO_STATION) + in_use[*ord >> 8] = 1; + } + + // Go through all stations and delete those that aren't in use + used=in_use; + FOR_ALL_STATIONS(st) { + if (st->xy != 0 && st->owner == _current_player && !*used && + ((tile = st->bus_tile) != 0 || + (tile = st->lorry_tile) != 0 || + (tile = st->train_tile) != 0 || + (tile = st->dock_tile) != 0 || + (tile = st->airport_tile) != 0)) { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + used++; + } + +} + +static void AiRemovePlayerRailOrRoad(Player *p, uint tile) +{ + byte m5; + + if (IS_TILETYPE(tile, MP_RAILWAY)) { + if (_map_owner[tile] != _current_player) + return; + m5 = _map5[tile]; + if ((m5&~0x3) != 0xC0) { +is_rail_crossing:; + m5 = GetRailTrackStatus(tile); + + if (m5 == 0xC || m5 == 0x30) + return; + + if (m5&0x25) { +pos_0: + if (!(GetRailTrackStatus(TILE_MASK(tile-TILE_XY(1,0)))&0x19)) { + p->ai.cur_dir_a = 0; + p->ai.cur_tile_a = tile; + p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE; + return; + } + } + + if (m5&0x2A) { +pos_1: + if (!(GetRailTrackStatus(TILE_MASK(tile+TILE_XY(0,1)))&0x16)) { + p->ai.cur_dir_a = 1; + p->ai.cur_tile_a = tile; + p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE; + return; + } + } + + if (m5&0x19) { +pos_2: + if (!(GetRailTrackStatus(TILE_MASK(tile+TILE_XY(1,0)))&0x25)) { + p->ai.cur_dir_a = 2; + p->ai.cur_tile_a = tile; + p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE; + return; + } + } + + if (m5&0x16) { +pos_3: + if (!(GetRailTrackStatus(TILE_MASK(tile-TILE_XY(0,1)))&0x2A)) { + p->ai.cur_dir_a = 3; + p->ai.cur_tile_a = tile; + p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE; + return; + } + } + } else { + static const byte _depot_bits[] = {0x19,0x16,0x25,0x2A}; + + m5 &= 3; + if (GetRailTrackStatus(tile + _tileoffs_by_dir[m5]) & _depot_bits[m5]) + return; + + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + } else if (IS_TILETYPE(tile, MP_STREET)) { + if (_map_owner[tile] != _current_player) + return; + + if ( (_map5[tile]&0xF0) == 0x10) + goto is_rail_crossing; + + if ( (_map5[tile]&0xF0) == 0x20) { + int dir; + + // Check if there are any stations around. + if (IS_TILETYPE(tile + TILE_XY(-1,0), MP_STATION) && + _map_owner[tile + TILE_XY(-1,0)] == _current_player) + return; + + if (IS_TILETYPE(tile + TILE_XY(1,0), MP_STATION) && + _map_owner[tile + TILE_XY(1,0)] == _current_player) + return; + + if (IS_TILETYPE(tile + TILE_XY(0,-1), MP_STATION) && + _map_owner[tile + TILE_XY(0,-1)] == _current_player) + return; + + if (IS_TILETYPE(tile + TILE_XY(0,1), MP_STATION) && + _map_owner[tile + TILE_XY(0,1)] == _current_player) + return; + + dir = _map5[tile] & 3; + + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + DoCommandByTile( + TILE_MASK(tile + _tileoffs_by_dir[dir]), + 8 >> (dir ^ 2), + 0, + DC_EXEC, + CMD_REMOVE_ROAD); + } + } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + byte b; + + if (_map_owner[tile] != _current_player || (_map5[tile] & 0xC6) != 0x80) + return; + + m5 = 0; + + b = _map5[tile] & 0x21; + if (b == 0) goto pos_0; + if (b == 1) goto pos_3; + if (b == 0x20) goto pos_2; + goto pos_1; + } +} + +static void AiStateRemoveTrack(Player *p) +{ + int num = 1000; + + do { + uint tile = ++p->ai.state_counter; + + // Iterated all tiles? + if (tile == 0) { + p->ai.state = AIS_REMOVE_STATION; + return; + } + + // Remove player stuff in that tile + AiRemovePlayerRailOrRoad(p, tile); + if (p->ai.state != AIS_REMOVE_TRACK) + return; + } while (--num); +} + +static void AiStateRemoveSingleRailTile(Player *p) +{ + // Remove until we can't remove more. + if (!AiRemoveTileAndGoForward(p)) { + p->ai.state = AIS_REMOVE_TRACK; + } +} + +static AiStateAction * const _ai_actions[] = { + AiCase0, + AiCase1, + AiStateVehLoop, + AiStateCheckReplaceVehicle, + AiStateDoReplaceVehicle, + AiStateWantNewRoute, + + AiStateBuildDefaultRailBlocks, + AiStateBuildRail, + AiStateBuildRailVeh, + AiStateDeleteRailBlocks, + + AiStateBuildDefaultRoadBlocks, + AiStateBuildRoad, + AiStateBuildRoadVehicles, + AiStateDeleteRoadBlocks, + + AiStateAirportStuff, + AiStateBuildDefaultAirportBlocks, + AiStateBuildAircraftVehicles, + + AiStateCheckShipStuff, + AiStateBuildDefaultShipBlocks, + AiStateDoShipStuff, + + AiStateSellVeh, + AiStateRemoveStation, + AiStateRemoveTrack, + + AiStateRemoveSingleRailTile +}; + +extern void ShowBuyCompanyDialog(uint player); + +static void AiHandleTakeover(Player *p) +{ + if (p->bankrupt_timeout != 0) { + if ((p->bankrupt_timeout-=8) > 0) + return; + p->bankrupt_timeout = 0; + DeleteWindowById(WC_BUY_COMPANY, _current_player); + if (_current_player == _local_player) { + AskExitToGameMenu(); + return; + } + if (IS_HUMAN_PLAYER(_current_player)) + return; + } + + if (p->bankrupt_asked == 255) + return; + + { + uint asked = p->bankrupt_asked; + Player *pp, *best_pl = NULL; + int32 best_val = -1; + uint old_p; + + // Ask the guy with the highest performance hist. + FOR_ALL_PLAYERS(pp) { + if (pp->is_active && + !(asked&1) && + pp->bankrupt_asked == 0 && + best_val < pp->old_economy[1].performance_history) { + best_val = pp->old_economy[1].performance_history; + best_pl = pp; + } + asked>>=1; + } + + // Asked all players? + if (best_val == -1) { + p->bankrupt_asked = 255; + return; + } + + SETBIT(p->bankrupt_asked, best_pl->index); + + if (best_pl->index == _local_player) { + p->bankrupt_timeout = 4440; + ShowBuyCompanyDialog(_current_player); + return; + } + if (IS_HUMAN_PLAYER(best_pl->index)) + return; + + // Too little money for computer to buy it? + if (best_pl->player_money >> 1 >= p->bankrupt_value) { + // Computer wants to buy it. + old_p = _current_player; + _current_player = p->index; + DoCommandByTile(0, old_p, 0, DC_EXEC, CMD_BUY_COMPANY); + _current_player = old_p; + } + } +} + +static void AiAdjustLoan(Player *p) +{ + int32 base = AiGetBasePrice(p); + + if (p->player_money > base * 1400) { + // Decrease loan + if (p->current_loan != 0) { + DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_DECREASE_LOAN); + } + } else if (p->player_money < base * 500) { + // Increase loan + if (p->current_loan < _economy.max_loan && + p->num_valid_stat_ent >= 2 && + -(p->old_economy[0].expenses+p->old_economy[1].expenses) < base * 60) { + DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_INCREASE_LOAN); + } + } +} + +static void AiBuildCompanyHQ(Player *p) +{ + TileIndex tile; + + if (p->location_of_house == 0 && + p->last_build_coordinate != 0) { + tile = AdjustTileCoordRandomly(p->last_build_coordinate, 8); + DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ); + } +} + + +void AiDoGameLoop(Player *p) +{ + _cur_ai_player = p; + + if (p->bankrupt_asked != 0) { + AiHandleTakeover(p); + return; + } + + if (IS_HUMAN_PLAYER(_current_player)) + return; + + AiAdjustLoan(p); + AiBuildCompanyHQ(p); + + if (_opt.diff.competitor_speed == 4) { + /* ultraspeed */ + _ai_actions[p->ai.state](p); + if (p->bankrupt_asked != 0) + return; + } else if (_opt.diff.competitor_speed != 3) { + p->ai.tick++; + if (!(p->ai.tick&1)) + return; + if (_opt.diff.competitor_speed != 2) { + if (!(p->ai.tick&2)) + return; + if (_opt.diff.competitor_speed == 0) { + if (!(p->ai.tick&4)) + return; + } + } + } +#if 0 + { + static byte old_state = 99; + static bool hasdots = false; + char *_ai_state_names[]={ + "AiCase0", + "AiCase1", + "AiStateVehLoop", + "AiStateCheckReplaceVehicle", + "AiStateDoReplaceVehicle", + "AiStateWantNewRoute", + "AiStateBuildDefaultRailBlocks", + "AiStateBuildRail", + "AiStateBuildRailVeh", + "AiStateDeleteRailBlocks", + "AiStateBuildDefaultRoadBlocks", + "AiStateBuildRoad", + "AiStateBuildRoadVehicles", + "AiStateDeleteRoadBlocks", + "AiStateAirportStuff", + "AiStateBuildDefaultAirportBlocks", + "AiStateBuildAircraftVehicles", + "AiStateCheckShipStuff", + "AiStateBuildDefaultShipBlocks", + "AiStateDoShipStuff", + "AiStateSellVeh", + "AiStateRemoveStation", + "AiStateRemoveTrack", + "AiStateRemoveSingleRailTile" + }; + + if (p->ai.state != old_state) { + if (hasdots) + printf("\n"); + hasdots=false; + printf("AiState: %s\n", _ai_state_names[old_state=p->ai.state]); + } else { + printf("."); + hasdots=true; + } + } +#endif + + _ai_actions[p->ai.state](p); +} diff --git a/aircraft_cmd.c b/aircraft_cmd.c new file mode 100644 --- /dev/null +++ b/aircraft_cmd.c @@ -0,0 +1,1890 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "engine.h" +#include "command.h" +#include "station.h" +#include "news.h" +#include "gfx.h" +#include "player.h" +#include "airport.h" + +static bool AirportMove(Vehicle *v, const AirportFTAClass *Airport); +static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport); +static bool AirportHasBlock(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport); +static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *Airport); +static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *Airport); +static void AirportGoToNextPosition(Vehicle *v, const AirportFTAClass *Airport); + +static void AircraftNextAirportPos_and_Order(Vehicle *v); +static byte GetAircraftFlyingAltitude(const Vehicle *v); + +static const SpriteID _aircraft_sprite[] = { + 0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD, + 0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5, + 0x0EAD, 0x0EE5, 0x0F05, 0x0F0D, + 0x0F15, 0x0F1D, 0x0F25, 0x0F2D, + 0x0EED, 0x0EF5, 0x0EFD, 0x0F35, + 0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5, + 0x0EBD, 0x0EC5 +}; + +int GetAircraftImage(Vehicle *v, byte direction) +{ + int spritenum = v->spritenum; + +#ifdef AIRCRAFT_CUSTOM_SPRITES // TODO --pasky + if (is_custom_sprite(spritenum)) { + int sprite = GetCustomVehicleSprite(v, direction); + + if (sprite) return sprite; + spritenum = _engine_original_sprites[v->engine_type]; + } +#endif + return direction + _aircraft_sprite[spritenum]; +} + +const byte _aircraft_cost_table[NUM_AIRCRAFT_ENGINES] = { + 14, 15, 16, 75, 15, 18, 17, 18, + 19, 20, 16, 18, 17, 30, 18, 19, + 27, 25, 20, 19, 18, 26, 16, 17, + 16, 16, 17, 18, 20, 21, 19, 24, + 80, 13, 18, 25, 32, 80, 15, 17, + 15 +}; + +const byte _aircraft_speed[NUM_AIRCRAFT_ENGINES] = { + 37, 37, 74, 181, 37, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 181, 74, + 181, 37, 37, 74, 74, 181, 25, 40, + 25 +}; + +const byte _aircraft_running_cost[NUM_AIRCRAFT_ENGINES] = { + 85, 100, 130, 250, 98, 240, 150, 245, + 192, 190, 135, 240, 155, 253, 210, 220, + 230, 225, 235, 220, 170, 210, 125, 145, + 130, 149, 170, 210, 230, 220, 160, 248, + 251, 85, 100, 140, 220, 255, 81, 77, + 80 +}; + +const byte _aircraft_num_mail[NUM_AIRCRAFT_ENGINES] = { + 4, 8, 10, 20, 6, 30, 15, 30, + 40, 25, 10, 35, 15, 50, 25, 25, + 40, 35, 30, 25, 20, 20, 10, 10, + 10, 10, 18, 25, 60, 65, 45, 80, + 45, 5, 9, 12, 40, 30, 15, 20, + 10 +}; + +const uint16 _aircraft_num_pass[NUM_AIRCRAFT_ENGINES] = { + 25, 65, 90,100, 30,200,100,150, + 220,230, 95,170,110,300,200,240, + 260,240,260,210,160,220, 80, 85, + 75, 85, 65,110,180,150, 85,400, + 130, 25, 60, 90,200,100, 40, 55, + 40 +}; + +const byte _aircraft_sounds[NUM_AIRCRAFT_ENGINES] = { + 6, 6, 7, 59, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 61, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 61, + 59, 69, 70, 7, 61, 59, 7, 7, + 7 +}; + +const byte _aircraft_table_3[NUM_AIRCRAFT_ENGINES] = { + 1, 0, 2, 8, 5, 6, 2, 2, + 3, 3, 2, 2, 4, 7, 4, 4, + 4, 3, 4, 4, 4, 4, 6, 2, + 11, 10, 15, 12, 13, 14, 16, 17, + 18, 20, 21, 22, 23, 24, 9, 19, + 25 +}; + +// &1 = regular aircraft +// &2 = crashes easily on small airports +const byte _aircraft_subtype[NUM_AIRCRAFT_ENGINES] = { + 1, 1, 3, 3, 1, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 1, 3, 3, 0, 0, + 0 +}; + +const byte _aircraft_acceleration[NUM_AIRCRAFT_ENGINES] = { + 18, 20, 35, 50, 20, 40, 35, 40, + 40, 40, 35, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 50, 40, + 40, 40, 40, 40, 40, 40, 40, 40, + 50, 18, 20, 40, 40, 50, 20, 20, + 20, +}; + +void DrawAircraftEngine(int x, int y, int engine, uint32 image_ormod) +{ + DrawSprite((6 + _aircraft_sprite[_aircraft_table_3[engine - AIRCRAFT_ENGINES_INDEX]]) | image_ormod, x, y); + + if ((_aircraft_subtype[engine - AIRCRAFT_ENGINES_INDEX]&1) == 0) + DrawSprite(0xF3D, x, y-5); +} + +void DrawAircraftEngineInfo(int engine, int x, int y, int maxw) +{ + engine -= AIRCRAFT_ENGINES_INDEX; + + SET_DPARAM32(0, ((_price.aircraft_base >> 3) * _aircraft_cost_table[engine]) >> 5); + SET_DPARAM16(1, _aircraft_speed[engine] << 3); + SET_DPARAM16(2, _aircraft_num_pass[engine]); + SET_DPARAM16(3, _aircraft_num_mail[engine]); + SET_DPARAM32(4, _aircraft_running_cost[engine] * _price.aircraft_running >> 8); + + DrawStringMultiCenter(x, y, STR_A02E_COST_MAX_SPEED_CAPACITY, maxw); +} + +/* Allocate many vehicles */ +bool AllocateVehicles(Vehicle **vl, int num) +{ + int i; + Vehicle *v; + bool success = true; + + for(i=0; i!=num; i++) { + vl[i] = v = AllocateVehicle(); + if (v == NULL) { + success = false; + break; + } + v->type = 1; + } + + while (--i >= 0) { + vl[i]->type = 0; + } + + return success; +} + +static int32 EstimateAircraftCost(uint16 engine_type) +{ + return _aircraft_cost_table[engine_type - AIRCRAFT_ENGINES_INDEX] * (_price.aircraft_base>>3)>>5; +} + + +/* p1 = engine */ +int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int32 value; + Vehicle *vl[3], *v, *u, *w; + byte unit_num; + uint tile = TILE_FROM_XY(x,y); + Engine *e; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + value = EstimateAircraftCost(p1); + + if (flags & DC_QUERY_COST) + return value; + + // allocate 2 or 3 vehicle structs, depending on type + if (!AllocateVehicles(vl, (_aircraft_subtype[p1 - AIRCRAFT_ENGINES_INDEX]&1) == 0 ? 3 : 2) || + _ptr_to_next_order >= endof(_order_array)) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + unit_num = GetFreeUnitNumber(VEH_Aircraft); + if (unit_num > _patches.max_aircraft) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + if (flags & DC_EXEC) { + v = vl[0]; + u = vl[1]; + + v->unitnumber = unit_num; + v->type = u->type = VEH_Aircraft; + v->direction = 3; + + v->owner = u->owner = _current_player; + + v->tile = tile; +// u->tile = 0; + + x = GET_TILE_X(tile)*16 + 5; + y = GET_TILE_Y(tile)*16 + 3; + + v->x_pos = u->x_pos = x; + v->y_pos = u->y_pos = y; + + u->z_pos = GetSlopeZ(x, y); + v->z_pos = u->z_pos + 1; + + v->x_offs = v->y_offs = -1; +// u->delta_x = u->delta_y = 0; + + v->sprite_width = v->sprite_height = 2; + v->z_height = 5; + + u->sprite_width = u->sprite_height = 2; + u->z_height = 1; + + v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; + u->vehstatus = VS_HIDDEN | VS_UNCLICKABLE | VS_DISASTER; + + v->spritenum = _aircraft_table_3[p1 - AIRCRAFT_ENGINES_INDEX]; +// v->cargo_count = u->number_of_pieces = 0; + + v->cargo_cap = _aircraft_num_pass[p1 - AIRCRAFT_ENGINES_INDEX]; + u->cargo_cap = _aircraft_num_mail[p1 - AIRCRAFT_ENGINES_INDEX]; + + v->cargo_type = CT_PASSENGERS; + u->cargo_type = CT_MAIL; + + v->string_id = STR_SV_AIRCRAFT_NAME; +// v->next_order_param = v->next_order = 0; + +// v->load_unload_time_rem = 0; +// v->progress = 0; + v->last_station_visited = 0xFF; +// v->destination_coords = 0; + + v->max_speed = _aircraft_speed[p1 - AIRCRAFT_ENGINES_INDEX]; + v->acceleration = _aircraft_acceleration[p1 - AIRCRAFT_ENGINES_INDEX]; + v->engine_type = (byte)p1; + + v->subtype = (_aircraft_subtype[p1 - AIRCRAFT_ENGINES_INDEX]&1) == 0 ? 0 : 2; + v->value = value; + + u->subtype = 4; + + e = &_engines[p1]; + v->reliability = e->reliability; + v->reliability_spd_dec = e->reliability_spd_dec; + v->max_age = e->lifelength * 366; + + _new_aircraft_id = v->index; + + *(v->schedule_ptr = _ptr_to_next_order++) = 0; + // the AI doesn't click on a tile to build airplanes, so the below code will + // never work. Therefore just assume the AI's planes always come from Hangar0 + v->u.air.pos = (_is_ai_player) ? 0:MAX_ELEMENTS; + + /* When we click on hangar we know the tile (it is in var 'tile')it is on. By that we know + its position in the array of depots the airport has.....we can search + ->layout for #th position of depot. Since layout must start with depots, it is simple + */ + { + Station *st; + const AirportFTAClass *Airport; + const uint16 *cur_depot; + byte i = 0; + st = DEREF_STATION(_map2[tile]); + Airport = GetAirport(st->airport_type); + // first element of depot array contains #of depots on the airport + for (cur_depot=&Airport->airport_depots[1]; i != Airport->airport_depots[0]; cur_depot++) { + if ((uint)(st->airport_tile + *cur_depot) == tile) { + assert(Airport->layout[i].heading == HANGAR); + v->u.air.pos = Airport->layout[i].position; + break; + } + i++; + } + // to ensure v->u.air.pos has been given a value + assert(v->u.air.pos != MAX_ELEMENTS); + } + + v->u.air.state = HANGAR; + v->u.air.previous_pos = v->u.air.pos; + v->u.air.targetairport = _map2[tile]; + v->next = u; + + v->service_interval = _patches.servint_aircraft; + + v->date_of_last_service = _date; + v->build_year = _cur_year; + + v->cur_image = u->cur_image = 0xEA0; + + VehiclePositionChanged(v); + VehiclePositionChanged(u); + + // Aircraft with 3 vehicles? + if (v->subtype == 0) { + w = vl[2]; + + u->next = w; + + w->type = VEH_Aircraft; + w->direction = 0; + w->owner = _current_player; + w->x_pos = v->x_pos; + w->y_pos = v->y_pos; + w->z_pos = v->z_pos + 5; + w->x_offs = w->y_offs = -1; + w->sprite_width = w->sprite_height = 2; + w->z_height = 1; + w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE; + w->subtype = 6; + w->cur_image = 0xF3D; + VehiclePositionChanged(w); + } + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + } + + return value; +} + +bool IsAircraftHangarTile(TileIndex tile) +{ + // 0x56 - hangar facing other way international airport (86) + // 0x20 - hangar large airport (32) + // 0x41 - hangar small airport (65) + return IS_TILETYPE(tile, MP_STATION) && + (_map5[tile] == 32 || _map5[tile] == 65 || _map5[tile] == 86); +} + +static bool CheckStoppedInHangar(Vehicle *v) +{ + if (!(v->vehstatus&VS_STOPPED) || + !IsAircraftHangarTile(v->tile)) { + _error_message = STR_A01B_AIRCRAFT_MUST_BE_STOPPED; + return false; + } + + return true; +} + + +void DoDeleteAircraft(Vehicle *v) +{ + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + DeleteVehicleChain(v); +} + +// p1 = vehicle +int32 CmdSellAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + // Invalidate depot + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + + DoDeleteAircraft(v); + + } + + return -(int32)v->value; +} + +// p1 = vehicle +int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + // cannot stop airplane when in flight, or when taking off / landing + if (v->u.air.state >= STARTTAKEOFF) { + return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT); + } + + if (flags & DC_EXEC) { + v->vehstatus ^= VS_STOPPED; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + } + + return 0; +} + +// p1 = vehicle +int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + Station *st; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (flags & DC_EXEC) { + if (v->next_order&OF_UNLOAD) + { v->cur_order_index++; } + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } else { + st = DEREF_STATION(v->u.air.targetairport); + // If an airport doesn't have terminals (so no landing space for airports), + // it surely doesn't have any hangars + if (st->xy == 0 || st->airport_tile == 0 || GetAirport(st->airport_type)->nofterminals == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; + v->next_order_param = v->u.air.targetairport; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } + + return 0; +} + +// p1 = vehicle +// p2 = new service int +int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->service_interval = (uint16)p2; + InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7); + } + + return 0; +} + +// p1 = vehicle +// p2 = new cargo type +int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v,*u; + int pass, mail; + int32 cost; + + SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN); + + v = &_vehicles[p1]; + if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v)) + return CMD_ERROR; + + pass = _aircraft_num_pass[v->engine_type - AIRCRAFT_ENGINES_INDEX]; + if (p2 != 0) { + pass >>= 1; + if (p2 != 5) + pass >>= 1; + } + _aircraft_refit_capacity = pass; + + cost = 0; + if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) { + cost = _price.aircraft_base >> 7; + } + + if (flags & DC_EXEC) { + v->cargo_cap = pass; + + u = v->next; + mail = _aircraft_num_mail[v->engine_type - AIRCRAFT_ENGINES_INDEX]; + if (p2 != 0) { + mail = 0; + } + u->cargo_cap = mail; + v->cargo_count = u->cargo_count = 0; + v->cargo_type = (byte)p2; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + + return cost; +} + +void HandleClickOnAircraft(Vehicle *v) +{ + ShowAircraftViewWindow(v); +} + +static void CheckIfAircraftNeedsService(Vehicle *v) +{ + Station *st; + + if (v->date_of_last_service + v->service_interval > _date) + return; + + if (v->vehstatus & VS_STOPPED) + return; + + if ((v->next_order & (OT_MASK | OF_FULL_LOAD)) == (OT_GOTO_DEPOT | OF_FULL_LOAD)) + return; + + if (_patches.gotodepot && IS_HUMAN_PLAYER(v->owner) && ScheduleHasDepotOrders(v->schedule_ptr)) + return; + + st = DEREF_STATION(v->next_order_param); + // only goto depot if the target airport has terminals (eg. it is airport) + if (st->xy != 0 && st->airport_tile != 0 && GetAirport(st->airport_type)->nofterminals != 0) { +// printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); +// v->u.air.targetairport = st->index; + v->next_order = OF_NON_STOP | OT_GOTO_DEPOT; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } else if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } +} + +void OnNewDay_Aircraft(Vehicle *v) +{ + int32 cost; + + if (v->subtype > 2) + return; + + if ((++v->day_counter & 7) == 0) + DecreaseVehicleValue(v); + + CheckVehicleBreakdown(v); + AgeVehicle(v); + CheckIfAircraftNeedsService(v); + + if (v->vehstatus & VS_STOPPED) + return; + + cost = _aircraft_running_cost[v->engine_type - AIRCRAFT_ENGINES_INDEX] * _price.aircraft_running / 364; + + v->profit_this_year -= cost >> 8; + + SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN); + SubtractMoneyFromPlayerFract(v->owner, cost); + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); +} + +void AircraftYearlyLoop() +{ + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2) { + v->profit_last_year = v->profit_this_year; + v->profit_this_year = 0; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } +} + +static void AgeAircraftCargo(Vehicle *v) +{ + if (_age_cargo_skip_counter != 0) + return; + + do { + if (v->cargo_days != 0xFF) + v->cargo_days++; + } while ( (v=v->next) != NULL ); +} + +static void HelicopterTickHandler(Vehicle *v) +{ + Vehicle *u; + int tick,spd; + uint16 img; + + u = v->next->next; + + if (u->vehstatus & VS_HIDDEN) + return; + + // if true, helicopter rotors do not rotate. This should only be the case if a helicopter is + // loading/unloading at a terminal or stopped + if ((v->next_order&OT_MASK) == OT_LOADING || (v->vehstatus&VS_STOPPED)) { + if (u->cur_speed != 0) { + u->cur_speed++; + if (u->cur_speed >= 0x80 && u->cur_image == 0xF40) { + u->cur_speed = 0; + } + } + } else { + if (u->cur_speed == 0) + u->cur_speed = 0x70; + + if (u->cur_speed >= 0x50) + u->cur_speed--; + } + + tick = ++u->tick_counter; + spd = u->cur_speed >> 4; + + if (spd == 0) { + img = 0xF3D; + if (u->cur_image == img) + return; + } else if (tick >= spd) { + u->tick_counter = 0; + img = u->cur_image + 1; + if (img > 0xF40) + img = 0xF3E; + } else + return; + + u->cur_image=img; + + BeginVehicleMove(u); + VehiclePositionChanged(u); + EndVehicleMove(u); +} + +static void SetAircraftPosition(Vehicle *v, int x, int y, int z) +{ + Vehicle *u; + int yt; + + v->x_pos = x; + v->y_pos = y; + v->z_pos = z; + + v->cur_image = GetAircraftImage(v, v->direction); + + BeginVehicleMove(v); + VehiclePositionChanged(v); + EndVehicleMove(v); + + u = v->next; + + yt = y - ((v->z_pos-GetSlopeZ(x, y-1)) >> 3); + u->x_pos = x; + u->y_pos = yt; + u->z_pos = GetSlopeZ(x,yt); + u->cur_image = v->cur_image; + + BeginVehicleMove(u); + VehiclePositionChanged(u); + EndVehicleMove(u); + + if ((u=u->next) != NULL) { + u->x_pos = x; + u->y_pos = y; + u->z_pos = z + 5; + + BeginVehicleMove(u); + VehiclePositionChanged(u); + EndVehicleMove(u); + } +} + +static void ServiceAircraft(Vehicle *v) +{ + Vehicle *u; + + v->cur_speed = 0; + v->subspeed = 0; + v->progress = 0; + v->vehstatus |= VS_HIDDEN; + + u = v->next; + u->vehstatus |= VS_HIDDEN; + if ((u=u->next) != NULL) { + u->vehstatus |= VS_HIDDEN; + u->cur_speed = 0; + } + + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + + v->date_of_last_service = _date; + v->breakdowns_since_last_service = 0; + v->reliability = _engines[v->engine_type].reliability; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); +} + +static void PlayAircraftSound(Vehicle *v) +{ + SndPlayVehicleFx(_aircraft_sounds[v->engine_type - AIRCRAFT_ENGINES_INDEX], v); +} + +static bool UpdateAircraftSpeed(Vehicle *v) +{ + uint spd = v->acceleration * 2; + byte t; + + v->subspeed = (t=v->subspeed) + (byte)spd; + spd = min( v->cur_speed + (spd >> 8) + (v->subspeed < t), v->max_speed); + + // adjust speed for broken vehicles + if(v->vehstatus&VS_AIRCRAFT_BROKEN) spd = min(spd, 27); + + //updates statusbar only if speed have changed to save CPU time + if (spd != v->cur_speed) { + v->cur_speed = spd; + if (_patches.vehicle_speed) + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + if (!(v->direction & 1)) { + spd = spd * 3 >> 2; + } + + if (spd == 0) + return false; + + if ((byte)++spd == 0) + return true; + + v->progress = (t = v->progress) - (byte)spd; + + return (t < v->progress); +} + +// get Aircraft running altitude +static byte GetAircraftFlyingAltitude(const Vehicle *v) +{ + byte maxz = 162; + if (v->max_speed != 37) { + maxz = 171; + if (v->max_speed != 74) {maxz = 180;} + } + return maxz; +} + +static bool Aircraft_5(Vehicle *v) +{ + Station *st; + const AirportMovingData *amd; + Vehicle *u; + byte z,dirdiff,newdir,maxz,curz; + GetNewVehiclePosResult gp; + uint dist; + int x,y; + + st = DEREF_STATION(v->u.air.targetairport); + + // prevent going to 0,0 if airport is deleted. + { + uint tile = st->airport_tile; + if (tile == 0) tile = st->xy; + // xy of destination + x = GET_TILE_X(tile)*16; + y = GET_TILE_Y(tile)*16; + } + + // get airport moving data + assert(v->u.air.pos < GetAirport(st->airport_type)->nofelements); + amd = &_airport_moving_datas[st->airport_type][v->u.air.pos]; + + // Helicopter raise + if (amd->flag & AMED_HELI_RAISE) { + u = v->next->next; + + // Make sure the rotors don't rotate too fast + if (u->cur_speed > 32) { + v->cur_speed = 0; + if (--u->cur_speed == 32) { + SndPlayVehicleFx(0x16, v); + } + } else { + u->cur_speed = 32; + if (UpdateAircraftSpeed(v)) { + v->tile = 0; + + // Reached altitude? + if (v->z_pos >= 184) { + v->cur_speed = 0; + return true; + } + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1); + } + } + return false; + } + + // Helicopter landing. + if (amd->flag & AMED_HELI_LOWER) { + if (UpdateAircraftSpeed(v)) { + if (st->airport_tile == 0) { + // FIXME - Aircraft_5 -> if station no longer exists, do not land + // helicopter will circle until sign disappears, then go to next order + // * what to do when it is the only order left, right now it just stays in 1 place + v->u.air.state = FLYING; + AircraftNextAirportPos_and_Order(v); + return false; + } + + // Vehicle is now at the airport. + v->tile = st->airport_tile; + + // Find altitude of landing position. + z = GetSlopeZ(x, y) + 1; + if (st->airport_type == AT_OILRIG) z += 54; + if (st->airport_type == AT_HELIPORT) z += 60; + + if (z == v->z_pos) { + u = v->next->next; + + // Increase speed of rotors. When speed is 80, we've landed. + if (u->cur_speed >= 80) + return true; + u->cur_speed+=4; + } else if (v->z_pos > z) { + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos-1); + } else { + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1); + } + } + return false; + } + + // Get distance from destination pos to current pos. + dist = myabs(x + amd->x - v->x_pos) + myabs(y + amd->y - v->y_pos); + + // Need exact position? + if (!(amd->flag & AMED_EXACTPOS) && dist <= (uint)((amd->flag&AMED_SLOWTURN)?8:4)) + return true; + + // At final pos? + if (dist == 0) { + + // Clamp speed to 12. + if (v->cur_speed > 12) + v->cur_speed = 12; + + // Change direction smoothly to final direction. + dirdiff = amd->direction - v->direction; + // if distance is 0, and plane points in right direction, no point in calling + // UpdateAircraftSpeed(). So do it only afterwards + if (dirdiff == 0) { + v->cur_speed = 0; + return true; + } + + if (!UpdateAircraftSpeed(v)) + return false; + + v->direction = (v->direction+((dirdiff&7)<5?1:-1)) & 7; + v->cur_speed >>= 1; + + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); + return false; + } + + // Clamp speed? + if (!(amd->flag & AMED_NOSPDCLAMP) && v->cur_speed > 12) + v->cur_speed = 12; + + if (!UpdateAircraftSpeed(v)) + return false; + + // Decrease animation counter. + if (v->load_unload_time_rem != 0) + v->load_unload_time_rem--; + + // Turn. Do it slowly if in the air. + newdir = GetDirectionTowards(v, x + amd->x, y + amd->y); + if (newdir != v->direction) { + if (amd->flag & AMED_SLOWTURN) { + if (v->load_unload_time_rem == 0) { + v->load_unload_time_rem = 8; + v->direction = newdir; + } + } else { + v->cur_speed >>= 1; + v->direction = newdir; + } + } + + // Move vehicle. + GetNewVehiclePos(v, &gp); + v->tile = gp.new_tile; + + // If vehicle is in the air, use tile coordinate 0. + if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) { + v->tile = 0; + } + + // Adjust Z for land or takeoff? + z = v->z_pos; + + if (amd->flag & AMED_TAKEOFF) { + z+=2; + // Determine running altitude + maxz = GetAircraftFlyingAltitude(v); + if (z > maxz) + z = maxz; + } + + if (amd->flag & AMED_LAND) { + if (st->airport_tile == 0) { + //FIXME -- FIXED - Aircraft_5 -> if station no longer exists, do not land + // * what to do when it is the only order left, right now it just stays in 1 place? + v->u.air.state = FLYING; + AircraftNextAirportPos_and_Order(v); + // get aircraft back on running altitude + SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); + return false; + } + + curz = GetSlopeZ(x, y) + 1; + + if (curz > z) { + z++; + } else { + int t = max(1, dist-4); + + z -= ((z - curz) + t - 1) / t; + if (z < curz) z = curz; + } + } + + // We've landed. Decrase speed when we're reaching end of runway. + if (amd->flag & AMED_BRAKE) { + curz = GetSlopeZ(x, y) + 1; + + if (z > curz) z--; + else if (z < curz) z++; + + if (dist < 64 && v->cur_speed > 12) + v->cur_speed -= 4; + } + + SetAircraftPosition(v, gp.x, gp.y, z); + return false; +} + +static const int8 _crashed_aircraft_moddir[4] = { + -1,0,0,1 +}; + +static void HandleCrashedAircraft(Vehicle *v) +{ + uint32 r; + Station *st; + + v->u.air.crashed_counter++; + + if (v->u.air.crashed_counter < 650) { + if (CHANCE16R(1,32,r)) { + v->direction = (v->direction+_crashed_aircraft_moddir[(r >> 16)&3]) & 7; + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); + r = Random(); + CreateEffectVehicleRel(v, + 4 + (r&0xF), + 4 + ((r>>4)&0xF), + ((r>>8)&0xF), + EV_DEMOLISH); + } + } else if (v->u.air.crashed_counter >= 10000) { + st = DEREF_STATION(v->u.air.targetairport); + // remove rubble of crashed airplane + + // clear runway-in on all airports, set by crashing plane + // small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc. + // but they all share the same number + CLRBITS(st->airport_flags, RUNWAY_IN_block); + + BeginVehicleMove(v); + EndVehicleMove(v); + + DoDeleteAircraft(v); + } +} + +static void HandleBrokenAircraft(Vehicle *v) +{ + if (v->breakdown_ctr != 1) { + v->breakdown_ctr = 1; + v->vehstatus |= VS_AIRCRAFT_BROKEN; + + if (v->breakdowns_since_last_service != 255) + v->breakdowns_since_last_service++; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } +} + +static const int8 _aircraft_smoke_xy[16] = { + 5,6,5,0,-5,-6,-5,0, /* x coordinates */ + 5,0,-5,-6,-5,0,5,6, /* y coordinate */ +}; + +static void HandleAircraftSmoke(Vehicle *v) +{ + if (!(v->vehstatus&VS_AIRCRAFT_BROKEN)) + return; + + if (v->cur_speed < 10) { + v->vehstatus &= ~VS_AIRCRAFT_BROKEN; + v->breakdown_ctr = 0; + return; + } + + if ((v->tick_counter & 0x1F) == 0) { + CreateEffectVehicleRel(v, + _aircraft_smoke_xy[v->direction], + _aircraft_smoke_xy[v->direction + 8], + 2, + EV_SMOKE_3 + ); + } +} + +static void ProcessAircraftOrder(Vehicle *v) +{ + uint order; + + // OT_GOTO_DEPOT, OT_LOADING + if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LOADING) { + if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + return; + } + + if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + v->date_of_last_service+v->service_interval > _date) { + v->cur_order_index++; + } + + if (v->cur_order_index >= v->num_orders) + v->cur_order_index = 0; + + order = v->schedule_ptr[v->cur_order_index]; + + if (order == 0) { + v->next_order = OT_NOTHING; + return; + } + + if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + return; + + v->next_order = (byte)order; + v->next_order_param = (byte)(order >> 8); + + // orders are changed in flight, ensure going to the right station + if ((order & OT_MASK) == OT_GOTO_STATION && v->u.air.state == FLYING) { + AircraftNextAirportPos_and_Order(v); + v->u.air.targetairport = order >> 8; + } + + InvalidateVehicleOrderWidget(v); +} + +static void HandleAircraftLoading(Vehicle *v, int mode) +{ + if (v->next_order == OT_NOTHING) + return; + + if (v->next_order != OT_DUMMY) { + if ((v->next_order&OT_MASK) != OT_LOADING) + return; + + if (mode != 0) + return; + + if (--v->load_unload_time_rem) + return; + + if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); + LoadUnloadVehicle(v); + return; + } + + { + byte b = v->next_order; + v->next_order = OT_NOTHING; + if (!(b & OF_NON_STOP)) + return; + } + } + v->cur_order_index++; + InvalidateVehicleOrderWidget(v); +} + +static void MaybeCrashAirplane(Vehicle *v) +{ + Station *st; + uint16 prob; + int i; + uint16 amt; + + st = DEREF_STATION(v->u.air.targetairport); + + //FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports + prob = 0x10000 / 1500; + if (st->airport_type == AT_SMALL && (_aircraft_subtype[v->engine_type - AIRCRAFT_ENGINES_INDEX]&2)) { + prob = 0x10000 / 20; + } + + if ((uint16)Random() > prob) + return; + + // Crash the airplane. Remove all goods stored at the station. + for(i=0; i!=NUM_CARGO; i++) { + st->goods[i].rating = 1; + st->goods[i].waiting_acceptance &= ~0xFFF; + } + + v->vehstatus |= VS_CRASHED; + v->u.air.crashed_counter = 0; + + CreateEffectVehicleRel(v, 4, 4, 8, EV_CRASHED_SMOKE); + + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + + amt = 2; + if (v->cargo_type == CT_PASSENGERS) amt += v->cargo_count; + SET_DPARAM16(0, amt); + + v->cargo_count = 0; + v->next->cargo_count = 0, + + SET_DPARAM16(1, st->index); + AddNewsItem(STR_A034_PLANE_CRASH_DIE_IN_FIREBALL, + NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), + v->index, + 0); + + ModifyStationRatingAround(TILE_FROM_XY(v->x_pos, v->y_pos), v->owner, -160, 30); + SndPlayVehicleFx(16, v); +} + +// we've landed and just arrived at a terminal +static void AircraftEntersTerminal(Vehicle *v) +{ + Station *st; + byte old_order; + + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) + return; + + st = DEREF_STATION(v->u.air.targetairport); + v->last_station_visited = v->u.air.targetairport; + + /* Check if station was ever visited before */ + if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) { + uint32 flags; + + st->had_vehicle_of_type |= HVOT_AIRCRAFT; + SET_DPARAM16(0, st->index); + // show newsitem of celebrating citizens + flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); + AddNewsItem( + STR_A033_CITIZENS_CELEBRATE_FIRST, + flags, + v->index, + 0); + } + + old_order = v->next_order; + v->next_order = OT_LOADING; + + if ((old_order & OT_MASK) == OT_GOTO_STATION && + v->next_order_param == v->last_station_visited) { + v->next_order = OT_LOADING | (old_order & (OF_UNLOAD|OF_FULL_LOAD)) | OF_NON_STOP; + } + + SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); + LoadUnloadVehicle(v); + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); +} + +static void AircraftEnterHangar(Vehicle *v) +{ + byte old_order; + + ServiceAircraft(v); + + MaybeRenewVehicle(v, EstimateAircraftCost(v->engine_type)); + + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + + old_order = v->next_order; + v->next_order = OT_NOTHING; + + if (old_order & OF_UNLOAD) { v->cur_order_index++; } + + else if (old_order & OF_FULL_LOAD) { // force depot visit + v->vehstatus |= VS_STOPPED; + + if (v->owner == _local_player) { + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_A014_AIRCRAFT_IS_WAITING_IN, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + } + } +} + +static void AircraftLand(Vehicle *v) +{ + v->sprite_width = v->sprite_height = 2; +} + +static void AircraftLandAirplane(Vehicle *v) +{ + AircraftLand(v); + SndPlayVehicleFx(0x15, v); + MaybeCrashAirplane(v); +} + +// set the right pos when heading to other airports after takeoff +static void AircraftNextAirportPos_and_Order(Vehicle *v) +{ + Station *st; + const AirportFTAClass *Airport; + + if ((v->next_order&OT_MASK) == OT_GOTO_STATION || + (v->next_order&OT_MASK) == OT_GOTO_DEPOT) + v->u.air.targetairport = v->next_order_param; + + st = DEREF_STATION(v->u.air.targetairport); + Airport = GetAirport(st->airport_type); + v->u.air.pos = v->u.air.previous_pos = Airport->entry_point; +} + +static void AircraftLeaveHangar(Vehicle *v) +{ + v->cur_speed = 0; + v->subspeed = 0; + v->progress = 0; + v->direction = 3; + v->vehstatus &= ~VS_HIDDEN; + { + Vehicle *u = v->next; + u->vehstatus &= ~VS_HIDDEN; + + // Rotor blades + if ((u=u->next) != NULL) { + u->vehstatus &= ~VS_HIDDEN; + u->cur_speed = 80; + } + } + + SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); +} + + +//////////////////////////////////////////////////////////////////////////////// +/////////////////// AIRCRAFT MOVEMENT SCHEME //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +static void AircraftEventHandler_EnterTerminal(Vehicle *v, const AirportFTAClass *Airport) +{ + AircraftEntersTerminal(v); + v->u.air.state = Airport->layout[v->u.air.pos].heading; +} + +static void AircraftEventHandler_EnterHangar(Vehicle *v, const AirportFTAClass *Airport) +{ + AircraftEnterHangar(v); + v->u.air.state = Airport->layout[v->u.air.pos].heading; +} + +// In an Airport Hangar +static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *Airport) +{ + // if we just arrived, execute EnterHangar first + if (v->u.air.previous_pos != v->u.air.pos) { + AircraftEventHandler_EnterHangar(v, Airport); + return; + } + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT && (v->vehstatus&VS_STOPPED)) { // if we were sent to the depot, stay there + v->next_order = OT_NOTHING; + return; + } + + if ((v->next_order&OT_MASK) != OT_GOTO_STATION && (v->next_order&OT_MASK) != OT_GOTO_DEPOT) + return; + + // if the block of the next position is busy, stay put + if (AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) {return;} + + // We are already at the target airport, we need to find a terminal + if (v->next_order_param == v->u.air.targetairport) { + // FindFreeTerminal: + // 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal + if (v->subtype != 0) {if(!AirportFindFreeTerminal(v, Airport)) {return;}} // airplane + else {if(!AirportFindFreeHelipad(v, Airport)) {return;}} // helicopter + } + else { // Else prepare for launch. + // airplane goto state takeoff, helicopter to helitakeoff + v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + } + AircraftLeaveHangar(v); + AirportMove(v, Airport); +} + +// At one of the Airport's Terminals +static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *Airport) +{ + // if we just arrived, execute EnterTerminal first + if (v->u.air.previous_pos != v->u.air.pos) { + AircraftEventHandler_EnterTerminal(v, Airport); + // on an airport with helipads, a helicopter will always land there + // and get serviced at the same time - patch setting + if (_patches.serviceathelipad) { + if (v->subtype == 0 && Airport->nofhelipads > 0) { + // an exerpt of ServiceAircraft, without the invisibility stuff + v->date_of_last_service = _date; + v->breakdowns_since_last_service = 0; + v->reliability = _engines[v->engine_type].reliability; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } + return; + } + + // removed &0x1F + if (v->next_order == OT_NOTHING) {return;} + + // if the block of the next position is busy, stay put + if (AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) { + return; + } + + // airport-road is free. We either have to go to another airport, or to the hangar + // ---> start moving + + switch (v->next_order&OT_MASK) { + case OT_GOTO_STATION: // ready to fly to another airport + // airplane goto state takeoff, helicopter to helitakeoff + v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + break; + case OT_GOTO_DEPOT: // visit hangar for serivicing, sale, etc. + if (v->next_order_param == v->u.air.targetairport) + v->u.air.state = HANGAR; + else + v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + break; + default: // orders have been deleted (no orders), goto depot and don't bother us + v->next_order = OT_NOTHING; + v->u.air.state = HANGAR; + } + AirportMove(v, Airport); +} + +static void AircraftEventHandler_General(Vehicle *v, const AirportFTAClass *Airport) +{ + printf("OK, you shouldn't be here, check your Airport Scheme!\n"); + assert(1 == v->u.air.state); // when here state is 0, so this always fails +} + +static void AircraftEventHandler_TakeOff(Vehicle *v, const AirportFTAClass *Airport) { + PlayAircraftSound(v); // play takeoffsound for airplanes + v->u.air.state = STARTTAKEOFF; +} + +static void AircraftEventHandler_StartTakeOff(Vehicle *v, const AirportFTAClass *Airport) +{ + v->sprite_width = v->sprite_height = 24; // ??? no idea what this is + v->u.air.state = ENDTAKEOFF; +} + +static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *Airport) +{ + v->u.air.state = FLYING; + // get the next position to go to, differs per airport + AircraftNextAirportPos_and_Order(v); +} + +static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *Airport) +{ + v->sprite_width = v->sprite_height = 24; // ??? no idea what this is + v->u.air.state = FLYING; + // get the next position to go to, differs per airport + AircraftNextAirportPos_and_Order(v); +} + +static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *Airport) +{ + Station *st; + byte landingtype; + AirportFTA *current; + uint16 tcur_speed, tsubspeed; + + st = DEREF_STATION(v->u.air.targetairport); + // flying device is accepted at this station + // small airport --> no helicopters (AIRCRAFT_ONLY) + // all other airports --> all types of flying devices (ALL) + // heliport/oilrig, etc --> no airplanes (HELICOPTERS_ONLY) + // runway busy or not allowed to use this airstation, circle + if (! (v->subtype == Airport->acc_planes || + st->airport_tile == 0 || (st->owner != OWNER_NONE && st->owner != v->owner) )) { + + // {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41}, + // if it is an airplane, look for LANDING, for helicopter HELILANDING + // it is possible to choose from multiple landing runways, so loop until a free one is found + landingtype = (v->subtype != 0) ? LANDING : HELILANDING; + current = Airport->layout[v->u.air.pos].next_in_chain; + while (current != NULL) { + if (current->heading == landingtype) { + // save speed before, since if AirportHasBlock is false, it resets them to 0 + // we don't want that for plane in air + // hack for speed thingie + tcur_speed = v->cur_speed; + tsubspeed = v->subspeed; + if (!AirportHasBlock(v, current, Airport)) { + v->u.air.state = landingtype; // LANDING / HELILANDING + // it's a bit dirty, but I need to set position to next position, otherwise + // if there are multiple runways, plane won't know which one it took (because + // they all have heading LANDING). And also occupy that block! + v->u.air.pos = current->next_position; + SETBITS(st->airport_flags, Airport->layout[v->u.air.pos].block); + return; + } + v->cur_speed = tcur_speed; + v->subspeed = tsubspeed; + } + current = current->next_in_chain; + } + } + v->u.air.state = FLYING; + v->u.air.pos = Airport->layout[v->u.air.pos].next_position; +} + +static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *Airport) +{ + AircraftLandAirplane(v); // maybe crash airplane + v->u.air.state = ENDLANDING; +} + +static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *Airport) +{ + AircraftLand(v); // helicopters don't crash + v->u.air.state = HELIENDLANDING; +} + +static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *Airport) +{ + // next block busy, don't do a thing, just wait + if(AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) {return;} + + // if going to terminal (OT_GOTO_STATION) choose one + // 1. in case all terminals are busy AirportFindFreeTerminal() returns false or + // 2. not going for terminal (but depot, no order), + // --> get out of the way to the hangar. + if ((v->next_order&OT_MASK) == OT_GOTO_STATION) { + if (AirportFindFreeTerminal(v, Airport)) {return;} + } + v->u.air.state = HANGAR; + +} + +static void AircraftEventHandler_HeliEndLanding(Vehicle *v, const AirportFTAClass *Airport) +{ + // next block busy, don't do a thing, just wait + if(AirportHasBlock(v, &Airport->layout[v->u.air.pos], Airport)) {return;} + + // if going to helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal + // 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or + // 2. not going for terminal (but depot, no order), + // --> get out of the way to the hangar IF there are terminals on the airport. + // --> else TAKEOFF + // the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes + // must go to a hangar. + if ((v->next_order&OT_MASK) == OT_GOTO_STATION) { + if (AirportFindFreeHelipad(v, Airport)) {return;} + } + v->u.air.state = (Airport->nofterminals != 0) ? HANGAR : HELITAKEOFF; +} + +typedef void AircraftStateHandler(Vehicle *v, const AirportFTAClass *Airport); +static AircraftStateHandler * const _aircraft_state_handlers[] = { + AircraftEventHandler_General, // TO_ALL = 0 + AircraftEventHandler_InHangar, // HANGAR = 1 + AircraftEventHandler_AtTerminal, // TERM1 = 2 + AircraftEventHandler_AtTerminal, // TERM2 = 3 + AircraftEventHandler_AtTerminal, // TERM3 = 4 + AircraftEventHandler_AtTerminal, // TERM4 = 5 + AircraftEventHandler_AtTerminal, // TERM5 = 6 + AircraftEventHandler_AtTerminal, // TERM6 = 7 + AircraftEventHandler_AtTerminal, // HELIPAD1 = 8 + AircraftEventHandler_AtTerminal, // HELIPAD2 = 9 + AircraftEventHandler_TakeOff, // TAKEOFF = 10 + AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11 + AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12 + AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13 + AircraftEventHandler_Flying, // FLYING = 14 + AircraftEventHandler_Landing, // LANDING = 15 + AircraftEventHandler_EndLanding, // ENDLANDING = 16 + AircraftEventHandler_HeliLanding, // HELILANDING = 17 + AircraftEventHandler_HeliEndLanding,// HELIENDLANDING = 18 +}; + +static void AirportClearBlock(Vehicle *v, const AirportFTAClass *Airport) +{ + Station *st; + // we have left the previous block, and entered the new one. Free the previous block + if (Airport->layout[v->u.air.previous_pos].block != Airport->layout[v->u.air.pos].block) { + st = DEREF_STATION(v->u.air.targetairport); + CLRBITS(st->airport_flags, Airport->layout[v->u.air.previous_pos].block); + } +} + +static void AirportGoToNextPosition(Vehicle *v, const AirportFTAClass *Airport) +{ + // if aircraft is not in position, wait until it is + if (!Aircraft_5(v)) {return;} + + AirportClearBlock(v, Airport); + AirportMove(v, Airport); // move aircraft to next position +} + +// gets pos from vehicle and next orders +static bool AirportMove(Vehicle *v, const AirportFTAClass *Airport) +{ + AirportFTA *current; + byte prev_pos; + bool retval = false; + + // error handling + if (v->u.air.pos >= Airport->nofelements) { + printf("position %d is not valid for current airport. Max position is %d\n", v->u.air.pos, Airport->nofelements-1); + assert(v->u.air.pos < Airport->nofelements); + } + + current = &Airport->layout[v->u.air.pos]; + // we have arrived in an important state (eg terminal, hangar, etc.) + if (current->heading == v->u.air.state) { + prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand + _aircraft_state_handlers[v->u.air.state](v, Airport); + if (v->u.air.state != FLYING) {v->u.air.previous_pos = prev_pos;} + return true; + } + + v->u.air.previous_pos = v->u.air.pos; // save previous location + + // there is only one choice to move to + if (current->next_in_chain == NULL) { + if (AirportSetBlocks(v, current, Airport)) { + v->u.air.pos = current->next_position; + } // move to next position + return retval; + } + + // there are more choices to choose from, choose the one that + // matches our heading + do { + if (v->u.air.state == current->heading || current->heading == TO_ALL) { + if (AirportSetBlocks(v, current, Airport)) { + v->u.air.pos = current->next_position; + } // move to next position + return retval; + } + current = current->next_in_chain; + } while (current != NULL); + + printf("Cannot move further on Airport...! pos:%d state:%d\n", v->u.air.pos, v->u.air.state); + printf("Airport entry point: %d, Vehicle: %d\n", Airport->entry_point, v->index); + assert(0); + return false; +} + +// returns true if the road ahead is busy, eg. you must wait before proceeding +static bool AirportHasBlock(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport) +{ + Station *st; + uint32 airport_flags; + AirportFTA *next, *reference; + reference = &Airport->layout[v->u.air.pos]; + next = &Airport->layout[current_pos->next_position]; + + // same block, then of course we can move + if (Airport->layout[current_pos->position].block != next->block) { + airport_flags = next->block; + st = DEREF_STATION(v->u.air.targetairport); + // check additional possible extra blocks + if (current_pos != reference && current_pos->block != NOTHING_block) { + airport_flags |= current_pos->block; + } + + if (HASBITS(st->airport_flags, airport_flags)) { + v->cur_speed = 0; + v->subspeed = 0; + return true; + } + } + return false; +} + +// returns true on success. Eg, next block was free and we have occupied it +static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport) +{ + Station *st; + uint32 airport_flags; + AirportFTA *current, *reference, *next; + next = &Airport->layout[current_pos->next_position]; + reference = &Airport->layout[v->u.air.pos]; + + // if the next position is in another block, check it and wait until it is free + if (Airport->layout[current_pos->position].block != next->block) { + airport_flags = next->block; + st = DEREF_STATION(v->u.air.targetairport); + //search for all all elements in the list with the same state, and blocks != N + // this means more blocks should be checked/set + current = current_pos; + if (current == reference) { current = current->next_in_chain;} + while (current != NULL) { + if (current->heading == current_pos->heading && current->block != 0) { + airport_flags |= current->block; + break; + } + current = current->next_in_chain; + }; + + // if the block to be checked is in the next position, then exclude that from + // checking, because it has been set by the airplane before + if (current_pos->block == next->block) {airport_flags ^= next->block;} + + if (HASBITS(st->airport_flags, airport_flags)) { + v->cur_speed = 0; + v->subspeed = 0; + return false; + } + + if (next->block != NOTHING_block) { + SETBITS(st->airport_flags, airport_flags); // occupy next block + } + } + return true; +} + +static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal) +{ + Station *st = DEREF_STATION(v->u.air.targetairport); + for (; i < last_terminal; i++) { + if (!HASBIT(st->airport_flags, i)) { + // TERMINAL# HELIPAD# + v->u.air.state = i + TERM1; // start moving to that terminal/helipad + SETBIT(st->airport_flags, i); // occupy terminal/helipad + return true; + } + } + return false; +} + +static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *Airport) +{ + byte nofterminalspergroup, i; + AirportFTA *temp; + Station *st; + + /* example of more terminalgroups + {0,HANGAR,NOTHING_block,1}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER_block,1}, {0,0,N,1}, + Heading 255 denotes a group. We see 2 groups here: + 1. group 0 -- TERM_GROUP1_block (check block) + 2. group 1 -- TERM_GROUP2_ENTER_block (check block) + First in line is checked first, group 0. If the block (TERM_GROUP1_block) is free, it + looks at the corresponding terminals of that group. If no free ones are found, other + possible groups are checked (in this case group 1, since that is after group 0). If that + fails, then attempt fails and plane waits + */ + if (Airport->nofterminalgroups > 1) { + st = DEREF_STATION(v->u.air.targetairport); + nofterminalspergroup = Airport->nofterminals / Airport->nofterminalgroups; + temp = Airport->layout[v->u.air.pos].next_in_chain; + while (temp != NULL) { + if (temp->heading == 255) { + if (!HASBITS(st->airport_flags, temp->block)) { + i = temp->next_position * nofterminalspergroup; // next_position denotes the group to check + // only that group will be checked (eg 6 terms, 2 groups) + // with i = 0 terms 1 - 3 and + // with i = 1 terms 4 - 6 + if (FreeTerminal(v, i, i + nofterminalspergroup)) {return true;} + } + } + else {return false;} // once the heading isn't 255, we've exhausted the possible blocks. So we cannot move + temp = temp->next_in_chain; + } + } + + // if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max) + return FreeTerminal(v, 0, Airport->nofterminals); +} + +static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *Airport) +{ + Station *st; + byte nofhelipadspergroup, i; + AirportFTA *temp; + + // if an airport doesn't have helipads, use terminals + if (Airport->nofhelipads == 0) {return AirportFindFreeTerminal(v, Airport);} + + // if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal() + if (Airport->nofhelipadgroups > 1) { + st = DEREF_STATION(v->u.air.targetairport); + nofhelipadspergroup = Airport->nofhelipads / Airport->nofhelipadgroups; + temp = Airport->layout[v->u.air.pos].next_in_chain; + while (temp != NULL) { + if (temp->heading == 255) { + if (!HASBITS(st->airport_flags, temp->block)) { + i = temp->next_position * nofhelipadspergroup; // next position is the group to check + // heliports start from after TERMINALS, so MAX_TERMINALS needs to be added + if (FreeTerminal(v, i + MAX_TERMINALS, i + MAX_TERMINALS + nofhelipadspergroup)) {return true;} + } + } + else {return false;} // once the heading isn't 255, we've exhausted the possible blocks. So we cannot move + temp = temp->next_in_chain; + } + } + // only 1 helicoptergroup, check all helipads + // The blocks for helipads start after the last terminal (MAX_TERMINALS) + else {return FreeTerminal(v, MAX_TERMINALS, Airport->nofhelipads + MAX_TERMINALS);} + return false; // it shouldn't get here anytime, but just to be sure +} + +static void AircraftEventHandler(Vehicle *v, int loop) +{ + v->tick_counter++; + + if (v->vehstatus & VS_CRASHED) { + HandleCrashedAircraft(v); + return; + } + + /* exit if aircraft is stopped */ + if (v->vehstatus & VS_STOPPED) + return; + + /* aircraft is broken down? */ + if (v->breakdown_ctr != 0) { + if (v->breakdown_ctr <= 2) { + HandleBrokenAircraft(v); + } else { + v->breakdown_ctr--; + } + } + + HandleAircraftSmoke(v); + ProcessAircraftOrder(v); + HandleAircraftLoading(v, loop); + + if ((v->next_order&OT_MASK) >= OT_LOADING) + return; + + // pass the right airport structure to the functions + // DEREF_STATION gets target airport (Station *st), its type is passed to GetAirport + // that returns the correct layout depending on type + AirportGoToNextPosition(v, GetAirport(DEREF_STATION(v->u.air.targetairport)->airport_type)); +} + +void Aircraft_Tick(Vehicle *v) +{ + int i; + + if (v->subtype > 2) + return; + + if (v->subtype == 0) + HelicopterTickHandler(v); + + AgeAircraftCargo(v); + + for(i=0; i!=6; i++) { + AircraftEventHandler(v, i); + if (v->type != VEH_Aircraft) // In case it was deleted + break; + } +} + +// need to be called to load aircraft from old version +void UpdateOldAircraft() +{ + Station *st; + Vehicle *v_oldstyle; + GetNewVehiclePosResult gp; + + // set airport_flags to 0 for all airports just to be sure + FOR_ALL_STATIONS(st) { + st->airport_flags = 0; // reset airport + // type of oilrig has been moved, update it (3-5) + if (st->airport_type == 3) {st->airport_type = AT_OILRIG;} + } + + FOR_ALL_VEHICLES(v_oldstyle) { + // airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor) + // skip those + if (v_oldstyle->type == VEH_Aircraft && v_oldstyle->subtype <= 2) { + // airplane in terminal stopped doesn't hurt anyone, so goto next + if ((v_oldstyle->vehstatus & VS_STOPPED) && (v_oldstyle->u.air.state == 0)) { + v_oldstyle->u.air.state = HANGAR; + continue; + } + + AircraftLeaveHangar(v_oldstyle); // make airplane visible if it was in a depot for example + v_oldstyle->vehstatus &= ~VS_STOPPED; // make airplane moving + v_oldstyle->u.air.state = FLYING; + AircraftNextAirportPos_and_Order(v_oldstyle); // move it to the entry point of the airport + GetNewVehiclePos(v_oldstyle, &gp); // get the position of the plane (to be used for setting) + v_oldstyle->tile = 0; // aircraft in air is tile=0 + + // correct speed of helicopter-rotors + if (v_oldstyle->subtype == 0) {v_oldstyle->next->next->cur_speed = 32;} + + // set new position x,y,z + SetAircraftPosition(v_oldstyle, gp.x, gp.y, GetAircraftFlyingAltitude(v_oldstyle)); + } + } +} + +void UpdateAirplanesOnNewStation(Station *st) +{ + GetNewVehiclePosResult gp; + Vehicle *v; + byte takeofftype; + uint16 cnt; + // only 1 station is updated per function call, so it is enough to get entry_point once + const AirportFTAClass *ap = GetAirport(st->airport_type); + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2) { + if (v->u.air.targetairport == st->index) { // if heading to this airport + /* update position of airplane. If plane is not flying, landing, or taking off + you cannot delete airport, so it doesn't matter + */ + if (v->u.air.state >= FLYING) { // circle around + v->u.air.pos = v->u.air.previous_pos = ap->entry_point; + v->u.air.state = FLYING; + // landing plane needs to be reset to flying height (only if in pause mode upgrade, + // in normal mode, plane is reset in Aircraft_5. It doesn't hurt for FLYING + GetNewVehiclePos(v, &gp); + // set new position x,y,z + SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); + } + else { + assert(v->u.air.state == ENDTAKEOFF || v->u.air.state == HELITAKEOFF); + takeofftype = (v->subtype == 0) ? HELITAKEOFF : ENDTAKEOFF; + // search in airportdata for that heading + // easiest to do, since this doesn't happen a lot + for (cnt = 0; cnt < ap->nofelements; cnt++) { + if (ap->layout[cnt].heading == takeofftype) { + v->u.air.pos = ap->layout[cnt].position; + break; + } + } + } + } + } + } +} diff --git a/aircraft_gui.c b/aircraft_gui.c new file mode 100644 --- /dev/null +++ b/aircraft_gui.c @@ -0,0 +1,1013 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "vehicle.h" +#include "gfx.h" +#include "station.h" +#include "command.h" +#include "engine.h" +#include "viewport.h" +#include "player.h" + +extern const byte _aircraft_cost_table[NUM_AIRCRAFT_ENGINES]; +extern const byte _aircraft_speed[NUM_AIRCRAFT_ENGINES]; +extern const uint16 _aircraft_num_pass[NUM_AIRCRAFT_ENGINES]; +extern const byte _aircraft_num_mail[NUM_AIRCRAFT_ENGINES]; +extern const byte _aircraft_running_cost[NUM_AIRCRAFT_ENGINES]; + + +static void DrawAircraftImage(Vehicle *v, int x, int y, VehicleID selection) +{ + int image = GetAircraftImage(v, 6); + uint32 ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)); + if (v->vehstatus & VS_CRASHED) ormod = 0x3248000; + DrawSprite(image | ormod, x+25, y+10); + if (v->subtype == 0) + DrawSprite(0xF3D, x+25, y+5); + if (v->index == selection) { + DrawFrameRect(x-1, y-1, x+58, y+21, 0xF, 0x10); + } +} + +static void CcBuildAircraft(bool success, uint tile, uint32 p1, uint32 p2) +{ + Vehicle *v; + + if (success) { + v = &_vehicles[_new_aircraft_id]; + if (v->tile == _backup_orders_tile) { + _backup_orders_tile = 0; + RestoreVehicleOrders(v, _backup_orders_data); + } + ShowAircraftViewWindow(v); + } +} + + +static void NewAircraftWndProc(Window *w, WindowEvent *e) +{ + YearMonthDay ymd; + + switch(e->event) { + + case WE_PAINT: { + if (w->window_number == 0) + SETBIT(w->disabled_state, 5); + + { + int count = 0; + int num = NUM_AIRCRAFT_ENGINES; + Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX]; + do { + if (HASBIT(e->player_avail, _local_player)) + count++; + } while (++e,--num); + SetVScrollCount(w, count); + } + + DrawWindowWidgets(w); + + { + int num = NUM_AIRCRAFT_ENGINES; + Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX]; + int x = 2; + int y = 15; + int sel = WP(w,buildtrain_d).sel_index; + int pos = w->vscroll.pos; + int engine_id = AIRCRAFT_ENGINES_INDEX; + int selected_id = -1; + + do { + if (HASBIT(e->player_avail, _local_player)) { + if (sel==0) selected_id = engine_id; + if (IS_INT_INSIDE(--pos, -4, 0)) { + DrawString(x+62, y+7, GetCustomEngineName(engine_id), sel==0 ? 0xC : 0x10); + DrawAircraftEngine(x+29, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player))); + y += 24; + } + sel--; + } + } while (++engine_id, ++e,--num); + + WP(w,buildtrain_d).sel_engine = selected_id; + + if (selected_id != -1) { + Engine *e; + + SET_DPARAM32(0, _aircraft_cost_table[selected_id - AIRCRAFT_ENGINES_INDEX] * (_price.aircraft_base>>3)>>5); + SET_DPARAM16(1, _aircraft_speed[selected_id - AIRCRAFT_ENGINES_INDEX] * 8); + SET_DPARAM16(2, _aircraft_num_pass[selected_id - AIRCRAFT_ENGINES_INDEX]); + SET_DPARAM16(3, _aircraft_num_mail[selected_id - AIRCRAFT_ENGINES_INDEX]); + SET_DPARAM32(4,_aircraft_running_cost[selected_id - AIRCRAFT_ENGINES_INDEX] * _price.aircraft_running >> 8); + + e = &_engines[selected_id]; + SET_DPARAM16(6, e->lifelength); + SET_DPARAM8(7, e->reliability * 100 >> 16); + ConvertDayToYMD(&ymd, e->intro_date); + SET_DPARAM16(5, ymd.year + 1920); + + DrawString(2, 111, STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0); + } + } + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + uint i = (e->click.pt.y - 14) / 24; + if (i < 4) { + WP(w,buildtrain_d).sel_index = i + w->vscroll.pos; + SetWindowDirty(w); + } + } break; + + case 5: { /* build */ + int sel_eng = WP(w,buildtrain_d).sel_engine; + if (sel_eng != -1) + DoCommandP(w->window_number, sel_eng, 0, CcBuildAircraft, CMD_BUILD_AIRCRAFT | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT)); + } break; + + case 6: /* rename */ + WP(w,buildtrain_d).rename_engine = WP(w,buildtrain_d).sel_engine; + ShowQueryString( + GetCustomEngineName(WP(w,buildtrain_d).sel_engine), + STR_A039_RENAME_AIRCRAFT_TYPE, + 31, + 160, + w->window_class, + w->window_number); + break; + } + break; + + case WE_4: + if (w->window_number != 0 && !FindWindowById(WC_VEHICLE_DEPOT, w->window_number)) { + DeleteWindow(w); + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE)); + } break; + } +} + +static const Widget _new_aircraft_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 239, 0, 13, STR_A005_NEW_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 228, 14, 109, 0x401, STR_A025_AIRCRAFT_SELECTION_LIST}, +{ WWT_SCROLLBAR, 14, 229, 239, 14, 109, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 239, 110, 161, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 119, 162, 173, STR_A006_BUILD_AIRCRAFT, STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT}, +{ WWT_PUSHTXTBTN, 14, 120, 239, 162, 173, STR_A037_RENAME, STR_A038_RENAME_AIRCRAFT_TYPE}, +{ WWT_LAST}, +}; + +static const WindowDesc _new_aircraft_desc = { + -1, -1, 240, 174, + WC_BUILD_VEHICLE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _new_aircraft_widgets, + NewAircraftWndProc +}; + +static void ShowBuildAircraftWindow(uint tile) +{ + Window *w; + + DeleteWindowById(WC_BUILD_VEHICLE, tile); + + w = AllocateWindowDesc(&_new_aircraft_desc); + w->window_number = tile; + w->vscroll.cap = 4; + + if (tile != 0) { + w->caption_color = _map_owner[tile]; + } else { + w->caption_color = _local_player; + } +} + +const byte _aircraft_refit_normal[] = { 0,1,4,5,6,7,8,9,10,0xFF }; +const byte _aircraft_refit_arctic[] = { 0,1,4,5,6,7,9,11,10,0xFF }; +const byte _aircraft_refit_desert[] = { 0,4,5,8,6,7,9,10,0xFF }; +const byte _aircraft_refit_candy[] = { 0,1,3,5,7,8,9,6,4,10,11,0xFF }; + +const byte * const _aircraft_refit_types[4] = { + _aircraft_refit_normal, _aircraft_refit_arctic, _aircraft_refit_desert, _aircraft_refit_candy +}; + +static void AircraftRefitWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + const byte *b; + int sel; + int x,y; + byte color; + int cargo; + + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + DrawString(1, 15, STR_A040_SELECT_CARGO_TYPE_TO_CARRY, 0); + + cargo = -1; + x = 6; + y = 25; + sel = WP(w,refit_d).sel; + b = _aircraft_refit_types[_opt.landscape]; + do { + color = 16; + if (sel == 0) { + cargo = *b; + color = 12; + } + sel--; + DrawString(x,y,_cargoc.names_s[*b], color); + y += 10; + } while (*++b != 0xFF); + + WP(w,refit_d).cargo = cargo; + + if (cargo != -1) { + int32 cost = DoCommandByTile(v->tile, v->index, cargo, DC_QUERY_COST, CMD_REFIT_AIRCRAFT); + if (cost != CMD_ERROR) { + SET_DPARAM32(2, cost); + SET_DPARAM16(0, _cargoc.names_long_p[cargo]); + SET_DPARAM16(1, _aircraft_refit_capacity); + DrawString(1, 137, STR_A041_NEW_CAPACITY_COST_OF_REFIT, 0); + } + } + + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + int y = e->click.pt.y - 25; + if (y >= 0) { + WP(w,refit_d).sel = y / 10; + SetWindowDirty(w); + } + } break; + case 4: /* refit button */ + if (WP(w,refit_d).cargo != 0xFF) { + Vehicle *v = &_vehicles[w->window_number]; + if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT))) + DeleteWindow(w); + } + break; + } + break; + } +} + +static const Widget _aircraft_refit_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 239, 0, 13, STR_A03C_REFIT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 239, 14, 135, 0x0, STR_A03E_SELECT_TYPE_OF_CARGO_FOR}, +{ WWT_IMGBTN, 14, 0, 239, 136, 157, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 239, 158, 169, STR_A03D_REFIT_AIRCRAFT, STR_A03F_REFIT_AIRCRAFT_TO_CARRY}, +{ WWT_LAST}, +}; + +static const WindowDesc _aircraft_refit_desc = { + -1,-1, 240, 170, + WC_VEHICLE_REFIT,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _aircraft_refit_widgets, + AircraftRefitWndProc +}; + +static void ShowAircraftRefitWindow(Vehicle *v) +{ + Window *w; + + DeleteWindowById(WC_VEHICLE_REFIT, v->index); + + _alloc_wnd_parent_num = v->index; + w = AllocateWindowDesc(&_aircraft_refit_desc); + w->window_number = v->index; + w->caption_color = v->owner; + WP(w,refit_d).sel = -1; +} + +static void AircraftDetailsWndProc(Window *w, WindowEvent *e) +{ + int mod; + Vehicle *v = &_vehicles[w->window_number], *u; + + switch(e->event) { + case WE_PAINT: + w->disabled_state = v->owner == _local_player ? 0 : (1 << 2); + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* Draw running cost */ + { + int year = v->age / 366; + StringID str; + + SET_DPARAM16(1, year); + + str = STR_0199_YEAR; + if (year != 1) { + str++; + if (v->max_age - 366 < v->age) + str++; + } + SET_DPARAM16(0, str); + SET_DPARAM16(2, v->max_age / 366); + SET_DPARAM32(3, _price.aircraft_running * _aircraft_running_cost[v->engine_type - AIRCRAFT_ENGINES_INDEX] >> 8); + DrawString(2, 15, STR_A00D_AGE_RUNNING_COST_YR, 0); + } + + /* Draw max speed */ + { + SET_DPARAM16(0, v->max_speed * 8); + DrawString(2, 25, STR_A00E_MAX_SPEED, 0); + } + + /* Draw profit */ + { + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(2, 35, STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR, 0); + } + + /* Draw breakdown & reliability */ + { + SET_DPARAM8(0, v->reliability * 100 >> 16); + SET_DPARAM16(1, v->breakdowns_since_last_service); + DrawString(2, 45, STR_A010_RELIABILITY_BREAKDOWNS, 0); + } + + /* Draw service interval text */ + { + SET_DPARAM16(0, v->service_interval); + SET_DPARAM16(1, v->date_of_last_service); + DrawString(13, 103, STR_883C_SERVICING_INTERVAL_DAYS, 0); + } + + DrawAircraftImage(v, 3, 57, INVALID_VEHICLE); + + { + int y = 57; + + do { + if (v->subtype <= 2) { + SET_DPARAM16(0, GetCustomEngineName(v->engine_type)); + SET_DPARAM16(1, 1920 + v->build_year); + SET_DPARAM32(2, v->value); + DrawString(60, y, STR_A011_BUILT_VALUE, 0); + y += 10; + + SET_DPARAM16(0, _cargoc.names_long_p[v->cargo_type]); + SET_DPARAM16(1, v->cargo_cap); + u = v->next; + SET_DPARAM16(2, _cargoc.names_long_p[u->cargo_type]); + SET_DPARAM16(3, u->cargo_cap); + DrawString(60, y, STR_A019_CAPACITY + (u->cargo_cap == 0), 0); + y += 14; + } + + if (v->cargo_count != 0) { + + /* Cargo names (fix pluralness) */ + SET_DPARAM8(0, v->cargo_type); + SET_DPARAM16(1, v->cargo_count); + SET_DPARAM16(2, v->cargo_source); + DrawString(60, y, STR_8813_FROM, 0); + + y += 10; + } + } while ( (v=v->next) != NULL); + } + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: /* rename */ + SET_DPARAM16(0, v->unitnumber); + ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number); + break; + + case 5: /* increase int */ + mod = 10; + goto change_int; + case 6: /* decrease int */ + mod = -10; +change_int: + mod += v->service_interval; + if (!IS_INT_INSIDE(mod, 30, 800+1)) + return; + DoCommandP(v->tile, v->index, mod, NULL, + CMD_CHANGE_AIRCRAFT_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING)); + break; + } + break; + + case WE_4: + if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL) + DeleteWindow(w); + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT)); + } break; + + } +} + + +static const Widget _aircraft_details_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 349, 0, 13, STR_A00C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 350, 389, 0, 13, STR_01AA_NAME, STR_A032_NAME_AIRCRAFT}, +{ WWT_IMGBTN, 14, 0, 389, 14, 55, 0x0}, +{ WWT_IMGBTN, 14, 0, 389, 56, 101, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 102, 107, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 108, 113, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL}, +{ WWT_IMGBTN, 14, 11, 389, 102, 113, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _aircraft_details_desc = { + -1,-1, 390, 114, + WC_VEHICLE_DETAILS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _aircraft_details_widgets, + AircraftDetailsWndProc +}; + + +static void ShowAircraftDetailsWindow(Vehicle *v) +{ + Window *w; + VehicleID veh = v->index; + + DeleteWindowById(WC_VEHICLE_ORDERS, veh); + DeleteWindowById(WC_VEHICLE_DETAILS, veh); + + _alloc_wnd_parent_num = veh; + w = AllocateWindowDesc(&_aircraft_details_desc); + w->window_number = veh; + w->caption_color = v->owner; +// w->vscroll.cap = 6; +// w->traindetails_d.tab = 0; +} + + +static const Widget _aircraft_view_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 249, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 231, 14, 103, 0x0, 0}, +{ WWT_6, 14, 2, 229, 16, 101, 0x0, 0}, +{ WWT_PUSHIMGBTN, 14, 0, 249, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 14, 31, 0x2AB, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 32, 49, 0x2AF, STR_A02A_SEND_AIRCRAFT_TO_HANGAR}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 50, 67, 0x2B4, STR_A03B_REFIT_AIRCRAFT_TO_CARRY}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 68, 85, 0x2B2, STR_A028_SHOW_AIRCRAFT_S_ORDERS}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 86, 103, 0x2B3, STR_A02B_SHOW_AIRCRAFT_DETAILS}, +{ WWT_LAST}, +}; + +static void AircraftViewWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + uint32 disabled = 1<<7; + StringID str; + + { + uint tile = v->tile; + if (IS_TILETYPE(tile, MP_STATION) && + (_map5[tile] == 32 || _map5[tile] == 65) && + v->vehstatus&VS_STOPPED) + disabled = 0; + } + + if (v->owner != _local_player) + disabled |= 1<<7 | 1<<6; + w->disabled_state = disabled; + + /* draw widgets & caption */ + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* draw the flag */ + DrawSprite((v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, 2, 105); + + if (v->vehstatus & VS_CRASHED) { + str = STR_8863_CRASHED; + } else if (v->vehstatus & VS_STOPPED) { + str = STR_8861_STOPPED; + } else { + switch(v->next_order & OT_MASK) { + case OT_GOTO_STATION: { + SET_DPARAM16(0, v->next_order_param); + SET_DPARAM16(1, v->cur_speed * 8); + str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; + } break; + + case OT_GOTO_DEPOT: { + SET_DPARAM16(0, v->next_order_param); + SET_DPARAM16(1, v->cur_speed * 8); + str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed; + } break; + + case OT_LOADING: + str = STR_882F_LOADING_UNLOADING; + break; + + default: + if (v->num_orders == 0) { + str = STR_NO_ORDERS + _patches.vehicle_speed; + SET_DPARAM16(0, v->cur_speed * 8); + } else + str = STR_EMPTY; + break; + } + } + + DrawStringCentered(125, 105, str, 0); + DrawWindowViewport(w); + } break; + + case WE_CLICK: { + Vehicle *v = &_vehicles[w->window_number]; + + switch(e->click.widget) { + case 4: /* start stop */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT)); + break; + case 5: /* center main view */ + ScrollMainWindowTo(v->x_pos, v->y_pos); + break; + case 6: /* goto hangar */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_MSG(STR_A012_CAN_T_SEND_AIRCRAFT_TO)); + break; + case 7: /* refit */ + ShowAircraftRefitWindow(v); + break; + case 8: /* show orders */ + ShowOrdersWindow(v); + break; + case 9: /* show details */ + ShowAircraftDetailsWindow(v); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number); + DeleteWindowById(WC_VEHICLE_REFIT, w->window_number); + DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number); + break; + } +} + + +static const WindowDesc _aircraft_view_desc = { + -1,-1, 250, 116, + WC_VEHICLE_VIEW ,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _aircraft_view_widgets, + AircraftViewWndProc +}; + + +void ShowAircraftViewWindow(Vehicle *v) +{ + Window *w; + + w = AllocateWindowDescFront(&_aircraft_view_desc, v->index); + if (w) { + w->caption_color = v->owner; + AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0); + } +} + +static void DrawAircraftDepotWindow(Window *w) +{ + uint tile; + Vehicle *v; + int num,x,y; + + tile = w->window_number; + + /* setup disabled buttons */ + w->disabled_state = (_map_owner[tile]==_local_player) ? 0 : ((1<<3)|(1<<5)); + + /* determine amount of items for scroller */ + num = 0; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2 && v->vehstatus&VS_HIDDEN && + v->tile == (TileIndex)tile) + num++; + } + SetVScrollCount(w, (num + 3) >> 2); + + SET_DPARAM16(0, _map2[tile]); + DrawWindowWidgets(w); + + x = 2; + y = 15; + num = w->vscroll.pos * 4; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && + v->subtype <= 2 && + v->vehstatus&VS_HIDDEN && + v->tile == (TileIndex)tile && + --num < 0 && num >= -8) { + + DrawAircraftImage(v, x+12, y, WP(w,traindepot_d).sel); + + SET_DPARAM16(0, v->unitnumber); + DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); + + DrawSprite( (v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, x, y+12); + + if ((x+=74) == 2+74*4) { + x -= 74*4; + y += 24; + } + } + } +} + +static int GetVehicleFromAircraftDepotWndPt(Window *w, int x, int y, Vehicle **veh) { + uint xt,yt,xm,ym; + Vehicle *v; + uint tile; + int pos; + + xt = x / 74; + xm = x % 74; + if (xt >= 4) + return 1; + + yt = (y - 14) / 24; + ym = (y - 14) % 24; + if (yt >= 2) + return 1; + + pos = (yt + w->vscroll.pos) * 4 + xt; + + tile = w->window_number; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && + v->subtype <= 2 && + v->vehstatus&VS_HIDDEN && + v->tile == (TileIndex)tile && + --pos < 0) { + *veh = v; + if (xm >= 12) + return 0; + + if (ym <= 12) + return -1; /* show window */ + + return -2; /* start stop */ + } + } + return 1; /* outside */ +} + +static void AircraftDepotClickAircraft(Window *w, int x, int y) +{ + Vehicle *v; + + switch(GetVehicleFromAircraftDepotWndPt(w, x, y, &v)) { + case 1: + return; + + case 0: + if (v != NULL) { + WP(w,traindepot_d).sel = v->index; + SetWindowDirty(w); + SetObjectToPlaceWnd( SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)) + GetAircraftImage(v, 6), 4, w); + } + break; + + case -1: + ShowAircraftViewWindow(v); + break; + + case -2: + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT)); + break; + + default: + NOT_REACHED(); + } +} + +static const Widget _aircraft_depot_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 330, 0, 13, STR_A002_AIRCRAFT_HANGAR, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 295, 14, 61, 0x204, STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT}, +{ WWT_IMGBTN, 14, 296, 319, 14, 61, 0x2A9, STR_A023_DRAG_AIRCRAFT_TO_HERE_TO}, +{ WWT_SCROLLBAR, 14, 320, 330, 14, 61, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 164, 62, 73, STR_A003_NEW_AIRCRAFT, STR_A022_BUILD_NEW_AIRCRAFT}, +{ WWT_PUSHTXTBTN, 14, 165, 330, 62, 73, STR_00E4_LOCATION, STR_A024_CENTER_MAIN_VIEW_ON_HANGAR}, +{ WWT_LAST}, +}; + + +static void AircraftDepotWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawAircraftDepotWindow(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: /* click aircraft */ + AircraftDepotClickAircraft(w, e->click.pt.x, e->click.pt.y); + break; + case 5: /* show build aircraft window */ + ShowBuildAircraftWindow(w->window_number); + break; + case 6: /* scroll to tile */ + ScrollMainWindowToTile(w->window_number); + break; + } + break; + + case WE_DESTROY: + DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + break; + + case WE_DRAGDROP: { + switch(e->click.widget) { + case 2: { + Vehicle *v; + VehicleID sel = WP(w,traindepot_d).sel; + + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + + if (GetVehicleFromAircraftDepotWndPt(w, e->dragdrop.pt.x, e->dragdrop.pt.y, &v) == 0 && + v != NULL && + sel == v->index) { + ShowAircraftViewWindow(v); + } + } break; + + case 3: + if (!HASBIT(w->disabled_state, 3) && + WP(w,traindepot_d).sel != INVALID_VEHICLE) { + Vehicle *v; + + HandleButtonClick(w, 3); + + v = &_vehicles[WP(w,traindepot_d).sel]; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + + _backup_orders_tile = v->tile; + BackupVehicleOrders(v, _backup_orders_data); + + if (!DoCommandP(v->tile, v->index, 0, NULL, CMD_SELL_AIRCRAFT | CMD_MSG(STR_A01C_CAN_T_SELL_AIRCRAFT))) + _backup_orders_tile = 0; + } + break; + default: + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + } + break; + } + break; + } +} + + + +static const WindowDesc _aircraft_depot_desc = { + -1, -1, 331, 74, + WC_VEHICLE_DEPOT,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _aircraft_depot_widgets, + AircraftDepotWndProc +}; + + +void ShowAircraftDepotWindow(uint tile) +{ + Window *w; + + w = AllocateWindowDescFront(&_aircraft_depot_desc, tile); + if (w) { + w->caption_color = _map_owner[tile]; + w->vscroll.cap = 2; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + _backup_orders_tile = 0; + } +} + +static void DrawSmallSchedule(Vehicle *v, int x, int y) { + uint16 *sched; + int sel; + uint ord; + int i = 0; + + sched = v->schedule_ptr; + sel = v->cur_order_index; + + while ((ord=*sched++) != 0) { + if (sel == 0) { + _stringwidth_base = 0xE0; + DoDrawString( "\xAF", x-6, y, 16); + _stringwidth_base = 0; + } + sel--; + + if ((ord & OT_MASK) == OT_GOTO_STATION) { + SET_DPARAM16(0, ord >> 8); + DrawString(x, y, STR_A036, 0); + + y += 6; + if (++i == 4) + break; + } + } +} + +static void PlayerAircraftWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + /* determine amount of items for scroller */ + { + Vehicle *v; + int num = 0; + byte owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner) + num++; + } + + SetVScrollCount(w, num); + } + + /* draw the widgets */ + { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawWindowWidgets(w); + } + + /* draw the aircraft */ + { + Vehicle *v; + int pos = w->vscroll.pos; + byte owner = (byte)w->window_number; + int x = 2; + int y = 15; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner && + --pos < 0 && pos >= -4) { + StringID str; + + DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y+13); + + SET_DPARAM16(0, v->unitnumber); + if (IsAircraftHangarTile(v->tile)) { + str = STR_021F; + } else { + str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; + } + DrawString(x, y+2, str, 0); + + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(x+19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + if (v->string_id != STR_SV_AIRCRAFT_NAME) { + SET_DPARAM16(0, v->string_id); + DrawString(x+19, y, STR_01AB, 0); + } + + DrawSmallSchedule(v, x+136, y); + + y += 36; + } + } + } + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* click on aircraft */ + int sel; + Vehicle *v; + byte owner; + + sel = (e->click.pt.y - 14) / 36; + + if ((uint)sel >= 4) + break; + sel += w->vscroll.pos; + owner = (byte)w->window_number; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner && + --sel < 0) { + ShowAircraftViewWindow(v); + break; + } + } + break; + } + case 4: { /* build new */ + uint tile; + + tile = _last_built_aircraft_depot_tile; + do { + if (_map_owner[tile] == _local_player && + IsAircraftHangarTile(tile)) { + ShowAircraftDepotWindow(tile); + ShowBuildAircraftWindow(tile); + return; + } + + tile = TILE_MASK(tile + 1); + } while(tile != _last_built_aircraft_depot_tile); + ShowBuildAircraftWindow(0); + } break; + } + break; + } +} + +static const Widget _player_aircraft_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 129, 158, 169, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES}, +{ WWT_IMGBTN, 14, 130, 259, 158, 169, 0x0, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _player_aircraft_desc = { + -1, -1, 260, 170, + WC_AIRCRAFT_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _player_aircraft_widgets, + PlayerAircraftWndProc +}; + +static const Widget _other_player_aircraft_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_player_aircraft_desc = { + -1, -1, 260, 158, + WC_AIRCRAFT_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _other_player_aircraft_widgets, + PlayerAircraftWndProc +}; + +void ShowPlayerAircraft(int player) +{ + Window *w; + + if ( player == _local_player) { + w = AllocateWindowDescFront(&_player_aircraft_desc, player); + } else { + w = AllocateWindowDescFront(&_other_player_aircraft_desc, player); + } + + if (w) { + w->caption_color = w->window_number; + w->vscroll.cap = 4; + } +} diff --git a/airport.c b/airport.c new file mode 100644 --- /dev/null +++ b/airport.c @@ -0,0 +1,283 @@ +#include "stdafx.h" +#include "airport.h" + +AirportFTAClass *CountryAirport; +AirportFTAClass *CityAirport; +AirportFTAClass *Heliport, *Oilrig; +AirportFTAClass *MetropolitanAirport; +AirportFTAClass *InternationalAirport; + +static void AirportFTAClass_Constructor(AirportFTAClass *Airport, + const byte nofterminals, const byte nofterminalgroups, + const byte nofhelipads, const byte nofhelipadgroups, + const byte entry_point, const byte acc_planes, + const AirportFTAbuildup *FA, + const TileIndex *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() +{ + // country airport + CountryAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); + AirportFTAClass_Constructor(CountryAirport, 2, 1, 0, 0, 16, ALL, _airport_fta_country, _airport_depots_country); + + // city airport + CityAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); + AirportFTAClass_Constructor(CityAirport, 3, 1, 0, 0, 19, ALL, _airport_fta_city, _airport_depots_city); + + // metropolitan airport + MetropolitanAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); + AirportFTAClass_Constructor(MetropolitanAirport, 3, 1, 0, 0, 20, ALL, _airport_fta_metropolitan, _airport_depots_metropolitan); + + // international airport + InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); + AirportFTAClass_Constructor(InternationalAirport, 6, 2, 2, 1, 37, ALL, _airport_fta_international, _airport_depots_international); + + // heliport, oilrig + Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); + AirportFTAClass_Constructor(Heliport, 0, 0, 1, 1, 7, HELICOPTERS_ONLY, _airport_fta_heliport_oilrig, _airport_depots_heliport_oilrig); + Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine +} + +void UnInitializeAirports() +{ + AirportFTAClass_Destructor(CountryAirport); + AirportFTAClass_Destructor(CityAirport); + AirportFTAClass_Destructor(Heliport); + AirportFTAClass_Destructor(MetropolitanAirport); + AirportFTAClass_Destructor(InternationalAirport); +} + +static void AirportFTAClass_Constructor(AirportFTAClass *Airport, + const byte nofterminals, const byte nofterminalgroups, + const byte nofhelipads, const byte nofhelipadgroups, + const byte entry_point, const byte acc_planes, + const AirportFTAbuildup *FA, + const TileIndex *depots) +{ + // 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 + if (nofterminalgroups > nofterminals) { printf("# of terminalgroups (%2d) must be less or equal to terminals (%2d)", nofterminals, nofterminalgroups);} + if (nofhelipadgroups > nofhelipads) { printf("# of helipadgroups (%2d) must be less or equal to helipads (%2d)", nofhelipads, nofhelipadgroups);} + + assert(nofterminals <= MAX_TERMINALS); + assert(nofhelipads <= MAX_HELIPADS); + assert(nofterminalgroups <= nofterminals); + assert(nofhelipadgroups <= nofhelipads); + + 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->nofterminals = nofterminals; + Airport->nofterminalgroups = nofterminalgroups; + Airport->nofhelipads = nofhelipads; + Airport->nofhelipadgroups = nofhelipadgroups; + Airport->acc_planes = acc_planes; + Airport->entry_point = entry_point; + Airport->airport_depots = (uint16*)depots; + + + // build the state machine + AirportBuildAutomata(Airport, FA); + //#ifdef _DEBUG + // {printf("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s)\n", Airport->nofelements, + // Airport->nofterminals, Airport->nofterminalgroups, Airport->nofhelipads, Airport->nofhelipadgroups);} + //#endif + + + { + byte _retval = AirportTestFTA(Airport); + if (_retval != MAX_ELEMENTS) {printf("ERROR with element: %d\n", _retval-1);} + assert(_retval == MAX_ELEMENTS); + } + // print out full information + // true -- full info including heading, block, etc + // false -- short info, only position and next position + //AirportPrintOut(Airport, false); +} + +static void AirportFTAClass_Destructor(AirportFTAClass *Airport) +{ + int i; + AirportFTA *current, *next; + + for (i = 0; i < Airport->nofelements; i++) { + current = Airport->layout[i].next_in_chain; + while (current != NULL) { + next = current->next_in_chain; + free(current); + current = next; + }; + } + free(Airport->layout); + free(Airport); +} + +static uint16 AirportGetNofElements(const AirportFTAbuildup *FA) +{ + int i; + uint16 nofelements = 0; + int temp = FA[0].position; + for (i = 0; i < MAX_ELEMENTS; i++) { + if (temp != FA[i].position) { + nofelements++; + temp = FA[i].position; + } + if (FA[i].position == MAX_ELEMENTS) {break;} + } + return nofelements; +} + +static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA) +{ + AirportFTA *FAutomata; + AirportFTA *current; + uint16 internalcounter, i; + FAutomata = (AirportFTA *)malloc(sizeof(AirportFTA) * Airport->nofelements); + Airport->layout = FAutomata; + internalcounter = 0; + + for (i = 0; i < Airport->nofelements; i++) { + current = &Airport->layout[i]; + current->position = FA[internalcounter].position; + current->heading = FA[internalcounter].heading; + current->block = FA[internalcounter].block; + current->next_position = FA[internalcounter].next_in_chain; + + // outgoing nodes from the same position, create linked list + while (current->position == FA[internalcounter+1].position) { + AirportFTA *newNode = (AirportFTA *)malloc(sizeof(AirportFTA)); + newNode->position = FA[internalcounter+1].position; + newNode->heading = FA[internalcounter+1].heading; + newNode->block = FA[internalcounter+1].block; + newNode->next_position = FA[internalcounter+1].next_in_chain; + // create link + current->next_in_chain = newNode; + current = current->next_in_chain; + internalcounter++; + } // while + current->next_in_chain = NULL; + internalcounter++; + } +} + +static byte AirportTestFTA(const AirportFTAClass *Airport) +{ + byte position, i, next_element; + AirportFTA *temp; + next_element = 0; + + for (i = 0; i < Airport->nofelements; i++) { + position = Airport->layout[i].position; + if (position != next_element) {return i;} + temp = &Airport->layout[i]; + + do { + if (temp->heading > MAX_HEADINGS && temp->heading != 255) {return i;} + if (temp->heading == 0 && temp->next_in_chain != 0) {return i;} + if (position != temp->position) {return i;} + if (temp->next_position >= Airport->nofelements) {return i;} + temp = temp->next_in_chain; + } while (temp != NULL); + next_element++; + } + return MAX_ELEMENTS; +} + +static const char* const _airport_heading_strings[MAX_HEADINGS+2] = { + "TO_ALL", + "HANGAR", + "TERM1", + "TERM2", + "TERM3", + "TERM4", + "TERM5", + "TERM6", + "HELIPAD1", + "HELIPAD2", + "TAKEOFF", + "STARTTAKEOFF", + "ENDTAKEOFF", + "HELITAKEOFF", + "FLYING", + "LANDING", + "ENDLANDING", + "HELILANDING", + "HELIENDLANDING", + "DUMMY" // extra heading for 255 +}; + +/* +static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report) +{ + AirportFTA *temp; + uint16 i; + byte heading; + + printf("(P = Current Position; NP = Next Position)\n"); + for (i = 0; i < Airport->nofelements; i++) { + temp = &Airport->layout[i]; + if (full_report) { + heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading; + printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position, + _airport_heading_strings[heading], AirportBlockToString(temp->block)); + } + else { printf("P:%2d NP:%2d", temp->position, temp->next_position);} + while (temp->next_in_chain != NULL) { + temp = temp->next_in_chain; + if (full_report) { + heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading; + printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position, + _airport_heading_strings[heading], AirportBlockToString(temp->block)); + } + else { printf("P:%2d NP:%2d", temp->position, temp->next_position);} + } + printf("\n"); + } +} + + +static byte AirportBlockToString(uint32 block) +{ + byte i = 0; + if (block & 0xffff0000) { block >>= 16; i += 16; } + if (block & 0x0000ff00) { block >>= 8; i += 8; } + if (block & 0x000000f0) { block >>= 4; i += 4; } + if (block & 0x0000000c) { block >>= 2; i += 2; } + if (block & 0x00000002) { i += 1; } + return i; +}*/ + +const AirportFTAClass* GetAirport(const byte airport_type) +{ + AirportFTAClass *Airport = NULL; + //FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code + // needs constant change if more airports are added + switch (airport_type) { + case AT_SMALL: Airport = CountryAirport; break; + case AT_LARGE: Airport = CityAirport; break; + case AT_METROPOLITAN: Airport = MetropolitanAirport; break; + case AT_HELIPORT: Airport = Heliport; break; + case AT_OILRIG: Airport = Oilrig; break; + case AT_INTERNATIONAL: Airport = InternationalAirport; break; + default: + #ifdef DEBUG__ + printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n"); + #endif + assert(airport_type <= AT_INTERNATIONAL); + } + return Airport; +} diff --git a/airport.h b/airport.h new file mode 100644 --- /dev/null +++ b/airport.h @@ -0,0 +1,52 @@ +#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 = 5 +}; + +// 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 + byte nofterminals; // number of terminals this airport has + byte nofterminalgroups; // terminals belong to so many groups (MAX is the nofterminals) + byte nofhelipads; // number of helipads this airport has + byte nofhelipadgroups; // helipads belong to so many groups (MAX is the nofhelipads) + 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 + uint16 *airport_depots; // gives the position of the depots on the airports + 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 UnInitializeAirports(); +const AirportFTAClass* GetAirport(const byte airport_type); + +#endif /* AIRPORT_H */ diff --git a/airport_gui.c b/airport_gui.c new file mode 100644 --- /dev/null +++ b/airport_gui.c @@ -0,0 +1,227 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" +#include "vehicle.h" +#include "station.h" +#include "airport.h" + +static byte _selected_airport_type; + +static void ShowBuildAirportPicker(); + + +static void CcBuildAirport(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1D, tile); + ResetObjectToPlace(); + } +} + +static void PlaceAirport(uint tile) +{ + DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE)); +} + +static void PlaceAir_DemolishArea(uint tile) +{ + VpStartPlaceSizing(tile, 4); +} + + +static void BuildAirClick_Airport(Window *w) +{ + if (HandlePlacePushButton(w, 2, 0xAA4, 1, PlaceAirport)) ShowBuildAirportPicker(); +} + +static void BuildAirClick_Demolish(Window *w) +{ + HandlePlacePushButton(w, 3, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea); +} + +static void BuildAirClick_Lower(Window *w) +{ + HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand); +} + +static void BuildAirClick_Raise(Window *w) +{ + HandlePlacePushButton(w, 5, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand); +} + +static void BuildAirClick_Purchase(Window *w) +{ + HandlePlacePushButton(w, 6, 0x12B8, 1, PlaceProc_BuyLand); +} + +typedef void OnButtonClick(Window *w); +static OnButtonClick * const _build_air_button_proc[] = { + BuildAirClick_Airport, + BuildAirClick_Demolish, + BuildAirClick_Lower, + BuildAirClick_Raise, + BuildAirClick_Purchase, +}; + +static void BuildAirToolbWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + break; + + case WE_CLICK: + if (e->click.widget-2 >= 0) + _build_air_button_proc[e->click.widget - 2](w); + 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: + w->click_state = 0; + SetWindowDirty(w); + w = FindWindowById(WC_BUILD_STATION, 0); + if (w != 0) + WP(w,def_d).close = true; + break; + } +} + +static const Widget _air_toolbar_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 129, 0, 13, STR_A000_AIRPORT_CONSTRUCT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT}, +{ WWT_PANEL, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 64, 85, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 86, 107, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 108, 129, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE}, +{ WWT_LAST}, +}; + + +static const WindowDesc _air_toolbar_desc = { + 510, 22, 130, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _air_toolbar_widgets, + BuildAirToolbWndProc +}; + +void ShowBuildAirToolbar() +{ + DeleteWindowById(WC_BUILD_TOOLBAR, 0); + AllocateWindowDescFront(&_air_toolbar_desc, 0); +} + +static void BuildAirportPickerWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int sel; + + if (WP(w,def_d).close) + return; + w->disabled_state = 0; + + sel = _selected_airport_type; + // FIXME -- BuildAirportPickerWndProc - set availability of airports by year, instead of airplane + if (!(_avail_aircraft & 1)) { w->disabled_state |= (1<<3); if (sel == AT_SMALL) sel = AT_LARGE; } + if (!(_avail_aircraft & 2)) { w->disabled_state |= (1<<4); if (sel == AT_LARGE) sel = AT_SMALL; } + if (!(_avail_aircraft & 4)) { w->disabled_state |= (1<<5); } // heliport + // 1980-1-1 is --> 21915 + // 1990-1-1 is --> 25568 + if (_date < 21915) {w->disabled_state |= (1<<6);} // metropilitan airport 1980 + if (_date < 25568) {w->disabled_state |= (1<<7);} // international airport 1990 + _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 (_station_show_coverage) SetTileSelectBigSize(-4, -4, 8, 8); + + 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); + break; + } + + case WE_CLICK: { + switch(e->click.widget) { + case 0: + ResetObjectToPlace(); + break; + case 3: case 4: case 5: case 6: case 7: + _selected_airport_type = e->click.widget - 3; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + case 8: case 9: + _station_show_coverage = e->click.widget - 8; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: { + if (WP(w,def_d).close) { + DeleteWindow(w); + return; + } + + CheckRedrawStationCoverage(w); + } break; + } +} + +static const Widget _build_airport_picker_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 147, 14, 130, 0x0, 0}, +{WWT_NODISTXTBTN, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT}, +{WWT_NODISTXTBTN, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT}, +{WWT_NODISTXTBTN, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT}, +{WWT_NODISTXTBTN, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT}, +{WWT_NODISTXTBTN, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT}, +{ WWT_CLOSEBOX, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, +{ WWT_CLOSEBOX, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, +{ WWT_LAST}, +}; + +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() +{ + AllocateWindowDesc(&_build_airport_desc); +} + +void InitializeAirportGui() +{ + _selected_airport_type = AT_SMALL; + _last_built_aircraft_depot_tile = 0; +} diff --git a/airport_movement.h b/airport_movement.h new file mode 100644 --- /dev/null +++ b/airport_movement.h @@ -0,0 +1,456 @@ +#ifndef AIRPORT_MOVEMENT_H +#define AIRPORT_MOVEMENT_H + +#include "stdafx.h" +#include "macros.h" + +// don't forget to change the airport_depots too for larger mapsizes. TILE_X_BITS 16 +// won't fit in uint16 for example and overflow will occur in the checking code! +// TrueLight -- So make it a TileIndex.. + +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,}, // 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 TileIndex _airport_depots_country[] = {1, TILE_XY(3,0)}; +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 TileIndex _airport_depots_city[] = {1, TILE_XY(5,0)}; +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 TileIndex _airport_depots_metropolitan[] = {1, TILE_XY(5,0)}; +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 TileIndex _airport_depots_international[] = {2, TILE_XY(0,3), TILE_XY(6,1)}; +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 +}; + +static const TileIndex _airport_depots_heliport_oilrig[] = {0}; +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[6] = { + _airport_moving_data_country, // Country Airfield (small) 4x3 + _airport_moving_data_town, // City Airport (large) 6x6 + _airport_moving_data_heliport, // Heliport + _airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways + _airport_moving_data_international, // International Airport (xlarge) - 2 runways + _airport_moving_data_oilrig // Oilrig +}; + +#endif /* AIRPORT_MOVEMENT_H */ diff --git a/bemidi.cpp b/bemidi.cpp new file mode 100644 --- /dev/null +++ b/bemidi.cpp @@ -0,0 +1,55 @@ +#ifdef __BEOS__ + +#include "stdafx.h" +#include "ttd.h" +#include "hal.h" + +// BeOS System Includes +#include + +BMidiSynthFile midiSynthFile; + +static char *bemidi_start(char **parm) { + return NULL; +} + +static void bemidi_stop(void) { + midiSynthFile.UnloadFile(); +} + +static void bemidi_play_song(const char *filename) { + bemidi_stop(); + entry_ref midiRef; + get_ref_for_path(filename, &midiRef); + midiSynthFile.LoadFile(&midiRef); + midiSynthFile.Start(); +} + +static void bemidi_stop_song(void) { + midiSynthFile.UnloadFile(); +} + +static bool bemidi_is_playing(void) { + if(midiSynthFile.IsFinished() == true) + { + return 0; + } else { + return 1; + } +} + + +static void bemidi_set_volume(byte vol) { + fprintf(stderr, "BeMidi: Set volume not implemented\n"); +} + +const HalMusicDriver _bemidi_music_driver = { + bemidi_start, + bemidi_stop, + bemidi_play_song, + bemidi_stop_song, + bemidi_is_playing, + bemidi_set_volume, +}; + +#endif // __BEOS__ diff --git a/bridge_gui.c b/bridge_gui.c new file mode 100644 --- /dev/null +++ b/bridge_gui.c @@ -0,0 +1,164 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" + +static struct BridgeData { + int count; + TileIndex start_tile; + TileIndex end_tile; + byte type; + byte indexes[MAX_BRIDGES]; + int32 costs[MAX_BRIDGES]; +} _bridge; + +extern const uint16 _bridge_type_price_mod[MAX_BRIDGES]; + +extern const PalSpriteID _bridge_sprites[MAX_BRIDGES]; +extern const uint16 _bridge_speeds[MAX_BRIDGES]; +extern const StringID _bridge_material[MAX_BRIDGES]; + +static void CcBuildBridge(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { SndPlayTileFx(0x25, tile); } +} + +static void BuildBridge(Window *w, int i) +{ + DeleteWindow(w); + DoCommandP(_bridge.end_tile, _bridge.start_tile, _bridge.indexes[i] | (_bridge.type << 8), CcBuildBridge, + CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE)); +} + +static void BuildBridgeWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int i; + + DrawWindowWidgets(w); + + for(i=0; i < 4 && i + w->vscroll.pos < _bridge.count; i++) { + int ind = _bridge.indexes[i + w->vscroll.pos]; + + SET_DPARAM32(2, _bridge.costs[i + w->vscroll.pos]); + SET_DPARAM16(1, (_bridge_speeds[ind] >> 4) * 10); + SET_DPARAM16(0, _bridge_material[ind]); + DrawSprite(_bridge_sprites[ind], 3, 15 + i * 22); + + DrawString(44, 15 + i*22 , STR_500D, 0); + } + } break; + + case WE_KEYPRESS: { + uint i = e->keypress.keycode - '1'; + if (i < 9 && i < (uint)_bridge.count) { + e->keypress.cont = false; + BuildBridge(w, i); + } + + break; + } + + case WE_CLICK: + if (e->click.widget == 2) { + uint ind = ((int)e->click.pt.y - 14) / 22; + if (ind < 4 && (ind += w->vscroll.pos) < (uint)_bridge.count) + BuildBridge(w, ind); + } + break; + } +} + +static const Widget _build_bridge_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 7, 0, 188, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK}, +{ WWT_SCROLLBAR, 7, 189, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +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, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 7, 0, 188, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK}, +{ WWT_SCROLLBAR, 7, 189, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_road_bridge_desc = { + -1, -1, 200, 102, + WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_road_bridge_widgets, + BuildBridgeWndProc +}; + + +void ShowBuildBridgeWindow(uint start, uint end, byte bridge_type) +{ + int j = 0; + int32 ret; + uint16 errmsg; + + DeleteWindowById(WC_BUILD_BRIDGE, 0); + + _bridge.type = bridge_type; + _bridge.start_tile = start; + _bridge.end_tile = end; + + errmsg = 0xFFFF; + + // only query bridge building possibility once, result is the same for all bridges! + // returns CMD_ERROR on failure, and priCe on success + ret = DoCommandByTile(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE); + + if (ret == CMD_ERROR) { + errmsg = _error_message; + } + // check which bridges can be built + else { + int bridge_len; // length of the middle parts of the bridge + int tot_bridge_len; // total length of bridge + + // get absolute bridge length + bridge_len = GetBridgeLength(start, end); + tot_bridge_len = bridge_len + 2; + + tot_bridge_len = CalcBridgeLenCostFactor(tot_bridge_len); + + for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes + + if (CheckBridge_Stuff(bridge_type, bridge_len)) { + // bridge is accepted, add to list + // add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST) + _bridge.costs[j] = ret + (((tot_bridge_len * _price.build_bridge) * _bridge_type_price_mod[bridge_type]) >> 8); + _bridge.indexes[j] = bridge_type; + j++; + } + } + } + + _bridge.count = j; + + if (j != 0) { + Window *w = AllocateWindowDesc((_bridge.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc); + w->vscroll.cap = 4; + w->vscroll.count = (byte)j; + } else { + ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, GET_TILE_X(end) * 16, GET_TILE_Y(end) * 16); + } +} diff --git a/changelog.txt b/changelog.txt new file mode 100644 --- /dev/null +++ b/changelog.txt @@ -0,0 +1,439 @@ +0.3.3 (2004-07-13) +------------------------------------------------------------------------ + +- Feature: (MorphOS/AmigaOS) network support +- Feature: improved german town name generator +- Change: scenarios now have the file extension .scn +- Fix: removing and upgrading tracks under a bridge when a train is on the bridge +- Change: default network port from 12345 (known trojan) to 3979 +- Fix: pause button was not synched in network games +- Fix: crash caused by invalid screen resolutions +- Fix: AI can not build tubular bridges in 1950, etc. Same restrictions apply to it, as to human players. +- Feature: transparent station signs +- Feature: show total cargo per wagon type in train details window +- Fix: volume, liters, was x100, should be x1000 +- Feature: bridges on slopes +- Fix: bridge building by towns was screwed when executed without testing first +- Feature: added Galician translation (by Condex) +- Change: crossing tunnels is now considered a cheat +- Fix: better AI route finding +- Fix: AI builds less inner-city bus stations +- Fix: Better industry spreading on random maps +- Fix: Two industries that accept the same goods can never be very close to each other +- Feature: Extra dynamite, allow the removal of town-owned roads, bridges, tunnels for a popularity rating penalty +- Feature: magic bulldozer cheat, that lets you remove industries, unmovables and town-owned buildings, roads and bridges +- Fix: destroying bridge (over water or 'higher bridge' with vehicle on it) +- Fix Game crashes when you hit the build rail button +- Fix: some scenarios had a max_railtype of 0 +- Fix: Bribe Autorithy. A failed attempt to bribe is now also stored in savegame +- Fix: 80% CPU load paused in fast-forward +- Feature: Enabled 'remove' button for stations +- Feature: Cheat GUI (activate with crtl-alt-c) The game remembers if you have used a cheat +- Fix: Some airport runways were treated +- Fix: minor minimap glitch +- Fix: station sorting scroll fails with not ennough stations +- Fix: desert ground for depots in the desert +- Feature: station sort implemented using qsort() +- Feature: station list shows #of stations owned by player +- Fix: trains could run on wrong track type under bridges +- Fix: screenshot hangs +- Feature: split canal/lock tool in two tools, one for building canals, one for locks. +- Fix: wrong sound with ships +- Fix: toy shop closes even though it has supply +- Fix: nordic characters +- Feature: make the HQ generate passengers and mail +- Fix: slso restore Service Interval when rebuying vehicle +- Fix: crash with map bits > 8 +- Fix: ufo crash in busstop +- Fix: town actions has empty row +- Change: made helicopters able to land on small airports again +- Feature: display number of houses in town overview window +- Fix: train stuck with the head in one depot and tail in another +- Fix: Optimized random radio tower spreading +- Feature: Land info now shows type of signal +- Fix: ground below trees is sometimes not covered by snow +- Fix: fast forward button in scenario editor +- Change: screenshots are saved to PERSONAL_DIR (unix) +- Fix: screenshot hotkey does not function in scenario editor +- Fix: allow deleting a bridge if a vehicle is below +- Fix: crash loading a scenario +- Fix: build tracks on water +- Fix: fast forward button pressed with tab +- Fix: vehicles don't get old +- Feature: realistic train reversing +- Feature: added support for 64 bit CPUs +- Fix: finance bug with some original scenarios +- Feature: added water quantity level "very low", which is the default for easy mode now +- Fix: 'Stopped' is shown when train is stopping and 'Reverse' is clicked +- Feature: realistic acceleration turned on, train must first slow down and stop before it can reverse +- Feature: (MorphOS build) various small improvement to make the the game feel more native +- Feature: alt + f now toggles full screen (alt + enter still works) +- Feature: (OSX build) command + q shows the quit window and command + f or enter toggles full screen (alt and control still works too) +- Feature: pasky's autorenew, autorenews vehicles if enabled. +- Feature: (incomplete) news history window +- Feature: larger smallmap size +- Feature: Austrian Citynames +- Feature: repaying most possible debt +- Feature: added Polish translation (by tomek) +- Feature: added Danish translation (by Gof.dk) +- Feature: pasky's grfspecial loader. You have to enable them in openttd.cfg using [newgrf] setting +- Feature: smooth economy changes +- Fix: 100% CPU bug +- Fix: crash when AI builds airport +- Fix: plays wrong music on main screen +- Fix: inflation was way too high when intrest rate = 0 +- Fix: can't sell anything if money is TOO negative +- Fix: fast forward button resets +- Feature: TTDPatch-style gotodepot. Ship depots and aircraft hangars can be inserted in the schedule as well. +- Feature: ability to add "service if needed" orders (the "full load" button changes to "service" after selecting a depot order) +- Feature: if a vehicle has depot orders in its schedule, automatic servicing is disabled +- Change: autosaves are now placed in save/autosave +- Feature: patch setting so that helicopters get serviced automatically on helipad +- Fix: "refit train" button remains +- Change: default savegame directory is /save in Linux +- Fix: enable up/down scrolling with the mouse +- Feature: center toolbar on screen +- Feature: sort savelist by date +- Feature: allow scrolling in both directions +- Feature: darkvater's two new airports (metropolitan in 1980 and international in 1990) +- Feature: Resizing the window in all SDL builds +- Fix: 1920 all trains +- Fix: wrong heli breakdownspeed +- Feature: added MIDI flag to makefile to set custom path to midi player +- Fix: station list cargo waiting display bug +- Fix: bug that could allow rails on steep slopes +- Fix: train depots and checkpoints not flooded by water +- Fix: added command line option (-i) to deactivate the grf check +- Fix: signal bug [ 949929 ] + + +0.3.2.1 (2004-05-23) +- Fix: use english.lng by default +- Fix: No bridges available in 1920 +- Fix: czech file was missing +- Feature: now builds on FreeBSD +- Feature: now builds on MorphOS + + +0.3.2 (2004-05-22) +- Feature: HP for trians limited to 16bit int +- Feature: added Czech translation +- Feature: train refitting +- Feature: auto euro +- Fix: don't allow building railroad stations on airports or bus stations +- Feature: industry directory +- Feature: added extend vehicle life/noexpire patch +- Feature: show revision number in title bar +- Fix: Enable mouse wheel scrolling and zooming in SDL +- Fix: Construct industries producing raw materials +- Fix: loading TTD saves gave incorrect reliability parameters for wagons +- Feature: random network games +- Fix: fixed order restore bug in network play +- Fix: network sync fix for train goto depot +- Feature: smallmap remembers size +- Fix: Only one statue per player per town +- Fix: enhanced patch configurator +- Fix: if realistic acceleration was enabled, train didn't accelerate if they entered a tunnel right after a slope +- Fix: remove sdl frameskip message +- Fix: road vehicle on hills speedfix +- Fix: CompanyValueGraph window too small for currency +- Fix: mkdir() problem in unix.c +- Fix: client kills server if it leaves a networkgame +- Change: autosave go to autosave/ +- Fix: Canal tool resets after 1 use +- Feature: remember value of show town names in smallmap +- Feature: norwegian translation +- Feature: norwegian currency +- Feature: slovak language +- Fix: smoother mouse cursor +- Fix: fixed a couple of overlapping memcpys +- Feature: use SO_REUSEADDR on listen socket +- Feature: unix sigabort handling +- Feature: hungarian translation +- Fix: quit to beos +- Fix: dragging to build canals sometimes crashed +- Fix: cactus plants died on desert +- Feature: added norwegian translation +- Feature: added more default resolutions +- Feature: return error message if DOS grf files are used +- Feature: bemidi support +- Fix: invalid letters in spanish town names +- Fix: rail upgrade button +- Fix: makefile reorganization +- Fix: Zoom out button not grayed out +- Fix: no space between some values and units +- Change: Plant area of trees now allowed for 20x20 area +- Change: "kmh^-1" to "km/h" +- Fix: Station catchment outline-tiles weren't shown properly on slopes +- Fix: oil rig station wasn't properly deleted +- Fix: fixed making screenshots in scenario editor +- Feature: added icelandic currency +- Change: show original savegame names for oldstyle savegames +- Fix: mac patches by bjarni +- Fix: fixed alignment issue in station drawing + + +0.3.1 (2004-04-26) +- Fix: shift+arrows keys scrolls faster (by pasky) +- Feature: bridge pillars for higher bridges +- Fix: [ 941880 ] "monorail in 1985" which allowed you to build monorail/maglev at any year +- Feature: remember cargo payment rates selection, default to all +- Fix: town ratings when companies are deleted/merged +- Fix: vehicle reliability calculation in third phase +- Change: new directory structure (*.grf+sample.cat in data subdir, *.lng in lang subdir) +- Feature: fast forward button +- Fix: random world button in scenario editor doesn't build cities, industries, trees +- Fix: loading worlds with no towns now fails +- Fix: outdated sort order after station renaming +- Feature: copy/share orders from trains in depot +- Fix: better train detection for copy orders +- Fix: [ 938481 ] Euro currency bug +- Fix: [ 938170 ] Go to xxx road depot selection bug (2) +- Fix: [ 934520 ] scrolling and newspaper in title screen +- Feature: swedish translation (by poLiSen) +- Fix: incorrect cargo_days for trains +- Feature: dragging to construct canals +- Fix array bounds error with train breakdown speeds +- Fix: towns deleting random tiles around houses +- Feature: can now have more than 128 towns +- Fix: incorrect road vehicle list caption for competitors +- Fix: vehicle menu graying after a bankrupty +- Feature: always allow building small airports patch +- Feature: colorful newspaper after a certain date +- Feature: build while paused patch +- Feature: polish town names +- Fix: selective road removal +- Feature: clear area now works in scenario editor +- Feature: drag&drop stations +- Fix: make houses available in 1920 to prevent hang +- Fix: duration of breakdown smoke +- Fix: slope bug under bridges +- Feature: more realistic train starting and stopping +- Fix: don't play invalid sounds (fixes road reconstruction crash) +- Fix: display correct train power with multihead engines +- Fix: buffer overflow caused by too long string in english.lng +- Fix: destroying things with no money + +0.3.0 (2004-04-14) +- Change: don't slow down trains as much on hills +- Fix: aircraft terminal wasn't properly freed if aircraft crashed +- Fix: fixed station acceptance bug +- Change: limit amount of radiotowers. +- Feature: cost estimation with Shift +- Change: changed speedkey from Shift to Tab. +- Feature: added patch for starting_date, takes a value on the form yyyy, yyyymm or yyyymmdd. +- Feature: support for multiheaded trains +- Feature: sell whole train by dragging loco to special trashcan +- Feature: drag the whole train with ctrl in depot +- Fix: fixed buy shares in company +- Feature: added convert rail tool +- Change: enhanced patches window with pages. +- Feature: patch to select what vehicle types the ai will build +- Feature: better slope graphics +- Fix: only deliver goods to stations that have a rating != 0 +- Feature: new pathfinding algorithm for trains (enable with new_pathfinding) +- Change: changed intro graphics +- Change: all player stuff is deleted when you load a scenario. +- Fix: added F hotkeys in scenario editor +- Feature: Added patch to use timidity for BeOS +- Feature: mousewheel can now be used to scroll in windows +- Feature: added coordinate display to landinfo window +- Feature: change default servicing interval for vehicles +- Feature: change max # of vehicles per player +- Fix: unable to raise land next to signal +- Feature: nonuniform stations patch +- Feature: moved error message box out of the way +- Fix: aircraft was shown instead of ships in player overview window +- Feature: canals/shiplifts +- Feature: build tree of random type +- Feature: build trees on area +- Feature: added color coded vehicle profits +- Feature: ability to close error messages with space. +- Fix: updated installer to take care of savegames more carefully +- Fix: don't make a new subsidy if there already exists one that is currently active by a company +- Fix: town directory sometimes showed huge numbers +- Fix: fixed bugs when changing owners of items (pieces of rail were not always deleted), +- Feature: network games (currently unsupported) +- Fix: fixed bug with large stations in train pathfinder +- Change: use save/ as save folder on win32 +- Feature: bigger demolish tool +- Change: moved date in news window +- Feature: two more bridges +- Feature: improved depot finding +- Feature: bribe the town authority +- Feature: allow building many trees on a single tile. +- Feature: added snow_line_height setting, only affects new games. +- Change: don't check if tiles around the clicked station is a station in order gui +- Fix: deleting docks doesn't produce land +- Fix: deleting ship depot doesn't produce land +- Fix: buoy is now treated as water when flooding +- Feature: errmsg_duration controls how long error messages are displayed +- Fix: combo presignals bug fix +- Fix: prevent going to 0,0 if airport/docks is deleted +- Feature: fullscreen_bpp setting in [win32] sets the bpp to use in fullscreen mode +- Fix: french town names had bad letters in them +- Feature: euro symbol +- Feature: high bridges +- Fix: order list when replacing train didn't work properly +- Change: keep checkpoint button down after placing +- Fix: start in the middle of the map +- Change: moved disk devices to bottom of list on win32 +- Fix: more error tolerant saveload code +- Feature: ZLIB savegames (smaller than before) +- Feature: PNG,PCX screenshot support +- Feature: indicate with gray in vehicle popup menus if company has no vehicles of that type +- Feature: clicking on the money brings up finances +- Fix: (OSX build) now runs even if sdl is not present on the system +- Fix: (OSX build) now runs on systems older than 10.3 +- Fix: (OSX build) altered compiler settings to make a completely stable app +- Feature: (OSX build) distribution now uses Apples package system for easier updates +- Feature: (OSX build) Application is now a proper bundle application + +0.2.1 (2004-04-04) +- Fix: copy orders crashed if you clicked on a wagon +- Feature: 'A' hotkey now always opens autorail +- Change: Moved autorail button +- Feature: X can be used to toggle transparent buildings +- Fix: don't show transparent buildings in intro +- Fix: installer doesn't delete savegames +- Feature: Hotkeys 1-9 can be used to build a bridge in the bridge window +- Feature: Added more hotkeys in the road build window + +0.2 (2004-04-03) + +- Feature: autoscroll (only works to left/right) +- Feature: train checkpoints, instead of ttdpatch's nonstop handling +- Feature: ttdpatch compatible nonstop handling +- Fix: news window was moved strangely when resizing +- Fix: fixed sign drawing bug in max zoom out mode +- Feature: refresh rate configuration setting +- Feature: town directory sorting options +- Feature: pre-signals (ctrl-click on existing signals to change signal type) +- Feature: show semaphores on the right side if right-sided traffic +- Improvement: increased number of windows on screen to 20 +- Feature: patch options configuration window +- Fix: road vehicles sometimes getting stuck +- Feature: autorail build tool +- Feature: "show yearly finances window" option +- Feature: "signals on drive side" patch (by Michael Polnick) +- Fix: connecting tracks behind depot causing incorrect signal behavior +- Fix: save/load diskspace bug +- Feature: "show full date in statusbar" option +- Feature: italian translation (by duepixel) +- Feature: road and rail removal by dragging a selection +- Feature: news item for "train is unprofitable" +- Feature: news item for "train is lost" +- Feature: (win32 build) double size mode (ctrl-d to toggle) +- Fix: incorrect bridge cost for long bridges +- Feature: "multiple similar industries in close proximity" option +- Feature: "multiple industries per down" option +- Feature: "crossing tunnels" option +- Feature: order sharing and copying ("goto" on other vehicle to copy, ctrl+"goto" to share) +- Feature: remember last built rail type +- Feature: "debtmax" faster loan management with ctrl key +- Fix: disallow buoy in north corner +- Feature: "go to depot" orders option +- Feature: "long bridges" option +- Feature: "select goods" option +- Feature: "no train service" option +- Feature: "no inflation" option +- Improvement: (OSX build) now starts when doubleclicked +- Improvement: (OSX build) significant performance increase +- Improvement: optimized startup time +- Feature: automatically detect available resolutions +- Feature: "full load any" option, as in ttdpatch +- Feature: automatic detection of available language files +- Feature: German translation (by truesatan and wuntvor) +- Improvement: sorted savegame list +- Feature: finnish town names (by Jpl) +- Feature: remember custom difficulty settings +- Fix: shift key now increases game speed only when game window is active +- Fix: ctrl button now works with SDL driver +- Feature: configuration file system +- Feature: show vehicle speed in vehicle view windows +- Fix: incorrect weight displayed in "new trains" window +- Feature: train depot window now has horizontal scrollbar +- Feature: mammoth trains +- Fix: incorrect train running cost in newspaper +- Feature: on-the-fly language selection +- Feature: load old premade ttd maps (must be renamed to .sv1 extension) + +0.1.4 + +- Feature: crash submit system on win32 +- Fix: train smoke clouds +- Fix: train engine sounds +- Fix: play all sounds at 11025 hz (fixes certain sounds) +- Feature: autosave +- Fix: scenario editor desert button now makes desert instead of lighthouse +- Fix: creating random town in scenario editor crash +- Fix: candy bubbles sometimes caused crash +- Fix: wrong speed was shown in news window for some vehicles +- Fix: graph color bleeding +- Feature: build on coasts +- Feature: Allow building transmitters, lighthouses and company headquarters on slopes +- Feature: now builds on MacOSX +- Fix: arrow keys with SDL driver +- Change: new savegame format +- Change: new format for english.lng +- Fix: don't allow trains to road depots +- Fix: road vehicle was sometimes shown inside depot +- Fix: arrow keys in sdl driver were wrong +- Fix: endianness bugs in save/load +- Fix: now builds on FreeBSD +- Fix: screenshot feature now works +- Fix: rail foundations sometimes displayed unnecessarily +- Fix: minor AI bugs +- Fix: fixed industry sounds +- Feature: in-game resolution selection via settings window +- Feature: Dutch town names +- Feature: Added load game menu item +- Fix: bug where ship depots were very expensive +- Fix: BeOS build (by MYOB) +- Fix: yearly expenses data being the same for the past two game years +- Fix: adding songs to playlists other than custom1 and custom2 +- Fix: first and last tracks playing the wrong music +- Fix: Palette animation for SDL video (rob) +- Fix: Get remaining disk space on most Unix-en (rob) +- Fix: screen went black when resizing + +0.1.3 + +- Fixed message options window +- Fixed company takeover/purchase +- Feature: Improved mouse scroll zooming +- Fixed station code so it's not possible to steal another player's temporarily deleted station +- Fixed subsidy owner bug when deleting station +- Fixed crash when deleting a bridge with a train on it +- Feature: Larger stations and possibility to join stations +- Fixed missing candy initial cargo payment values +- Fixed Goods and Food/FizzyDrinks subsidies +- Fixed graphical glitch in subsidies window +- Take over company dialog was not shown properly +- Fixed crash if player windows were open while the company went bankrupt +- Fixed train slowness on hills +- Feature: swedish town names (patch by glottis) +- Feature: more currencies +- Better window resizing/zooming +- Added goto road vehicle depot for road vehicle orders +- Possibility to use either semaphores or signals (Ctrl key) +- Limited the scrolling rate for year selector in scenario editor + +0.1.2 + +- Mouse wheel can be used to zoom in out on win32 (ludde) +- Implemented some support for resizing the window dynamically in win32 (ludde) +- Fixed tunnel mouse icon for maglev and monorail + +0.1.1 + +- Preliminary presignal support +- Added external MIDI driver for unix version (by robertnorris) +- Added DirectMusic driver for Win32 version +- Fixed problem where directories weren't displayed under Linux (by Markus) +- Center windows properly in higher resolutions +- Added "build tracks on slopes" feature +- Fixed colors in map window for routes +- Command line -g flag now optionally takes a game to load +- Fixed road drive side +- Fixed "Fund road construction" not clickable when unavailable diff --git a/clear_cmd.c b/clear_cmd.c new file mode 100644 --- /dev/null +++ b/clear_cmd.c @@ -0,0 +1,806 @@ +#include "stdafx.h" +#include "ttd.h" +#include "viewport.h" +#include "command.h" + +typedef struct TerraformerHeightMod { + TileIndex tile; + byte height; +} TerraformerHeightMod; + +typedef struct TerraformerState { + int height[4]; + uint32 flags; + + int direction; + int modheight_count; + int tile_table_count; + + int32 cost; + + TileIndex *tile_table; + TerraformerHeightMod *modheight; + +} TerraformerState; + +static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile) +{ + TileIndex *t; + int count; + + if ((GET_TILE_X(tile) == TILE_X_MAX) || (GET_TILE_Y(tile) == TILE_Y_MAX)) + 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 _map_type_and_height[tile] & 0xF; +} + +static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile) +{ + int count; + TileIndex *t; + + count = ts->tile_table_count; + + if (count >= 625) + return; + + for(t = ts->tile_table; count != 0; count--,t++) { + if (*t == tile) + return; + } + + ts->tile_table[ts->tile_table_count++] = tile; +} + +static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile) +{ + TerraformAddDirtyTile(ts, tile+TILE_XY(0,-1)); + TerraformAddDirtyTile(ts, tile+TILE_XY(-1,-1)); + TerraformAddDirtyTile(ts, tile+TILE_XY(-1,0)); + TerraformAddDirtyTile(ts, tile); +} + +static int TerraformProc(TerraformerState *ts, uint tile, int mode) +{ + int r; + int32 ret; + + assert(tile < TILES_X * TILES_Y); + + if ((r=TerraformAllowTileProcess(ts, tile)) <= 0) + return r; + + if ((_map_type_and_height[tile] >> 4) == MP_RAILWAY) { + static const byte _railway_modes[4] = {8, 0x10, 4, 0x20}; + static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb}; + + // 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 the other corner. + if ((GetTileSlope(tile, NULL)&0xF) == _railway_dangslopes[mode]) { + _error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK; + return -1; + } + + // If we have a single diagonal track there, the other side of + // tile can be terraformed. + if ((_map5[tile]&~0x40) == _railway_modes[mode]) + return 0; + } + + ret = DoCommandByTile(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR); + + if (ret == CMD_ERROR) { + _terraform_err_tile = tile; + return -1; + } + + ts->cost += ret; + + if (ts->tile_table_count >= 625) + return -1; + ts->tile_table[ts->tile_table_count++] = tile; + + return 0; +} + +static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height) +{ + int nh; + TerraformerHeightMod *mod; + int count; + + assert(tile < TILES_X * TILES_Y); + + if (height < 0) { + _error_message = STR_1003_ALREADY_AT_SEA_LEVEL; + return false; + } + + _error_message = STR_1004_TOO_HIGH; + + if (height > 0xF) + return false; + + nh = TerraformGetHeightOfTile(ts, tile); + if (nh < 0 || height == nh) + return false; + + if (TerraformProc(ts, tile, 0)<0) + return false; + + if (TerraformProc(ts, tile + TILE_XY(0,-1), 1)<0) + return false; + + if (TerraformProc(ts, tile + TILE_XY(-1,-1), 2)<0) + return false; + + if (TerraformProc(ts, tile + TILE_XY(-1,0), 3)<0) + return false; + + mod = ts->modheight; + count = ts->modheight_count; + + for(;;) { + if (count == 0) { + if (ts->modheight_count >= 576) + return false; + ts->modheight_count++; + break; + } + if (mod->tile == (TileIndex)tile) + break; + mod++; + count--; + } + + mod->tile = (TileIndex)tile; + mod->height = (byte)height; + + ts->cost += _price.terraform; + + { + int direction = ts->direction, r; + const TileIndexDiff *ttm; + + static const TileIndexDiff _terraform_tilepos[5] = {TILE_XY(1,0), TILE_XY(-2,0), TILE_XY(1,1), TILE_XY(0,-2), 0 }; + + for(ttm = _terraform_tilepos; *ttm != 0; ttm++) { + tile += *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 + * p1 - corners + * p2 - direction + */ + +int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TerraformerState ts; + uint tile; + int direction; + + TerraformerHeightMod modheight_data[576]; + TileIndex tile_table_data[625]; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + _error_message = INVALID_STRING_ID; + _terraform_err_tile = 0; + + ts.direction = direction = p2 ? 1 : -1; + ts.flags = flags; + ts.modheight_count = ts.tile_table_count = 0; + ts.cost = 0; + ts.modheight = modheight_data; + ts.tile_table = tile_table_data; + + tile = TILE_FROM_XY(x,y); + + if (p1 & 1) { + if (!TerraformTileHeight(&ts, tile+TILE_XY(1,0), + (_map_type_and_height[tile+TILE_XY(1,0)]&0xF) + direction)) + return CMD_ERROR; + } + + if (p1 & 2) { + if (!TerraformTileHeight(&ts, tile+TILE_XY(1,1), + (_map_type_and_height[tile+TILE_XY(1,1)]&0xF) + direction)) + return CMD_ERROR; + } + + if (p1 & 4) { + if (!TerraformTileHeight(&ts, tile+TILE_XY(0,1), + (_map_type_and_height[tile+TILE_XY(0,1)]&0xF) + direction)) + return CMD_ERROR; + } + + if (p1 & 8) { + if (!TerraformTileHeight(&ts, tile+TILE_XY(0,0), + (_map_type_and_height[tile+TILE_XY(0,0)]&0xF) + direction)) + return CMD_ERROR; + } + + if (direction == -1) { + /* Check if tunnel would take damage */ + int count; + TileIndex *ti = ts.tile_table; + + for(count = ts.tile_table_count; count != 0; count--, ti++) { + uint z, t; + uint tile = *ti; + + z = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,0)); + t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,0)); + if (t <= z) z = t; + t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,1)); + if (t <= z) z = t; + t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,1)); + if (t <= z) z = t; + + if (!CheckTunnelInWay(tile, z*8)) + return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE); + } + } + + if (flags & DC_EXEC) { + /* Clear the landscape at the tiles */ + { + int count; + TileIndex *ti = ts.tile_table; + for(count = ts.tile_table_count; count != 0; count--, ti++) { + DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + } + } + + /* change the height */ + { + int count; + TerraformerHeightMod *mod; + uint til; + + mod = ts.modheight; + for(count = ts.modheight_count; count != 0; count--, mod++) { + til = mod->tile; + + // Change tile height + _map_type_and_height[til] = (_map_type_and_height[til]&~0x0F)|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; +} + + +/* + * p1 - start + */ + +int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) +{ + int size_x, size_y; + int sx, sy; + uint h, curh; + uint tile; + int32 ret, cost, money; + + // remember level height + h = _map_type_and_height[p1]&0xF; + + ex >>= 4; ey >>= 4; + + // make sure sx,sy are smaller than ex,ey + sx = GET_TILE_X(p1); + sy = GET_TILE_Y(p1); + if (ex < sx) intswap(ex, sx); + if (ey < sy) intswap(ey, sy); + tile = TILE_XY(sx,sy); + + size_x = ex-sx+1; + size_y = ey-sy+1; + + money = GetAvailableMoneyForCommand(); + cost = 0; + + BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) + curh = _map_type_and_height[tile2]&0xF; + while (curh != h) { + ret = DoCommandByTile(tile2, 8, (curh > h)?0:1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND); + if (ret == CMD_ERROR) 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) + + if (cost == 0) return CMD_ERROR; + return cost; +} + +/* Purchase a land area + * p1 = unused + * p2 = unused + */ + +int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + int32 cost; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (IS_TILETYPE(tile, MP_UNMOVABLE) && + _map5[tile] == 3 && + _map_owner[tile] == _current_player) + return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT); + + cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (cost == CMD_ERROR) + 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; +} + + +int32 ClearTile_Clear(uint tile, byte flags) { + static const int32 * _clear_price_table[] = { + NULL, + &_price.clear_1, &_price.clear_1,&_price.clear_1, + &_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land, + &_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2, + &_price.clear_3,&_price.clear_3,&_price.clear_3,&_price.clear_3, + &_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land, + &_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land, + &_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2, + }; + const int32 *price = _clear_price_table[_map5[tile] & 0x1F]; + + if (flags & DC_EXEC) + DoClearSquare(tile); + + if (price == NULL) + return 0; + return *price; +} + +int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!CheckTileOwnership(tile)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) + DoClearSquare(tile); + + return - _price.purchase_land*2; +} + + +#include "table/clear_land.h" + + +void DrawClearLandTile(TileInfo *ti, byte set) +{ + DrawGroundSprite(0xF54 + _tileh_to_sprite[ti->tileh] + set * 19); +} + +void DrawHillyLandTile(TileInfo *ti) +{ + if (ti->tileh != 0) { + DrawGroundSprite(0xFA0 + _tileh_to_sprite[ti->tileh]); + } else { + DrawGroundSprite(_landscape_clear_sprites[((ti->x^ti->y) >> 4) & 0x7]); + } +} + +void DrawClearLandFence(TileInfo *ti, byte img) +{ + byte z = ti->z; + + if (ti->tileh & 2) { + z += 8; + if (ti->tileh == 0x17) + z += 8; + } + + if (img & 0x38) { + DrawGroundSpriteAt(_clear_land_fence_sprites_1[((img >> 3) & 7) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z); + } + + if (img & 0x7) { + DrawGroundSpriteAt(_clear_land_fence_sprites_1[(img & 7) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z); + } +} + +static void DrawTile_Clear(TileInfo *ti) +{ + + switch((ti->map5 & (7<<2)) >> 2) { + case 0: + DrawClearLandTile(ti, (ti->map5 & 3)); + break; + + case 1: + DrawHillyLandTile(ti); + break; + + case 2: + DrawGroundSprite(0xFB7 + _tileh_to_sprite[ti->tileh]); + break; + + case 3: + DrawGroundSprite( _clear_land_sprites_1[_map3_lo[ti->tile]&0xF] + _tileh_to_sprite[ti->tileh]); + break; + + case 4: + DrawGroundSprite( _clear_land_sprites_2[ti->map5&3] + _tileh_to_sprite[ti->tileh]); + break; + + case 5: + DrawGroundSprite( _clear_land_sprites_3[ti->map5&3] + _tileh_to_sprite[ti->tileh]); + break; + } + + DrawClearLandFence(ti, _map3_hi[ti->tile] >> 2); +} + +uint GetSlopeZ_Clear(TileInfo *ti) { return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; } + +static void GetAcceptedCargo_Clear(uint tile, AcceptedCargo *ac) +{ + /* unused */ +} + +static void AnimateTile_Clear(uint tile) +{ + /* unused */ +} + +void TileLoopClearHelper(uint tile) +{ + byte img_1, img_2; + static byte img_by_map5[8] = { 0,0,0,2, 1,1,0,0, }; + uint dirty = -1; + + img_1 = 0; + if (IS_TILETYPE(tile, MP_CLEAR)) { + img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2]; + } else if (IS_TILETYPE(tile, MP_TREES) && (_map2[tile] & 0x30) == 0x20) { + img_1 = 1; + } + + img_2 = 0; + if (IS_TILETYPE(TILE_ADDXY(tile, 1, 0), MP_CLEAR)) { + img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2]; + } else if (IS_TILETYPE(TILE_ADDXY(tile, 1, 0), MP_TREES) && (_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20) { + img_2 = 1; + } + + if (!(_map3_hi[tile] & 0xE0)) { + if ( (img_1&2) != (img_2&2) ) { + _map3_hi[tile] |= 3 << 5; + dirty = tile; + } + } else { + if (img_1 == 1 && img_2 == 1) { + _map3_hi[tile] &= ~(3 << 5); + dirty = tile; + } + } + + img_2 = 0; + if (IS_TILETYPE(TILE_ADDXY(tile, 0, 1), MP_CLEAR)) { + img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2]; + } else if (IS_TILETYPE(TILE_ADDXY(tile, 0, 1), MP_TREES) && (_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20) { + img_2 = 1; + } + + if (!(_map3_hi[tile] & 0x1C)) { + if ( (img_1&2) != (img_2&2) ) { + _map3_hi[tile] |= 3 << 2; + dirty = tile; + } + } else { + if (img_1 == 1 && img_2 == 1) { + _map3_hi[tile] &= ~(3 << 2); + dirty = tile; + } + } + + if (dirty != -1) + MarkTileDirtyByTile(dirty); +} + + +/* convert into snowy tiles */ +static void TileLoopClearAlps(uint tile) +{ + int k; + byte m5,tmp; + + /* distance from snow line, in steps of 8 */ + k = GetTileZ(tile) - _opt.snow_line; + + m5 = _map5[tile] & 0x1C; + tmp = _map5[tile] & 3; + + if (k < -8) { + /* snow_m2_down */ + if (m5 != 0x10) + return; + if (tmp == 0) + m5 = 3; + } else if (k == -8) { + /* snow_m1 */ + if (m5 != 0x10) { + m5 = 0x10; + } else if (tmp != 0) { + m5 = (tmp - 1) + 0x10; + } else + return; + } else if (k < 8) { + /* snow_0 */ + if (m5 != 0x10) { + m5 = 0x10; + } else if (tmp != 1) { + m5 = 1; + if (tmp != 0) + m5 = tmp - 1; + m5 += 0x10; + } else + return; + } else if (k == 8) { + /* snow_p1 */ + if (m5 != 0x10) { + m5 = 0x10; + } else if (tmp != 2) { + m5 = 2; + if (tmp <= 2) + m5 = tmp + 1; + m5 += 0x10; + } else + return; + } else { + /* snow_p2_up */ + if (m5 != 0x10) { + m5 = 0x10; + } else if (tmp != 3) { + m5 = tmp + 1 + 0x10; + } else + return; + } + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); +} + +static void TileLoopClearDesert(uint tile) +{ + if ( (_map5[tile] & 0x1C) == 0x14) + return; + + if (GetMapExtraBits(tile) == 1) { + _map5[tile] = 0x17; + } else { + if (GetMapExtraBits(tile+TILE_XY(1,0)) != 1 && + GetMapExtraBits(tile+TILE_XY(-1,0)) != 1 && + GetMapExtraBits(tile+TILE_XY(0,1)) != 1 && + GetMapExtraBits(tile+TILE_XY(0,-1)) != 1) + return; + _map5[tile] = 0x15; + } + + MarkTileDirtyByTile(tile); +} + +static void TileLoop_Clear(uint tile) +{ + byte m5,m3; + + TileLoopClearHelper(tile); + + if (_opt.landscape == LT_DESERT) { + TileLoopClearDesert(tile); + } else if (_opt.landscape == LT_HILLY) { + TileLoopClearAlps(tile); + } + + m5 = _map5[tile]; + if ( (m5 & 0x1C) == 0x10 || (m5 & 0x1C) == 0x14) + return; + + if ( (m5 & 0x1C) != 0xC) { + if ( (m5 & 3) == 3) + return; + + if (_game_mode != GM_EDITOR) { + m5 += 0x20; + if (m5 >= 0x20) { + // Didn't overflow + _map5[tile] = m5; + return; + } + /* did overflow, so continue */ + } else { + m5 = ((byte)Random() > 21) ? (2) : (6); + } + m5++; + } else if (_game_mode != GM_EDITOR) { + /* handle farm field */ + m5 += 0x20; + if (m5 >= 0x20) { + // Didn't overflow + _map5[tile] = m5; + return; + } + /* overflowed */ + m3 = _map3_lo[tile] + 1; + assert( (m3 & 0xF) != 0); + if ( (m3 & 0xF) >= 9) /* NOTE: will not work properly if m3&0xF == 0xF */ + m3 &= ~0xF; + _map3_lo[tile] = m3; + } + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); +} + +void GenerateClearTile() +{ + int i,j; + uint tile,tile_new; + uint32 r; + + /* add hills */ + i = (Random() & 0x3FF) | 0x400; + do { + tile = TILE_MASK(Random()); + if (IS_TILETYPE(tile, MP_CLEAR)) + _map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (1<<2)); + } while (--i); + + /* add grey squares */ + i = (Random() & 0x7F) | 0x80; + do { + r = Random(); + tile = TILE_MASK(r); + if (IS_TILETYPE(tile, MP_CLEAR)) { + j = ((r >> 16) & 0xF) + 5; + for(;;) { + _map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (2<<2)); + do { + if (--j == 0) goto get_out; + tile_new = tile + _tileoffs_by_dir[Random() & 3]; + } while (!IS_TILETYPE(tile_new, MP_CLEAR)); + tile = tile_new; + } +get_out:; + } + } while (--i); +} + +static void ClickTile_Clear(uint tile) +{ + /* not used */ +} + +uint32 GetTileTrackStatus_Clear(uint tile, int mode) +{ + return 0; +} + +static const StringID _clear_land_str[4+8-1] = { + STR_080B_ROUGH_LAND, + STR_080A_ROCKS, + STR_080E_FIELDS, + STR_080F_SNOW_COVERED_LAND, + STR_0810_DESERT, + 0, + 0, + STR_080C_BARE_LAND, + STR_080D_GRASS, + STR_080D_GRASS, + STR_080D_GRASS, +}; + +static void GetTileDesc_Clear(uint tile, TileDesc *td) +{ + int i = (_map5[tile]>>2) & 7; + if (i == 0) + i = (_map5[tile] & 3) + 8; + td->str = _clear_land_str[i - 1]; + td->owner = _map_owner[tile]; +} + +static void ChangeTileOwner_Clear(uint tile, byte old_player, byte new_player) +{ + return; +} + +void InitializeClearLand() { + _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 */ +}; diff --git a/command.c b/command.c new file mode 100644 --- /dev/null +++ b/command.c @@ -0,0 +1,493 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gui.h" +#include "command.h" +#include "player.h" + +#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(CmdBuildSignals); +DEF_COMMAND(CmdRemoveSignals); + +DEF_COMMAND(CmdTerraformLand); + +DEF_COMMAND(CmdPurchaseLandArea); +DEF_COMMAND(CmdSellLandArea); + +DEF_COMMAND(CmdBuildTunnel); + +DEF_COMMAND(CmdBuildTrainDepot); +DEF_COMMAND(CmdBuildTrainCheckpoint); +DEF_COMMAND(CmdRenameCheckpoint); +DEF_COMMAND(CmdRemoveTrainCheckpoint); + +DEF_COMMAND(CmdBuildTruckStation); + +DEF_COMMAND(CmdBuildBusStation); + +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(CmdTrainGotoDepot); +DEF_COMMAND(CmdForceTrainProceed); +DEF_COMMAND(CmdReverseTrainDirection); + +DEF_COMMAND(CmdModifyOrder); +DEF_COMMAND(CmdSkipOrder); +DEF_COMMAND(CmdDeleteOrder); +DEF_COMMAND(CmdInsertOrder); +DEF_COMMAND(CmdChangeTrainServiceInt); +DEF_COMMAND(CmdRestoreOrderIndex); + +DEF_COMMAND(CmdBuildIndustry); +//DEF_COMMAND(CmdDestroyIndustry); + +DEF_COMMAND(CmdBuildCompanyHQ); +DEF_COMMAND(CmdSetPlayerFace); +DEF_COMMAND(CmdSetPlayerColor); + +DEF_COMMAND(CmdIncreaseLoan); +DEF_COMMAND(CmdDecreaseLoan); + +DEF_COMMAND(CmdWantEnginePreview); + +DEF_COMMAND(CmdNameVehicle); +DEF_COMMAND(CmdRenameEngine); + +DEF_COMMAND(CmdChangeCompanyName); +DEF_COMMAND(CmdChangePresidentName); + +DEF_COMMAND(CmdRenameStation); + +DEF_COMMAND(CmdSellAircraft); +DEF_COMMAND(CmdStartStopAircraft); +DEF_COMMAND(CmdBuildAircraft); +DEF_COMMAND(CmdSendAircraftToHangar); +DEF_COMMAND(CmdChangeAircraftServiceInt); +DEF_COMMAND(CmdRefitAircraft); + +DEF_COMMAND(CmdPlaceSign); +DEF_COMMAND(CmdRenameSign); + +DEF_COMMAND(CmdBuildRoadVeh); +DEF_COMMAND(CmdStartStopRoadVeh); +DEF_COMMAND(CmdSellRoadVeh); +DEF_COMMAND(CmdSendRoadVehToDepot); +DEF_COMMAND(CmdTurnRoadVeh); +DEF_COMMAND(CmdChangeRoadVehServiceInt); + +DEF_COMMAND(CmdPause); +DEF_COMMAND(CmdResume); + +DEF_COMMAND(CmdBuyShareInCompany); +DEF_COMMAND(CmdSellShareInCompany); +DEF_COMMAND(CmdBuyCompany); + +DEF_COMMAND(CmdBuildTown); + +DEF_COMMAND(CmdRenameTown); +DEF_COMMAND(CmdDoTownAction); + +DEF_COMMAND(CmdSetRoadDriveSide); +DEF_COMMAND(CmdSetTownNameType); + +DEF_COMMAND(CmdChangeDifficultyLevel); + +DEF_COMMAND(CmdStartStopShip); +DEF_COMMAND(CmdSellShip); +DEF_COMMAND(CmdBuildShip); +DEF_COMMAND(CmdSendShipToDepot); +DEF_COMMAND(CmdChangeShipServiceInt); +DEF_COMMAND(CmdRefitShip); + + +DEF_COMMAND(CmdStartNewGame); +DEF_COMMAND(CmdLoadGame); +DEF_COMMAND(CmdCreateScenario); +DEF_COMMAND(CmdSetSinglePlayer); + +DEF_COMMAND(CmdSetNewLandscapeType); + +DEF_COMMAND(CmdGenRandomNewGame); +DEF_COMMAND(CmdCloneOrder); + +DEF_COMMAND(CmdClearArea); + +DEF_COMMAND(CmdMoneyCheat); +DEF_COMMAND(CmdBuildCanal); + +DEF_COMMAND(CmdPlayerCtrl); + +DEF_COMMAND(CmdLevelLand); + +DEF_COMMAND(CmdRefitRailVehicle); + +DEF_COMMAND(CmdBuildLock); + +DEF_COMMAND(CmdStartScenario); + +/* The master command table */ +static CommandProc * const _command_proc_table[] = { + CmdBuildRailroadTrack, /* 0 */ + CmdRemoveRailroadTrack, /* 1 */ + CmdBuildSingleRail, /* 2 */ + CmdRemoveSingleRail, /* 3 */ + CmdLandscapeClear, /* 4 */ + CmdBuildBridge, /* 5 */ + CmdBuildRailroadStation, /* 6 */ + CmdBuildTrainDepot, /* 7 */ + CmdBuildSignals, /* 8 */ + CmdRemoveSignals, /* 9 */ + CmdTerraformLand, /* 10 */ + CmdPurchaseLandArea, /* 11 */ + CmdSellLandArea, /* 12 */ + CmdBuildTunnel, /* 13 */ + CmdRemoveFromRailroadStation, /* 14 */ + CmdConvertRail, /* 15 */ + CmdBuildTrainCheckpoint, /* 16 */ + CmdRenameCheckpoint, /* 17 */ + CmdRemoveTrainCheckpoint, /* 18 */ + CmdBuildTruckStation, /* 19 */ + NULL, /* 20 */ + CmdBuildBusStation, /* 21 */ + NULL, /* 22 */ + CmdBuildLongRoad, /* 23 */ + CmdRemoveLongRoad, /* 24 */ + CmdBuildRoad, /* 25 */ + CmdRemoveRoad, /* 26 */ + CmdBuildRoadDepot, /* 27 */ + NULL, /* 28 */ + CmdBuildAirport, /* 29 */ + CmdBuildDock, /* 30 */ + CmdBuildShipDepot, /* 31 */ + CmdBuildBuoy, /* 32 */ + CmdPlantTree, /* 33 */ + CmdBuildRailVehicle, /* 34 */ + CmdMoveRailVehicle, /* 35 */ + CmdStartStopTrain, /* 36 */ + NULL, /* 37 */ + CmdSellRailWagon, /* 38 */ + CmdTrainGotoDepot, /* 39 */ + CmdForceTrainProceed, /* 40 */ + CmdReverseTrainDirection, /* 41 */ + + CmdModifyOrder, /* 42 */ + CmdSkipOrder, /* 43 */ + CmdDeleteOrder, /* 44 */ + CmdInsertOrder, /* 45 */ + + CmdChangeTrainServiceInt, /* 46 */ + + CmdBuildIndustry, /* 47 */ + CmdBuildCompanyHQ, /* 48 */ + CmdSetPlayerFace, /* 49 */ + CmdSetPlayerColor, /* 50 */ + + CmdIncreaseLoan, /* 51 */ + CmdDecreaseLoan, /* 52 */ + + CmdWantEnginePreview, /* 53 */ + + CmdNameVehicle, /* 54 */ + CmdRenameEngine, /* 55 */ + + CmdChangeCompanyName, /* 56 */ + CmdChangePresidentName, /* 57 */ + + CmdRenameStation, /* 58 */ + + CmdSellAircraft, /* 59 */ + CmdStartStopAircraft, /* 60 */ + CmdBuildAircraft, /* 61 */ + CmdSendAircraftToHangar, /* 62 */ + CmdChangeAircraftServiceInt, /* 63 */ + CmdRefitAircraft, /* 64 */ + + CmdPlaceSign, /* 65 */ + CmdRenameSign, /* 66 */ + + CmdBuildRoadVeh, /* 67 */ + CmdStartStopRoadVeh, /* 68 */ + CmdSellRoadVeh, /* 69 */ + CmdSendRoadVehToDepot, /* 70 */ + CmdTurnRoadVeh, /* 71 */ + CmdChangeRoadVehServiceInt, /* 72 */ + + CmdPause, /* 73 */ + + CmdBuyShareInCompany, /* 74 */ + CmdSellShareInCompany, /* 75 */ + CmdBuyCompany, /* 76 */ + + CmdBuildTown, /* 77 */ + NULL, /* 78 */ + NULL, /* 79 */ + CmdRenameTown, /* 80 */ + CmdDoTownAction, /* 81 */ + + CmdSetRoadDriveSide, /* 82 */ + CmdSetTownNameType, /* 83 */ + NULL, /* 84 */ + CmdChangeDifficultyLevel, /* 85 */ + + CmdStartStopShip, /* 86 */ + CmdSellShip, /* 87 */ + CmdBuildShip, /* 88 */ + CmdSendShipToDepot, /* 89 */ + CmdChangeShipServiceInt, /* 90 */ + CmdRefitShip, /* 91 */ + + CmdStartNewGame, /* 92 */ + CmdLoadGame, /* 93 */ + CmdCreateScenario, /* 94 */ + CmdSetSinglePlayer, /* 95 */ + NULL, /* 96 */ + CmdSetNewLandscapeType, /* 97 */ + + CmdGenRandomNewGame, /* 98 */ + + CmdCloneOrder, /* 99 */ + + CmdClearArea, /* 100 */ + CmdResume, /* 101 */ + + CmdMoneyCheat, /* 102 */ + CmdBuildCanal, /* 103 */ + CmdPlayerCtrl, /* 104 */ + + CmdLevelLand, /* 105 */ + + CmdRefitRailVehicle, /* 106 */ + CmdRestoreOrderIndex, /* 107 */ + CmdBuildLock, /* 108 */ + CmdStartScenario /* 109 */ + + //CmdDestroyIndustry, /* 109 */ +}; + +int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc) +{ + return DoCommand(GET_TILE_X(tile)*16, GET_TILE_Y(tile)*16, p1, p2, flags, procc); +} + + +//extern void _stdcall Sleep(int s); + +int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc) +{ + int32 res; + CommandProc *proc; + + proc = _command_proc_table[procc]; + + if (_docommand_recursive == 0) { + _error_message = INVALID_STRING_ID; + // update last build coord of player + if ( (x|y) != 0 && _current_player < MAX_PLAYERS) { + DEREF_PLAYER(_current_player)->last_build_coordinate = TILE_FROM_XY(x,y); + } + } + + _docommand_recursive++; + + // only execute the test call if it's toplevel, or we're not execing. + if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) { + res = proc(x, y, flags&~DC_EXEC, p1, p2); + if ((uint32)res >> 16 == 0x8000) { + 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--; + return res; + } + } + + // execute the command here. + _yearly_expenses_type = 0; + res = proc(x, y, flags, p1, p2); + if ((uint32)res >> 16 == 0x8000) { + if (res & 0xFFFF) _error_message = res & 0xFFFF; +error: + _docommand_recursive--; + return CMD_ERROR; + } + + // if toplevel, subtract the money. + if (--_docommand_recursive == 0) { + SubtractMoneyFromPlayer(res); + } + + return res; +} + +int32 GetAvailableMoneyForCommand() +{ + uint pid = _current_player; + if (pid >= 8) return 0x7FFFFFFF; // max int + return DEREF_PLAYER(pid)->player_money; +} + +// toplevel network safe docommand function for the current player. must not be called recursively. +// the callback is called when the command succeeded or failed. +bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd) +{ + int32 res = 0,res2; + CommandProc *proc; + uint32 flags; + bool notest; + + int x = GET_TILE_X(tile)*16; + int y = GET_TILE_Y(tile)*16; + + assert(_docommand_recursive == 0); + + _error_message = INVALID_STRING_ID; + _error_message_2 = cmd >> 16; + _additional_cash_required = 0; + + // spectator has no rights. + if (_current_player == 0xff) { + ShowErrorMessage(_error_message, _error_message_2, x, y); + 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]; + + // this command is a notest command? + notest = + (cmd & 0xFF) == CMD_CLEAR_AREA || + (cmd & 0xFF) == CMD_CONVERT_RAIL || + (cmd & 0xFF) == CMD_LEVEL_LAND || + (cmd & 0xFF) == CMD_TRAIN_GOTO_DEPOT; + + if (_networking && (cmd & CMD_ASYNC)) notest = true; + + _docommand_recursive = 1; + + // cost estimation only? + if (_shift_pressed && _current_player == _local_player && !(cmd & CMD_DONT_NETWORK)) { + // estimate the cost. + res = proc(x, y, flags, p1, p2); + if ((uint32)res >> 16 == 0x8000) { + if (res & 0xFFFF) _error_message = res & 0xFFFF; + ShowErrorMessage(_error_message, _error_message_2, x, y); + } else { + ShowEstimatedCostOrIncome(res, x, y); + } + + _docommand_recursive = 0; + return false; + } + + + + // unless the command is a notest command, check if it can be executed. + if (!notest) { + // first test if the command can be executed. + res = proc(x,y, flags, p1, p2); + if ((uint32)res >> 16 == 0x8000) { + if (res & 0xFFFF) _error_message = res & 0xFFFF; + goto show_error; + } + // no money? + if (res != 0 && !CheckPlayerHasMoney(res)) goto show_error; + } + + // put the command in a network queue and execute it later? + if (_networking && !(cmd & CMD_DONT_NETWORK)) { + NetworkSendCommand(tile, p1, p2, cmd, callback); + _docommand_recursive = 0; + return true; + } + + // update last build coordinate of player. + if ( tile != 0 && _current_player < MAX_PLAYERS) DEREF_PLAYER(_current_player)->last_build_coordinate = tile; + + // actually try and execute the command. + _yearly_expenses_type = 0; + res2 = proc(x,y, flags|DC_EXEC, p1, p2); + + if (!notest) { + assert(res == res2); // sanity check + } else { + if ((uint32)res2 >> 16 == 0x8000) { + if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF; + goto show_error; + } + } + + SubtractMoneyFromPlayer(res2); + + if (_current_player == _local_player && _game_mode != GM_EDITOR) { + if (res2 != 0) + ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2); + if (_additional_cash_required) { + SET_DPARAM32(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); + return true; + +show_error: + // show error message if the command fails? + if (_current_player == _local_player && _error_message_2 != 0) + ShowErrorMessage(_error_message, _error_message_2, x,y); + +callb_err: + _docommand_recursive = 0; + + if (callback) callback(false, tile, p1, p2); + return false; +} diff --git a/command.h b/command.h new file mode 100644 --- /dev/null +++ b/command.h @@ -0,0 +1,180 @@ +#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_CHECKPOINT = 16, + CMD_RENAME_CHECKPOINT = 17, + CMD_REMOVE_TRAIN_CHECKPOINT = 18, + + CMD_BUILD_TRUCK_STATION = 19, + CMD_BUILD_BUS_STATION = 21, + CMD_BUILD_LONG_ROAD = 23, + CMD_REMOVE_LONG_ROAD = 24, + CMD_BUILD_ROAD = 25, + CMD_REMOVE_ROAD = 26, + CMD_BUILD_ROAD_DEPOT = 27, + + CMD_BUILD_AIRPORT = 29, + + CMD_BUILD_DOCK = 30, + + CMD_BUILD_SHIP_DEPOT = 31, + CMD_BUILD_BUOY = 32, + + CMD_PLANT_TREE = 33, + + CMD_BUILD_RAIL_VEHICLE = 34, + CMD_MOVE_RAIL_VEHICLE = 35, + + CMD_START_STOP_TRAIN = 36, + + CMD_SELL_RAIL_WAGON = 38, + + CMD_TRAIN_GOTO_DEPOT = 39, + CMD_FORCE_TRAIN_PROCEED = 40, + CMD_REVERSE_TRAIN_DIRECTION = 41, + + CMD_MODIFY_ORDER = 42, + CMD_SKIP_ORDER = 43, + CMD_DELETE_ORDER = 44, + CMD_INSERT_ORDER = 45, + + CMD_CHANGE_TRAIN_SERVICE_INT = 46, + + CMD_BUILD_INDUSTRY = 47, + + CMD_BUILD_COMPANY_HQ = 48, + CMD_SET_PLAYER_FACE = 49, + CMD_SET_PLAYER_COLOR = 50, + + CMD_INCREASE_LOAN = 51, + CMD_DECREASE_LOAN = 52, + + CMD_WANT_ENGINE_PREVIEW = 53, + + CMD_NAME_VEHICLE = 54, + CMD_RENAME_ENGINE = 55, + CMD_CHANGE_COMPANY_NAME = 56, + CMD_CHANGE_PRESIDENT_NAME = 57, + CMD_RENAME_STATION = 58, + + CMD_SELL_AIRCRAFT = 59, + CMD_START_STOP_AIRCRAFT = 60, + CMD_BUILD_AIRCRAFT = 61, + CMD_SEND_AIRCRAFT_TO_HANGAR = 62, + CMD_CHANGE_AIRCRAFT_SERVICE_INT = 63, + CMD_REFIT_AIRCRAFT = 64, + + CMD_PLACE_SIGN = 65, + CMD_RENAME_SIGN = 66, + + CMD_BUILD_ROAD_VEH = 67, + CMD_START_STOP_ROADVEH = 68, + CMD_SELL_ROAD_VEH = 69, + CMD_SEND_ROADVEH_TO_DEPOT = 70, + CMD_TURN_ROADVEH = 71, + CMD_CHANGE_ROADVEH_SERVICE_INT = 72, + + CMD_PAUSE = 73, + + CMD_BUY_SHARE_IN_COMPANY = 74, + CMD_SELL_SHARE_IN_COMPANY = 75, + CMD_BUY_COMPANY = 76, + + CMD_BUILD_TOWN = 77, + + CMD_RENAME_TOWN = 80, + CMD_DO_TOWN_ACTION = 81, + + CMD_SET_ROAD_DRIVE_SIDE = 82, + CMD_SET_TOWN_NAME_TYPE = 83, + + + CMD_CHANGE_DIFFICULTY_LEVEL = 85, + + CMD_START_STOP_SHIP = 86, + CMD_SELL_SHIP = 87, + CMD_BUILD_SHIP = 88, + CMD_SEND_SHIP_TO_DEPOT = 89, + CMD_CHANGE_SHIP_SERVICE_INT = 90, + CMD_REFIT_SHIP = 91, + + CMD_START_NEW_GAME = 92, + CMD_LOAD_GAME = 93, + CMD_CREATE_SCENARIO = 94, + CMD_SET_SINGLE_PLAYER = 95, + + CMD_SET_NEW_LANDSCAPE_TYPE = 97, + + CMD_GEN_RANDOM_NEW_GAME = 98, + + CMD_CLONE_ORDER = 99, + CMD_CLEAR_AREA = 100, + + CMD_RESUME = 101, + + 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_START_SCENARIO = 109, + + //CMD_DESTROY_INDUSTRY = 109, +}; + +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_DONT_NETWORK = 0x800, // execute the command without sending it on the network + CMD_ASYNC = 0x1000, // execute the command asynchronously without testing first in networking +}; + +//#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) + +/* 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); + +int32 GetAvailableMoneyForCommand(); + +#endif /* COMMAND_H */ diff --git a/configure b/configure new file mode 100644 --- /dev/null +++ b/configure @@ -0,0 +1,24 @@ +#!/bin/sh - + +SDLCONFIG=`which sdl-config || which sdl11-config || which sdl12-config || echo ` +if [ -n "$SDLCONFIG" ] ; then + echo "SDL config is located at: $SDLCONFIG" + sed -e"s@XX_SDL_CONFIG_PLACEHOLDER_XX@$SDLCONFIG@g" < Jamfile.next > tmp && mv tmp Jamfile +else + echo "********************************" + echo "ERROR! SDL CONFIG WAS NOT FOUND!" + echo "********************************" + exit 1 +fi + +echo "Configure complete. Now use 'jam' to build" +echo "Add -sWITH_PNG= to build with PNG support" +echo "Add -sWITH_ZLIB=1 to enable zlib savegame support" +echo "Add -sRELEASE=1 to build an optimized executable" +echo "Add -sWITH_BONE_NETWORKING=1 to build with BeOS BONE networking support" +echo "Add -sBEOS_MIDI=1 to enable BeOS native MIDI (libmidi.so) music output" +echo "" +echo "For people using make:" +echo "write make (or gmake)" +echo "configure have nothing to do with the makefile" + diff --git a/data/canalsw.grf b/data/canalsw.grf new file mode 100644 index 0000000000000000000000000000000000000000..045eae15e8b7c42ae5cf5f9bccf165e298f64814 GIT binary patch literal 41639 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 z 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 z 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 K(*F-ovaW8bBOrzV diff --git a/data/signalsw.grf b/data/signalsw.grf new file mode 100644 index 0000000000000000000000000000000000000000..ca78876d09756ac8fb2dc87f631df0e59a1b6044 GIT binary patch literal 22939 zc%1E9U2GiJb)K31pP8lT^@>`P^3IOEw#GE&&{~_aVvJ z;-93ETcl`RCz%Fq!?bC@1`a@E2yly_z{2puUN$ACW;qU-ijc{5PU#a<_)i(T;n-4xw|X=ZqY(3V^m zX}b`U;dh01yiHWjZB}LtgLOn(b}QE$HBYG*@G`fHZaU{vy)NV1cf+``UOWH^P2?jpO)&|`cVUc$;k?(*IL6|2)7ucL7+YfKmO>@h?)c0|kX>3WSteQu9o}b<9-$e6iE%^jKN6 zc!Rb1IGZf`+oHE=`~2DzEmlsh(s)hT2Es*)FhvpK(5MBWN?{sBp8;L*N!n2*(CNT@ zL$qWUt#7h%6>rL8;fs-%WooN-wh=| zmbz?egPep7)9le|p5mTMPRMcDE@;}tEkE^?CQHUDla<0#>>XJzrcXTu8Z^=rPTBk- z#_zpy<7uGWmL)x1vV&H?EAN!st;xr&)c46?$LqN$fDC4p(HQAO&+Mha9V?C~vl+w6 z$56m&uo}R%Jw)&lJ)fNVjJO@;*LPdV>^-2s7~mMzvOWMKPtAx+g_ zs1adZm5|(VHDFh&C^_F*V2C>My=050c{`ahyi82*T1Z4$+)>n0Se@Fi`UFajrsa#7 zeSgMR)HQvnHe+CXL))2#?AYS&M8r|#-gAK2Q{?XKjfm_R=PE_S@qI_rNPDl3h+Gcu zT8qdf@b*+hc7wS)5pjs#9fIlYp@{4ZWmh8ND30%)&+&8v@lr|K{T;~e5OyUaj$-!S z`ONO@iHz(HY)3NUIN*q0?;6VptWIrMy=ob`M5A4Wj9kv*Kf?SUCI11~rhJhE^S(Ns^{gJXZL>4z%X zf3Ll_RtZD8`PY(4Ot;--2BHeDz=~%jKf6!P}lM>{d6;rMT#|ovaJ~ShP zg80k68RBb2mc_7W!l;*_g^HqjpQg9y#qX{)Lv2M1wa^W{(DY4zl`a&;xGIK=8?T;1 z6b%(c8!uhiFi)=HGe#u^HfsF=T^nN@fCgUMC%?`)2kb-A|CxdwrsH5q<|LS+HsYB9L;|`oEI2>P*2%Oy(g=%m{bV>)mIhY#8XxU zKwMoI&NFfW?Gb>7q-5rj9o+@3YANDlT}6CsQW0M~EtMMyIcbHdA)6DGjh`!2c>S3@VN;?f6Eh-)@QI~-9MAZmgS;hT{T?F&^ zFt`fC(x#UO!?JU6L#L3N}BR3%j^$S^9<-A`<@E7YArDUC%m+Ja*a3uI>@I>&5;B@eXrPnY|rm_&P z6zM(WI9jYP9-)~c>;Gu69zYz{#gy2(zQNYYpd{*-!$`6u{uiTqC|zbM%1%t8Y$%_% zp?t~797uevq~5KTe>5w%aIkiieM&^-^9QjnTD0cHoXT8LaT$cT-_Rs=vg$;KS6VLAD8D0 zvsDA)>V^Wys=NuXj1Vy^93`NtzRHGmEoo7i^*c1zR{+Cn1cTq!<0@_ltz=lwAiwt! zOkCBq{9Kwww`&*GTu^`Hg8GxXm`LjEI3JB?Xb?RSJTHH{NC8Z~T(r#0N*0QBGponM z#<5kf@ZBvSknwT)9Fw?tFp_6$8=4w>xmiNiz|2*c7AA*dvdOAQ+#RABPv@l<9aC`Z zRRza>Pr)T7k-tfBNt@u3V+0q!H87**b%x9D4>U|_6)hillS%==yiV%VL_qmyQlTG5 z@*fY-y};sOg(E+uaO7tdj;H`fR0u~LBph)o;qb2~6*hGK{I;$Rfbx(w8sOq_eK{FX z;=o-c4tzq1Lvma+Xkyx^!_1;OwCa(n!~RHrLeB;dMVnQ4KGaUie)Yn#zZ~3^s{*46 zm&H;BI)JEDraL1<6Tt2-2k!SEH>ydtgOhf75BnJgOh4xv_Yb-m+d8L(4H z!;vWNNI0(4;`vIxt|EnVgM)caLol^1lWfztu=FerKd=nTit3<@`i7)0JxR$~vUM%L zH6;14H|2xW!z`1d5D&T|lP!ox8~2MO9;`;pHj2Na+9;w4G_t9UqAs;jG)-+p^Ju@7 zpNGKgbIJkXsFqw8zaDc9dX} z`KT5*uCa1BN;!H?J_(pOP&o(=R8DXk zRPOAda$G6g)hY+!Ksg9!LphwiRt|^i(CJ004)CJ=PH%svKFseIUI+Squ1L*0rM_F5|d|B5Y(CEQebiKI0+PS~lxxd=EzuLLK+PS~lxxd=EzuLLK+PS~l zxxd=EzuLLK+PS~lxxd=EzuLLK+PS~l`Tu0KlisH+d7JOdXS5U;hLNfFW7}{uZp$$= z1<0XQSm}qdW-R-%TV4q>B8`1nv32##Hq!zf2rxC741LQBnn<3z&x)a>s5Y0 zclikUC>;Rt17#QW?fZPFUnlPBTCjN7!X?VUQ2X2;*uF0A(lWD{E`zPge@&Yn{TR=JagFGj3l1J!g zTO%ZEu>~#WTf)OyhKcBi$)fW7{*nTW2`d3koMZ5_S`;_F#F;?a)MJ3&o^EAPudk1t)}78edq%ClRPY2@vLYGoPoa>Pl_+0%O1wb7T7}2S7*al zyneEut-X7$(+t;4Oth+*+$c<9vNoJdJR}^DE=rKA$qZ$Q{53#0zSemA^`Sb zX@MP%B_oj=PsqpPnRt$U5s$u1p&yZdMhmPnM%s&J-~;AGTA}s)9>c9_WDz~Oi)Vt@ z{~euPQz~(>-0N;~Sl6Q4k@MnqeDkUq3+BJNf0un*@dqrw<>lH4gLHcGNTQUs5t$x5 z*a;{Uuc-oUKr-hzG2)=XCuEnsM&2Z~sG+=J^M>h&TJ8+5VJsO_&hWpY{qm{g7xavc zMUCHrew9>oN*aBZ%u7T$poPp$FcSG5Mq!d!-i+FESl)-pku*O|2Vj_+ye%KhtxjxOo!V}7+m5ccxuXmEs>h>9uPhdnOcqHdf|N4;Mfn6DU3`L{k@pOKgQROTc#SWuFC!nzmyy3m%gDj$;N9TezbXF&C!&?z zcel+~D5u1ta>5LQlhk-yRXG2E?!`4RM$*Y@B%K(1A)Pc|k#yqRG+-w$7tW2FeJ@An zx0lpsE(3F+9ZV;wJR6+M4}O7=Dt?hPI}S!0TcuRXwX|MvJBfbhTeGG?xL;giMP2DU_X%*Y|dht}zMWg5Y%Wjm%;f*{B+e9`W_(5V; zd{B@oKu3_q3D#U!*_aM19+yojdE(^AgV;>VDRxqxWz*t!)jZqx*75nW!sp`(Ki_M1 z8A1{B#k2W-&QI31j7gFT03;TM1558mb&}t@xH*^KQFR|RQ}7|bM~sz_xW&g^)Q9Dq zu*9!Y6raZh(V5FFI4`|D_~9PkU%>?wl$D{N-~w(6>jN`x>sHj%v)CIvBHl{=fhXdh z_vWUH-W>70l>JH3ax;s4r&#wrS{$a76)X@-yO84Xu|96fI4G#9tO~e=;bfBDml8eppsw*r`9(fC7%q|n;t!Pr;!l+W zyh<8dB?owm9N=Dbvj6PGHo`o$5vE3$1M0@@+?|^=mD*ZzM3R%xI{5&Y?M~fSinlZ; zW|Ggz8O$4j@*(-U@*(-Q@*!3NNxR`LZTR8w@!;+L5BKcO?#eTfyv33|zVFM660xx8 zLs|d=oGXSq0Px2?aH>DuMu7z6~c}w?hvPKxyN9mD2Ku zp|rSVq}UA0iasY=)Xl@-=?;H|TtL03)y~YK)lRF<)E@=J!*K_ieK)&LKFdz(9{)96 z+quTdQPM;RV}@^?y1?l~Q?JXmJRsY8hJdAmr+1~dS7dp&+FQcy6Rd+)0a31Zpp|uw zBBLGab>jkhDV{cbZI?p46=LFjAWi{dZ*E-&XD_wcz2~>F38wywZ+we+_JcjXtrg!? z6coRqxw@fDcR{{fCa#|#J5-cTFIGkQeTfNsu^>Ann?1;853<=?mrdtd z2=e<`zG^{sNRVlrRO>0Vq`TML_%#z`hXnc35PL7k7cR_SH$lE|k^Z_0GIc)$nYw>N Yke%x+$m9Y9nOxWqWM{h|t9IA^7w8CYIsgCw diff --git a/disaster_cmd.c b/disaster_cmd.c new file mode 100644 --- /dev/null +++ b/disaster_cmd.c @@ -0,0 +1,980 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "command.h" +#include "news.h" +#include "gfx.h" +#include "station.h" +#include "town.h" +#include "industry.h" +#include "player.h" +#include "airport_movement.h" + +static void DisasterClearSquare(uint tile) +{ + int type; + + if (!EnsureNoVehicle(tile)) + return; + + type = _map_type_and_height[tile] >> 4; + + if (type == MP_RAILWAY) { + if (IS_HUMAN_PLAYER(_map_owner[tile])) + DoClearSquare(tile); + } else if (type == MP_HOUSE) { + byte p = _current_player; + _current_player = OWNER_NONE; + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + _current_player = p; + } else if (type == MP_TREES || type == MP_CLEAR) { + DoClearSquare(tile); + } +} + +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 = TILE_FROM_XY(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->next_order = 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 = TILE_FROM_XY(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; + uint tile; + + ++v->tick_counter; + + if (v->next_order < 2) { + if (v->tick_counter&1) + return; + + GetNewVehiclePos(v, &gp); + + SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); + + if (v->next_order == 1) { + if (++v->age == 38) { + v->next_order = 2; + v->age = 0; + } + + if ((v->tick_counter&7)==0) { + CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE_3); + } + } else if (v->next_order == 0) { + tile = v->tile; /**/ + + if (IS_TILETYPE(tile, MP_STATION) && + IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && + IS_HUMAN_PLAYER(_map_owner[tile])) { + + v->next_order = 1; + v->age = 0; + + SET_DPARAM16(0, _map2[tile]); + AddNewsItem(STR_B000_ZEPPELIN_DISASTER_AT, + NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), + v->index, + 0); + } + } + if (v->y_pos >= (TILES_Y+9) * 16 - 1) + DeleteDisasterVeh(v); + return; + } + + if (v->next_order > 2) { + if (++v->age <= 13320) + return; + + tile = v->tile; /**/ + + if (IS_TILETYPE(tile, MP_STATION) && + IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && + IS_HUMAN_PLAYER(_map_owner[tile])) { + + st = DEREF_STATION(_map2[tile]); + 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_CRASHED_SMOKE); + SndPlayVehicleFx(0x10, v); + v->u.disaster.image_override = 0xF42; + } else if (v->age == 70) { + v->u.disaster.image_override = 0xF43; + } else if (v->age <= 300) { + if (!(v->tick_counter&7)) { + uint32 r = Random(); + + CreateEffectVehicleRel(v, + -7 + (r&0xF), + -7 + (r>>4&0xF), + 5 + (r>>8&0x7), + EV_DEMOLISH); + } + } else if (v->age == 350) { + v->next_order = 3; + v->age = 0; + } + + tile = v->tile;/**/ + if (IS_TILETYPE(tile, MP_STATION) && + IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && + IS_HUMAN_PLAYER(_map_owner[tile])) { + + st = DEREF_STATION(_map2[tile]); + 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) ? 0xF45 : 0xF44; + + if (v->next_order == 0) { +// fly around randomly + int x = GET_TILE_X(v->dest_tile)*16; + int y = GET_TILE_Y(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 = TILE_MASK(Random()); + return; + } + v->next_order = 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 = &_vehicles[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_CRASHED_SMOKE); + SndPlayVehicleFx(0x10, v); + DeleteDisasterVeh(v); + } + } +} + +static void DestructIndustry(Industry *i) +{ + uint tile; + byte index = i - _industries; + + for(tile=0; tile != TILES_X*TILES_Y; tile++) { + if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == index) { + _map_owner[tile] = 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->next_order == 1 && v->tick_counter&4) ? 0xF4F : 0; + + GetNewVehiclePos(v, &gp); + SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); + + if (gp.x < -160) { + DeleteDisasterVeh(v); + return; + } + + if (v->next_order == 2) { + if (!(v->tick_counter&3)) { + Industry *i = DEREF_INDUSTRY(v->dest_tile); + int x = GET_TILE_X(i->xy)*16; + int y = GET_TILE_Y(i->xy)*16; + uint32 r = Random(); + + CreateEffectVehicleAbove( + x + (r & 0x3F), + y + (r >> 6 & 0x3F), + (r >> 12 & 0xF), + EV_DEMOLISH); + + if (++v->age >= 55) + v->next_order = 3; + } + } else if (v->next_order == 1) { + if (++v->age == 112) { + Industry *i; + + v->next_order = 2; + v->age = 0; + + i = DEREF_INDUSTRY(v->dest_tile); + DestructIndustry(i); + + SET_DPARAM16(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(0x10, i->xy); + } + } else if (v->next_order == 0) { + int x,y; + uint tile; + int ind; + + x = v->x_pos - 15*16; + y = v->y_pos; + + if ( (uint)x > (TILES_X-1) * 16-1) + return; + + tile = TILE_FROM_XY(x,y); + if (!IS_TILETYPE(tile, MP_INDUSTRY)) + return; + + v->dest_tile = ind = _map2[tile]; + + if (DEREF_INDUSTRY(ind)->type == IT_OIL_REFINERY) { + v->next_order = 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->next_order == 1 && v->tick_counter&4) ? 0xF53 : 0; + + GetNewVehiclePos(v, &gp); + SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos); + + if (gp.x > TILES_X * 16 + 9*16 - 1) { + DeleteDisasterVeh(v); + return; + } + + if (v->next_order == 2) { + if (!(v->tick_counter&3)) { + Industry *i = DEREF_INDUSTRY(v->dest_tile); + int x = GET_TILE_X(i->xy)*16; + int y = GET_TILE_Y(i->xy)*16; + uint32 r = Random(); + + CreateEffectVehicleAbove( + x + (r & 0x3F), + y + (r >> 6 & 0x3F), + (r >> 12 & 0xF), + EV_DEMOLISH); + + if (++v->age >= 55) + v->next_order = 3; + } + } else if (v->next_order == 1) { + if (++v->age == 112) { + Industry *i; + + v->next_order = 2; + v->age = 0; + + i = DEREF_INDUSTRY(v->dest_tile); + DestructIndustry(i); + + SET_DPARAM16(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(0x10, i->xy); + } + } else if (v->next_order == 0) { + int x,y; + uint tile; + int ind; + + x = v->x_pos - 15*16; + y = v->y_pos; + + if ( (uint)x > (TILES_X-1) * 16-1) + return; + + tile = TILE_FROM_XY(x,y); + if (!IS_TILETYPE(tile, MP_INDUSTRY)) + return; + + v->dest_tile = ind = _map2[tile]; + + if (DEREF_INDUSTRY(ind)->type == IT_FACTORY) { + v->next_order = 1; + v->age = 0; + } + } +} + +// Helicopter rotor blades +static void DisasterTick_3b(Vehicle *v) +{ + if (++v->tick_counter & 1) + return; + + if (++v->cur_image == 0xF40 + 1) + v->cur_image = 0xF3E; + + 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; + uint tile,tile_org; + + v->tick_counter++; + + if (v->next_order == 1) { + int x = GET_TILE_X(v->dest_tile)*16 + 8; + int y = GET_TILE_Y(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->next_order = 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); + SET_DPARAM16(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->next_order < 1) { + + int x = GET_TILE_X(v->dest_tile)*16; + int y = GET_TILE_Y(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 = TILE_MASK(Random()); + return; + } + v->next_order = 1; + + tile_org = tile = TILE_MASK(Random()); + do { + if (IS_TILETYPE(tile, MP_RAILWAY) && + (_map5[tile]&~3)!=0xC0 && IS_HUMAN_PLAYER(_map_owner[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 > TILES_X * 16 + 9*16 - 1) { + DeleteDisasterVeh(v); + return; + } + + if (v->next_order == 0) { + u = &_vehicles[v->u.disaster.unk2]; + if (abs(v->x_pos - u->x_pos) > 16) + return; + v->next_order = 1; + + CreateEffectVehicleRel(u, 0, 7, 8, EV_CRASHED_SMOKE); + SndPlayVehicleFx(0x10, u); + + DeleteDisasterVeh(u); + + for(i=0; i!=80; i++) { + uint32 r = Random(); + CreateEffectVehicleAbove( + v->x_pos-32+(r&0x3F), + v->y_pos-32+(r>>5&0x3F), + 0, + EV_DEMOLISH); + } + + BEGIN_TILE_LOOP(tile,6,6,v->tile - TILE_XY(3,3)) + tile = TILE_MASK(tile); + DisasterClearSquare(tile); + END_TILE_LOOP(tile,6,6,v->tile - TILE_XY(3,3)) + } +} + +// Submarine handler +static void DisasterTick_5_and_6(Vehicle *v) +{ + uint32 r; + GetNewVehiclePosResult gp; + uint 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 + _tileoffs_by_dir[v->direction >> 1]; + if (IsValidTile(tile) && + (r=GetTileTrackStatus(tile,4),(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 + ((Random()&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 HandleClickOnDisasterVeh(Vehicle *v) +{ + // not used +} + +void OnNewDay_DisasterVehicle(Vehicle *v) +{ + // not used +} + +typedef void DisasterInitProc(); + +// Zeppeliner which crashes on a small airport +static void Disaster0_Init() +{ + Vehicle *v = ForceAllocateSpecialVehicle(), *u; + Station *st; + int x; + + if (v == NULL) + return; + + for(st=_stations;;) { + if (st->xy && st->airport_tile != 0 && + st->airport_type <= 1 && + IS_HUMAN_PLAYER(st->owner)) { + x = (GET_TILE_X(st->xy) + 2) * 16; + break; + } + + if (++st == endof(_stations)) { + x = (GET_TILE_X(Random())) * 16 + 8; + 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() +{ + Vehicle *v = ForceAllocateSpecialVehicle(), *u; + int x; + + if (v == NULL) + return; + + x = (GET_TILE_X(Random())) * 16 + 8; + + InitializeDisasterVehicle(v, x, 0, 135, 3, 2); + v->dest_tile = TILE_XY(TILES_X/2,TILES_Y/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() +{ + Industry *i, *found; + Vehicle *v,*u; + int x,y; + + for(found=NULL,i=_industries; i != endof(_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 = (TILES_X+9) * 16 - 1; + y = GET_TILE_Y(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() +{ + Industry *i, *found; + Vehicle *v,*u,*w; + int x,y; + + for(found=NULL,i=_industries; i != endof(_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 = GET_TILE_Y(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() +{ + Vehicle *v = ForceAllocateSpecialVehicle(), *u; + int x,y; + + if (v == NULL) + return; + + x = (GET_TILE_X(Random())) * 16 + 8; + + y = (TILES_X-1)*16-1; + InitializeDisasterVehicle(v, x, y, 135, 7, 9); + v->dest_tile = TILE_XY(TILES_X/2,TILES_Y/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() +{ + Vehicle *v = ForceAllocateSpecialVehicle(); + int x,y; + byte dir; + uint32 r; + + if (v == NULL) + return; + + r = Random(); + x = (GET_TILE_X(r)) * 16 + 8; + + y = 8; + dir = 3; + if (r & 0x80000000) { y = (TILES_X-1) * 16 - 8 - 1; dir = 7; } + InitializeDisasterVehicle(v, x, y, 0, dir,13); + v->age = 0; +} + +// Submarine type 2 +static void Disaster6_Init() +{ + Vehicle *v = ForceAllocateSpecialVehicle(); + int x,y; + byte dir; + uint32 r; + + if (v == NULL) + return; + + r = Random(); + x = (GET_TILE_X(r)) * 16 + 8; + + y = 8; + dir = 3; + if (r & 0x80000000) { y = (TILES_X-1) * 16 - 8 - 1; dir = 7; } + InitializeDisasterVehicle(v, x, y, 0, dir,14); + v->age = 0; +} + +static void Disaster7_Init() +{ + Industry *i; + int maxloop = 15; + int index = Random() & 0xF; + + do { + for(i=_industries; i != endof(_industries); i++) { + if (i->xy != 0 && i->type == IT_COAL_MINE && --index < 0) { + + SET_DPARAM16(0, i->town->index); + AddNewsItem(STR_B005_COAL_MINE_SUBSIDENCE_LEAVES, + NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ACCIDENT,0), i->xy + TILE_XY(1,1), 0); + + { + uint tile = i->xy; + int step = _tileoffs_by_dir[Random() & 3]; + int count = 30; + do { + DisasterClearSquare(tile); + tile = TILE_MASK(tile + step); + } while (--count); + } + return; + } + } + } while (--maxloop != 0); +} + +static DisasterInitProc * const _disaster_initprocs[] = { + Disaster0_Init, + Disaster1_Init, + Disaster2_Init, + Disaster3_Init, + Disaster4_Init, + Disaster5_Init, + Disaster6_Init, + Disaster7_Init, +}; + +typedef struct { + byte min,max; +} DisasterYears; + +#define MK(a,b) {a-20,b-20} +static const DisasterYears _dis_years[8] = { + MK(30,55), + MK(40,70), + MK(60,90), + MK(70,100), + MK(100,200), + MK(40,65), + MK(75,110), + MK(50,85), +}; + + +void DoDisaster() +{ + byte buf[8]; + byte year = _cur_year; + int i,j; + + for(i=j=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[(uint16)Random() * j >> 16]](); +} + + +static void ResetDisasterDelay() +{ + _disaster_delay = (int)(Random() & 0x1FF) + 730; +} + +void DisasterDailyLoop() +{ + if (--_disaster_delay != 0) + return; + + ResetDisasterDelay(); + + if (_opt.diff.disasters != 0) + DoDisaster(); +} + +void StartupDisasters() { + ResetDisasterDelay(); +} + diff --git a/dock_gui.c b/dock_gui.c new file mode 100644 --- /dev/null +++ b/dock_gui.c @@ -0,0 +1,323 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" + +static void ShowBuildDockStationPicker(); +static void ShowBuildDocksDepotPicker(); + +static byte _ship_depot_direction; + +static void CcBuildDocks(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0, tile); + ResetObjectToPlace(); + } +} + +static void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { SndPlayTileFx(0, tile); } +} + + +static void PlaceDocks_Dock(uint tile) +{ + DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE)); +} + +static void PlaceDocks_Depot(uint tile) +{ + DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_AUTO | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT)); +} + +static void PlaceDocks_Buoy(uint tile) +{ + DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE)); +} + +static void PlaceDocks_DemolishArea(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_AND_Y); +} + +static void PlaceDocks_BuildCanal(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_OR_Y); +} + +static void PlaceDocks_BuildLock(uint tile) +{ + DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS)); +} + + +static void BuildDocksClick_Dock(Window *w) +{ + + if (HandlePlacePushButton(w, 2, 0xE54, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker(); +} + +static void BuildDocksClick_Depot(Window *w) +{ + if (HandlePlacePushButton(w, 3, 0x2D1, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker(); +} + +static void BuildDocksClick_Buoy(Window *w) +{ + HandlePlacePushButton(w, 4, 0x2BE, 1, PlaceDocks_Buoy); +} + +static void BuildDocksClick_Demolish(Window *w) +{ + HandlePlacePushButton(w, 5, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea); +} + +static void BuildDocksClick_Lower(Window *w) +{ + HandlePlacePushButton(w, 6, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand); +} + +static void BuildDocksClick_Raise(Window *w) +{ + HandlePlacePushButton(w, 7, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand); +} + +static void BuildDocksClick_Purchase(Window *w) +{ + HandlePlacePushButton(w, 8, 0x12B8, 1, PlaceProc_BuyLand); +} + +static void BuildDocksClick_Canal(Window *w) +{ + HandlePlacePushButton(w, 9, SPR_OPENTTD_BASE + 11, 1, PlaceDocks_BuildCanal); +} + +static void BuildDocksClick_Lock(Window *w) +{ + HandlePlacePushButton(w, 10, SPR_OPENTTD_BASE + 64, 1, PlaceDocks_BuildLock); +} + +typedef void OnButtonClick(Window *w); +static OnButtonClick * const _build_docks_button_proc[] = { + BuildDocksClick_Dock, + BuildDocksClick_Depot, + BuildDocksClick_Buoy, + BuildDocksClick_Demolish, + BuildDocksClick_Lower, + BuildDocksClick_Raise, + BuildDocksClick_Purchase, + BuildDocksClick_Canal, + BuildDocksClick_Lock, +}; + +static void BuildDocksToolbWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + break; + + case WE_CLICK: { + if (e->click.widget - 2 >= 0) _build_docks_button_proc[e->click.widget - 2](w); + } 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 == VPM_X_AND_Y) + DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + 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: + w->click_state = 0; + SetWindowDirty(w); + + w = FindWindowById(WC_BUILD_STATION, 0); + if (w != NULL) WP(w,def_d).close=true; + + w = FindWindowById(WC_BUILD_DEPOT, 0); + if (w != NULL) WP(w,def_d).close=true; + break; + + case WE_PLACE_PRESIZE: { + uint tile_from, tile_to; + + tile_from = tile_to = e->place.tile; + switch(GetTileSlope(tile_from, NULL)) { + case 3: tile_to += TILE_XY(-1,0); break; + case 6: tile_to += TILE_XY(0,-1); break; + case 9: tile_to += TILE_XY(0,1); break; + case 12:tile_to += TILE_XY(1,0); break; + } + VpSetPresizeRange(tile_from, tile_to); + } break; + } +} + +static const Widget _build_docks_toolb_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 197, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 21, 14, 35, 746, STR_981D_BUILD_SHIP_DOCK}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 748, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 693, STR_9834_POSITION_BUOY_WHICH_CAN}, +{ WWT_PANEL, 7, 66, 87, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 88, 109, 14, 35, 695, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 110, 131, 14, 35, 694, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 132, 153, 14, 35, 4791, STR_0329_PURCHASE_LAND_FOR_FUTURE}, +{ WWT_PANEL, 7, 154, 175, 14, 35, SPR_OPENTTD_BASE+65, STR_BUILD_CANALS_TIP}, +{ WWT_PANEL, 7, 176, 197, 14, 35, SPR_CANALS_BASE+69, STR_BUILD_LOCKS_TIP}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_docks_toolbar_desc = { + 640-197, 22, 198, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_docks_toolb_widgets, + BuildDocksToolbWndProc +}; + +void ShowBuildDocksToolbar() +{ + DeleteWindowById(WC_BUILD_TOOLBAR, 0); + AllocateWindowDesc(&_build_docks_toolbar_desc); +} + +static void BuildDockStationWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + if (WP(w,def_d).close) + return; + DrawWindowWidgets(w); + DrawStationCoverageAreaText(2, 15, (uint)-1); + } break; + + case WE_CLICK: { + if (e->click.widget == 0) { + ResetObjectToPlace(); + } + } break; + + case WE_MOUSELOOP: { + if (WP(w,def_d).close) { + DeleteWindow(w); + return; + } + + CheckRedrawStationCoverage(w); + break; + } + } +} + +static const Widget _build_dock_station_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 147, 14, 45, 0x0, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_dock_station_desc = { + -1, -1, 148, 46, + WC_BUILD_STATION,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_dock_station_widgets, + BuildDockStationWndProc +}; + +static void ShowBuildDockStationPicker() +{ + AllocateWindowDesc(&_build_dock_station_desc); +} + +static void UpdateDocksDirection() +{ + 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 0: + ResetObjectToPlace(); + break; + case 3: + case 4: + _ship_depot_direction = e->click.widget - 3; + SndPlayFx(0x13); + UpdateDocksDirection(); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: + if (WP(w,def_d).close) + DeleteWindow(w); + break; + } +} + +static const Widget _build_docks_depot_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 203, 14, 85, 0x0, 0}, +{ WWT_PANEL, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, +{ WWT_PANEL, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, +{ WWT_LAST}, +}; + +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() +{ + AllocateWindowDesc(&_build_docks_depot_desc); + UpdateDocksDirection(); +} + + +void InitializeDockGui() +{ + _ship_depot_direction = 0; +} diff --git a/docs/Howto_compile_lng_files_from_CLI.txt b/docs/Howto_compile_lng_files_from_CLI.txt new file mode 100644 --- /dev/null +++ b/docs/Howto_compile_lng_files_from_CLI.txt @@ -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 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 + diff --git a/docs/Manual.txt b/docs/Manual.txt new file mode 100644 --- /dev/null +++ b/docs/Manual.txt @@ -0,0 +1,101 @@ +Welcome to the manual for OpenTTD. The latest release version at the time of writing is 0.3.2. + +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. + +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. + +Once you have obtained a recent copy of the source, you must build it. Windows build instructions will be provided later. + +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: +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 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". + +If you want MIDI music, copy the 'gm' folder from the original game directory/CD to the OpenTTD folder. + +1.3 Running OpenTTD. + +On Windows, you can use a third-party launcher such as OTTD-Launcher to run OpenTTD directly from Explorer. Otherwise, navigate via the command prompt to the correct location and launch ttd.exe. + +On Linux, navigate at the shell to the correct location and run ttd. + +On BeOS and Mac OS-X, just double click the ttd binary in the Tracker/Finder. You can also start from the shell. + +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. + +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. + +Game Settings lets you set regional settings - currency, language, town names, etc. It also lets you select the resolution to run the game at, as well as the screenshot format to use. + +Configure Patches lets you select which patches to use in the game. This allows you ro set the game play to either original Transport Tycoon Deluxe compatible mode or a mode more like playing under TTD-Patch. Patches include building on slopes, longer bridges, longer trains, pre-signals, and TTD-Patch compatible handling of non-stop orders. + +2.1 Gameplay + +This section of the manual is written with the assumption that you already know the gameplay basics of Transport Tycoon Deluxe, on either DOS or Windows. As you must have the Windows Transport Tycoon Deluxe CD to play OpenTTD, you should either have a paper manual or the complete manual in PDF format on the disk. This section will only cover the gameplay differences from Transport Tycoon Deluxe. + +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. + +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. + +2.4 Freeform Rail Laying. + +Along side the other rail laying buttons, you will see a button that looks somewhat like a crossing. This is the freeform rail laying tool., and it allows you to drag rail in any direction to lay it. This has a number of advantages, one of the main ones being that it can seriously speed up the laying of diagonal tracks. + +2.5 Vehicle Queuing (with Quantum Effects) + +This useful addition to OpenTTD means that road vehicles will queue outside a road station to wait for a space rather than attempt to enter it immediately. As anyone who has operated a large road network with busy stations will know, road vehicles quickly pile up inside stations. This will prevent that. The Quantum Effects are down to a bug in the game that means that mutliple vehicles will often only take up one space in the queue. However, this is almost too useful to fix, and should still be there in later versions. This can be enabled/disabled. + +2.6 Building On Slopes + +This allows you to build roads, rails, stations and depots on slopes. It also allows the construction of trasmitters and lighthouses on slopes in the scenario editor. There are some minor differences between OpenTTD's and TTD-Patch's handling of building on slopes, the main one being that bridges must still have solid land at their endings. + +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. + +2.8 Long trains + +OpenTTD allows trains of around 60 cars length, hence allowing you to use 7 square stations to their capacity and beyond. + +2.9 Speed Display + +This addition to OpenTTD allows you to see the current speed of any vehicle in their status window. Just open the status window of a vehicle and you can see the speed at that given moment. This allows you to see wheter better bridges, flatter/straighter track or more powerful engines could be used to increase the speed of a vehicle + +2.10 More Trains, More Ships, More Everything! + +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 + +OpenTTD now supports rudimentary TCP/IP based network play. This is not supported on all platforms. To start a server, use the '-n' CLI switch, and start a client with '-n' and the servers IP adress. The OpenTTD network play runs over port 12345, so you may need to open this on your firewall. + +2.12 Rail Recycling. + +This button, at the end of the train construction window, lets you 'recycle' track to a new type. It also works on bridges, tunnels, stations and depots. + +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. \ No newline at end of file diff --git a/docs/README_if_game_crashed_on_OSX.txt b/docs/README_if_game_crashed_on_OSX.txt new file mode 100644 --- /dev/null +++ b/docs/README_if_game_crashed_on_OSX.txt @@ -0,0 +1,38 @@ +Since you are reading this, OpenTTD have crashed. This file tells you how +to fix the most common problems or make to make a bug report, that the +developers can use to track down the problem + +The first thing you need to do is to get the error message. You can access OSX's build-in log by double-clicking Crash_Log_Opener. OTTD will do that if that file is present in the same folder as OTTD and is not renamed. However, major crashes can prevent the autoopen feature and you have to do it manually then +If Crash_Log_Opener doesn't work you can view the log by opening Console inside Applications/utilities. + +If you use the Console app, you should look at the buttom of the console.log window + +The problems are as follows: +NOTE: build from source means to download the source and compile +yourself. If you get one of the build from source error with the version +that is downloaded on a dmg file, you should make a bug report + +--Didn't find a needed file: + you just give it the file it asks for. It even tells you what +folder it wants it in + most common version of this problem is "Error: Cannot open file +'data/sample.cat'" + if you get that one, that means that you haven't got all the +needed files from the WINDOWS version of TTD + or if you build from source, + +--Error: No available language packs + you need at least one .lng file in your lang folder. This applies +only to people who build from source + +--spritecache.c:237: failed assertion `b' + you got an outdated grf file. Update from the data folder in the +source. This applies only to people, who build from source + +--assertion error that are not triggered by one of the errors listed in +this file: + you most likely found a bug. Write down the assertion and try to +see if you can reproduce it. If you can, make a + savegame from just before it happens (autosaves are useful here) +and post a bugreport with it on sourceforge + Write what you did to trigger the bug and what assertion it made diff --git a/docs/Readme_Mandrake_Linux.txt b/docs/Readme_Mandrake_Linux.txt new file mode 100644 --- /dev/null +++ b/docs/Readme_Mandrake_Linux.txt @@ -0,0 +1,60 @@ +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 the WINDOWS version of Transport Tycoon Deluxe to openttd/data/ + sample.cat + trg1r.grf + trgcr.grf + trghr.grf + trgir.grf + trgtr.grf + + +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 $ \ No newline at end of file diff --git a/docs/Readme_Windows_MSVC6.0.txt b/docs/Readme_Windows_MSVC6.0.txt new file mode 100644 --- /dev/null +++ b/docs/Readme_Windows_MSVC6.0.txt @@ -0,0 +1,89 @@ +Compilung OpenTTD using MS VC6.0 + + +Step 1 +------------------ +Downloaded: +Useful.zip http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633 +SDL.zip http://www.libsdl.org/release/SDL-1.2.7-win32.zip +DirectX7.0 SDK http://www.tt-forums.net/download.php?id=15989 + (or alternatively the latest DirectX SDK from Microsoft) +afxres.h http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H + + +Step 2 +------------------ +Put the newly downloaded files in the VC lib and include directories +(Where D:\program files\ is your local location of VC) + + +* zconf.h [useful.zip] +* zlib.h [useful.zip] +* afxres.h +in + D:\Program Files\Microsoft Visual Studio\VC98\Include + +* zlibstat.lib [usefull.zip] +* SDL.lib [SDL.zip +* libpng.lib [usefull.zip] +in + D:\Program Files\Microsoft Visual Studio\VC98\Lib + +You can also make custum directories, for libraries (.lib) and includes/header files (.h) and +add it to the VC paths via: +Tools -> Options -> Directories -> show directories for: +a) include files (the include dir: D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include ) +b) library files (the lib dir, D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib ) + + +Step 3: DirextX SDK +------------------ +(This should work with the latest DirectX SDK as well.) +The installation with DirectX 7 was odd, so you'd better use the version available via the forum, see also +the download link on top. + +Copy the DirectX 7 SDK files, leaving the directory stucture intact, to the directory: + D:\Program Files\Microsoft Visual Studio\VC98\ +thus resulting in + D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include and + D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib + +Step 3.1 + +Add these two folders to the search path of VC. +In VC6.0: Tools -> Options -> Directories -> show directories for: +a) include files (the include dir: D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include ) +b) libraru files (the lib dir, D:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib ) + + +Step 4 +----------------- +Copy the following files from the WINDOWS version of Transport Tycoon Deluxe to the data folder + sample.cat + trg1r.grf + trgcr.grf + trghr.grf + trgir.grf + trgtr.grf + + + +Step 5 +----------------- +Compile ... + + +Step 6 +----------------- + +Now it should work, it worked for me :) + +Go ahead and make that patch! + +Happy Hacking! + + + +------------------ +written by Dribbel + diff --git a/docs/directmusic.txt b/docs/directmusic.txt new file mode 100644 --- /dev/null +++ b/docs/directmusic.txt @@ -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 \ No newline at end of file diff --git a/docs/landscape.html b/docs/landscape.html new file mode 100644 --- /dev/null +++ b/docs/landscape.html @@ -0,0 +1,611 @@ + + + + + + +Transport Tycoon Deluxe savegame internals + + + + +

Landscape

+

+Five arrays are used to encode the information of the contents of each tile. These arrays are referred to as map_owner, map2, map3_lo, type_and_height and map5. The known encodings are listed in the table below. The most important value is the class of a tile, stored in the upper 4 bits of the type_and_height array. +

+

+Owner values 00 through 07 are companies (they're indices into the array of companies), 10 is no owner, 11 appears to be reserved for water, 80 and above are towns (in this case the low 7 bits contain an index into the town array). +

+

+TTD's class-specific periodic tile processing routine is called once every +256 ticks for each tile. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassMeaning & details of encoding
0 +
    +
  • map5 bits 4..0: tile type: + + + + + + + + + + + + + + +
    00  bare land
    01  1/3 grass
    02  2/3 grass
    03  full grass
    07  rough land
    0B  rocks
    0F  fields; type of fields in map3_lo bits 3..0 (legal values: 0 through 9)
    10  1/4 snow
    11  2/4 snow
    12  3/4 snow
    13  full snow
    15  partial desert
    17  full desert
    +
  • +
  • map5 bits 7..6: update counter, incremented on every periodic processing for tile types other than 03, 07, 0B and 10 and above, on wraparound the tile is updated (for fields, the type of fields in map3_lo is increased, for other types the tile type in map5 is increased) +
    (for snow and desert, these bits are not used, tile is updated on every periodic processing) +
  • +
  • map_owner: owner of the tile (normally 10) +
  • +
  • map3_hi bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none); bits 4..2: same for the SE border +
  • +
+
1 +map5 bit 7 clear: railway track +
    +
  • map5 bits 0..5: track layout: bit set = track present: + + + + + + + +
    bit 0: in the X direction
    bit 1: in the Y direction
    bit 2: in the north corner (direction W-E)
    bit 3: in the south corner (direction W-E)
    bit 4: in the west corner (direction N-S)
    bit 5: in the east corner (direction N-S)
  • +
  • map5 bit 6 set = with signals: +
      +
    • map3_lo bits 7..4: bit set = signal present: +
        +
      • For track in the X direction: + + + +
        bit 6: signal in the SW direction
        bit 7: signal in the NE direction
      • +
      • For track in the Y direction: + + + +
        bit 6: signal in the NW direction
        bit 7: signal in the SE direction
      • +
      • For tracks in the W-E direction: + + + + + +
        bit 4: signal in the W direction on the track in the S corner
        bit 5: signal in the E direction on the track in the S corner
        bit 6: signal in the W direction on the track in the N corner
        bit 7: signal in the E direction on the track in the N corner
      • +
      • For tracks in the N-S direction: + + + + + +
        bit 4: signal in the S direction on the track in the E corner
        bit 5: signal in the N direction on the track in the E corner
        bit 6: signal in the S direction on the track in the W corner
        bit 7: signal in the N direction on the track in the W corner
      • +
    • +
    • map2 bits 7..4: bit clear = signal shows red; same bits as in map3_lo
    • +
    • OpenTTD bits in map3_hi: + + + + + + + +
      bits 1..0: type of signal:
      00: normal signals
      01: pre-signals
      10: exit-signals
      11: combo-signals
      bit 2: set = semaphore signals, clear = light signals
    • +
  • +
  • map_owner: owner of the track +
  • +
  • map2 bits 0..3: + + + + + + + + + + + + + + +
    0  on bare land
    1  on grass, no fences
    2  fence on the NW side
    3  fence on the SE side
    4  fences on the NW and SE sides
    5  fence on the NE side
    6  fence on the SW side
    7  fences on the NE and SW sides
    8  fence on the E side (track in the W corner)
    9  fence on the W side (track in the E corner)
    A  fence on the S side (track in the N corner)
    B  fence on the N side (track in the S corner)
    C  on snow or desert
  • +
  • map3_lo bits 0..3 = track type: 0 - conventional railway, 1 - monorail, 2 - maglev +
  • +
+map5 bits 7 and 6 set: railway depot / checkpoints +
    +
  • map5 value C0..C3: railway depot +
    map5 bits 1..0 - direction: exit towards: 00 = NE, 01 = SE, 02 = SW, 03 = NW
  • +
  • map5 value C4..C5: checkpoint +
    bit 0: clear = in X direction, set = in Y direction +
    +
    +
  • map_owner: owner of the depot / checkpoint
  • +
  • map3_lo bits 0..3 = track type
  • +
+
2 +map5 bits 7..4 clear: road +
    +
  • map5 bits 3..0: road layout: bit set = road piece present: + + + + + +
    bit 0: NW piece
    bit 1: SW piece
    bit 2: SE piece
    bit 3: NE piece
  • +
  • map_owner: owner of the road
  • +
  • map2 bits 0..2: 0 - on bare land, 1 - on grass, 2 - paved, 3 - with streetlights, 5 - tree-lined, 6 - on grass with road works, 7 - paved with road works
  • +
  • map3_hi bit 7 set = on snow or desert
  • +
+map5 bit 4 set, bits 7..5 clear: level crossing +
    +
  • map5 bit 3: clear - road in the X direction, set - road in the Y direction (railway track always perpendicular)
  • +
  • map5 bit 2: set if crossing lights are on
  • +
  • map_owner: owner of the railway track
  • +
  • map2 bits 0..2: 0 - on bare land, 1 - on grass, 2 or higher - paved
  • +
  • map3_lo bits 0..7: owner of the road
  • +
  • map3_hi bits 3..0: track type
  • +
  • map3_hi bit 7 set = on snow or desert
  • +
+map5 bit 5 set: road depot +
    +
  • map5 bits 3..0 - direction: exit towards: 0 = NE, 1 = SE, 2 = SW, 3 = NW
  • +
  • map_owner: owner of the depot
  • +
  • map3_hi bit 7 set = on snow or desert (not displayed, but set internally)
  • +
+
3 +Town building +
    +
  • map2: town building type: +

    Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Type Size Climates Description
    00  1×1temperatetall office block
    01  1×1temperateoffice block
    02  1×1temperatesmall block of flats
    03  1×1temperatechurch
    04  1×1temperate, sub-arctic, sub-tropicallarge office block
    05  1×1snowlarge office block
    06  1×1temperatetown houses
    07..08  1×2temperatehotel
    09  1×1temperate, sub-arctic, sub-tropical  statue
    0A  1×1temperate, sub-arctic, sub-tropicalfountain
    0B  1×1temperatepark (with a pond)
    0C  1×1temperatepark (with an alley)
    0D  1×1temperateoffice block
    0E..10  1×1temperatevarious types of shops and offices
    11  1×1temperate, sub-arctic, sub-tropicalmodern office building
    12  1×1temperatewarehouse
    13  1×1temperateoffice block (with spiral stairway on the side)
    14..17  2×2temperatestadium
    18  1×1temperateold houses
    19  1×1temperatecottages
    1A  1×1temperatehouses
    1B  1×1temperateflats
    1C  1×1temperatetall office block
    1D  1×1temperateshops and offices
    1E  1×1temperate, sub-tropicalshops and offices
    1F  1×1temperatetheatre
    20..23  2×2temperate, sub-arctic, sub-tropicalstadium (modern style)
    24  1×1temperate, sub-arctic, sub-tropicaloffices (the modern 'vertical tube' style)
    25  1×1sub-arctichouses
    26  1×1snowhouses
    27  1×1temperatecinema
    28..2B  2×2temperateshopping mall
    2C  1×1sub-arcticflats
    2D  1×1snowflats
    2E  1×1sub-arctichouses
    2F  1×1snowhouses
    30  1×1sub-arctichouses
    31  1×1snowhouses
    32  1×1sub-arctic, sub-tropicaltall office block
    33  1×1snowtall office block
    34  1×1sub-arctictall office block
    35  1×1snowtall office block
    36  1×1sub-arctic, sub-tropicaltall office block
    37  1×1snowtall office block
    38  1×1sub-arctichouses
    39  1×1snowhouses
    3A  1×1sub-arcticshops and offices
    3B  1×1snowshops and offices
    3C  1×1sub-arcticchurch
    3D  1×1snowchurch
    3E  1×1sub-arctichouses
    3F  1×1snowhouses
    40  1×1sub-arcticshops and offices
    41  1×1snowshops and offices
    42..43  1×2sub-arctichotel
    44..45  1×2snowhotel
    46  1×1sub-arctic, sub-tropicalshops and offices
    47  1×1snowshops and offices
    48  1×1sub-arctictall office block
    49  1×1snowtall office block
    4A..4B  2×1sub-arctictall office block
    4C..4D  2×1snowtall office block
    4E  1×1sub-tropicalhouses (with a tree in a corner)
    4F, 50  1×1sub-tropicalhouses
    51  1×1sub-tropicalhouses (suburb-type)
    52  1×1sub-tropicalflats
    53  1×1sub-tropicalchurch
    54  1×1sub-tropicalhouses (with two trees in front)
    55, 56  1×1sub-tropicalflats
    57..58  2×1sub-tropicaltall office block
    59  1×1sub-tropicalflats
    5A  1×1sub-tropicaltall office block
    5B  1×1toylandchurch
    5C..61  1×1toylandvarious types of toyland houses
    62  1×1toylandtall office block
    63..64  1×2toylandhouses ('shoe' style)
    65  1×1toylandtall office block
    66  1×1toylandigloo
    67  1×1toylandtepees
    68, 69  1×1toylandshops and offices
    6A  1×1toylandtall office block
    6B  1×1toylandstatue
    6C  1×1toylandteapot-house
    6D  1×1toylandpiggy-bank
  • +
  • map3_lo bits 7..6: stage of construction (3 = completed)
  • +
  • map5 bits 2..0: construction counter, for buildings under construction incremented on every periodic tile processing, on wraparound the stage of construction in map3_lo is increased
  • +
  • for large office blocks (types 04 and 05): +
      +
    • map_owner bits 6..0: position of the lift
    • +
    • map_owner bit 7: if set the lift is moving
    • +
    • map5 bit 7: if set then map5 bits 5..0 hold the final position of the lift divided by 6 (valid values 0..6 except 1)
    • +
  • +
+
4 +Trees +
    +
  • map5 bits 7..6: number of trees minus one
  • +
  • map5 bits 2..0: growth status: 0..2 - one of trees is growing, 3 - all trees are fully grown, 4..6 - one of trees is withering
  • +
  • map3_lo bits 7..0: type of trees: + + + + + + + +
    00..0B  temperate climate trees
    0C..13  sub-arctic climate trees
    14..1A  rainforest trees
    1B cactus plants
    1C..1F  sub-tropical climate, non-rainforest, non-desert trees
    20..28  toyland trees
    +(note: the actually displayed set of trees depends on both type and number of trees) +
  • +
  • map3_hi bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)
  • +
  • map3_hi bits 4..2: type of hedge on the SE border of the tile (1 through 6, or 0=none)
  • +
  • map2 bits 5..4: + + + + +
    0  on grass
    1  on rough land
    2  on snow or desert; map2 bits 7..6 - amount of snow or desert (for desert always set to 3 in TTD) +
  • +
  • map2 bits 3..0: update counter, incremented on every periodic processing, on wraparound the growth status is updated (or, if it's 3, a random action is taken)
  • +
  • map_owner: owner (normally 10)
  • +
+
5 +Station tile +
    +
  • map5: tile type: + + + + + + + + + + +
    00..07  railway station +
    00..01 - open platform, 02..03 - open platform with station building, 04....07 - roofed platform +
    bit 0: clear = in X direction, set = in Y direction +
    08..33  large airport + + + + + + + + + + +
    0B  pad 1
    16..19  runway middle
    1A  runway ending
    1C  control tower
    20  hangar
    21  pad 3
    22  pad 2
    27..32  radar (animated)
    33  transmitter
    +The initial layout of a large airport is (rows in Y direction, columns in X direction): +
    +1F 1B 1E 33 26 1A
    +09 24 0B 0C 0D 16
    +21 1D 23 0E 0F 17
    +09 22 0D 11 10 18
    +09 08 14 13 12 19
    +20 0A 15 1C 27 1A
    +
    +
    34..41  small airport + + + + + + +
    3A..3D  field with the wind meter (animated)
    3E  runway south ending
    3F  runway middle
    40  runway north ending
    41  hangar
    +The initial layout of a small airport is (rows in Y direction, columns in X direction): +
    +36 3A 40
    +35 39 3F
    +34 38 3F
    +41 37 3E
    +
    +
    42 heliport
    43..46  lorry loading area; +exit towards: 43 - NE, 44 - SE, 45 - SW, 46 - NW +
    47..4A  bus station; +exit towards: 47 - NE, 48 - SE, 49 - SW, 4A - NW +
    4B oilfield
    4C..51  ship dock; +4C - SW coast part, 4D - NW coast part, 4E - NE coast part, 4F - SE coast part, 50 - X direction water part, 51 - Y direction water part +
    52 buoy
    +
  • +
  • map_owner: owner of the station
  • +
  • map2: index into the array of stations
  • +
  • map3_lo bits 0..3: track type for railway stations, must be 0 for all the other stations
  • +
+
6 +
    +
  • map5: tile type: + + + + +
    00  water
    01  coast or riverbank
    10..1B  canal locks + +
    10  middle part, (SW-NE direction) +
    11  middle part, (NW-SE direction) +
    12  middle part, (NE-SW direction) +
    13  middle part, (SE-NW direction) +
    14  lower part, (SW-NE direction) +
    15  lower part, (NW-SE direction) +
    16  lower part, (NE-SW direction) +
    17  lower part, (SE-NW direction) +
    18  upper part, (SW-NE direction) +
    19  upper part, (NW-SE direction) +
    1A  upper part, (NE-SW direction) +
    1B  upper part, (SE-NW direction) +
    +
    80..83  ship depots + + + +
    80  ship depot, NE part (X direction) +
    81  ship depot, SW part (X direction) +
    82  ship depot, NW part (Y direction) +
    83  ship depot, SE part (Y direction) + +
    +
  • +
  • map_owner: owner (for water and coasts normally 11)
  • +
+
7 +Void +

+Tiles of this class form an invisible, one tile wide border at the south (bottom) edges of the map, so as to protect several algorithms from the consequences of a wraparound at the edges. +

+
8 +Industry tile +
    +
  • map5: type: +
    (note: this is not the same as the industry type stored in the array of industries) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    00..06  coal mine + + + +
    00  wheel tower when not animated
    01  wheel tower when animated; animation state in map_owner bits 5..0; map_owner bit 6 set = sound already generated
    +
    07..0A  power station + + + +
    08  chimney
    0A  transformer; animation progress in map_owner bits 5..2 (valid range 0..7)
    +
    0B..0F  sawmill
    10..11  forest + + +
    11  trees cut down
    +
    12..17  oil refinery
    18..1C  oil rig
    1D..20  oil wells + + + +
    1D  not animated
    1E..20  various stages of animation; progress of animation in map_owner bits 1..0
    +
    21..26  farm
    27..2A  factory (temperate climate)
    2B..2E  printing works
    2F..33  copper ore mine + + + + +
    2F  wheel tower when not animated
    30  wheel tower when animated; animation state in map_owner bits 5..0; map_owner bit 6 set = sound already generated
    31  chimney
    +
    34..39  steel mill
    3A..3B  bank (temperate climate)
    3C..3F  food processing plant
    40..47  paper mill
    48..58  gold mine + + + +
    4F  wheel tower when not animated
    58  wheel tower when animated; animation state in map_owner bits 5..0; map_owner bit 6 set = sound already generated
    +
    59..5A  bank (sub-arctic or sub-tropical climate)
    5B..63  diamond mine
    64..73  iron ore mine
    74fruit plantation
    75rubber plantation
    76..77  water supply
    78water tower
    79..7C  factory (sub-tropical climate)
    7D..80  lumber mill
    81..82  candyfloss forest + + +
    82  candyfloss 'trees' cut down
    +
    83..86  sweet factory
    87..88  battery farm + + +
    88  batteries 'reaped'
    +
    89cola wells
    8A..8D  toy shop
    8E..93  toy factory + + +
    8F  animated part; animation state in map3_lo (valid range 00..31)
    +tile animation is started (map3_hi zeroed) on the periodic processing if field 2C in the corresponding industry array entry is nonzero
    +while the animation is in progress (see the array at 04328) map3_hi holds the number of animation cycles that have already taken place; when this number reaches 8 the animation is stopped
    +
    94..9B  plastic fountains (various stages of cyclic animation)
    9C..9F  fizzy drink factory
    A0..A3  bubble generator + + + +
    A1  generators
    A2  bubble capture facility; animation state in map3_lo (valid range 00..27)
    +
    A4..A6  toffee quarry + + +
    A5  animated part; animation state in map3_lo (valid range 00..45)
    +
    A7..AE  sugar mine + + +
    AE  animated part; animation state in map3_lo (valid range 00..5F)
    +
  • +
  • map2: index into the array of industries +
  • +
  • map_owner bit 7: clear = under construction +
      +
    • map_owner bits 4..2: construction counter, for buildings under construction incremented on every periodic tile processing +
    • +
  • +
  • map_owner bits 1..0: stage of construction (3 = completed), incremented when the construction counter wraps around +
    the meaning is different for some animated tiles which are never under construction (types 01, 1E..20, 30, 58; see above) +
  • +
+
9 +map5 bits 7..4 clear: tunnel entrance/exit +
    +
  • map5 bits 3..2: 0 - railway tunnel, 1 - road tunnel
  • +
  • map5 bits 1..0 - direction: entrance towards: 0 = NE, 1 = SE, 2 = SW, 3 = NW
  • +
  • map_owner: owner of the tunnel
  • +
  • map3_lo bits 3..0 = track type for railway tunnel, must be 0 for road tunnel
  • +
  • map3_hi bit 7 set = on snow or desert
  • +
+map5 bit 7 set: bridge +
  • +map5 bit 6 clear: bridge ending +
      +
    • map5 bit 5: clear - northern, set - southern ending
    • +
    • map3_lo bits 3..0 = type of track on the bridge, must be 0 for road bridge
    • +
    • map_owner: owner of the bridge
    • +
    +map5 bit 6 set: bridge middle part +
      +
    • map5 bit 5 clear: +
        +
      • map5 bits 4..3: land under bridge: 0 - grass, snow or desert, 1 - water
      • +
      +map5 bit 5 set: +
        +
      • map5 bits 4..3: transport route under bridge: 0 - railway, 1 - road
      • +
      +
    • map3_lo bits 7..4 = type of track on the bridge, must be 0 for road bridge
    • +
    • map3_lo bits 3..0 = type of track under the bridge, if any
    • +
    • map2 bits 3..0: bridge piece (0..5) +
    • map_owner: owner of the land under bridge
    • +
  • +
  • map5 bits 2..1: 0 - railway bridge, 1 - road bridge
  • +
  • map5 bit 0: clear - bridge in the X direction, set - bridge in the Y direction
  • +
  • map2 bits 7..4: bridge type: + + + + + + + + + + + + + +
    Type Max. speed (mph) Description
    0  20wooden
    1  30concrete
    2  40girder, steel
    3  50suspension, concrete
    4  60suspension, steel
    5  70suspension, steel
    6  100cantilever, steel
    7  130cantilever, steel
    8  150cantilever, steel
    9  160girder, steel
    A  200tubular, steel
  • +
  • map3_hi bit 7 set = on snow or desert
  • +
+
A +
    +
  • map5: tile type: + + + + + + +
    00  transmitter
    01  lighthouse
    02  company statue
    03  company-owned land
    80..93  company headquarters (5 sets of 4 tiles each, updated quarterly depending on the company performance)
    +
  • +
  • map_owner: owner of the object (for lighthouses and transmitters normally 10)
  • +
+
+Classes B through F are reserved. The presence of a tile in one of the reserved classes will crash TTD. +
+ + +
+Copyright © 2003 by Marcin Grzegorczyk.
+Transport Tycoon and Transport Tycoon Deluxe are Copyright © by Chris Sawyer. All the other trademarks are the property of their respective owners.
+ + + diff --git a/docs/tileh.png b/docs/tileh.png new file mode 100644 index 0000000000000000000000000000000000000000..47d92938c00b4fece01cf11e546232b3f1713af4 GIT binary patch literal 37601 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, ti->y, ti->z); +} + + +static uint GetSlopeZ_Dummy(TileInfo *ti) { + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; +} + +static int32 ClearTile_Dummy(uint tile, byte flags) { + return_cmd_error(STR_0001_OFF_EDGE_OF_MAP); +} + + +static void GetAcceptedCargo_Dummy(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void GetTileDesc_Dummy(uint tile, TileDesc *td) +{ + td->str = STR_EMPTY; + td->owner = OWNER_NONE; +} + +static void AnimateTile_Dummy(uint tile) +{ + /* not used */ +} + +static void TileLoop_Dummy(uint tile) +{ + /* not used */ +} + +static void ClickTile_Dummy(uint tile) +{ + /* not used */ +} + +static void ChangeTileOwner_Dummy(uint tile, byte old_player, byte new_player) +{ + /* not used */ +} + +static uint32 GetTileTrackStatus_Dummy(uint tile, int 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 */ +}; + diff --git a/economy.c b/economy.c new file mode 100644 --- /dev/null +++ b/economy.c @@ -0,0 +1,1372 @@ +#include "stdafx.h" +#include "ttd.h" +#include "news.h" +#include "player.h" +#include "station.h" +#include "vehicle.h" +#include "window.h" +#include "gfx.h" +#include "command.h" +#include "saveload.h" +#include "economy.h" +#include "industry.h" +#include "town.h" + +static void UpdatePlayerHouse(Player *p, uint score) +{ + byte val; + uint tile = p->location_of_house; + + if (tile == 0) + return; + + (val = 128, score < 170) || + (val+= 4, score < 350) || + (val+= 4, score < 520) || + (val+= 4, score < 720) || + (val+= 4, true); + +/* house is already big enough */ + if (val <= _map5[tile]) + return; + + _map5[tile + TILE_XY(0,0)] = val; + _map5[tile + TILE_XY(0,1)] = ++val; + _map5[tile + TILE_XY(1,0)] = ++val; + _map5[tile + TILE_XY(1,1)] = ++val; + + MarkTileDirtyByTile(tile + TILE_XY(0,0)); + MarkTileDirtyByTile(tile + TILE_XY(0,1)); + MarkTileDirtyByTile(tile + TILE_XY(1,0)); + MarkTileDirtyByTile(tile + TILE_XY(1,1)); +} + +uint32 CalculateCompanyValue(Player *p) { + byte owner = p->index; + uint32 value; + + { + Station *st; + uint num = 0; + + FOR_ALL_STATIONS(st) { + if (st->xy != 0 && st->owner == owner) { + uint facil = st->facilities; + do num += (facil&1); while (facil >>= 1); + } + } + + value = num * _price.station_value * 25; + } + + { + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->owner != owner) + continue; + if (v->type == VEH_Train || + v->type == VEH_Road || + (v->type == VEH_Aircraft && v->subtype<=2) || + v->type == VEH_Ship) { + value += v->value * 3 >> 1; + } + } + } + + if (p->player_money > 0) + value += p->player_money; + + return value; +} + +static void UpdateCompanyRatingAndValue(Player *p) +{ + byte owner = p->index; + uint score; + +/* Count vehicles */ + { + Vehicle *v; + int32 min_profit = MAX_INT; + uint num = 0; + + FOR_ALL_VEHICLES(v) { + if (v->owner != owner) + continue; + if ((v->type == VEH_Train && v->subtype == 0) || + v->type == VEH_Road || + (v->type == VEH_Aircraft && v->subtype<=2) || + v->type == VEH_Ship) { + num++; + if (v->age > 730) { + if (min_profit >= v->profit_last_year) + min_profit = v->profit_last_year; + } + } + } + + score = (num < 120) ? num * 100 / 120 : 100; + + if (min_profit != MAX_INT && min_profit > 0) + score += (min_profit < 10000) ? min_profit/100 : 100; + } + +/* Count stations */ + { + uint num = 0; + Station *st; + + FOR_ALL_STATIONS(st) { + if (st->xy != 0 && st->owner == owner) { + int facil = st->facilities; + do num += facil&1; while (facil>>=1); + } + } + score += (num < 80) ? num * 100 / 80 : 100; + } + +/* Generate statistics depending on recent income statistics */ + { + PlayerEconomyEntry *pee; + int numec; + int32 min_income; + uint32 max_income; + + numec = min(p->num_valid_stat_ent, 12); + if (numec != 0) { + min_income = 0x7FFFFFFF; + max_income = 0; + pee = p->old_economy; + do { + min_income = min(min_income, pee->income + pee->expenses); + max_income = max(max_income, pee->income + pee->expenses); + } while (++pee,--numec); + + if (min_income > 0) + score += min_income >= 50000 ? 50 : min_income / 1000; + + score += max_income >= 100000 ? 100 : max_income / 1000; + } + } + +/* Generate score depending on amount of transported cargo */ + { + PlayerEconomyEntry *pee; + int numec; + uint32 total_delivered; + + numec = min(p->num_valid_stat_ent, 4); + if (numec != 0) { + pee = p->old_economy; + total_delivered = 0; + do { + total_delivered += pee->delivered_cargo; + } while (++pee,--numec); + + score += total_delivered >= 40000 ? 400 : total_delivered / 100; + } + } + +/* Generate score for variety of cargo */ + { + uint cargo = p->cargo_types; + uint num = 0; + do num += cargo&1; while (cargo>>=1); + score += num < 8 ? num * 50 / 8 : 50; + p->cargo_types = 0; + } + +/* Generate score for player money */ + { + int32 money = p->player_money; + if (money > 0) { + score += money < 10000000 ? money / (10000000/50) : 50; + } + } + +/* Generate score for loan */ + { + score += (250000 - p->current_loan) >= 0 ? (250000 - p->current_loan) / 5000 : 0; + } + + p->old_economy[0].performance_history = score; + UpdatePlayerHouse(p, score); + p->old_economy[0].company_value = CalculateCompanyValue(p); +} + +// use 255 as new_player to delete the player. +void ChangeOwnershipOfPlayerItems(byte old_player, byte new_player) +{ + byte old = _current_player; + _current_player = old_player; + + if (new_player == 255) { + Subsidy *s; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xff && s->age >= 12) { + Station *st = DEREF_STATION(s->to); + if (st->owner == old_player) + s->cargo_type = 0xff; + } + } + } + + // take care of rating in towns + { + Town *t; + + // if a player takes over, give the ratings to that player. + if (new_player != 255) { + FOR_ALL_TOWNS(t) if (t->xy && HASBIT(t->have_ratings, old_player)) { + if (HASBIT(t->have_ratings, new_player)) { + // use max of the two ratings. + t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]); + } else { + SETBIT(t->have_ratings, new_player); + t->ratings[new_player] = t->ratings[old_player]; + } + } + } + + // reset rating for the towns. + FOR_ALL_TOWNS(t) if (t->xy) { + t->ratings[old_player] = 500; + CLRBIT(t->have_ratings, old_player); + } + } + + { + int num_train = 0; + int num_road = 0; + int num_ship = 0; + int num_aircraft = 0; + Vehicle *v; + + // Determine Ids for the new vehicles + FOR_ALL_VEHICLES(v) { + if (v->owner == new_player) { + if (v->type == VEH_Train && v->subtype == 0) + num_train++; + else if (v->type == VEH_Road) + num_road++; + else if (v->type == VEH_Ship) + num_ship++; + else if (v->type == VEH_Aircraft && v->subtype <= 2) + num_aircraft++; + } + } + + FOR_ALL_VEHICLES(v) { + if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_Train, VEH_Aircraft+1) ) { + if (new_player == 255) { + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + DeleteWindowById(WC_VEHICLE_DETAILS, v->index); + DeleteWindowById(WC_VEHICLE_ORDERS, v->index); + DeleteVehicle(v); + } else { + v->owner = new_player; + if (v->type == VEH_Train && v->subtype == 0) + v->unitnumber = ++num_train; + else if (v->type == VEH_Road) + v->unitnumber = ++num_road; + else if (v->type == VEH_Ship) + v->unitnumber = ++num_ship; + else if (v->type == VEH_Aircraft && v->subtype <= 2) + v->unitnumber = ++num_aircraft; + } + } + } + } + + // Change ownership of tiles + { + uint tile = 0; + do { + ChangeTileOwner(tile, old_player, new_player); + } while (++tile != TILES_X * TILES_Y); + } + + // Change color of existing windows + if (new_player != 255) { + Window *w; + for(w=_windows; w != _last_window; w++) { + if (w->caption_color == old_player) + w->caption_color = new_player; + } + } + + _current_player = old; + + MarkWholeScreenDirty(); +} + +extern void DeletePlayerWindows(int pi); + +static void PlayersCheckBankrupt(Player *p) +{ + int owner; + uint32 val; + + if (p->player_money >= 0) { + p->quarters_of_bankrupcy = 0; + return; + } + + p->quarters_of_bankrupcy++; + + owner = p->index; + + if (p->quarters_of_bankrupcy == 2) { +year_2: + AddNewsItem( (StringID)(owner + 16), + NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0); + + } else if (p->quarters_of_bankrupcy == 3) { + if (IS_HUMAN_PLAYER(owner)) + goto year_2; + + val = CalculateCompanyValue(p); + if (val == 0) goto year_4; + + p->bankrupt_value = val; + p->bankrupt_asked = 1 << owner; + p->bankrupt_timeout = 0; + } else if (p->quarters_of_bankrupcy == 4) { +year_4: + DeletePlayerWindows(owner); + + if (IS_HUMAN_PLAYER(owner)) { +// what does this code do?? + InitNewsItemStructs(); + DeleteWindowById(WC_NEWS_WINDOW, 0); + } + +// Show bankrupt news + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + AddNewsItem( (StringID)(owner + 16*3), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0); + + if (IS_HUMAN_PLAYER(owner)) { + p->bankrupt_asked = 255; + p->bankrupt_timeout = 0x456; + } else { + p->money64 = p->player_money = 100000000; + ChangeOwnershipOfPlayerItems(owner, 0xFF); + p->is_active = false; + } + } +} + +void DrawNewsBankrupcy(Window *w) +{ + Player *p; + + DrawNewsBorder(w); + + p = DEREF_PLAYER(WP(w,news_d).ni->string_id & 15); + DrawPlayerFace(p->face, p->player_color, 2, 23); + GfxFillRect(3, 23, 3+91, 23+118, 0x4323); + + SET_DPARAM16(0, p->president_name_1); + SET_DPARAM32(1, p->president_name_2); + + DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94); + + switch(WP(w,news_d).ni->string_id >> 4) { + case 1: + DrawStringCentered(w->width>>1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, 0); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, + w->width - 101); + break; + + case 2: { + int32 price; + + DrawStringCentered(w->width>>1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, 0); + COPY_IN_DPARAM(0,WP(w,news_d).ni->params, 2); + SET_DPARAM16(2, p->name_1); + SET_DPARAM32(3, p->name_2); + price = WP(w,news_d).ni->params[2]; + SET_DPARAM32(4, price); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + price==0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, + w->width - 101); + break; + } + + case 3: + DrawStringCentered(w->width>>1, 1, STR_705C_BANKRUPT, 0); + COPY_IN_DPARAM(0,WP(w,news_d).ni->params, 2); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_705D_HAS_BEEN_CLOSED_DOWN_BY, + w->width - 101); + break; + + case 4: + DrawStringCentered(w->width>>1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, 0); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + COPY_IN_DPARAM(2,WP(w,news_d).ni->params, 2); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_705F_STARTS_CONSTRUCTION_NEAR, + w->width - 101); + break; + + default: + NOT_REACHED(); + } +} + +StringID GetNewsStringBankrupcy(NewsItem *ni) +{ + Player *p = DEREF_PLAYER(ni->string_id & 0xF); + + switch(ni->string_id >> 4) { + case 1: + SET_DPARAM16(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE); + SET_DPARAM16(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED); + SET_DPARAM16(2, p->name_1); + SET_DPARAM32(3, p->name_2); + return STR_02B6; + case 2: + SET_DPARAM16(0, STR_7059_TRANSPORT_COMPANY_MERGER); + SET_DPARAM16(1, STR_705A_HAS_BEEN_SOLD_TO_FOR); + COPY_IN_DPARAM(2,ni->params, 2); + SET_DPARAM16(4, p->name_1); + SET_DPARAM32(5, p->name_2); + COPY_IN_DPARAM(6,ni->params + 2, 1); + return STR_02B6; + case 3: + SET_DPARAM16(0, STR_705C_BANKRUPT); + SET_DPARAM16(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY); + COPY_IN_DPARAM(2,ni->params, 2); + return STR_02B6; + case 4: + SET_DPARAM16(0, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED); + SET_DPARAM16(1, STR_705F_STARTS_CONSTRUCTION_NEAR); + SET_DPARAM16(2, p->name_1); + SET_DPARAM32(3, p->name_2); + COPY_IN_DPARAM(4,ni->params, 2); + return STR_02B6; + default: + NOT_REACHED(); + } + + /* useless, but avoids compiler warning this way */ + return 0; +} + +static void PlayersGenStatistics() +{ + Station *st; + Player *p; + + FOR_ALL_STATIONS(st) { + if (st->xy != 0) { + _current_player = st->owner; + SET_EXPENSES_TYPE(EXPENSES_PROPERTY); + SubtractMoneyFromPlayer(_price.station_value >> 1); + } + } + + if (!HASBIT(1<<0|1<<3|1<<6|1<<9, _cur_month)) + return; + + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + memmove(&p->old_economy, &p->cur_economy, sizeof(p->old_economy)); + memset(&p->cur_economy, 0, sizeof(p->cur_economy)); + + if (p->num_valid_stat_ent != 24) + p->num_valid_stat_ent++; + + UpdateCompanyRatingAndValue(p); + PlayersCheckBankrupt(p); + + if (p->block_preview != 0) + p->block_preview--; + } + } + + InvalidateWindow(WC_INCOME_GRAPH, 0); + InvalidateWindow(WC_OPERATING_PROFIT, 0); + InvalidateWindow(WC_DELIVERED_CARGO, 0); + InvalidateWindow(WC_PERFORMANCE_HISTORY, 0); + InvalidateWindow(WC_COMPANY_VALUE, 0); + InvalidateWindow(WC_COMPANY_LEAGUE, 0); +} + +static void AddSingleInflation(int32 *value, uint16 *frac, int32 amt) +{ + int64 tmp; + int32 low; + tmp = BIGMULS(*value, amt); + *frac = (uint16)(low = (uint16)tmp + *frac); + *value += (int32)(tmp >> 16) + (low >> 16); +} + +static void AddInflation() +{ + int i; + int32 inf = _economy.infl_amount * 54; + + for(i=0; i!=NUM_PRICES; i++) { + AddSingleInflation( (int32*)&_price + i, _price_frac + i, inf ); + } + + _economy.max_loan_unround += BIGMULUS(_economy.max_loan_unround, inf, 16); + + if (_economy.max_loan + 50000 <= _economy.max_loan_unround) + _economy.max_loan += 50000; + + inf = _economy.infl_amount_pr * 54; + for(i=0; i!=NUM_CARGO; i++) { + AddSingleInflation( + _cargo_payment_rates + i, + _cargo_payment_rates_frac + i, + inf + ); + } + + InvalidateWindowClasses(WC_BUILD_VEHICLE); + InvalidateWindowClasses(WC_VEHICLE_DETAILS); + InvalidateWindow(WC_PAYMENT_RATES, 0); +} + +static void PlayersPayInterest() +{ + Player *p; + int interest = _economy.interest_rate * 54; + + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + + _current_player = p->index; + SET_EXPENSES_TYPE(EXPENSES_LOAN_INT); + + SubtractMoneyFromPlayer(BIGMULUS(p->current_loan, interest, 16)); + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + SubtractMoneyFromPlayer(_price.station_value >> 2); + } +} + +static void HandleEconomyFluctuations() +{ + if (_opt.diff.economy == 0) + return; + + if (--_economy.fluct == 0) { + _economy.fluct = - (int)(Random()&3); + AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NEWS_FLAGS(NM_NORMAL,0,NT_ECONOMY,0), 0, 0); + } else if (_economy.fluct == -12) { + _economy.fluct = (Random()&255) + 312; + AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NEWS_FLAGS(NM_NORMAL,0,NT_ECONOMY,0), 0, 0); + } +} + +static byte _price_category[NUM_PRICES] = { + 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 1, 1, + 2, +}; + +static const int32 _price_base[NUM_PRICES] = { + 100, 100, 95, 65, 275, 600, 500, 700, + 450, 200, 180, 600, 200, 200, 350, 400000, + 2000, 700000, 14000, 65000, 20, 250, 20, 40, + 200, 500, 20, -70, 10, 50, 80, 80, + 90, 30, 10000, 50, 30, 50, 50, 55, + 1600, 40, 5600, 5200, 4800, 9600, 1600, 5600, + 1000000, +}; + +void StartupEconomy() +{ + int i; + + assert(sizeof(_price) == NUM_PRICES * sizeof(int32)); + + for(i=0; i!=NUM_PRICES; i++) { + int32 price = _price_base[i]; + if (_price_category[i] != 0) { + uint mod = _price_category[i] == 1 ? _opt.diff.vehicle_costs : _opt.diff.construction_cost; + if (mod < 1) { + price = price * 3 >> 2; + } else if (mod > 1) { + price = price * 9 >> 3; + } + } + ((int32*)&_price)[i] = price; + _price_frac[i] = 0; + } + + _economy.interest_rate = _opt.diff.initial_interest; + _economy.infl_amount = _opt.diff.initial_interest; + _economy.infl_amount_pr = max(0, _opt.diff.initial_interest - 1); + _economy.max_loan_unround = _economy.max_loan = _opt.diff.max_loan * 1000; + _economy.fluct = (byte)(Random()) + 168; +} + +Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode) +{ + int tile, tile2; + Industry *i; + Town *t; + Station *st; + Pair tp; + + /* if mode is false, convert into plural */ + SET_DPARAM16(0, _cargoc.names_s[s->cargo_type] + (mode?0:32)); + + if (s->age < 12) { + if (!(s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL)) { + SET_DPARAM16(1, STR_2029); + i = DEREF_INDUSTRY(s->from); + tile = i->xy; + SET_DPARAM16(2, i->town->townnametype); + SET_DPARAM32(3, i->town->townnameparts); + + SET_DPARAM16(4, i->type + STR_4802_COAL_MINE); + + if (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD) { + SET_DPARAM16(5, STR_2029); + i = DEREF_INDUSTRY(s->to); + tile2 = i->xy; + SET_DPARAM16(8, i->type + STR_4802_COAL_MINE); + SET_DPARAM16(6, i->town->townnametype); + SET_DPARAM32(7, i->town->townnameparts); + } else { + t = DEREF_TOWN(s->to); + tile2 = t->xy; + SET_DPARAM16(5, t->townnametype); + SET_DPARAM32(6, t->townnameparts); + } + } else { + t = DEREF_TOWN(s->from); + tile = t->xy; + SET_DPARAM16(1, t->townnametype); + SET_DPARAM32(2, t->townnameparts); + + t = DEREF_TOWN(s->to); + tile2 = t->xy; + SET_DPARAM16(3, t->townnametype); + SET_DPARAM32(4, t->townnameparts); + } + } else { + st = DEREF_STATION(s->from); + tile = st->xy; + SET_DPARAM16(1, st->index); + + st = DEREF_STATION(s->to); + tile2 = st->xy; + SET_DPARAM16(2, st->index); + } + + tp.a = tile; + tp.b = tile2; + + return tp; +} + +void DeleteSubsidyWithIndustry(byte index) +{ + Subsidy *s; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age < 12 && + s->cargo_type != CT_PASSENGERS && s->cargo_type != CT_MAIL && + (index == s->from || (s->cargo_type!=CT_GOODS && s->cargo_type!=CT_FOOD && index==s->to))) { + s->cargo_type = 0xFF; + } + } +} + +void DeleteSubsidyWithStation(byte index) +{ + Subsidy *s; + bool dirty = false; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age >= 12 && + (s->from == index || s->to == index)) { + s->cargo_type = 0xFF; + dirty = true; + } + } + + if (dirty) + InvalidateWindow(WC_SUBSIDIES_LIST, 0); +} + +typedef struct FoundRoute { + uint distance; + byte cargo; + void *from; + void *to; +} FoundRoute; + +static void FindSubsidyPassengerRoute(FoundRoute *fr) +{ + Town *from,*to; + + fr->distance = (uint)-1; + + fr->from = from = DEREF_TOWN(RandomRange(_total_towns)); + if (from->xy == 0 || from->population < 400) + return; + + fr->to = to = DEREF_TOWN(RandomRange(_total_towns)); + if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42) + return; + + fr->distance = GetTileDist(from->xy, to->xy); +} + +static void FindSubsidyCargoRoute(FoundRoute *fr) +{ + Industry *i; + int trans, total; + byte cargo; + + fr->distance = (uint)-1; + + fr->from = i = DEREF_INDUSTRY(RandomRange(_total_industries)); + if (i->xy == 0) + return; + + // Randomize cargo type + if (Random()&1 && i->produced_cargo[1] != 0xFF) { + cargo = i->produced_cargo[1]; + trans = i->pct_transported[1]; + total = i->total_production[1]; + } else { + cargo = i->produced_cargo[0]; + trans = i->pct_transported[0]; + total = i->total_production[0]; + } + + // Quit if no production in this industry + // or if the cargo type is passengers + // or if the pct transported is already large enough + if (total == 0 || trans > 42 || cargo == 0xFF || cargo == CT_PASSENGERS) + return; + + fr->cargo = cargo; + + if (cargo == CT_GOODS || cargo == CT_FOOD) { + // The destination is a town + Town *t = DEREF_TOWN(RandomRange(_total_towns)); + + // Only want big towns + if (t->xy == 0 || t->population < 900) + return; + fr->distance = GetTileDist(i->xy, t->xy); + fr->to = t; + } else { + // The destination is an industry + Industry *i2 = DEREF_INDUSTRY(RandomRange(_total_industries)); + + // The industry must accept the cargo + if (i == i2 || i2->xy == 0 || + (cargo != i2->accepts_cargo[0] && + cargo != i2->accepts_cargo[1] && + cargo != i2->accepts_cargo[2])) + return; + fr->distance = GetTileDist(i->xy, i2->xy); + fr->to = i2; + } +} + +static bool CheckSubsidyDuplicate(Subsidy *s) +{ + Subsidy *ss; + + for(ss=_subsidies; ss != endof(_subsidies); ss++) { + if (s != ss && +// ss->age < 12 && + ss->from == s->from && + ss->to == s->to && + ss->cargo_type == s->cargo_type) { + s->cargo_type = 0xFF; + return true; + } + } + return false; +} + +static void SubsidyMonthlyHandler() +{ + Subsidy *s; + Pair pair; + Station *st; + uint n; + FoundRoute fr; + bool modified = false; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == 0xFF) + continue; + + if (s->age == 12-1) { + pair = SetupSubsidyDecodeParam(s, 1); + AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b); + s->cargo_type = 0xFF; + modified = true; + } else if (s->age == 2*12-1) { + st = DEREF_STATION(s->to); + if (st->owner == _local_player) { + pair = SetupSubsidyDecodeParam(s, 1); + AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b); + } + s->cargo_type = 0xFF; + modified = true; + } else { + s->age++; + } + } + + // 25% chance to go on + if (CHANCE16(1,4)) { + // Find a free slot + s = _subsidies; + while (s->cargo_type != 0xFF) { + if (++s == endof(_subsidies)) + goto no_add; + } + + n = 1000; + do { + FindSubsidyPassengerRoute(&fr); + if (fr.distance <= 70) { + s->cargo_type = CT_PASSENGERS; + s->from = ((Town*)fr.from)->index; + s->to = ((Town*)fr.to)->index; + goto add_subsidy; + } + FindSubsidyCargoRoute(&fr); + if (fr.distance <= 70) { + s->cargo_type = fr.cargo; + s->from = (Industry*)fr.from - _industries; + s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : (Industry*)fr.to - _industries; + add_subsidy: + if (!CheckSubsidyDuplicate(s)) { + s->age = 0; + pair = SetupSubsidyDecodeParam(s, 0); + AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b); + modified = true; + break; + } + } + } while (--n); + } +no_add:; + if (modified) + InvalidateWindow(WC_SUBSIDIES_LIST, 0); +} + +static const byte _subsidies_desc[] = { + SLE_VAR(Subsidy,cargo_type, SLE_UINT8), + SLE_VAR(Subsidy,age, SLE_UINT8), + SLE_VAR(Subsidy,from, SLE_UINT8), + SLE_VAR(Subsidy,to, SLE_UINT8), + SLE_END() +}; + +static void Save_SUBS() +{ + int i; + Subsidy *s; + + for(i=0; i!=lengthof(_subsidies); i++) { + s = &_subsidies[i]; + if (s->cargo_type != 0xFF) { + SlSetArrayIndex(i); + SlObject(s, _subsidies_desc); + } + } +} + +static void Load_SUBS() +{ + int index; + while ((index = SlIterateArray()) != -1) + SlObject(&_subsidies[index], _subsidies_desc); +} + +int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type) +{ + int cargo = cargo_type; + byte f; + + /* zero the distance if it's the bank and very short transport. */ + if (_opt.landscape == LT_NORMAL && cargo == CT_VALUABLES && dist < 10) + dist = 0; + + f = 255; + if (transit_days > _cargoc.transit_days_1[cargo]) { + transit_days -= _cargoc.transit_days_1[cargo]; + f -= transit_days; + + if (transit_days > _cargoc.transit_days_2[cargo]) { + transit_days -= _cargoc.transit_days_2[cargo]; + + if (f < transit_days) + f = 0; + else + f -= transit_days; + } + } + if (f < 31) f = 31; + + return BIGMULSS(dist * f * num_pieces, _cargo_payment_rates[cargo], 21); +} + +static void DeliverGoodsToIndustry(TileIndex xy, byte cargo_type, int num_pieces) +{ + Industry *ind, *best; + int t, u; + + /* Check if there's an industry close to the station that accepts + * the cargo */ + best = NULL; + u = 0x11; + for(ind = _industries; ind != endof(_industries); ind++) { + if (ind->xy != 0 && (cargo_type == ind->accepts_cargo[0] || cargo_type + == ind->accepts_cargo[1] || cargo_type == ind->accepts_cargo[2]) && + ind->produced_cargo[0] != 0xFF && + ind->produced_cargo[0] != cargo_type && + (t=GetTileDist(ind->xy, xy)) < u) { + u = t; + best = ind; + } + } + + /* Found one? */ + if (best != NULL) { + best->was_cargo_delivered = true; + best->cargo_waiting[0] = min(best->cargo_waiting[0] + num_pieces, 0xFFFF); + } +} + +static bool CheckSubsidised(Station *from, Station *to, byte cargo_type) +{ + Subsidy *s; + TileIndex xy; + Pair pair; + Player *p; + + // check if there is an already existing subsidy that applies to us + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == cargo_type && + s->age >= 12 && + s->from == from->index && + s->to == to->index) + return true; + } + + /* check if there's a new subsidy that applies.. */ + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == cargo_type && s->age < 12) { + + /* Check distance from source */ + if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL) { + xy = DEREF_TOWN(s->from)->xy; + } else { + xy = (DEREF_INDUSTRY(s->from))->xy; + } + if (GetTileDist1D(xy, from->xy) > 9) + continue; + + /* Check distance from dest */ + if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL || cargo_type == CT_GOODS || cargo_type == CT_FOOD) { + xy = DEREF_TOWN(s->to)->xy; + } else { + xy = (DEREF_INDUSTRY(s->to))->xy; + } + + if (GetTileDist1D(xy, to->xy) > 9) + continue; + + /* Found a subsidy, change the values to indicate that it's in use */ + s->age = 12; + s->from = from->index; + s->to = to->index; + + /* Add a news item */ + pair = SetupSubsidyDecodeParam(s, 0); + INJECT_DPARAM(2); + + p = DEREF_PLAYER(_current_player); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + AddNewsItem( + STR_2031_SERVICE_SUBSIDY_AWARDED + _opt.diff.subsidy_multiplier, + NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), + pair.a, pair.b); + + InvalidateWindow(WC_SUBSIDIES_LIST, 0); + return true; + } + } + return false; +} + +static int32 DeliverGoods(int num_pieces, byte cargo_type, byte source, byte dest, byte days_in_transit) +{ + bool subsidised; + Station *s_from, *s_to; + int32 profit; + + assert(num_pieces > 0); + + // Update player statistics + { + Player *p = DEREF_PLAYER(_current_player); + p->cur_economy.delivered_cargo += num_pieces; + SETBIT(p->cargo_types, cargo_type); + } + + // Get station pointers. + s_from = DEREF_STATION(source); + s_to = DEREF_STATION(dest); + + // Check if a subsidy applies. + subsidised = CheckSubsidised(s_from, s_to, cargo_type); + + // Increase town's counter for some special goods types + { + Town *t = s_to->town; + if (cargo_type == CT_FOOD) t->new_act_food += num_pieces; + if (cargo_type == CT_STEEL) t->new_act_paper += num_pieces; + } + + // Give the goods to the industry. + DeliverGoodsToIndustry(s_to->xy, cargo_type, num_pieces); + + // Determine profit + { + int t = GetTileDist(s_from->xy, s_to->xy); + int r = num_pieces; + profit = 0; + do { + int u = min(r, 255); + r -= u; + profit += GetTransportedGoodsIncome(u, t, days_in_transit, cargo_type); + } while (r != 0); + } + + // Modify profit if a subsidy is in effect + if (subsidised) { + if (_opt.diff.subsidy_multiplier < 1) { + /* 1.5x */ + profit += profit >> 1; + } else if (_opt.diff.subsidy_multiplier == 1) { + /* 2x */ + profit *= 2; + } else if (_opt.diff.subsidy_multiplier == 2) { + /* 3x */ + profit *= 3; + } else { + /* 4x */ + profit *= 4; + } + } + + // Computers get 25% extra profit if they're intelligent. + if (_opt.diff.competitor_intelligence>=1 && !IS_HUMAN_PLAYER(_current_player)) + profit += profit >> 2; + + return profit; +} + +int LoadUnloadVehicle(Vehicle *v) +{ + int profit = 0; + int unloading_time = 20; + Vehicle *u = v; + int result = 0; + int last_visited; + Station *st; + GoodsEntry *ge; + int t; + uint count, cap; + + assert((v->next_order&0x1F) == OT_LOADING); + + v->cur_speed = 0; + _current_player = v->owner; + + st = DEREF_STATION(last_visited = v->last_station_visited); + + for(;;) { + if (v->cargo_cap == 0) + goto next_vehicle; + + ge = &st->goods[v->cargo_type]; + + /* unload? */ + if (v->cargo_count != 0) { + if (v->cargo_source != (byte)last_visited && ge->waiting_acceptance & 0x8000) { + // deliver goods to the station + unloading_time += v->cargo_count; /* TTDBUG: bug in original TTD */ + profit += DeliverGoods(v->cargo_count, v->cargo_type, v->cargo_source, last_visited, v->cargo_days); + result |= 1; + v->cargo_count = 0; + } else if (u->next_order & OF_UNLOAD) { + /* unload goods and let it wait at the station */ + st->time_since_unload = 0; + + if ((t=ge->waiting_acceptance & 0xFFF) == 0) { + // No goods waiting at station + ge->enroute_time = v->cargo_days; + ge->enroute_from = v->cargo_source; + } else { + // Goods already waiting at station. Set counters to the worst value. + if (v->cargo_days >= ge->enroute_time) + ge->enroute_time = v->cargo_days; + if ((byte)last_visited != ge->enroute_from) + ge->enroute_from = v->cargo_source; + } + // Update amount of waiting cargo + ge->waiting_acceptance = (ge->waiting_acceptance &~0xFFF) | min(v->cargo_count + t, 0xFFF); + result |= 2; + v->cargo_count = 0; + } + } + + /* don't pick up goods that we unloaded */ + if (u->next_order & OF_UNLOAD) + goto next_vehicle; + + /* update stats */ + ge->days_since_pickup = 0; + t = u->max_speed; + if (u->type == VEH_Road) t >>=1; + + // if last speed is 0, we treat that as if no vehicle has ever visited the station. + ge->last_speed = t < 255 ? t : 255; + ge->last_age = _cur_year - v->build_year; + + // If there's goods waiting at the station, and the vehicle + // has capacity for it, load it on the vehicle. + if ((count=ge->waiting_acceptance & 0xFFF) != 0 && + (cap = v->cargo_cap - v->cargo_count) != 0) { + if (cap > count) cap = count; + v->cargo_count += cap; + ge->waiting_acceptance -= cap; + unloading_time += cap; + st->time_since_load = 0; + + // And record the source of the cargo, and the days in travel. + v->cargo_source = ge->enroute_from; + v->cargo_days = ge->enroute_time; + result |= 2; + st->last_vehicle = v->index; + } + +next_vehicle:; + if (!(v = v->next)) + break; + } + + v = u; + + if (v->type == VEH_Train) { + int num = - (int)GetStationPlatforms(st, v->tile) * 2; + do num++; while ( (v=v->next) != NULL); + if (num > 0) { + unloading_time <<=1; + unloading_time += num * unloading_time; + } + v = u; + } + + v->load_unload_time_rem = unloading_time; + + if (result != 0) { + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + if (result & 2) + InvalidateWindow(WC_STATION_VIEW, last_visited); + + if (profit != 0) { + v->profit_this_year += profit; + SubtractMoneyFromPlayer(-profit); + + if (_current_player == _local_player) + SndPlayVehicleFx(0x12, v); + + ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, -profit); + } + } + + return result; +} + +void PlayersMonthlyLoop() +{ + PlayersGenStatistics(); + if (_patches.inflation) + AddInflation(); + PlayersPayInterest(); + HandleEconomyFluctuations(); + SubsidyMonthlyHandler(); +} + +static void DoAcquireCompany(Player *p) +{ + Player *owner; + int i,pi; + int32 value; + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM32(2, p->bankrupt_value); + AddNewsItem( (StringID)(_current_player + 16*2), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0); + + // original code does this a little bit differently + pi = p->index; + ChangeOwnershipOfPlayerItems(pi, _current_player); + + if (p->bankrupt_value == 0) { + owner = DEREF_PLAYER(_current_player); + owner->current_loan += p->current_loan; + } + + value = CalculateCompanyValue(p) >> 2; + for(i=0; i!=4; i++) { + if (p->share_owners[i] != 0xFF) { + owner = DEREF_PLAYER(p->share_owners[i]); + owner->money64 += value; + owner->yearly_expenses[0][EXPENSES_OTHER] += value; + UpdatePlayerMoney32(owner); + } + } + + p->is_active = false; + + DeletePlayerWindows(pi); +} + +int32 CmdBuyShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p; + int32 cost; + byte *b; + int i; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + p = DEREF_PLAYER(p1); + + cost = CalculateCompanyValue(p) >> 2; + if (flags & DC_EXEC) { + b = p->share_owners; + while (*b != 0xFF) b++; /* share owners is guaranteed to contain at least one 0xFF */ + *b = _current_player; + + for(i=0;p->share_owners[i] == _current_player;) { + if (++i == 4) { + p->bankrupt_value = 0; + DoAcquireCompany(p); + break; + } + } + InvalidateWindow(WC_COMPANY, (int)p1); + } + return cost; +} + +int32 CmdSellShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p; + int32 cost; + byte *b; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + p = DEREF_PLAYER(p1); + + /* adjust it a little to make it less profitable to sell and buy */ + cost = CalculateCompanyValue(p) >> 2; + cost = -(cost - (cost >> 7)); + + if (flags & DC_EXEC) { + b = p->share_owners; + while (*b != _current_player) b++; /* share owners is guaranteed to contain player */ + *b = 0xFF; + InvalidateWindow(WC_COMPANY, (int)p1); + } + return cost; +} + +int32 CmdBuyCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p; + SET_EXPENSES_TYPE(EXPENSES_OTHER); + p = DEREF_PLAYER(p1); + if (flags & 1) { + DoAcquireCompany(p); + } + return p->bankrupt_value; +} + +// Prices +static void SaveLoad_PRIC() +{ + SlArray(&_price, NUM_PRICES, SLE_INT32); + SlArray(&_price_frac, NUM_PRICES, SLE_UINT16); +} + +// Cargo payment rates +static void SaveLoad_CAPR() +{ + SlArray(&_cargo_payment_rates, NUM_CARGO, SLE_INT32); + SlArray(&_cargo_payment_rates_frac, NUM_CARGO, SLE_UINT16); +} + +static const byte _economy_desc[] = { + SLE_VAR(Economy,max_loan, SLE_INT32), + SLE_VAR(Economy,max_loan_unround, SLE_INT32), + SLE_VAR(Economy,fluct, SLE_FILE_I16 | SLE_VAR_I32), + SLE_VAR(Economy,interest_rate, SLE_UINT8), + SLE_VAR(Economy,infl_amount, SLE_UINT8), + SLE_VAR(Economy,infl_amount_pr, SLE_UINT8), + SLE_END() +}; + +// Economy variables +static void SaveLoad_ECMY() +{ + SlObject(&_economy, &_economy_desc); +} + +const ChunkHandler _economy_chunk_handlers[] = { + { 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH}, + { 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH}, + { 'SUBS', Save_SUBS, Load_SUBS, CH_ARRAY}, + { 'ECMY', SaveLoad_ECMY, SaveLoad_ECMY, CH_RIFF | CH_LAST}, +}; + + + + diff --git a/economy.h b/economy.h new file mode 100644 --- /dev/null +++ b/economy.h @@ -0,0 +1,34 @@ +#ifndef ECONOMY_H +#define ECONOMY_H + +typedef struct { + // Maximum possible loan + int32 max_loan; + int32 max_loan_unround; + // Economy fluctuation status + int fluct; + // Interest + byte interest_rate; + byte infl_amount; + byte infl_amount_pr; +} Economy; + +VARDEF Economy _economy; + +typedef struct Subsidy { + byte cargo_type; + byte age; + byte from; + byte to; +} Subsidy; + + +VARDEF Subsidy _subsidies[MAX_PLAYERS]; +Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode); +void DeleteSubsidyWithIndustry(byte index); +void DeleteSubsidyWithStation(byte index); + +int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type); +uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount); + +#endif /* ECONOMY_H */ diff --git a/engine.c b/engine.c new file mode 100644 --- /dev/null +++ b/engine.c @@ -0,0 +1,550 @@ +#include "stdafx.h" +#include "ttd.h" +#include "engine.h" +#include "table/engines.h" +#include "player.h" +#include "command.h" +#include "vehicle.h" +#include "news.h" +#include "saveload.h" + +#define UPDATE_PLAYER_RAILTYPE(e,p) if ((byte)(e->railtype + 1) > p->max_railtype) p->max_railtype = e->railtype + 1; + +enum { + ENGINE_AVAILABLE = 1, + ENGINE_INTRODUCING = 2, + ENGINE_PREVIEWING = 4, +}; + +/* This maps per-landscape cargo ids to globally unique cargo ids usable ie. in + * the custom GRF files. It is basically just a transcribed table from + * TTDPatch's newgrf.txt. */ +byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = { + /* LT_NORMAL */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 }, + /* LT_HILLY */ { 0, 1, 2, 3, 4, 5, 6, 7, 28, 11, 10, 12 }, + /* LT_DESERT */ { 0, 16, 2, 3, 13, 5, 6, 7, 14, 15, 10, 12 }, + /* LT_CANDY */ { 0, 17, 2, 18, 19, 20, 21, 22, 23, 24, 25, 26 }, + // 27 is paper in temperate climate in TTDPatch + // Following can be renumbered: + // 29 is the default cargo for the purpose of spritesets + // 30 is the purchase list image (the equivalent of 0xff) for the purpose of spritesets +}; + +/* These two arrays provide a reverse mapping. */ +byte _local_cargo_id_ctype[NUM_CID] = { + CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, // 0-7 + CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, // 8-15 + CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, // 16-23 + CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER /* unsup. */, CT_HILLY_UNUSED // 24-28 +}; + +/* LT'th bit is set of the particular landscape if cargo available there. + * 1: LT_NORMAL, 2: LT_HILLY, 4: LT_DESERT, 8: LT_CANDY */ +byte _local_cargo_id_landscape[NUM_CID] = { + 15, 3, 15, 7, 3, 7, 7, 7, 1, 1, 7, 2, 7, // 0-12 + 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 2, // 13-28 +}; + +void ShowEnginePreviewWindow(int engine); + +void DeleteCustomEngineNames() +{ + uint i; + StringID old; + + for(i=0; i!=TOTAL_NUM_ENGINES; i++) { + old = _engine_name_strings[i]; + _engine_name_strings[i] = i + STR_8000_KIRBY_PAUL_TANK_STEAM; + DeleteName(old); + } + + _vehicle_design_names &= ~1; +} + +void LoadCustomEngineNames() +{ + // XXX: not done */ + DEBUG(misc, 1) ("LoadCustomEngineNames: not done"); +} + +static void SetupEngineNames() +{ + uint i; + + for(i=0; i!=TOTAL_NUM_ENGINES; i++) + _engine_name_strings[i] = STR_SV_EMPTY; + + DeleteCustomEngineNames(); + LoadCustomEngineNames(); +} + +static void AdjustAvailAircraft() +{ + uint16 date = _date; + byte avail = 0; + if (date >= 12784) avail |= 2; // big airport + if (date < 14610 || _patches.always_small_airport) avail |= 1; // small airport + if (date >= 15706) avail |= 4; // enable heliport + + if (avail != _avail_aircraft) { + _avail_aircraft = avail; + InvalidateWindow(WC_BUILD_STATION, 0); + } +} + +static void CalcEngineReliability(Engine *e) +{ + uint age = e->age; + + if (age < e->duration_phase_1) { + uint start = e->reliability_start; + e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; + } else if ((age -= e->duration_phase_1) < e->duration_phase_2) { + e->reliability = e->reliability_max; + } else if ((age -= e->duration_phase_2) < e->duration_phase_3) { + uint max = e->reliability_max; + e->reliability = (int)age * (int)(e->reliability_final - max) / e->duration_phase_3 + max; + } else { + e->player_avail = _patches.never_expire_vehicles ? -1 : 0; + e->reliability = e->reliability_final; + } +} + +void StartupEngines() +{ + Engine *e; + const EngineInfo *ei; + uint32 r; + + SetupEngineNames(); + + + for(e=_engines, ei=_engine_info; e != endof(_engines); e++,ei++) { + e->age = 0; + e->railtype = ei->railtype_climates >> 4; + e->flags = 0; + e->player_avail = 0; + + r = Random(); + e->intro_date = (uint16)((r & 0x1FF) + ei->base_intro); + if (e->intro_date <= _date) { + e->age = (_date - e->intro_date) >> 5; + e->player_avail = (byte)-1; + e->flags |= ENGINE_AVAILABLE; + } + + e->reliability_start = (uint16)(((r >> 16) & 0x3fff) + 0x7AE0); + r = Random(); + e->reliability_max = (uint16)((r & 0x3fff) + 0xbfff); + e->reliability_final = (uint16)(((r>>16) & 0x3fff) + 0x3fff); + + r = Random(); + e->duration_phase_1 = (uint16)((r & 0x1F) + 7); + e->duration_phase_2 = (uint16)(((r >> 5) & 0xF) + ei->base_life * 12 - 96); + e->duration_phase_3 = (uint16)(((r >> 9) & 0x7F) + 120); + + e->reliability_spd_dec = (ei->unk2&0x7F) << 2; + + /* my invented flag for something that is a wagon */ + if (ei->unk2 & 0x80) { + e->age = 0xFFFF; + } else { + CalcEngineReliability(e); + } + + e->lifelength = ei->lifelength + _patches.extend_vehicle_life; + + // prevent certain engines from ever appearing. + if (!HASBIT(ei->railtype_climates, _opt.landscape)) { + e->flags |= ENGINE_AVAILABLE; + e->player_avail = 0; + } + } + + AdjustAvailAircraft(); +} + + +uint32 _engine_refit_masks[256]; + + +// TODO: We don't support cargo-specific wagon overrides. Pretty exotic... ;-) --pasky + +struct WagonOverride { + byte *train_id; + int trains; + struct SpriteSuperSet superset; +}; + +static struct WagonOverrides { + int overrides_count; + struct WagonOverride *overrides; +} _engine_wagon_overrides[256]; + +void SetWagonOverrideSprites(byte engine, struct SpriteSuperSet *superset, + byte *train_id, int trains) +{ + struct WagonOverrides *wos; + struct WagonOverride *wo; + + wos = &_engine_wagon_overrides[engine]; + wos->overrides_count++; + wos->overrides = realloc(wos->overrides, + wos->overrides_count * sizeof(struct WagonOverride)); + + wo = &wos->overrides[wos->overrides_count - 1]; + wo->superset = *superset; + wo->trains = trains; + wo->train_id = malloc(trains); + memcpy(wo->train_id, train_id, trains); +} + +static struct SpriteSuperSet *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine) +{ + struct WagonOverrides *wos = &_engine_wagon_overrides[engine]; + int i; + + // XXX: This could turn out to be a timesink on profiles. We could always just + // dedicate 65535 bytes for an [engine][train] trampoline. + + for (i = 0; i < wos->overrides_count; i++) { + struct WagonOverride *wo = &wos->overrides[i]; + int j; + + for (j = 0; j < wo->trains; j++) { + if (wo->train_id[j] == overriding_engine) + return &wo->superset; + } + } + return NULL; +} + + +byte _engine_original_sprites[256]; +// 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list) +// (It isn't and shouldn't be like this in the GRF files since new cargo types +// may appear in future - however it's more convenient to store it like this in +// memory. --pasky) +static struct SpriteSuperSet _engine_custom_sprites[256][NUM_CID]; + +void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteSuperSet *superset) +{ + assert(superset->sprites_per_set == 4 || superset->sprites_per_set == 8); + _engine_custom_sprites[engine][cargo] = *superset; +} + +int GetCustomEngineSprite(byte engine, uint16 overriding_engine, byte cargo, + byte loaded, byte in_motion, byte direction) +{ + struct SpriteSuperSet *superset = &_engine_custom_sprites[engine][cargo]; + int totalsets, spriteset; + int r; + + if (overriding_engine != 0xffff) { + struct SpriteSuperSet *overset; + + overset = GetWagonOverrideSpriteSet(engine, overriding_engine); + if (overset) superset = overset; + } + + if (!superset->sprites_per_set && cargo != 29) { + // This superset is empty but perhaps there'll be a default one. + superset = &_engine_custom_sprites[engine][29]; + } + + if (!superset->sprites_per_set) { + // This superset is empty. This function users should therefore + // look up the sprite number in _engine_original_sprites. + return 0; + } + + direction %= 8; + if (superset->sprites_per_set == 4) + direction %= 4; + + totalsets = in_motion ? superset->loaded_count : superset->loading_count; + + // My aim here is to make it possible to visually determine absolutely + // empty and totally full vehicles. --pasky + if (loaded == 100 || totalsets == 1) { // full + spriteset = totalsets - 1; + } else if (loaded == 0 || totalsets == 2) { // empty + spriteset = 0; + } else { // something inbetween + spriteset = loaded * (totalsets - 2) / 100 + 1; + // correct possible rounding errors + if (!spriteset) + spriteset = 1; + else if (spriteset == totalsets - 1) + spriteset--; + } + + r = (in_motion ? superset->loaded[spriteset] : superset->loading[spriteset]) + direction; + return r; +} + + +static char *_engine_custom_names[256]; + +void SetCustomEngineName(int engine, char *name) +{ + _engine_custom_names[engine] = strdup(name); +} + +StringID GetCustomEngineName(int engine) +{ + if (!_engine_custom_names[engine]) + return _engine_name_strings[engine]; + strcpy(_userstring, _engine_custom_names[engine]); + return STR_SPEC_USERSTRING; +} + + +void AcceptEnginePreview(Engine *e, int player) +{ + Player *p; + + SETBIT(e->player_avail, player); + + p = DEREF_PLAYER(player); + + UPDATE_PLAYER_RAILTYPE(e,p); + + e->preview_player = 0xFF; + InvalidateWindowClasses(WC_BUILD_VEHICLE); +} + +void EnginesDailyLoop() +{ + Engine *e; + int i,num; + Player *p; + uint mask; + int32 best_hist; + int best_player; + + if (_cur_year >= 130) + return; + + for(e=_engines,i=0; i!=TOTAL_NUM_ENGINES; e++,i++) { + if (e->flags & ENGINE_INTRODUCING) { + if (e->flags & ENGINE_PREVIEWING) { + if (!--e->preview_wait) { + e->flags &= ~ENGINE_PREVIEWING; + DeleteWindowById(WC_ENGINE_PREVIEW, i); + e->preview_player++; + } + } else if (e->preview_player != 0xFF) { + num = e->preview_player; + mask = 0; + do { + best_hist = -1; + best_player = -1; + FOR_ALL_PLAYERS(p) { + if (p->is_active && p->block_preview == 0 && !HASBIT(mask,p->index) && + p->old_economy[0].performance_history > best_hist) { + best_hist = p->old_economy[0].performance_history; + best_player = p->index; + } + } + if (best_player == -1) { + e->preview_player = 0xFF; + goto next_engine; + } + mask |= (1 << best_player); + } while (--num != 0); + + if (!IS_HUMAN_PLAYER(best_player)) { + /* TTDBUG: TTD has a bug here */ + AcceptEnginePreview(e, best_player); + } else { + e->flags |= ENGINE_PREVIEWING; + e->preview_wait = 20; + if (IS_INTERACTIVE_PLAYER(best_player)) { + ShowEnginePreviewWindow(i); + } + } + } + } + next_engine:; + } +} + +int32 CmdWantEnginePreview(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + AcceptEnginePreview(&_engines[p1], _current_player); + } + return 0; +} + +void NewVehicleAvailable(Engine *e) +{ + Vehicle *v; + Player *p; + int index = e - _engines; + + // In case the player didn't build the vehicle during the intro period, + // prevent that player from getting future intro periods for a while. + if (e->flags&ENGINE_INTRODUCING) { + FOR_ALL_PLAYERS(p) { + if (!HASBIT(e->player_avail,p->index)) + continue; + + for(v=_vehicles;;) { + if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || + (v->type == VEH_Aircraft && v->subtype <= 2)) { + if (v->owner == p->index && v->engine_type == index) break; + } + if (++v == endof(_vehicles)) { + p->block_preview = 20; + break; + } + } + } + } + + // Now available for all players + e->player_avail = (byte)-1; + FOR_ALL_PLAYERS(p) { + if (p->is_active) + UPDATE_PLAYER_RAILTYPE(e,p); + } + + e->flags = (e->flags & ~ENGINE_INTRODUCING) | ENGINE_AVAILABLE; + + if ((byte)index < NUM_TRAIN_ENGINES) { + AddNewsItem(index, NEWS_FLAGS(NM_CALLBACK, 0, NT_NEW_VEHICLES, DNC_TRAINAVAIL), 0, 0); + } else if ((byte)index < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES) { + AddNewsItem(index, NEWS_FLAGS(NM_CALLBACK, 0, NT_NEW_VEHICLES, DNC_ROADAVAIL), 0, 0); + } else if ((byte)index < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES) { + AddNewsItem(index, NEWS_FLAGS(NM_CALLBACK, 0, NT_NEW_VEHICLES, DNC_SHIPAVAIL), 0, 0); + } else { + AddNewsItem(index, NEWS_FLAGS(NM_CALLBACK, 0, NT_NEW_VEHICLES, DNC_AIRCRAFTAVAIL), 0, 0); + } + + InvalidateWindowClasses(WC_BUILD_VEHICLE); +} + +void EnginesMonthlyLoop() +{ + Engine *e; + + if (_cur_year < 130) { + for(e=_engines; e != endof(_engines); e++) { + // Age the vehicle + if (e->flags&ENGINE_AVAILABLE && e->age != 0xFFFF) { + e->age++; + CalcEngineReliability(e); + } + + if (!(e->flags & ENGINE_AVAILABLE) && (uint16)(_date - min(_date, 365)) >= e->intro_date) { + // Introduce it to all players + NewVehicleAvailable(e); + } else if (!(e->flags & (ENGINE_AVAILABLE|ENGINE_INTRODUCING)) && _date >= e->intro_date) { + // Introduction date has passed.. show introducing dialog to one player. + e->flags |= ENGINE_INTRODUCING; + e->preview_player = 1; // Give to the player with the highest rating. + } + } + } + AdjustAvailAircraft(); +} + +int32 CmdRenameEngine(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str; + + str = AllocateName((byte*)_decode_parameters, 0); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + StringID old_str = _engine_name_strings[p1]; + _engine_name_strings[p1] = str; + DeleteName(old_str); + _vehicle_design_names |= 3; + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + + return 0; +} + +int GetPlayerMaxRailtype(int p) +{ + Engine *e; + int rt = 0; + int i; + + for(e=_engines,i=0; i!=lengthof(_engines); e++,i++) { + if (!HASBIT(e->player_avail, p)) + continue; + + if ((i >= 27 && i < 54) || (i >= 57 && i < 84) || (i >= 89 && i < 116)) + continue; + + if (rt < e->railtype) + rt = e->railtype; + } + + return rt + 1; +} + + +static const byte _engine_desc[] = { + SLE_VAR(Engine,intro_date, SLE_UINT16), + SLE_VAR(Engine,age, SLE_UINT16), + SLE_VAR(Engine,reliability, SLE_UINT16), + SLE_VAR(Engine,reliability_spd_dec, SLE_UINT16), + SLE_VAR(Engine,reliability_start, SLE_UINT16), + SLE_VAR(Engine,reliability_max, SLE_UINT16), + SLE_VAR(Engine,reliability_final, SLE_UINT16), + SLE_VAR(Engine,duration_phase_1, SLE_UINT16), + SLE_VAR(Engine,duration_phase_2, SLE_UINT16), + SLE_VAR(Engine,duration_phase_3, SLE_UINT16), + + SLE_VAR(Engine,lifelength, SLE_UINT8), + SLE_VAR(Engine,flags, SLE_UINT8), + SLE_VAR(Engine,preview_player, SLE_UINT8), + SLE_VAR(Engine,preview_wait, SLE_UINT8), + SLE_VAR(Engine,railtype, SLE_UINT8), + SLE_VAR(Engine,player_avail, SLE_UINT8), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + +static void Save_ENGN() +{ + Engine *e; + int i; + for(i=0,e=_engines; i != lengthof(_engines); i++,e++) { + SlSetArrayIndex(i); + SlObject(e, _engine_desc); + } +} + +static void Load_ENGN() +{ + int index; + while ((index = SlIterateArray()) != -1) { + SlObject(&_engines[index], _engine_desc); + } +} + +static void LoadSave_ENGS() +{ + SlArray(_engine_name_strings, lengthof(_engine_name_strings), SLE_STRINGID); +} + +const ChunkHandler _engine_chunk_handlers[] = { + { 'ENGN', Save_ENGN, Load_ENGN, CH_ARRAY}, + { 'ENGS', LoadSave_ENGS, LoadSave_ENGS, CH_RIFF | CH_LAST}, +}; + + + diff --git a/engine.h b/engine.h new file mode 100644 --- /dev/null +++ b/engine.h @@ -0,0 +1,137 @@ +#ifndef ENGINE_H +#define ENGINE_H + +typedef struct RailVehicleInfo { + byte image_index; + byte flags; /* 1=multihead engine, 2=wagon */ + byte base_cost; + uint16 max_speed; + uint16 power; + byte weight; + byte running_cost_base; + byte engclass; // 0: steam, 1: diesel, 2: electric + byte capacity; + byte cargo_type; +} RailVehicleInfo; + +typedef struct ShipVehicleInfo { + byte image_index; + byte base_cost; + uint16 max_speed; + byte cargo_type; + uint16 capacity; + byte running_cost; + byte sfx; + byte refittable; +} ShipVehicleInfo; + + +typedef struct EngineInfo { + uint16 base_intro; + byte unk2; + byte lifelength; + byte base_life; + byte railtype_climates; +} EngineInfo; + +typedef struct Engine { + uint16 intro_date; + uint16 age; + uint16 reliability; + uint16 reliability_spd_dec; + uint16 reliability_start, reliability_max, reliability_final; + uint16 duration_phase_1, duration_phase_2, duration_phase_3; + byte lifelength; + byte flags; + byte preview_player; + byte preview_wait; + byte railtype; + byte player_avail; +} Engine; + + +enum { + RVI_MULTIHEAD = 1, + RVI_WAGON = 2, +}; + + +void StartupEngines(); + + +struct SpriteSuperSet { + // XXX: Would anyone ever need more than 16 spritesets? Maybe we should + // use even less, now we take whole 8kb for custom sprites table, oh my! + byte sprites_per_set; // means number of directions - 4 or 8 + // Loaded = in motion, loading = not moving + // Each superset contains several spritesets, for various loading stages + byte loaded_count; + uint16 loaded[16]; // sprite ids + byte loading_count; + uint16 loading[16]; // sprite ids +}; + +extern byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO]; +enum { + CID_DEFAULT = 29, + CID_PURCHASE = 30, + NUM_CID = 31, +}; +extern byte _local_cargo_id_ctype[NUM_CID]; +extern byte _local_cargo_id_landscape[NUM_CID]; + +extern uint32 _engine_refit_masks[256]; + +extern byte _engine_original_sprites[256]; +void SetWagonOverrideSprites(byte engine, struct SpriteSuperSet *superset, byte *train_id, int trains); +void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteSuperSet *superset); +// loaded is in percents, overriding_engine 0xffff is none +int GetCustomEngineSprite(byte engine, uint16 overriding_engine, byte cargo, byte loaded, byte in_motion, byte direction); +#define GetCustomVehicleSprite(v, direction) \ + GetCustomEngineSprite(v->engine_type, v->type == VEH_Train ? v->u.rail.first_engine : -1, \ + _global_cargo_id[_opt.landscape][v->cargo_type], \ + ((v->cargo_count + 1) * 100) / (v->cargo_cap + 1), \ + !!v->cur_speed, direction); + +void SetCustomEngineName(int engine, char *name); +StringID GetCustomEngineName(int engine); + + +void DrawTrainEngine(int x, int y, int engine, uint32 image_ormod); +void DrawRoadVehEngine(int x, int y, int engine, uint32 image_ormod); +void DrawShipEngine(int x, int y, int engine, uint32 image_ormod); +void DrawAircraftEngine(int x, int y, int engine, uint32 image_ormod); + +void DrawTrainEngineInfo(int engine, int x, int y, int maxw); +void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw); +void DrawShipEngineInfo(int engine, int x, int y, int maxw); +void DrawAircraftEngineInfo(int engine, int x, int y, int maxw); + +void AcceptEnginePreview(Engine *e, int player); + +void LoadCustomEngineNames(); +void DeleteCustomEngineNames(); + + +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_NORMAL_RAIL_ENGINES+NUM_MONORAIL_ENGINES+NUM_MAGLEV_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]; +VARDEF StringID _engine_name_strings[TOTAL_NUM_ENGINES]; + +extern EngineInfo _engine_info[TOTAL_NUM_ENGINES]; +extern RailVehicleInfo _rail_vehicle_info[]; +#define ship_vehicle_info(e) _ship_vehicle_info[e - SHIP_ENGINES_INDEX] +extern ShipVehicleInfo _ship_vehicle_info[]; + +#endif diff --git a/engine_gui.c b/engine_gui.c new file mode 100644 --- /dev/null +++ b/engine_gui.c @@ -0,0 +1,224 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "engine.h" +#include "command.h" +#include "news.h" + +void DrawShipEngine(int x, int y, int engine, uint32 image_ormod); +void DrawShipEngineInfo(int engine, int x, int y, int maxw); + + +StringID GetEngineCategoryName(byte engine) +{ + if (engine < NUM_NORMAL_RAIL_ENGINES) + return STR_8102_RAILROAD_LOCOMOTIVE; + + if (engine < NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES) + return STR_8106_MONORAIL_LOCOMOTIVE; + + if (engine < NUM_TRAIN_ENGINES) + return STR_8107_MAGLEV_LOCOMOTIVE; + + if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES) + return STR_8103_ROAD_VEHICLE; + + if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES) + return STR_8105_SHIP; + + return STR_8104_AIRCRAFT; +} + +static const Widget _engine_preview_widgets[] = { +{ WWT_TEXTBTN, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 5, 11, 299, 0, 13, STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 5, 0, 299, 14, 191, 0x0}, +{ WWT_PUSHTXTBTN, 5, 85, 144, 172, 183, STR_00C9_NO}, +{ WWT_PUSHTXTBTN, 5, 155, 214, 172, 183, STR_00C8_YES}, +{ WWT_LAST}, +}; + +typedef void DrawEngineProc(int x, int y, int engine, uint32 image_ormod); +typedef void DrawEngineInfoProc(int x, int y, int engine, int maxw); + +typedef struct DrawEngineInfo { + DrawEngineProc *engine_proc; + DrawEngineInfoProc *info_proc; +} DrawEngineInfo; + +static const DrawEngineInfo _draw_engine_list[4] = { + {DrawTrainEngine,DrawTrainEngineInfo}, + {DrawRoadVehEngine,DrawRoadVehEngineInfo}, + {DrawShipEngine,DrawShipEngineInfo}, + {DrawAircraftEngine,DrawAircraftEngineInfo}, +}; + +static void EnginePreviewWndProc(Window *w, WindowEvent *e) +{ + byte eng; + int engine; + const DrawEngineInfo *dei; + int width; + + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + engine = w->window_number; + + SET_DPARAM16(0, GetEngineCategoryName(engine)); + DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296); + + DrawStringCentered(w->width >> 1, 80, GetCustomEngineName(engine), 0x10); + + eng = (byte)engine; + (dei = _draw_engine_list,eng < NUM_TRAIN_ENGINES) || + (dei++,eng < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES) || + (dei++,eng < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES) || + (dei++, true); + + width = w->width; + dei->engine_proc(width >> 1, 100, engine, 0); + dei->info_proc(engine, width >> 1, 130, width - 52); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: DeleteWindow(w); break; + case 4: + DoCommandP(0, w->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW); + DeleteWindow(w); + break; + } + break; + } +} + +static const WindowDesc _engine_preview_desc = { + WDP_CENTER, WDP_CENTER, 300, 192, + WC_ENGINE_PREVIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _engine_preview_widgets, + EnginePreviewWndProc +}; + + +void ShowEnginePreviewWindow(int engine) +{ + Window *w; + + w = AllocateWindowDesc(&_engine_preview_desc); + w->window_number = engine; +} + +void DrawNewsNewTrainAvail(Window *w) +{ + int engine; + + DrawNewsBorder(w); + + engine = WP(w,news_d).ni->string_id; + SET_DPARAM16(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); + + SET_DPARAM16(0, GetCustomEngineName(engine)); + DrawStringMultiCenter(w->width >> 1, 57, STR_885A, w->width - 2); + + DrawTrainEngine(w->width >> 1, 88, engine, 0); + GfxFillRect(25, 56, w->width - 56, 112, 0x4323); + DrawTrainEngineInfo(engine, w->width >> 1, 129, w->width - 52); +} + +StringID GetNewsStringNewTrainAvail(NewsItem *ni) +{ + int engine = ni->string_id; + SET_DPARAM16(0, STR_8859_NEW_NOW_AVAILABLE); + SET_DPARAM16(1, GetEngineCategoryName(engine)); + SET_DPARAM16(2, GetCustomEngineName(engine)); + return STR_02B6; +} + +void DrawNewsNewAircraftAvail(Window *w) +{ + int engine; + + DrawNewsBorder(w); + + engine = WP(w,news_d).ni->string_id; + + DrawStringMultiCenter(w->width >> 1, 20, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE, w->width - 2); + GfxFillRect(25, 56, w->width - 25, w->height - 2, 10); + + SET_DPARAM16(0, GetCustomEngineName(engine)); + DrawStringMultiCenter(w->width >> 1, 57, STR_A02D, w->width - 2); + + DrawAircraftEngine(w->width >> 1, 93, engine, 0); + GfxFillRect(25, 56, w->width - 56, 110, 0x4323); + DrawAircraftEngineInfo(engine, w->width >> 1, 131, w->width - 52); +} + +StringID GetNewsStringNewAircraftAvail(NewsItem *ni) +{ + int engine = ni->string_id; + SET_DPARAM16(0, STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE); + SET_DPARAM16(1, GetCustomEngineName(engine)); + return STR_02B6; +} + +void DrawNewsNewRoadVehAvail(Window *w) +{ + int engine; + + DrawNewsBorder(w); + + engine = WP(w,news_d).ni->string_id; + DrawStringMultiCenter(w->width >> 1, 20, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE, w->width - 2); + GfxFillRect(25, 56, w->width - 25, w->height - 2, 10); + + SET_DPARAM16(0, GetCustomEngineName(engine)); + DrawStringMultiCenter(w->width >> 1, 57, STR_9029, w->width - 2); + + DrawRoadVehEngine(w->width >> 1, 88, engine, 0); + GfxFillRect(25, 56, w->width - 56, 112, 0x4323); + DrawRoadVehEngineInfo(engine, w->width >> 1, 129, w->width - 52); +} + +StringID GetNewsStringNewRoadVehAvail(NewsItem *ni) +{ + int engine = ni->string_id; + SET_DPARAM16(0, STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE); + SET_DPARAM16(1, GetCustomEngineName(engine)); + return STR_02B6; +} + +void DrawNewsNewShipAvail(Window *w) +{ + int engine; + + DrawNewsBorder(w); + + engine = WP(w,news_d).ni->string_id; + + DrawStringMultiCenter(w->width >> 1, 20, STR_982C_NEW_SHIP_NOW_AVAILABLE, w->width - 2); + GfxFillRect(25, 56, w->width - 25, w->height - 2, 10); + + SET_DPARAM16(0, GetCustomEngineName(engine)); + DrawStringMultiCenter(w->width >> 1, 57, STR_982D, w->width - 2); + + DrawShipEngine(w->width >> 1, 93, engine, 0); + GfxFillRect(25, 56, w->width - 56, 110, 0x4323); + DrawShipEngineInfo(engine, w->width >> 1, 131, w->width - 52); +} + +StringID GetNewsStringNewShipAvail(NewsItem *ni) +{ + int engine = ni->string_id; + SET_DPARAM16(0, STR_982C_NEW_SHIP_NOW_AVAILABLE); + SET_DPARAM16(1, GetCustomEngineName(engine)); + return STR_02B6; +} diff --git a/extmidi.c b/extmidi.c new file mode 100644 --- /dev/null +++ b/extmidi.c @@ -0,0 +1,103 @@ +#ifndef __BEOS__ +#ifndef __MORPHOS__ +#include "stdafx.h" + +#include "ttd.h" +#include "hal.h" +#include +#include +#include +#include +#include +#include + +#ifndef EXTERNAL_PLAYER +#define EXTERNAL_PLAYER "/usr/bin/timidity" +#endif + +static pid_t _pid; + +static void extmidi_kill(void) { + if(_pid > 0) { + kill(_pid, SIGKILL); + while(waitpid(_pid, NULL, WNOHANG) != _pid); + } + _pid = 0; +} + +static char *extmidi_start(char **parm) { + _pid = 0; + + return NULL; +} + +static void extmidi_stop(void) { + extmidi_kill(); +} + +static void extmidi_play_song(const char *filename) { + extmidi_kill(); + + _pid = fork(); + if(_pid < 0) { + fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno)); + _pid = 0; + return; + } + + if(_pid == 0) { + #if defined(MIDI_ARG) + execl(EXTERNAL_PLAYER, "extmidi", MIDI_ARG, filename, NULL); + #else + execl(EXTERNAL_PLAYER, "extmidi", filename, NULL); + #endif + + fprintf(stderr, "extmidi: couldn't execl: %s\n", strerror(errno)); + + exit(0); + } + + + + usleep(500); + + + if(_pid == waitpid(_pid, NULL, WNOHANG)) { + fprintf(stderr, "extmidi: play song failed\n"); + _pid = 0; + + usleep(5000); + + } +} + +static void extmidi_stop_song(void) { + extmidi_kill(); +} + +static bool extmidi_is_playing(void) { + if(_pid == 0) + return 0; + + if(waitpid(_pid, NULL, WNOHANG) == _pid) { + _pid = 0; + return 0; + } + + return 1; +} + +static void extmidi_set_volume(byte vol) { + fprintf(stderr, "extmidi: set volume not implemented\n"); +} + +const HalMusicDriver _extmidi_music_driver = { + extmidi_start, + extmidi_stop, + extmidi_play_song, + extmidi_stop_song, + extmidi_is_playing, + extmidi_set_volume, +}; +#endif /* __MORPHOS__ */ +#endif /* __BEOS__ */ diff --git a/fileio.c b/fileio.c new file mode 100644 --- /dev/null +++ b/fileio.c @@ -0,0 +1,123 @@ +#include "stdafx.h" +#include "ttd.h" +#if defined(UNIX) +#include // 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() +{ + 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() +{ + 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() +{ + byte b = FioReadByte(); + return (FioReadByte() << 8) | b; +} + +uint32 FioReadDword() +{ + 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); +} + +void FioCloseAll() +{ + int i; + + for(i=0; i!=lengthof(_fio.handles); i++) { + if (_fio.handles[i] != NULL) { + fclose(_fio.handles[i]); + _fio.handles[i] = NULL; + } + } +} + +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"); + } +#endif + + if (f == NULL) + error("Cannot open file '%s'", buf); + + _fio.handles[slot] = f; + FioSeekToFile(slot << 24); +} + + diff --git a/fileio.h b/fileio.h new file mode 100644 --- /dev/null +++ b/fileio.h @@ -0,0 +1,15 @@ +#ifndef FILEIO_H +#define FILEIO_H + +void FioSeekTo(uint32 pos, int mode); +void FioSeekToFile(uint32 pos); +uint32 FioGetPos(); +byte FioReadByte(); +uint16 FioReadWord(); +uint32 FioReadDword(); +void FioCloseAll(); +void FioOpenFile(int slot, const char *filename); +void FioReadBlock(void *ptr, uint size); +void FioSkipBytes(int n); + +#endif /* FILEIO_H */ diff --git a/functions.h b/functions.h new file mode 100644 --- /dev/null +++ b/functions.h @@ -0,0 +1,253 @@ +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +/* vehicle.c */ + +/* window.c */ + + +/* landscape.c */ +void FindLandscapeHeight(TileInfo *ti, uint x, uint y); +void FindLandscapeHeightByTile(TileInfo *ti, uint tile); +uint GetTileSlope(uint tile, int *h); +int GetTileZ(uint tile); + +void DoClearSquare(uint tile); +void CDECL ModifyTile(uint tile, uint flags, ...); +void SetMapExtraBits(uint tile, byte flags); +uint GetMapExtraBits(uint tile); +void RunTileLoop(); + +uint GetPartialZ(int x, int y, int corners); +uint GetSlopeZ(int x, int y); +uint32 GetTileTrackStatus(uint tile, int mode); +void GetAcceptedCargo(uint tile, AcceptedCargo *ac); +void ChangeTileOwner(uint tile, byte old_player, byte new_player); +void AnimateTile(uint tile); +void ClickTile(uint tile); +void GetTileDesc(uint tile, TileDesc *td); +void DrawTile(TileInfo *ti); + +uint TileAddWrap(TileIndex tile, int add); +enum { + TILE_WRAPPED = (uint)-1 +}; + +bool IsValidTile(uint tile); + +#if !defined(NEW_ROTATION) +static Point FORCEINLINE RemapCoords(int x, int y, int z) { Point pt = { (y-x)*2, y + x -z }; return pt; } +#else +static Point FORCEINLINE RemapCoords(int x, int y, int z) { Point pt = { (x + y)*2, x - y -z }; return pt; } +#endif + +static Point FORCEINLINE RemapCoords2(int x, int y) { return RemapCoords(x, y, GetSlopeZ(x, y)); } + +/* game.c */ +byte *GetString(byte *buffr, uint16 string); +void InjectDparam(int amount); + +int32 GetParamInt32(); +int GetParamInt16(); +int GetParamInt8(); +int GetParamUint16(); + + +/* sound.c */ +void SndPlayTileFx(int sound, TileIndex tile); +void SndPlayVehicleFx(int sound, Vehicle *v); +void SndPlayFx(int sound); + +/* clear_land.c */ +void DrawHillyLandTile(TileInfo *ti); +void DrawClearLandTile(TileInfo *ti, byte set); +void DrawClearLandFence(TileInfo *ti, byte img); +void TileLoopClearHelper(uint tile); + +/* station_land.c */ +void StationPickerDrawSprite(int x, int y, int railtype, int image); + +/* track_land.c */ +void DrawTrainDepotSprite(int x, int y, int image, int railtype); + +/* road_land.c */ +void DrawRoadDepotSprite(int x, int y, int image); + +/* water_land.c */ +void DrawShipDepotSprite(int x, int y, int image); +void TileLoop_Water(uint tile); + +/* players.c */ +bool CheckPlayerHasMoney(int32 cost); +void SubtractMoneyFromPlayer(int32 cost); +void SubtractMoneyFromPlayerFract(byte player, int32 cost); +bool CheckOwnership(byte owner); +bool CheckTileOwnership(uint tile); +StringID GetPlayerNameString(byte player); + +/* standard */ +void ShowInfo(const char *str); +void CDECL ShowInfoF(const char *str, ...); +void NORETURN CDECL error(const char *str, ...); +void memswap(void *a, void *b, size_t size); + +/* ttd.c */ +uint32 Random(); +uint RandomRange(uint max); + +uint32 InteractiveRandom(); /* Used for random sequences that are not the same on the other end of the multiplayer link */ +void SetDate(uint date); +/* facedraw.c */ +void DrawPlayerFace(uint32 face, int color, int x, int y); + +/* texteff.c */ +void MoveAllTextEffects(); +void AddTextEffect(StringID msg, int x, int y, uint16 duration); +void InitTextEffects(); +void DrawTextEffects(DrawPixelInfo *dpi); + +bool AddAnimatedTile(uint tile); +void DeleteAnimatedTile(uint tile); +void AnimateAnimatedTiles(); +void InitializeAnimatedTiles(); + +/* tunnelbridge_cmd.c */ +bool CheckTunnelInWay(uint tile, int z); +bool CheckBridge_Stuff(byte bridge_type, int bridge_len); +uint32 GetBridgeLength(TileIndex begin, TileIndex end); +int CalcBridgeLenCostFactor(int x); + +/* network.c */ +typedef void CommandCallback(bool success, uint tile, uint32 p1, uint32 p2); +bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd); + +void NetworkConnect(const char *hostname, int port); +void NetworkReceive(); +void NetworkSend(); +void NetworkProcessCommands(); +void NetworkListen(int port); +void NetworkInitialize(); +void NetworkShutdown(); +void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback); +void NetworkStartSync(); +void NetworkUDPListen(int port); +void NetworkUDPReceive(); +void NetworkIPListInit(); +bool NetworkUDPSearchServer(); + +/* misc_cmd.c */ +void PlaceTreesRandomly(); + +uint GetTileDist(TileIndex xy1, TileIndex xy2); +uint GetTileDist1D(TileIndex xy1, TileIndex xy2); +uint GetTileDist1Db(TileIndex xy1, TileIndex xy2); +uint GetTileDistAdv(TileIndex xy1, TileIndex xy2); +bool CheckDistanceFromEdge(TileIndex tile, uint distance); + +void InitializeLandscapeVariables(bool only_constants); + +/* misc.c */ +void DeleteName(StringID id); +byte *GetName(int id, byte *buff); +StringID AllocateName(const byte *name, byte skip); +void ConvertDayToYMD(YearMonthDay *ymd, uint16 date); +uint ConvertYMDToDay(uint year, uint month, uint day); +uint ConvertIntDate(uint date); + + + +/* misc functions */ +void MarkTileDirty(int x, int y); +void MarkTileDirtyByTile(TileIndex tile); +void InvalidateWindow(byte cls, WindowNumber number); +void InvalidateWindowWidget(byte cls, WindowNumber number, byte widget_index); +void InvalidateWindowClasses(byte cls); +void DeleteWindowById(WindowClass cls, WindowNumber number); + +void SetObjectToPlaceWnd(int icon, byte mode, Window *w); +void SetObjectToPlace(int icon, byte mode, byte window_class, uint16 window_num); + +void ResetObjectToPlace(); +bool ScrollMainWindowToTile(TileIndex tile); +bool ScrollMainWindowTo(int x, int y); +void DrawSprite(uint32 img, int x, int y); +bool EnsureNoVehicle(TileIndex tile); +bool EnsureNoVehicleZ(TileIndex tile, byte z); +void MarkAllViewportsDirty(int left, int top, int right, int bottom); +void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost); +void MarkWholeScreenDirty(); + +void DrawFoundation(TileInfo *ti, uint f); + +bool CheckIfAuthorityAllows(uint tile); +Town *ClosestTownFromTile(uint tile, uint threshold); +void ChangeTownRating(Town *t, int add, int max); + +uint GetRoadBitsByTile(TileIndex tile); +int GetTownRadiusGroup(Town *t, uint tile); +int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type); +void ShowRenameSignWindow(SignStruct *ss); +void ShowRenameCheckpointWindow(Checkpoint *cp); +int FindFirstBit(uint32 x); +void ShowHighscoreTable(int tbl); +TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng); + +enum SaveOrLoadResult { + SL_OK = 0, // completed successfully + SL_ERROR = 1, // error that was caught before internal structures were modified + SL_REINIT = 2, // error that was caught in the middle of updating game state, need to clear it. (can only happen during load) +}; +enum SaveOrLoadMode { + SL_INVALID = -1, + SL_LOAD = 0, + SL_SAVE = 1, + SL_OLD_LOAD = 2, +}; + +int SaveOrLoad(const char *filename, int mode); + +void AfterLoadTown(); +void AskExitGame(); +void AskExitToGameMenu(); + +void RedrawAutosave(); + +StringID RemapOldStringID(StringID s); + +void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str); + +enum { + SLD_LOAD_GAME = 0, + SLD_LOAD_SCENARIO = 1, + SLD_SAVE_GAME = 2, + SLD_SAVE_SCENARIO = 3, + SLD_NEW_GAME = 4, +}; +void ShowSaveLoadDialog(int mode); + +void ttd_strlcpy(char *dst, const char *src, size_t len); + +// callback from drivers that is called if the game size changes dynamically +void GameSizeChanged(); +void ZoomInOrOutToCursor(bool in); +bool MakeScreenshot(); +bool MakeWorldScreenshot(int left, int top, int width, int height, int zoom); +bool FileExists(const char *filename); +bool ReadLanguagePack(int index); +void InitializeLanguagePacks(); +byte *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize); +int GetLanguageList(char **languages, int max); + +const char *GetScreenshotFormatDesc(int i); +void InitializeScreenshotFormats(); +void SetScreenshotFormat(int i); +void CheckSwitchToEuro(); + +void LoadFromConfig(); +void SaveToConfig(); +int ttd_main(int argc, char* argv[]); + +void DeterminePaths(); +char * CDECL str_fmt(const char *str, ...); + +#endif /* FUNCTIONS_H */ diff --git a/gfx.c b/gfx.c new file mode 100644 --- /dev/null +++ b/gfx.c @@ -0,0 +1,1930 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gfx.h" +#include "table/palettes.h" +#include "hal.h" + +static void GfxMainBlitter(byte *sprite, int x, int y, int mode); +void GfxInitPalettes(); + +static int _stringwidth_out; +static byte _cursor_backup[64*64]; +static Rect _invalid_rect; +static byte *_color_remap_ptr; +static byte _string_colorremap[3]; + +#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH/64) +static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8]; + + +static void memcpy_pitch(void *d, void *s, int w, int h, int spitch, int dpitch) +{ + byte *dp = (byte*)d; + byte *sp = (byte*)s; + + assert(h >= 0); + if (h != 0) do { + memcpy(dp, sp, w); + dp += dpitch; + sp += spitch; + } while (--h); +} + + +void GfxScroll(int left, int top, int width, int height, int xo, int yo) { + byte *src, *dst; + int p; + int ht; + + if (xo == 0 && yo == 0) + return; + + if (_cursor.visible) + UndrawMouseCursor(); + + p = _screen.pitch; + + if (yo > 0 || (yo == 0 && xo > 0)) { + // Calculate pointers + dst = _screen.dst_ptr + (top+height-1) * p + (left+width-1); + src = dst - yo * p; + + // Decrease height and increase top + top += yo; + height -= yo; + assert(height > 0); + + // Adjust left & width + if (xo >= 0) { + left += xo; + src -= xo; + width -= xo; + } else { + dst += xo; + width += xo; + } + + // Offset pointers to fit into the memmove call + dst += -width + 1; + src += -width + 1; + ht = height; + + do { + memmove(dst, src, width); + src -= p; + dst -= p; + } while (--ht); + + + // This part of the screen is now dirty. + _video_driver->make_dirty(left, top, width, height); + + } else { + // Calculate pointers to mem. + dst = _screen.dst_ptr + top * p + left; + src = dst - yo * p; + + // Decrese height. (yo is <=0). + height += yo; + assert(height > 0); + + // Adjust left & width + if (xo >= 0) { + dst += xo; + left += xo; + width -= xo; + } else { + src -= xo; + width += xo; + } + + ht = height; + + do { + memcpy(dst, src, width); + src += p; + dst += p; + } while (--ht); + + // This part of the screen is now dirty. + _video_driver->make_dirty(left, top, width, height); + } +} + + +void GfxFillRect(int left, int top, int right, int bottom, int color) { + DrawPixelInfo *dpi = _cur_dpi; + byte *dst,*ctab; + + if (dpi->zoom != 0) + return; + + if (left > right || top > bottom) + return; + + if (right < dpi->left || left >= dpi->left + dpi->width) + return; + + if (bottom < dpi->top || top >= dpi->top + dpi->height) + return; + + if ( (left -= dpi->left) < 0) left = 0; + right = right - dpi->left + 1; + if (right > dpi->width) right=dpi->width; + right -= left; + assert(right > 0); + + if ( (top -= dpi->top) < 0) top = 0; + bottom = bottom - dpi->top + 1; + if (bottom > dpi->height) bottom=dpi->height; + bottom -= top; + assert(bottom > 0); + + dst = dpi->dst_ptr + top * dpi->pitch + left; + + if (!(color & 0x8000)) { + if (!(color & 0x4000)) { + do { + memset(dst, color, right); + dst += dpi->pitch; + } while (--bottom); + } else { + /* use colortable mode */ + ctab = GetSpritePtr(color & 0x3FFF) + 1; + do { + int i; + for(i=0; i!=right;i++) + dst[i] = ctab[dst[i]]; + dst += dpi->pitch; + } while (--bottom); + } + } else { + byte bo = 0; + do { + int i; + byte b = (bo^=1); + for(i=0; i!=right;i++) + if ((b^=1) != 0) + dst[i] = (byte)color; + dst += dpi->pitch; + } while (--bottom); + } +} + +void GfxSetPixel(int x, int y, int color) +{ + DrawPixelInfo *dpi = _cur_dpi; + if ((x-=dpi->left) < 0 || x>=dpi->width || (y-=dpi->top)<0 || y>=dpi->height) + return; + dpi->dst_ptr[y*dpi->pitch+x] = color; +} + +void GfxDrawLine(int x, int y, int x2, int y2, int color) +{ + int dy; + int dx; + int stepx, stepy; + int frac; + + // Check clipping first + { + DrawPixelInfo *dpi = _cur_dpi; + int t; + + if (x < dpi->left && x2 < dpi->left) + return; + + if (y < dpi->top && y2 < dpi->top) + return; + + t = dpi->left + dpi->width; + if (x > t && x2 > t) + return; + + t = dpi->top + dpi->height; + if (y > t && y2 > t) + return; + } + + dy = (y2 - y) * 2; + if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } + + dx = (x2 - x) * 2; + if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } + + GfxSetPixel(x, y, color); + if (dx > dy) { + frac = dy - (dx >> 1); + while (x != x2) { + if (frac >= 0) { + y += stepy; + frac -= dx; + } + x += stepx; + frac += dy; + GfxSetPixel(x, y, color); + } + } else { + frac = dx - (dy >> 1); + while (y != y2) { + if (frac >= 0) { + x += stepx; + frac -= dy; + } + y += stepy; + frac += dx; + GfxSetPixel(x, y, color); + } + } +} + +// ASSIGNMENT OF ASCII LETTERS < 32 +// 0 - end of string +// 1 - SETX +// 2 - SETXY +// 3-7 - +// 8 - TINYFONT +// 9 - BIGFONT +// 10 - newline +// 11-14 - +// 15-31 - 17 colors + + +enum { + ASCII_LETTERSTART = 32, + + ASCII_SETX = 1, + ASCII_SETXY = 2, + + ASCII_TINYFONT = 8, + ASCII_BIGFONT = 9, + ASCII_NL = 10, + + ASCII_COLORSTART = 15, +}; + + +/* returns right coordinate */ +int DrawString(int x, int y, uint16 str, byte color) +{ + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + return DoDrawString(str_buffr, x, y, color); +} + + +void DrawStringRightAligned(int x, int y, uint16 str, byte color) +{ + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + DoDrawString(str_buffr, x - GetStringWidth(str_buffr), y, color); +} + + +int DrawStringCentered(int x, int y, uint16 str, byte color) +{ + int w; + + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + w = GetStringWidth(str_buffr); + DoDrawString(str_buffr, x - (w>>1), y, color); + + return w; +} + +void DrawStringCenterUnderline(int x, int y, uint16 str, byte color) +{ + int w = DrawStringCentered(x, y, str, color); + GfxFillRect(x-(w>>1), y+10, x-(w>>1)+w, y+10, _string_colorremap[1]); +} + +uint32 FormatStringLinebreaks(byte *str, int maxw) { + int num = 0; + int base = _stringwidth_base; + int w; + byte *last_space; + byte c; + + for(;;) { + w = 0; + last_space = NULL; + + for(;;) { + c = *str++; + if (c == ' ') last_space = str; + + if (c >= ASCII_LETTERSTART) { + w += _stringwidth_table[base + ((byte)c) - 0x20]; + if (w > maxw) { + str = last_space; + if (str == NULL) + return num + (base << 16); + break; + } + } else { + if (c == 0) return num + (base << 16); + if (c == ASCII_NL) break; + + if (c == ASCII_SETX) str++; + else if (c == ASCII_SETXY) str += 2; + else if (c == ASCII_TINYFONT) base = 224; + else if (c == ASCII_BIGFONT) base = 448; + } + } + + num++; + str[-1] = 0; + } +} + + +void DrawStringMultiCenter(int x, int y, uint16 str, int maxw) +{ + uint32 tmp; + int num, w, mt, t; + byte *src; + byte c; + + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + tmp = FormatStringLinebreaks(str_buffr, maxw); + num = (uint16)tmp; + t = tmp >> 16; + + mt = 10; + if (t != 0) { + mt = 6; + if (t != 244) mt = 18; + } + + y -= (mt >> 1) * num; + + src = str_buffr; + + for(;;) { + w = GetStringWidth(src); + DoDrawString(src, x - (w>>1), y, 0xFE); + _stringwidth_base = _stringwidth_out; + + for(;;) { + c = *src++; + if (c == 0) { + y += mt; + if (--num < 0) { + _stringwidth_base = 0; + return; + } + break; + } else if (c == ASCII_SETX) { + src++; + } else if (c == ASCII_SETXY) { + src+=2; + } + } + } +} + +void DrawStringMultiLine(int x, int y, uint16 str, int maxw) { + uint32 tmp; + int num, w, mt, t; + byte *src; + byte c; + + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + tmp = FormatStringLinebreaks(str_buffr, maxw); + num = (uint16)tmp; + t = tmp >> 16; + mt = 10; + if (t != 0) { + mt = 6; + if (t != 244) mt = 18; + } + + src = str_buffr; + + for(;;) { + w = GetStringWidth(src); + DoDrawString(src, x, y, 0xFE); + _stringwidth_base = _stringwidth_out; + + for(;;) { + c = *src++; + if (c == 0) { + y += mt; + if (--num < 0) { + _stringwidth_base = 0; + return; + } + break; + } else if (c == ASCII_SETX) { + src++; + } else if (c == ASCII_SETXY) { + src+=2; + } + } + } +} + +int GetStringWidth(const byte *str) { + int w = -1; + byte c; + int base = _stringwidth_base; + + for(;;) { + c = *str++; + if (c == 0) + return w; + if (c >= ASCII_LETTERSTART) { + w += _stringwidth_table[base + c - ASCII_LETTERSTART]; + } else { + if (c == ASCII_SETX) str++; + else if (c == ASCII_SETXY) str += 2; + else if (c == ASCII_TINYFONT) base = 224; + else if (c == ASCII_BIGFONT) base = 448; + } + } +} + +void DrawFrameRect(int left, int top, int right, int bottom, int ctab, int flags) { + byte color_2 = _color_list[ctab].window_color_1a; + byte color_interior = _color_list[ctab].window_color_bga; + byte color_3 = _color_list[ctab].window_color_bgb; + byte color = _color_list[ctab].window_color_2; + + if (!(flags & 0x8)) { + if (!(flags & 0x20)) { + GfxFillRect(left, top, left, bottom-1, color); + GfxFillRect(left+1, top, right-1, top, color); + GfxFillRect(right, top, right, bottom-1, color_2); + GfxFillRect(left, bottom, right, bottom, color_2); + if (!(flags & 0x10)) { + GfxFillRect(left+1, top+1, right-1, bottom-1, color_interior); + } + } else { + GfxFillRect(left, top, left, bottom, color_2); + GfxFillRect(left+1, top, right, top, color_2); + GfxFillRect(right, top+1, right, bottom-1, color); + GfxFillRect(left+1, bottom, right, bottom, color); + if (!(flags & 0x10)) { + GfxFillRect(left+1, top+1, right-1, bottom-1, + flags&0x40 ? color_interior : color_3); + } + } + } else if (flags & 0x1) { + // transparency + GfxFillRect(left, top, right, bottom, 0x4322); + } else { + GfxFillRect(left, top, right, bottom, color_interior); + } +} + +int DoDrawString(const byte *string, int x, int y, byte color) { + DrawPixelInfo *dpi = _cur_dpi; + int base = _stringwidth_base; + byte c, *b; + int xo = x, yo = y; + + if (color != 0xFE) { + if (x >= dpi->left + dpi->width || + x + _screen.width*2 <= dpi->left || + y >= dpi->top + dpi->height || + y + _screen.height <= dpi->top) + return x; + + if (color != 0xFF) { +switch_color:; + b = GetSpritePtr(674); + _string_colorremap[1] = b[color*2+8]; + _string_colorremap[2] = b[color*2+9]; + _color_remap_ptr = _string_colorremap; + } + } + +check_bounds: + if (y + 19 <= dpi->top || dpi->top + dpi->height <= y) { +skip_char:; + for(;;) { + c = *string++; + if (c < ASCII_LETTERSTART) goto skip_cont; + } + } + + for(;;) { + c = *string++; +skip_cont:; + if (c == 0) { + _stringwidth_out = base; + return x; + } + if (c >= ASCII_LETTERSTART) { + if (x >= dpi->left + dpi->width) goto skip_char; + if (x + 26 >= dpi->left) { + GfxMainBlitter(GetSpritePtr(base + 2 + c - ASCII_LETTERSTART), x, y, 1); + } + x += _stringwidth_table[base + c - ' ']; + } else if (c == ASCII_NL) { // newline = {} + x = xo; + y += 10; + if (base != 0) { + y -= 4; + if (base != 0xE0) + y += 12; + } + goto check_bounds; + } else if (c >= ASCII_COLORSTART) { // change color? + color = (byte)(c - ASCII_COLORSTART); + goto switch_color; + } else if (c == ASCII_SETX) { // {SETX} + x = xo + *string++; + } else if (c == ASCII_SETXY) {// {SETXY} + x = xo + *string++; + y = yo + *string++; + } else if (c == ASCII_TINYFONT) { // {TINYFONT} + base = 0xE0; + } else if (c == ASCII_BIGFONT) { // {BIGFONT} + base = 0x1C0; + } else { + printf("Unknown string command character %d\n", c); + } + } +} + +void DrawSprite(uint32 img, int x, int y) { + if (img & 0x8000) { + _color_remap_ptr = GetSpritePtr(img >> 16) + 1; + GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 1); + } else if (img & 0x4000) { + _color_remap_ptr = GetSpritePtr(img >> 16) + 1; + GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 2); + } else { + GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 0); + } +} + +typedef struct BlitterParams { + int start_x, start_y; + byte *sprite, *sprite_org; + byte *dst; + int mode; + int width, height; + int width_org, height_org; + int pitch; + byte info; +} BlitterParams; + +static void GfxBlitTileZoomIn(BlitterParams *bp) +{ + byte *src_o = bp->sprite, *src; + int num, skip; + byte done; + byte *dst, *ctab; + + if (bp->mode & 1) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if ( (skip -= bp->start_x) > 0) { + dst += skip; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + + while (num >= 4) { + dst[3] = ctab[src[3]]; + dst[2] = ctab[src[2]]; + dst[1] = ctab[src[1]]; + dst[0] = ctab[src[0]]; + dst += 4; + src += 4; + num -= 4; + } + while (num) { + *dst++ = ctab[*src++]; + num--; + } + } while (!(done & 0x80)); + + bp->dst += bp->pitch; + } while (--bp->height); + } else if (bp->mode & 2) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src_o += num + 2; + + dst = bp->dst; + + if ( (skip -= bp->start_x) > 0) { + dst += skip; + } else { + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + while (num) { + *dst = ctab[*dst]; + dst++; + num--; + } + } while (!(done & 0x80)); + + bp->dst += bp->pitch; + } while (--bp->height); + + } else { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if ( (skip -= bp->start_x) > 0) { + dst += skip; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } +#if defined(_WIN32) + if (num & 1) *dst++ = *src++; + if (num & 2) { *(uint16*)dst = *(uint16*)src; dst += 2; src += 2; } + if (num >>= 2) { + do { + *(uint32*)dst = *(uint32*)src; + dst += 4; + src += 4; + } while (--num); + } +#else + memcpy(dst, src, num); +#endif + } while (!(done & 0x80)); + + bp->dst += bp->pitch; + } while (--bp->height); + } +} + +static void GfxBlitZoomInUncomp(BlitterParams *bp) +{ + byte *src = bp->sprite; + byte *dst = bp->dst; + int height = bp->height; + int width = bp->width; + int i; + + assert(height > 0); + assert(width > 0); + + if (bp->mode & 1) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr; + byte b; + + do { + for(i=0; i!=width; i++) { + if ((b=ctab[src[i]]) != 0) + dst[i] = b; + } + src += bp->width_org; + dst += bp->pitch; + } while (--height); + } + } else if (bp->mode & 2) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr; + do { + for(i=0; i!=width; i++) + if (src[i]) + dst[i] = ctab[dst[i]]; + src += bp->width_org; + dst += bp->pitch; + } while (--height); + } + } else { + if (!(bp->info & 1)) { + do { + memcpy(dst, src, width); + src += bp->width_org; + dst += bp->pitch; + } while (--height); + } else { + do { + int n = width; + while (n >= 4) { + if (src[0]) dst[0] = src[0]; + if (src[1]) dst[1] = src[1]; + if (src[2]) dst[2] = src[2]; + if (src[3]) dst[3] = src[3]; + + dst += 4; + src += 4; + n -= 4; + } + + while (n) { + if (src[0]) dst[0] = src[0]; + src++; + dst++; + n--; + } + + src += bp->width_org - width; + dst += bp->pitch - width; + + } while (--height); + } + } +} + +static void GfxBlitTileZoomMedium(BlitterParams *bp) +{ + byte *src_o = bp->sprite, *src; + int num, skip; + byte done; + byte *dst, *ctab; + + if (bp->mode & 1) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + src++; + if (!--num) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 1; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + num = (num + 1) >> 1; + if (num) { + do { + *dst = ctab[*src]; + dst++; + src+=2; + } while (--num); + } + } while (!(done & 0x80)); + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + } while (--bp->height); + } else if (bp->mode & 2) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + if (!--num) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 1; + } else { + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + num = (num + 1) >> 1; + if (num) { + do { + *dst = ctab[*dst]; + dst++; + } while (--num); + } + + } while (!(done & 0x80)); + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + } while (--bp->height); + + } else { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + do { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + src++; + if (!--num) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 1; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + num = (num + 1) >> 1; + + if (num) { + do { + *dst = *src; + dst++; + src+=2; + } while (--num); + } + + } while (!(done & 0x80)); + + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + + } while (--bp->height); + } +} + +static void GfxBlitZoomMediumUncomp(BlitterParams *bp) +{ + byte *src = bp->sprite; + byte *dst = bp->dst; + int height = bp->height; + int width = bp->width; + int i; + + assert(height > 0); + assert(width > 0); + + if (bp->mode & 1) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr,b; + height >>= 1; + if (height) do { + for(i=0; i!=width>>1; i++) + if ((b=ctab[src[i*2]]) != 0) + dst[i] = b; + src += bp->width_org * 2; + dst += bp->pitch; + } while (--height); + } + } else if (bp->mode & 2) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr; + height >>= 1; + if (height) do { + for(i=0; i!=width>>1; i++) + if (src[i*2]) + dst[i] = ctab[dst[i]]; + src += bp->width_org * 2; + dst += bp->pitch; + } while (--height); + } + } else { + if (bp->info & 1) { + height >>= 1; + if (height) do { + for(i=0; i!=width>>1; i++) + if (src[i*2]) + dst[i] = src[i*2]; + src += bp->width_org * 2; + dst += bp->pitch; + } while (--height); + } + } +} + +static void GfxBlitTileZoomOut(BlitterParams *bp) +{ + byte *src_o = bp->sprite, *src; + int num, skip; + byte done; + byte *dst, *ctab; + + if (bp->mode & 1) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + for(;;) { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + src++; + if (!--num) + continue; + } + + if (skip & 2) { + skip+=2; + src+=2; + if ((num-=2) <= 0) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 2; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + num = (num + 3) >> 2; + if (num) { + do { + *dst = ctab[*src]; + dst++; + src+=4; + } while (--num); + } + } while (!(done & 0x80)); + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + } + } else if (bp->mode & 2) { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + for(;;) { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + if (!--num) + continue; + } + + if (skip & 2) { + skip+=2; + if ((num-=2) <= 0) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 2; + } else { + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + ctab = _color_remap_ptr; + num = (num + 3) >> 2; + if (num) { + do { + *dst = ctab[*dst]; + dst++; + } while (--num); + } + + } while (!(done & 0x80)); + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + } + } else { + src_o += READ_LE_UINT16(src_o + bp->start_y * 2); + for(;;) { + do { + done = src_o[0]; + num = done & 0x7F; + skip = src_o[1]; + src = src_o + 2; + src_o += num + 2; + + dst = bp->dst; + + if (skip & 1) { + skip++; + src++; + if (!--num) + continue; + } + + if (skip & 2) { + skip+=2; + src+=2; + if ((num-=2) <= 0) + continue; + } + + if ( (skip -= bp->start_x) > 0) { + dst += skip >> 2; + } else { + src -= skip; + num += skip; + if (num <= 0) + continue; + skip = 0; + } + + skip = skip + num - bp->width; + if (skip > 0) { + num -= skip; + if (num <= 0) + continue; + } + + num = (num + 3) >> 2; + + if (num) { + do { + *dst = *src; + dst++; + src+=4; + } while (--num); + } + + } while (!(done & 0x80)); + + bp->dst += bp->pitch; + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + + do { + done = src_o[0]; + src_o += (done & 0x7F) + 2; + } while (!(done & 0x80)); + if (!--bp->height) + return; + } + } +} + +static void GfxBlitZoomOutUncomp(BlitterParams *bp) +{ + byte *src = bp->sprite; + byte *dst = bp->dst; + int height = bp->height; + int width = bp->width; + int i; + + assert(height > 0); + assert(width > 0); + + if (bp->mode & 1) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr,b; + height >>= 2; + if (height) do { + for(i=0; i!=width>>2; i++) + if ((b=ctab[src[i*4]]) != 0) + dst[i] = b; + src += bp->width_org * 4; + dst += bp->pitch; + } while (--height); + } + } else if (bp->mode & 2) { + if (bp->info & 1) { + byte *ctab = _color_remap_ptr; + height >>= 2; + if (height) do { + for(i=0; i!=width>>2; i++) + if (src[i*4]) + dst[i] = ctab[dst[i]]; + src += bp->width_org * 4; + dst += bp->pitch; + } while (--height); + } + } else { + if (bp->info & 1) { + height >>= 2; + if (height) do { + for(i=0; i!=width>>2; i++) + if (src[i*4]) + dst[i] = src[i*4]; + src += bp->width_org * 4; + dst += bp->pitch; + } while (--height); + } + } +} + +typedef void (*BlitZoomFunc)(BlitterParams *bp); + +static void GfxMainBlitter(byte *sprite, int x, int y, int mode) +{ + DrawPixelInfo *dpi = _cur_dpi; + int start_x, start_y; + byte info; + BlitterParams bp; + int zoom_mask = ~((1 << (dpi->zoom))-1); + + static const BlitZoomFunc zf_tile[3] = + { + GfxBlitTileZoomIn, + GfxBlitTileZoomMedium, + GfxBlitTileZoomOut + }; + static const BlitZoomFunc zf_uncomp[3] = + { + GfxBlitZoomInUncomp, + GfxBlitZoomMediumUncomp, + GfxBlitZoomOutUncomp + }; + + /* decode sprite header */ + x += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->x_offs); + y += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->y_offs); + bp.width_org = bp.width = READ_LE_UINT16(&((SpriteHdr*)sprite)->width); + bp.height_org = bp.height = ((SpriteHdr*)sprite)->height; + info = ((SpriteHdr*)sprite)->info; + bp.info = info; + bp.sprite_org = bp.sprite = sprite + sizeof(SpriteHdr); + bp.dst = dpi->dst_ptr; + bp.mode = mode; + bp.pitch = dpi->pitch; + + assert(bp.height > 0); + assert(bp.width > 0); + + if (info & 8) { + /* tile blit */ + start_y = 0; + + if (dpi->zoom > 0) { + start_y += bp.height &~ zoom_mask; + bp.height &= zoom_mask; + if (bp.height == 0) return; + y&=zoom_mask; + } + + if ( (y -= dpi->top) < 0) { + if ((bp.height += y) <= 0) + return; + start_y -= y; + y = 0; + } else { + bp.dst += bp.pitch * (y>>(dpi->zoom)); + } + bp.start_y = start_y; + + if ( (y = y + bp.height - dpi->height) > 0) { + if ( (bp.height -= y) <= 0) + return; + } + + start_x = 0; + x &= zoom_mask; + if ( (x -= dpi->left) < 0) { + if ((bp.width += x) <= 0) + return; + start_x -= x; + x = 0; + } + bp.start_x = start_x; + bp.dst += x>>(dpi->zoom); + + if ( (x = x + bp.width - dpi->width) > 0) { + if ( (bp.width -= x) <= 0) + return; + } + + zf_tile[dpi->zoom](&bp); + } else { + + bp.sprite += bp.width * (bp.height & ~zoom_mask); + bp.height &= zoom_mask; + if (bp.height == 0) + return; + + y &= zoom_mask; + + if ( (y -= dpi->top) < 0) { + if ((bp.height += y) <= 0) + return; + bp.sprite -= bp.width * y; + y = 0; + } else { + bp.dst += bp.pitch * (y>>(dpi->zoom)); + } + + if ( (y = y + bp.height - dpi->height) > 0) { + if ( (bp.height -= y) <= 0) + return; + } + + start_x = 0; + + x &= zoom_mask; + + if ( (x -= dpi->left) < 0) { + if ((bp.width += x) <= 0) + return; + start_x -= x; + bp.sprite -= x; + x = 0; + } + bp.dst += x>>(dpi->zoom); + + if ( (x = x + bp.width - dpi->width) > 0) { + if ( (bp.width -= x) <= 0) + return; + start_x += x; + } + bp.start_x = start_x; + + if (info&2) { + int totpix = bp.height_org * bp.width_org; + byte *dst = (byte*)alloca(totpix); + byte *src = bp.sprite_org; + signed char b; + + bp.sprite += (dst - src); + + while (totpix != 0) { + assert(totpix > 0); + b = *src++; + if (b >= 0) { + int i, count=b; + for(i=0; i!=count; i++) + dst[i] = src[i]; + dst += count; + src += count; + totpix -= count; + } else { + byte *tmp = dst- (((b&7)<<8)|(*src++)); + int i; + int count = -(b >> 3); + + for(i=0; i!=count; i++) + dst[i] = tmp[i]; + dst += count; + totpix -= count; + } + } + } + zf_uncomp[dpi->zoom](&bp); + } +} + + +void GfxScalePalette(int pal, byte scaling) +{ + byte *dst, *src; + size_t count; + + GfxInitPalettes(); + + dst = _cur_palette; + src = GET_PALETTE(pal); + count = 256; + do { + dst[0] = (byte)(src[0] * scaling >> 8); + dst[1] = (byte)(src[1] * scaling >> 8); + dst[2] = (byte)(src[2] * scaling >> 8); + dst += 3; + src += 3; + } while (--count); +} + +void GfxInitPalettes() +{ + memcpy(_cur_palette, _palettes[0], 256*3); + _pal_first_dirty = 0; + _pal_last_dirty = 255; +} + + +#define EXTR(p,q) (((uint16)(_timer_counter * (p)) * (q)) >> 16) +#define EXTR2(p,q) (((uint16)(~_timer_counter * (p)) * (q)) >> 16) +#define COPY_TRIPLET do {d[0]=s[0+j]; d[1]=s[1+j]; d[2]=s[2+j];d+=3;}while(0) + +void DoPaletteAnimations() +{ + const byte *s; + byte *d; + int j; + int i; + const ExtraPaletteValues *ev = &_extra_palette_values; + byte old_val[28*3]; + + d = _cur_palette + 217*3; + memcpy(old_val, d, 28*3); + + // Dark blue water + s = ev->a; + if (_opt.landscape == LT_CANDY) s = ev->ac; + j = EXTR(320,5) * 3; + for(i=0; i!=5; i++) { + COPY_TRIPLET; + j+=3; + if (j == 15) j = 0; + } + + // Glittery water + s = ev->b; + if (_opt.landscape == LT_CANDY) s = ev->bc; + j = EXTR(128, 15) * 3; + for(i=0; i!=5; i++) { + COPY_TRIPLET; + j += 9; + if (j >= 45) j -= 45; + } + + s = ev->e; + j = EXTR2(512, 5) * 3; + for(i=0; i!=5; i++) { + COPY_TRIPLET; + j += 3; + if (j == 3*5) j = 0; + } + + // Oil refinery fire animation + s = ev->oil_ref; + j = EXTR2(512, 7) * 3; + for(i=0; i!=7; i++) { + COPY_TRIPLET; + j += 3; + if (j == 3*7) j = 0; + } + + // Radio tower blinking + { + byte i,v; + i = (_timer_counter >> 1) & 0x7F; + (v = 255, i < 0x3f) || + (v = 128, i < 0x4A || i >= 0x75) || + (v = 20); + d[0] = v; + d[1] = d[2] = 0; + d += 3; + + i ^= 0x40; + (v = 255, i < 0x3f) || + (v = 128, i < 0x4A || i >= 0x75) || + (v = 20); + d[0] = v; + + d[1] = d[2] = 0; + d += 3; + } + + // Handle lighthouse and stadium animation + s = ev->lighthouse; + j = EXTR(256, 4) * 3; + for(i=0; i!=4; i++) { + COPY_TRIPLET; + j += 3; + if (j == 3*4) j = 0; + } + + if (memcmp(old_val, _cur_palette + 217*3, 28*3)) { + if (_pal_first_dirty > 217) _pal_first_dirty = 217; + if (_pal_last_dirty < 217+29-1) _pal_last_dirty = 217+29-1; + } +} + + +void LoadStringWidthTable() +{ + int i; + byte *b; + + b = _stringwidth_table; + + // 2 equals space. + for(i=2; i != 0xE2; i++) { + *b++ = (byte)((i < 93 || i >= 129 || i == 98) ? GetSpritePtr(i)[2] : 0); + } + + for(i=0xE2; i != 0x1C2; i++) { + *b++ = (byte)((i < 317 || i >= 353) ? GetSpritePtr(i)[2]+1 : 0); + } + + for(i=0x1C2; i != 0x2A2; i++) { + *b++ = (byte)((i < 541 || i >= 577) ? GetSpritePtr(i)[2]+1 : 0); + } +} + +void ScreenSizeChanged() +{ + // check the dirty rect + if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width; + if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height; + + // screen size changed and the old bitmap is invalid now, so we don't want to undraw it + _cursor.visible = false; +} + +void UndrawMouseCursor() +{ + if (_cursor.visible) { + _cursor.visible = false; + memcpy_pitch( + _screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch, + _cursor_backup, + _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x, _screen.pitch); + + _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); + } +} + +void DrawMouseCursor() +{ + int x,y,w,h; + + // Don't draw the mouse cursor if it's already drawn + if (_cursor.visible) { + if (!_cursor.dirty) + return; + UndrawMouseCursor(); + } + + w = _cursor.size.x; + x = _cursor.pos.x + _cursor.offs.x; + if (x < 0) { w += x; x=0; } + if (w>_screen.width-x) { w = _screen.width-x; } + if (w <= 0) return; + _cursor.draw_pos.x = x; + _cursor.draw_size.x = w; + + h = _cursor.size.y; + y = _cursor.pos.y + _cursor.offs.y; + if (y < 0) { h += y; y=0; } + if (h>_screen.height-y) { h = _screen.height-y; } + if (h <= 0) return; + _cursor.draw_pos.y = y; + _cursor.draw_size.y = h; + + assert(w*h < sizeof(_cursor_backup)); + + // Make backup of stuff below cursor + memcpy_pitch( + _cursor_backup, + _screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch, + _cursor.draw_size.x, _cursor.draw_size.y, _screen.width, _cursor.draw_size.x); + + // Draw cursor on screen + _cur_dpi = &_screen; + DrawSprite(_cursor.sprite, _cursor.pos.x, _cursor.pos.y); + + _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); + + _cursor.visible = true; + _cursor.dirty = false; +} + +void DbgScreenRect(int left, int top, int right, int bottom) +{ + DrawPixelInfo dp,*old; + + old = _cur_dpi; + _cur_dpi = &dp; + dp = _screen; + GfxFillRect(left, top, right-1, bottom-1, rand() & 255); + _cur_dpi = old; +} + +extern bool _dbg_screen_rect; + +void RedrawScreenRect(int left, int top, int right, int bottom) +{ + assert(right <= _screen.width && bottom <= _screen.height); + if (_cursor.visible) { + if (right > _cursor.draw_pos.x && + left < _cursor.draw_pos.x + _cursor.draw_size.x && + bottom > _cursor.draw_pos.y && + top < _cursor.draw_pos.y + _cursor.draw_size.y) { + UndrawMouseCursor(); + } + } + +#if defined(_DEBUG) + if (_dbg_screen_rect) + DbgScreenRect(left, top, right, bottom); + else +#endif + DrawOverlappedWindowForAll(left, top, right, bottom); + + _video_driver->make_dirty(left, top, right-left, bottom-top); +} + +void DrawDirtyBlocks() +{ + byte *b = _dirty_blocks; + int x=0,y=0; + int w = (_screen.width + 63) & ~63; + int h = _screen.height; + + do { + if (*b != 0) { + int left,top; + int right = x + 64; + int bottom = y; + byte *p = b; + int h2; + // First try coalescing downwards + do { + *p = 0; + p += DIRTY_BYTES_PER_LINE; + bottom += 8; + } while (bottom != h && *p); + + // Try coalescing to the right too. + h2 = (bottom - y) >> 3; + assert(h2>0); + p = b; + + while (right != w) { + byte *p2 = ++p; + int h = h2; + // Check if a full line of dirty flags is set. + do { + if (!*p2) goto no_more_coalesc; + p2 += DIRTY_BYTES_PER_LINE; + } while (--h); + + // Wohoo, can combine it one step to the right! + // Do that, and clear the bits. + right += 64; + + h = h2; + p2 = p; + do { + *p2 = 0; + p2 += DIRTY_BYTES_PER_LINE; + } while (--h); + } + no_more_coalesc:; + + left = x; + top = y; + + if (left < _invalid_rect.left)left = _invalid_rect.left; + if (top < _invalid_rect.top) top = _invalid_rect.top; + if (right > _invalid_rect.right)right = _invalid_rect.right; + if (bottom > _invalid_rect.bottom)bottom = _invalid_rect.bottom; + + if (left < right && top < bottom) { + RedrawScreenRect(left, top, right, bottom); + } + + } + } while (b++, (x+=64) != w || (x=0,b+=-(w>>6)+DIRTY_BYTES_PER_LINE,(y+=8) != h)); + + _invalid_rect.left = w; + _invalid_rect.top = h; + _invalid_rect.right = 0; + _invalid_rect.bottom = 0; +} + + +void SetDirtyBlocks(int left, int top, int right, int bottom) +{ + byte *b; + int width,height,i; + + if (left < 0) left = 0; + if (top < 0) top = 0; + if (right > _screen.width) right = _screen.width; + if (bottom > _screen.height) bottom = _screen.height; + + if (left >= right || top >= bottom) + return; + + if (left < _invalid_rect.left) _invalid_rect.left = left; + if (top < _invalid_rect.top) _invalid_rect.top = top; + if (right > _invalid_rect.right)_invalid_rect.right = right; + if (bottom > _invalid_rect.bottom)_invalid_rect.bottom = bottom; + + left >>= 6; + top >>= 3; + + b = _dirty_blocks + top * DIRTY_BYTES_PER_LINE + left; + + width = ((right-1) >> 6) - left + 1; + height = ((bottom-1) >> 3) - top + 1; + + assert(width > 0 && height > 0); + + do { + i=width; + do b[--i] = 0xFF; while (i); + + b += DIRTY_BYTES_PER_LINE; + } while (--height); +} + +void MarkWholeScreenDirty() +{ + SetDirtyBlocks(0, 0, _screen.width, _screen.height); +} + +bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, int width, int height) +{ + int t; + + if (o == NULL) + o = _cur_dpi; + + n->zoom = 0; + + assert(width > 0); + assert(height > 0); + + n->left = 0; + if ((left -= o->left) < 0) { + if ((width += left) < 0) + return false; + n->left = -left; + left = 0; + } + + if ((t=width + left - o->width) > 0) { + if ((width -= t) < 0) + return false; + } + n->width = width; + + n->top = 0; + if ((top -= o->top) < 0) { + if ((height += top) < 0) + return false; + n->top = -top; + top = 0; + } + + n->dst_ptr = o->dst_ptr + left + top * (n->pitch = o->pitch); + + if ((t=height + top - o->height) > 0) { + if ((height-=t) < 0) + return false; + } + n->height = height; + + + return true; +} + +static void SetCursorSprite(uint cursor) +{ + CursorVars *cv = &_cursor; + byte *p; + + if (cv->sprite == cursor) + return; + + p = GetSpritePtr(cursor & 0x3FFF); + cv->sprite = cursor; + cv->size.y = *(byte*)(p+1); + cv->size.x = READ_LE_UINT16(p+2); + cv->offs.x = (int16)READ_LE_UINT16(p+4); + cv->offs.y = (int16)READ_LE_UINT16(p+6); + + cv->dirty = true; +} + +static void SwitchAnimatedCursor() +{ + CursorVars *cv = &_cursor; + const uint16 *cur; + uint sprite; + + cur = cv->animate_cur; + if (cur == NULL || *cur == 0xFFFF) + cur = cv->animate_list; + sprite = cur[0]; + cv->animate_timeout = cur[1]; + cv->animate_cur = cur + 2; + + SetCursorSprite(sprite); +} + +void CursorTick() { + CursorVars *cv = &_cursor; + if (cv->animate_timeout && !--cv->animate_timeout) + SwitchAnimatedCursor(); +} + +void SetMouseCursor(uint cursor) +{ + // Turn off animation + _cursor.animate_timeout = 0; + // Set cursor + SetCursorSprite(cursor); +} + +void SetAnimatedMouseCursor(const uint16 *table) +{ + _cursor.animate_list = table; + _cursor.animate_cur = NULL; + SwitchAnimatedCursor(); +} + +bool ChangeResInGame(int w, int h) +{ + if ((_screen.width != w || _screen.height != h) && !_video_driver->change_resolution(w, h)) + return false; + + _cur_resolution[0] = w; + _cur_resolution[1] = h; + return true; +} diff --git a/gfx.h b/gfx.h new file mode 100644 --- /dev/null +++ b/gfx.h @@ -0,0 +1,110 @@ +#ifndef GFX_H +#define GFX_H + + +typedef struct ColorList { + byte unk0, unk1, unk2; + byte window_color_1a, window_color_1b; + byte window_color_bga, window_color_bgb; + byte window_color_2; +} ColorList; + +struct DrawPixelInfo { + byte *dst_ptr; + int left, top, width, height; + int pitch; + uint16 zoom; +}; + + +typedef struct SpriteHdr { + byte info; + byte height; + uint16 width; + int16 x_offs, y_offs; +} SpriteHdr; +assert_compile(sizeof(SpriteHdr) == 8); + +typedef struct CursorVars { + Point pos, size, offs, delta; + Point draw_pos, draw_size; + uint32 sprite; + + int wheel; // mouse wheel movement + const uint16 *animate_list, *animate_cur; + uint animate_timeout; + + bool visible; + bool dirty; + bool fix_at; +} CursorVars; + + +void RedrawScreenRect(int left, int top, int right, int bottom); +void GfxScroll(int left, int top, int width, int height, int xo, int yo); +int DrawStringCentered(int x, int y, uint16 str, byte color); +int DrawString(int x, int y, uint16 str, byte color); +void DrawStringCenterUnderline(int x, int y, uint16 str, byte color); +int DoDrawString(const byte *string, int x, int y, byte color); +void DrawStringRightAligned(int x, int y, uint16 str, byte color); +void GfxFillRect(int left, int top, int right, int bottom, int color); +void GfxDrawLine(int left, int top, int right, int bottom, int color); +void DrawFrameRect(int left, int top, int right, int bottom, int color, int flags); + +int GetStringWidth(const byte *str); +void LoadStringWidthTable(); +void DrawStringMultiCenter(int x, int y, uint16 str, int maxw); +void DrawStringMultiLine(int x, int y, uint16 str, int maxw); +void DrawDirtyBlocks(); +void SetDirtyBlocks(int left, int top, int right, int bottom); +void MarkWholeScreenDirty(); + +void GfxInitPalettes(); + +bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, int width, int height); + +/* window.c */ +void DrawOverlappedWindowForAll(int left, int top, int right, int bottom); + +/* spritecache.c */ +byte *GetSpritePtr(uint sprite); +void GfxInitSpriteMem(byte *ptr, uint32 size); +void GfxLoadSprites(); + +void SetMouseCursor(uint cursor); +void SetAnimatedMouseCursor(const uint16 *table); +void CursorTick(); +void DrawMouseCursor(); +void ScreenSizeChanged(); +void UndrawMouseCursor(); +bool ChangeResInGame(int w, int h); + +typedef struct { + int xoffs, yoffs; + int xsize, ysize; +} SpriteDimension; + +const SpriteDimension *GetSpriteDimension(uint sprite); + +/* gfx.c */ +VARDEF int _stringwidth_base; +VARDEF byte _stringwidth_table[0x2A0]; + +VARDEF DrawPixelInfo _screen; +VARDEF DrawPixelInfo *_cur_dpi; +VARDEF ColorList _color_list[16]; +VARDEF CursorVars _cursor; + +VARDEF int _pal_first_dirty; +VARDEF int _pal_last_dirty; + +/* spritecache.c */ +//enum { NUM_SPRITES = 0x1320 }; +//enum { NUM_SPRITES = 0x1500 }; +enum { NUM_SPRITES = 0x3500 }; // 1500 + space for custom GRF sets + +/* tables.h */ +extern byte _palettes[4][256 * 3]; +VARDEF byte _cur_palette[768]; + +#endif diff --git a/graph_gui.c b/graph_gui.c new file mode 100644 --- /dev/null +++ b/graph_gui.c @@ -0,0 +1,857 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "player.h" + +static uint _legend_showbits; +static uint _legend_cargobits; + +/************************/ +/* GENERIC GRAPH DRAWER */ +/************************/ + +typedef struct GraphDrawer { + uint sel; + byte num_dataset; + byte num_on_x_axis; + byte month; + byte year; + bool include_neg; + byte num_vert_lines; + uint16 unk61A; + uint16 unk61C; + int left, top; + uint height; + StringID format_str_y_axis; + byte color_3, color_2, bg_line_color; + byte colors[16]; + uint32 cost[16][24]; +} GraphDrawer; + +void DrawGraph(GraphDrawer *gw) +{ + + int i,j,k; + int x,y,old_x,old_y; + int color; + int right, bottom; + int num_x, num_dataset; + uint32 *row_ptr, *col_ptr; + int32 mx; + int adj_height; + uint32 y_scaling, tmp; + int32 value; + int32 cur_val; + uint sel; + + color = _color_list[gw->bg_line_color].window_color_1b; + + /* draw the vertical lines */ + i = gw->num_vert_lines; assert(i > 0); + x = gw->left + 66; + bottom = gw->top + gw->height - 1; + do { + GfxFillRect(x, gw->top, x, bottom, color); + x += 22; + } while (--i); + + /* draw the horizontal lines */ + i = 9; + x = gw->left + 44; + y = gw->height + gw->top; + right = gw->left + 44 + gw->num_vert_lines*22-1; + + do { + GfxFillRect(x, y, right, y, color); + y -= gw->height >> 3; + } while (--i); + + /* draw vertical edge line */ + GfxFillRect(x, gw->top, x, bottom, gw->color_2); + + adj_height = gw->height; + if (gw->include_neg) adj_height >>= 1; + + /* draw horiz edge line */ + y = adj_height + gw->top; + GfxFillRect(x, y, right, y, gw->color_2); + + /* find the max element */ + if (gw->num_on_x_axis == 0) + return; + + num_dataset = gw->num_dataset;assert(num_dataset > 0); + row_ptr = gw->cost[0]; + mx = 0; + do { + num_x = gw->num_on_x_axis;assert(num_x > 0); + col_ptr = row_ptr; + do { + if (*col_ptr != 0x80000000) { + mx = max(mx, myabs(*col_ptr)); + } + } while (col_ptr++, --num_x); + } while (row_ptr+=24, --num_dataset); + + /* setup scaling */ + y_scaling = 0x80000000; + value = adj_height * 2; + + if (mx > value) { + mx = (mx + 7) & ~7; + y_scaling = (uint32) (((uint64) (value>>1) << 32) / mx); + value = mx; + } + + /* draw text strings on the y axis */ + tmp = value; + if (gw->include_neg) tmp >>= 1; + x = gw->left + 45; + y = gw->top - 3; + i = 9; + do { + SET_DPARAM16(0, gw->format_str_y_axis); + SET_DPARAM32(1, tmp); + tmp -= (value >> 3); + DrawStringRightAligned(x, y, STR_0170, gw->color_3); + y += gw->height >> 3; + } while (--i); + + /* draw strings on the x axis */ + if (gw->month != 0xFF) { + x = gw->left + 44; + y = gw->top + gw->height + 1; + j = gw->month; + k = gw->year + 1920; + i = gw->num_on_x_axis;assert(i>0); + do { + SET_DPARAM16(2, k); + SET_DPARAM16(0, j + STR_0162_JAN); + SET_DPARAM16(1, j + STR_0162_JAN + 2); + DrawString(x, y, j == 0 ? STR_016F : STR_016E, gw->color_3); + + j += 3; + if (j >= 12) { + j = 0; + k++; + } + x += 22; + } while (--i); + } else { + x = gw->left + 52; + y = gw->top + gw->height + 1; + j = gw->unk61A; + i = gw->num_on_x_axis;assert(i>0); + do { + SET_DPARAM16(0, j); + DrawString(x, y, STR_01CB, gw->color_3); + j += gw->unk61C; + x += 22; + } while (--i); + } + + /* draw lines and dots */ + i = 0; + row_ptr = gw->cost[0]; + sel = gw->sel; + do { + if (!(sel & 1)) { + x = gw->left + 55; + j = gw->num_on_x_axis;assert(j>0); + col_ptr = row_ptr; + color = gw->colors[i]; + old_y = old_x = 0x80000000; + do { + cur_val = *col_ptr++; + if (cur_val != (int32)0x80000000) { + y = adj_height - BIGMULSS(cur_val, y_scaling >> 1, 31) + gw->top; + + GfxFillRect(x-1, y-1, x+1, y+1, color); + if (old_x != 0x80000000) + GfxDrawLine(old_x, old_y, x, y, color); + + old_x = x; + old_y = y; + } else { + old_x = 0x80000000; + } + } while (x+=22,--j); + } + } while (sel>>=1,row_ptr+=24, ++i < gw->num_dataset); +} + +/****************/ +/* GRAPH LEGEND */ +/****************/ + +void DrawPlayerIcon(int p, int x, int y) +{ + DrawSprite(SPRITE_PALETTE(PLAYER_SPRITE_COLOR(p) + 0x2EB), x, y); +} + +static void GraphLegendWndProc(Window *w, WindowEvent *e) +{ + Player *p; + + switch(e->event) { + case WE_PAINT: + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + SETBIT(_legend_showbits, p->index); + } + w->click_state = ((~_legend_showbits) << 3); + DrawWindowWidgets(w); + + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + + DrawPlayerIcon(p->index, 4, 18+p->index*12); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, GetPlayerNameString(p->index)); + DrawString(21,17+p->index*12,STR_7021,HASBIT(_legend_showbits, p->index) ? 0x10 : 0xC); + } + break; + + case WE_CLICK: + if (IS_INT_INSIDE(e->click.widget, 3, 11)) { + _legend_showbits ^= (1 << (e->click.widget-3)); + SetWindowDirty(w); + InvalidateWindow(WC_INCOME_GRAPH, 0); + InvalidateWindow(WC_OPERATING_PROFIT, 0); + InvalidateWindow(WC_DELIVERED_CARGO, 0); + InvalidateWindow(WC_PERFORMANCE_HISTORY, 0); + } + break; + } +} + +static const Widget _graph_legend_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 249, 0, 13, STR_704E_KEY_TO_COMPANY_GRAPHS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 249, 14, 113, 0x0}, +{ WWT_IMGBTN, 14, 2, 247, 16, 27, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 28, 39, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 40, 51, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 52, 63, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 64, 75, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 76, 87, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 88, 99, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_IMGBTN, 14, 2, 247, 100, 111, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, +{ WWT_LAST}, +}; + +static const WindowDesc _graph_legend_desc = { + -1, -1, 250, 114, + WC_GRAPH_LEGEND,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _graph_legend_widgets, + GraphLegendWndProc +}; + +static void ShowGraphLegend() +{ + AllocateWindowDescFront(&_graph_legend_desc, 0); +} + +/********************/ +/* OPERATING PROFIT */ +/********************/ + +static void SetupGraphDrawerForPlayers(GraphDrawer *gd) +{ + Player *p; + uint showbits = _legend_showbits; + int nums; + int mo,yr; + + // Exclude the players which aren't valid + FOR_ALL_PLAYERS(p) { + if (!p->is_active) CLRBIT(showbits,p->index); + } + gd->sel = showbits; + gd->num_vert_lines = 24; + + nums = 0; + FOR_ALL_PLAYERS(p) { + if (p->is_active) nums = max(nums,p->num_valid_stat_ent); + } + gd->num_on_x_axis = min(nums,24); + + mo = (_cur_month/3-nums)*3; + yr = _cur_year; + while (mo < 0) { + yr--; + mo += 12; + } + + gd->year = yr; + gd->month = mo; +} + +static void OperatingProfitWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + GraphDrawer gd; + Player *p; + int i,j; + int numd; + + DrawWindowWidgets(w); + + gd.left = 2; + gd.top = 18; + gd.height = 136; + gd.include_neg = true; + gd.format_str_y_axis = STR_7023; + gd.color_3 = 0x10; + gd.color_2 = 0xD7; + gd.bg_line_color = 0xE; + + SetupGraphDrawerForPlayers(&gd); + + numd = 0; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + gd.colors[numd] = _color_list[p->player_color].window_color_bgb; + for(j=gd.num_on_x_axis,i=0; --j >= 0;) { + gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? 0x80000000 : (p->old_economy[j].income + p->old_economy[j].expenses); + i++; + } + numd++; + } + gd.num_dataset=numd; + + DrawGraph(&gd); + break; + } + + case WE_CLICK: + if (e->click.widget == 2) + ShowGraphLegend(); + break; + } +} + +static const Widget _operating_profit_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7025_OPERATING_PROFIT_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, +{ WWT_IMGBTN, 14, 0, 575, 14, 173, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _operating_profit_desc = { + -1, -1, 576, 174, + WC_OPERATING_PROFIT,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _operating_profit_widgets, + OperatingProfitWndProc +}; + + +void ShowOperatingProfitGraph() +{ + if (AllocateWindowDescFront(&_operating_profit_desc, 0)) { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + _legend_showbits = 0; + } +} + + +/****************/ +/* INCOME GRAPH */ +/****************/ + +static void IncomeGraphWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + GraphDrawer gd; + Player *p; + int i,j; + int numd; + + DrawWindowWidgets(w); + + gd.left = 2; + gd.top = 18; + gd.height = 104; + gd.include_neg = false; + gd.format_str_y_axis = STR_7023; + gd.color_3 = 0x10; + gd.color_2 = 0xD7; + gd.bg_line_color = 0xE; + SetupGraphDrawerForPlayers(&gd); + + numd = 0; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + gd.colors[numd] = _color_list[p->player_color].window_color_bgb; + for(j=gd.num_on_x_axis,i=0; --j >= 0;) { + gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? 0x80000000 : (p->old_economy[j].income); + i++; + } + numd++; + } + + gd.num_dataset = numd; + + DrawGraph(&gd); + break; + } + + case WE_CLICK: + if (e->click.widget == 2) + ShowGraphLegend(); + break; + } +} + +static const Widget _income_graph_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7022_INCOME_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, +{ WWT_IMGBTN, 14, 0, 575, 14, 141, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _income_graph_desc = { + -1, -1, 576, 142, + WC_INCOME_GRAPH,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _income_graph_widgets, + IncomeGraphWndProc +}; + +void ShowIncomeGraph() +{ + if (AllocateWindowDescFront(&_income_graph_desc, 0)) { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + _legend_showbits = 0; + } +} + +/*******************/ +/* DELIVERED CARGO */ +/*******************/ + +static void DeliveredCargoGraphWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + GraphDrawer gd; + Player *p; + int i,j; + int numd; + + DrawWindowWidgets(w); + + gd.left = 2; + gd.top = 18; + gd.height = 104; + gd.include_neg = false; + gd.format_str_y_axis = STR_7024; + gd.color_3 = 0x10; + gd.color_2 = 0xD7; + gd.bg_line_color = 0xE; + SetupGraphDrawerForPlayers(&gd); + + numd = 0; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + gd.colors[numd] = _color_list[p->player_color].window_color_bgb; + for(j=gd.num_on_x_axis,i=0; --j >= 0;) { + gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? 0x80000000 : p->old_economy[j].delivered_cargo; + i++; + } + numd++; + } + + gd.num_dataset = numd; + + DrawGraph(&gd); + break; + } + + case WE_CLICK: + if (e->click.widget == 2) + ShowGraphLegend(); + break; + } +} + +static const Widget _delivered_cargo_graph_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7050_UNITS_OF_CARGO_DELIVERED, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, +{ WWT_IMGBTN, 14, 0, 575, 14, 141, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _delivered_cargo_graph_desc = { + -1, -1, 576, 142, + WC_DELIVERED_CARGO,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _delivered_cargo_graph_widgets, + DeliveredCargoGraphWndProc +}; + +void ShowDeliveredCargoGraph() +{ + if (AllocateWindowDescFront(&_delivered_cargo_graph_desc, 0)) { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + _legend_showbits = 0; + } +} + +/***********************/ +/* PERFORMANCE HISTORY */ +/***********************/ + +static void PerformanceHistoryWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + GraphDrawer gd; + Player *p; + int i,j; + int numd; + + DrawWindowWidgets(w); + + gd.left = 2; + gd.top = 18; + gd.height = 200; + gd.include_neg = false; + gd.format_str_y_axis = STR_7024; + gd.color_3 = 0x10; + gd.color_2 = 0xD7; + gd.bg_line_color = 0xE; + SetupGraphDrawerForPlayers(&gd); + + numd = 0; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + gd.colors[numd] = _color_list[p->player_color].window_color_bgb; + for(j=gd.num_on_x_axis,i=0; --j >= 0;) { + gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? 0x80000000 : p->old_economy[j].performance_history; + i++; + } + numd++; + } + gd.num_dataset = numd; + + DrawGraph(&gd); + break; + } + + case WE_CLICK: + if (e->click.widget == 2) + ShowGraphLegend(); + break; + } +} + +static const Widget _performance_history_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7051_COMPANY_PERFORMANCE_RATINGS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, +{ WWT_IMGBTN, 14, 0, 575, 14, 237, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _performance_history_desc = { + -1, -1, 576, 238, + WC_PERFORMANCE_HISTORY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _performance_history_widgets, + PerformanceHistoryWndProc +}; + +void ShowPerformanceHistoryGraph() +{ + if (AllocateWindowDescFront(&_performance_history_desc, 0)) { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + _legend_showbits = 0; + } +} + +/*****************/ +/* COMPANY VALUE */ +/*****************/ + +static void CompanyValueGraphWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + GraphDrawer gd; + Player *p; + int i,j; + int numd; + + DrawWindowWidgets(w); + + gd.left = 2; + gd.top = 18; + gd.height = 200; + gd.include_neg = false; + gd.format_str_y_axis = STR_7023; + gd.color_3 = 0x10; + gd.color_2 = 0xD7; + gd.bg_line_color = 0xE; + SetupGraphDrawerForPlayers(&gd); + + numd = 0; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) + continue; + gd.colors[numd] = _color_list[p->player_color].window_color_bgb; + for(j=gd.num_on_x_axis,i=0; --j >= 0;) { + gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? 0x80000000 : (p->old_economy[j].company_value); + i++; + } + numd++; + } + gd.num_dataset = numd; + + + DrawGraph(&gd); + break; + } + + case WE_CLICK: + if (e->click.widget == 2) + ShowGraphLegend(); + break; + } +} + +static const Widget _company_value_graph_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7052_COMPANY_VALUES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, +{ WWT_IMGBTN, 14, 0, 575, 14, 237, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _company_value_graph_desc = { + -1, -1, 576, 238, + WC_COMPANY_VALUE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _company_value_graph_widgets, + CompanyValueGraphWndProc +}; + +void ShowCompanyValueGraph() +{ + if (AllocateWindowDescFront(&_company_value_graph_desc, 0)) { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + _legend_showbits = 0; + } +} + +/*****************/ +/* PAYMENT RATES */ +/*****************/ + +static const byte _cargo_legend_colors[12] = {152, 32, 15, 174, 208, 194, 191, 84, 184, 10, 202, 215}; + +static void CargoPaymentRatesWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int i, j, x, y; + GraphDrawer gd; + + gd.sel = _legend_cargobits; + w->click_state = (~_legend_cargobits) << 3; + DrawWindowWidgets(w); + + x = 495; + y = 25; + + for(i=0; i!=NUM_CARGO; i++) { + GfxFillRect(x, y, x+8, y+5, 0); + GfxFillRect(x+1, y+1, x+7, y+4, _cargo_legend_colors[i]); + SET_DPARAM16(0, _cargoc.names_s[i]); + DrawString(x+14, y, STR_7065, 0); + y += 8; + } + + gd.left = 2; + gd.top = 24; + gd.height = 104; + gd.include_neg = false; + gd.format_str_y_axis = STR_7023; + gd.color_3 = 16; + gd.color_2 = 215; + gd.bg_line_color = 14; + gd.num_dataset = 12; + gd.num_on_x_axis = 20; + gd.num_vert_lines = 20; + gd.month = 0xFF; + gd.unk61A = 10; + gd.unk61C = 10; + + for(i=0; i!=NUM_CARGO; i++) { + gd.colors[i] = _cargo_legend_colors[i]; + for(j=0; j!=20; j++) { + gd.cost[i][j] = GetTransportedGoodsIncome(10, 20, j*6+6,i); + } + } + + DrawGraph(&gd); + + DrawString(2 + 46, 24 + gd.height + 7, STR_7062_DAYS_IN_TRANSIT, 0); + DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, 0); + } break; + + case WE_CLICK: { + switch(e->click.widget) { + case 3: case 4: case 5: case 6: + case 7: case 8: case 9: case 10: + case 11: case 12: case 13: case 14: + _legend_cargobits ^= 1 << (e->click.widget - 3); + SetWindowDirty(w); + break; + } + } break; + } +} + +static const Widget _cargo_payment_rates_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 567, 0, 13, STR_7061_CARGO_PAYMENT_RATES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 567, 14, 141, 0x0, 0}, +{ WWT_PANEL, 12, 493, 562, 24, 31, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 32, 39, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 40, 47, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 48, 55, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 56, 63, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 64, 71, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 72, 79, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 80, 87, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 88, 95, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 96, 103, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 104, 111, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_PANEL, 12, 493, 562, 112, 119, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, +{ WWT_LAST}, +}; + +static const WindowDesc _cargo_payment_rates_desc = { + -1, -1, 568, 142, + WC_PAYMENT_RATES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _cargo_payment_rates_widgets, + CargoPaymentRatesWndProc +}; + + +void ShowCargoPaymentRates() +{ + AllocateWindowDescFront(&_cargo_payment_rates_desc, 0); +} + +/************************/ +/* COMPANY LEAGUE TABLE */ +/************************/ + +static const StringID _performance_titles[] = { + STR_7066_ENGINEER, + STR_7066_ENGINEER, + STR_7067_TRAFFIC_MANAGER, + STR_7067_TRAFFIC_MANAGER, + STR_7068_TRANSPORT_COORDINATOR, + STR_7068_TRANSPORT_COORDINATOR, + STR_7069_ROUTE_SUPERVISOR, + STR_7069_ROUTE_SUPERVISOR, + STR_706A_DIRECTOR, + STR_706A_DIRECTOR, + STR_706B_CHIEF_EXECUTIVE, + STR_706B_CHIEF_EXECUTIVE, + STR_706C_CHAIRMAN, + STR_706C_CHAIRMAN, + STR_706D_PRESIDENT, + STR_706E_TYCOON, +}; + +static StringID GetPerformanceTitleFromValue(uint v) +{ + return _performance_titles[minu(v, 1000) >> 6]; +} + +static int CDECL _perf_hist_comp(const void *elem1, const void *elem2 ) { + Player *p1 = *(Player**)elem1; + Player *p2 = *(Player**)elem2; + int32 v = p2->old_economy[1].performance_history - p1->old_economy[1].performance_history; + return (v!=0) | (v >> (sizeof(int32)*8-1)); +} + +static void CompanyLeagueWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p; + Player *plist[MAX_PLAYERS]; + size_t pl_num, i; + + DrawWindowWidgets(w); + + pl_num=0; + FOR_ALL_PLAYERS(p) { + if (p->is_active) + plist[pl_num++] = p; + } + assert(pl_num > 0); + + qsort(plist, pl_num, sizeof(Player*), _perf_hist_comp); + + i = 0; + do { + SET_DPARAM16(0, i + 1 + STR_01AB); + p = plist[i]; + SET_DPARAM16(1, p->name_1); + SET_DPARAM32(2, p->name_2); + + SET_DPARAM16(3, GetPlayerNameString(p->index)); + SET_DPARAM16(4, GetPerformanceTitleFromValue(p->old_economy[1].performance_history)); + + DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, 0); + DrawPlayerIcon(p->index, 27, 16 + i * 10); + } while (++i != pl_num); + + break; + } + } +} + + +static const Widget _company_league_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 399, 0, 13, STR_7053_COMPANY_LEAGUE_TABLE, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 399, 14, 96, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _company_league_desc = { + -1, -1, 400, 97, + WC_COMPANY_LEAGUE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _company_league_widgets, + CompanyLeagueWndProc +}; + +void ShowCompanyLeagueTable() +{ + AllocateWindowDescFront(&_company_league_desc,0); +} diff --git a/grfspecial.c b/grfspecial.c new file mode 100644 --- /dev/null +++ b/grfspecial.c @@ -0,0 +1,1072 @@ +#include "stdafx.h" + +#include + +#include "ttd.h" +#include "gfx.h" +#include "fileio.h" +#include "engine.h" + +/* TTDPatch extended GRF format codec + * (c) Petr Baudis 2004 (GPL'd) + * Contains portions of documentation by TTDPatch team. + * Thanks especially to Josef Drexler for the documentation as well as a lot + * of help at #tycoon. Also thanks to Michael Blunck for is GRF files which + * served as subject to the initial testing of this codec. */ + +extern int _skip_sprites; + +static const char *_cur_grffile; +static int _cur_spriteid; + +typedef void (*SpecialSpriteHandler)(byte *buf, int len); + +static const int _vehshifts[4] = { + 0, + ROAD_ENGINES_INDEX, + SHIP_ENGINES_INDEX, + AIRCRAFT_ENGINES_INDEX, +}; + + +enum grfmsg_severity { + GMS_NOTICE, + GMS_WARN, + GMS_ERROR, + GMS_FATAL, +}; + +static void CDECL grfmsg(enum grfmsg_severity severity, const char *str, ...) +{ + static const char * const severitystr[4] = { "Notice", "Warning", "Error", "Fatal" }; + va_list va; + + va_start(va, str); + fprintf(stderr, "[%s][%s] ", _cur_grffile, severitystr[severity]); + vfprintf(stderr, str, va); + va_end(va); + fprintf(stderr, "\n"); +} + +static byte INLINE grf_load_byte(byte **buf) { + return *(*buf)++; +} + + +static uint16 grf_load_word(byte **buf) +{ + uint16 val; + byte *p = *buf; + val = p[0]; + val |= p[1] << 8; + *buf = p + 2; + return val; +} + +static uint16 grf_load_dword(byte **buf) +{ + uint32 val; + byte *p = *buf; + val = p[0]; + val |= p[1] << 8; + val |= p[2] << 16; + val |= p[3] << 24; + *buf = p + 4; + return val; +} + +typedef int (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len); + +#define foreach_engine for (i = 0; i < numinfo; i++) + +static void dewagonize(int condition, int engine) +{ + EngineInfo *ei = &_engine_info[engine]; + RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; + + if (condition) { + ei->unk2 &= ~0x80; + rvi->flags &= ~2; + } else { + ei->unk2 |= 0x80; + rvi->flags |= 2; + } +} + +static int RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len) +{ + EngineInfo *ei = &_engine_info[engine]; + RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; + byte *buf = *bufp; + int i; + int ret = 0; + + switch (prop) { + case 0x05: + { /* Track type */ + foreach_engine { + uint8 tracktype = grf_load_byte(&buf); + + ei[i].railtype_climates &= 0xf; + ei[i].railtype_climates |= tracktype << 4; + } + break; + } + case 0x08: + { /* AI passenger service */ + /* TODO */ + foreach_engine { + grf_load_byte(&buf); + } + ret = 1; + break; + } + case 0x09: + { /* Speed */ + foreach_engine { + uint16 speed = grf_load_word(&buf); + + rvi[i].max_speed = speed; + dewagonize(speed, engine + i); + } + break; + } + case 0x0b: + { /* Power */ + foreach_engine { + uint16 power = grf_load_word(&buf); + + rvi[i].power = power; + dewagonize(power, engine + i); + } + break; + } + case 0x0d: + { /* Running cost factor */ + foreach_engine { + uint8 runcostfact = grf_load_byte(&buf); + + rvi[i].running_cost_base = runcostfact; + dewagonize(runcostfact, engine + i); + } + break; + } + case 0x0e: + { /* Running cost base */ + foreach_engine { + uint32 base = grf_load_dword(&buf); + + switch (base) { + case 0x4c30: + rvi[i].engclass = 0; + break; + case 0x4c36: + rvi[i].engclass = 1; + break; + case 0x4c3c: + rvi[i].engclass = 2; + break; + } + dewagonize(base, engine + i); + } + break; + } + case 0x12: + { /* Sprite ID */ + foreach_engine { + uint8 spriteid = grf_load_byte(&buf); + + if (spriteid == 0xfd && rvi[i].image_index != 0xfd) + _engine_original_sprites[engine + i] = rvi[i].image_index; + rvi[i].image_index = spriteid; + } + break; + } + case 0x13: + { /* Dual-headed */ + foreach_engine { + uint8 dual = grf_load_byte(&buf); + + if (dual) { + rvi[i].flags |= 1; + } else { + rvi[i].flags &= ~1; + } + } + break; + } + case 0x14: + { /* Cargo capacity */ + foreach_engine { + uint8 capacity = grf_load_byte(&buf); + + rvi[i].capacity = capacity; + } + break; + } + case 0x15: + { /* Cargo type */ + foreach_engine { + uint8 ctype = grf_load_byte(&buf); + + rvi[i].cargo_type = ctype; + } + break; + } + case 0x16: + { /* Weight */ + foreach_engine { + uint8 weight = grf_load_byte(&buf); + + rvi[i].weight = weight; + } + break; + } + case 0x17: + { /* Cost factor */ + foreach_engine { + uint8 cfactor = grf_load_byte(&buf); + + rvi[i].base_cost = cfactor; + } + break; + } + case 0x18: + { /* AI rank */ + /* TODO: _railveh_score should be merged to _rail_vehicle_info. */ + foreach_engine { + grf_load_byte(&buf); + } + ret = 1; + break; + } + case 0x19: + { /* Engine traction type */ + /* TODO: What do the individual numbers mean? + * XXX: And in what base are they, in fact? --pasky */ + foreach_engine { + uint8 traction = grf_load_byte(&buf); + int engclass; + + if (traction <= 0x07) + engclass = 0; + else if (traction <= 0x27) + engclass = 1; + else if (traction <= 0x31) + engclass = 2; + else + break; + + rvi[i].engclass = engclass; + } + break; + } + /* TODO */ + /* Fall-through for unimplemented four bytes long properties. */ + case 0x1d: /* Refit cargo */ + foreach_engine { + grf_load_word(&buf); + } + /* Fall-through for unimplemented two bytes long properties. */ + case 0x1b: /* Powered wagons power bonus */ + foreach_engine { + grf_load_byte(&buf); + } + /* Fall-through for unimplemented one byte long properties. */ + case 0x1a: /* Sort order */ + case 0x1c: /* Refit cost */ + case 0x1e: /* Callback */ + case 0x1f: /* Tractive effort */ + case 0x21: /* Shorter tenders */ + case 0x22: /* Visual */ + case 0x23: /* Powered wagons weight bonus */ + /* TODO */ + foreach_engine { + grf_load_byte(&buf); + } + ret = 1; + break; + default: + ret = 1; + break; + } + *bufp = buf; + return ret; +} + +static int ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len) +{ + ShipVehicleInfo *svi = &_ship_vehicle_info[engine]; + byte *buf = *bufp; + int i; + int ret = 0; + + //printf("e %x prop %x?\n", engine, prop); + switch (prop) { + case 0x08: + { /* Sprite ID */ + foreach_engine { + uint8 spriteid = grf_load_byte(&buf); + + if (spriteid == 0xff) + spriteid = 0xfd; // ships have different custom id in the GRF file + + // This is currently not used but there's no reason + // in not having it here for the future. + if (spriteid == 0xfd + && svi[i].image_index != 0xfd) + _engine_original_sprites[SHIP_ENGINES_INDEX + + engine + i] + = svi[i].image_index; + svi[i].image_index = spriteid; + } + break; + } + case 0x09: + { /* Refittable */ + foreach_engine { + uint8 refittable = grf_load_byte(&buf); + + svi[i].refittable = refittable; + } + break; + } + case 0x0a: + { /* Cost factor */ + foreach_engine { + uint8 cost_factor = grf_load_byte(&buf); + + svi[i].base_cost = cost_factor; // ?? is it base_cost? + } + break; + } + case 0x0b: + { /* Speed */ + foreach_engine { + uint8 speed = grf_load_byte(&buf); + + svi[i].max_speed = speed; // ?? units + } + break; + } + case 0x0c: + { /* Cargo type */ + + foreach_engine { + uint8 cargo = grf_load_byte(&buf); + + // XXX: Need to consult this with patchman yet. +#if 0 + // Documentation claims this is already the + // per-landscape cargo type id, but newships.grf + // assume otherwise. + cargo = local_cargo_id_ctype[cargo]; +#endif + svi[i].cargo_type = cargo; + } + break; + } + case 0x0d: + { /* Cargo capacity */ + foreach_engine { + uint16 capacity = grf_load_word(&buf); + + svi[i].capacity = capacity; + } + break; + } + case 0x0f: + { /* Running cost factor */ + foreach_engine { + uint8 runcost = grf_load_byte(&buf); + + svi[i].running_cost = runcost; + } + break; + } + case 0x10: + { /* SFX */ + foreach_engine { + uint8 sfx = grf_load_byte(&buf); + + svi[i].sfx = sfx; + } + break; + } + case 0x11: + { /* Cargos available for refitting */ + foreach_engine { + uint32 refit_mask = grf_load_dword(&buf); + + _engine_refit_masks[SHIP_ENGINES_INDEX + engine + i] = refit_mask; + } + break; + } + case 0x12: + { /* Callback */ + /* TODO */ + ret = 1; + break; + } + default: + ret = 1; + break; + } + + *bufp = buf; + return ret; +} + +#undef shift_buf + +static void VehicleChangeInfo(byte *buf, int len) +{ + byte *bufend = buf + len; + int i; + + /* <00> ()... + * + * B feature 0, 1, 2 or 3 for trains, road vehicles, ships or planes + * 4 for defining new train station sets + * B num-props how many properties to change per vehicle/station + * B num-info how many vehicles/stations to change + * B id ID of first vehicle/station to change, if num-info is + * greater than one, this one and the following + * vehicles/stations will be changed + * B property what property to change, depends on the feature + * V new-info new bytes of info (variable size; depends on properties) */ + /* TODO: Only trains and ships are supported for now. */ + + static const VCI_Handler handler[5] = { + RailVehicleChangeInfo, + NULL, + ShipVehicleChangeInfo, + NULL, + NULL, + }; + + if (len > 5) { + uint8 feature = buf[1]; + uint8 numprops = buf[2]; + uint8 numinfo = buf[3]; + byte engine = buf[4]; + EngineInfo *ei; + + if (feature != 0 && feature != 2) { + grfmsg(GMS_WARN, "VehicleChangeInfo: Unsupported vehicle type %x, skipping.", feature); + return; + } + + ei = &_engine_info[engine + _vehshifts[feature]]; + + buf += 5; + + while (numprops-- && buf < bufend) { + uint8 prop = grf_load_byte(&buf); + + switch (prop) { + case 0x00: { + /* Introduction date */ + foreach_engine { + uint16 date = grf_load_word(&buf); + + ei[i].base_intro = date; + } + break; + } + case 0x02: { + /* Decay speed */ + foreach_engine { + uint8 decay = grf_load_byte(&buf); + + ei[i].unk2 &= 0x80; + ei[i].unk2 |= decay & 0x7f; + } + break; + } + case 0x03: { + /* Vehicle life */ + foreach_engine { + uint8 life = grf_load_byte(&buf); + + ei[i].lifelength = life; + } + break; + } + case 0x04: { + /* Model life */ + foreach_engine { + uint8 life = grf_load_byte(&buf); + + ei[i].base_life = life; + } + break; + } + case 0x06: { + /* Climates available */ + foreach_engine { + uint8 climates = grf_load_byte(&buf); + + ei[i].railtype_climates &= 0xf0; + ei[i].railtype_climates |= climates; + } + break; + } + case 0x07: { + /* Loading speed */ + /* Hyronymus explained me what does + * this mean and insists on having a + * credit ;-). --pasky */ + /* TODO: This needs to be supported by + * LoadUnloadVehicle() first. */ + foreach_engine { + grf_load_byte(&buf); + } + goto ignoring; + } + default: + { + if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) { +ignoring: + grfmsg(GMS_WARN, "VehicleChangeInfo: Ignoring property %x.", prop); + } + break; + } + } + } + } +#undef shift_buf +} + + +/* A sprite superset contains all sprites of a given vehicle (or multiple + * vehicles) when carrying given cargo. It consists of several sprite sets. + * Superset ids are refered as "cargo id"s by TTDPatch documentation, + * contributing to the global confusion. + * + * A sprite set contains all sprites of a given vehicle carrying given cargo at + * a given *stage* - that is usually its load stage. Ie. you can have a + * spriteset for an empty wagon, wagon full of coal, half-filled wagon etc. + * Each spriteset contains eight sprites (one per direction) or four sprites if + * the vehicle is symmetric. */ + +static int _spriteset_start; +static int _spriteset_numsets; +static int _spriteset_numents; +static int _spriteset_feature; + +static int _spritesset_count; +static struct SpriteSuperSet *_spritesset; + +static void SpriteNewSet(byte *buf, int len) +{ + /* <01> + * + * B feature feature to define sprites for + * 0, 1, 2, 3: veh-type, 4: train stations + * B num-sets number of sprite sets + * B num-ent how many entries per sprite set + * For vehicles, this is the number of different + * vehicle directions in each sprite set + * Set num-dirs=8, unless your sprites are symmetric. + * In that case, use num-dirs=4. + * For stations, must be 12 (hex) for the eighteen + * different sprites that make up a station */ + /* TODO: No stations support. */ + + if (len == 4) { + uint8 feature = buf[1]; + + if (feature == 4) { + _spriteset_start = 0; + grfmsg(GMS_WARN, "SpriteNewSet: Stations unsupported, skipping."); + return; + } + + _spriteset_start = _cur_spriteid + 1; + _spriteset_numsets = buf[2]; + _spriteset_numents = buf[3]; + _spriteset_feature = feature; + } +} + +static void SpriteNewSuperset(byte *buf, int len) +{ + byte *bufend = buf + len; + + /* <02> + * + * B feature see action 1 + * B set-id ID of this particular definition + * B type/num-entries + * if 80 or greater, this is a randomized or variational + * list definition, see below + * otherwise it specifies a number of entries, the exact + * meaning depends on the feature + * V feature-specific-data (huge mess, don't even look it up --pasky) */ + /* TODO: Only trains supported now. No 0x80-types (ugh). */ + /* TODO: Also, empty sprites aren't handled for now. Need to investigate + * the "opacity" rules for these, that is which sprite to fall back to + * when. --pasky */ + + if (bufend - buf > 4) { + uint8 feature = buf[1]; + uint8 setid = buf[2]; + uint8 numloaded = buf[3]; + uint8 numloading = buf[4]; + struct SpriteSuperSet *superset; + int i; + + if (feature == 4) { + grfmsg(GMS_WARN, "SpriteNewSuperset: Stations unsupported, skipping."); + return; + } + + if (numloaded == 0x81) { + // XXX: This is _VERY_ ad hoc just to handle Dm3. And that is + // a semi-futile ask because the great Patchman himself says + // this is just buggy. It dereferences last (first) byte of + // a schedule list pointer of the vehicle and if it's 0xff + // it uses superset 01, otherwise it uses superset 00. Now + // if _you_ understand _that_... We just assume it is never + // 0xff and therefore go for superset 00. --pasky + uint8 var = buf[4]; + //uint8 shiftnum = buf[5]; + //uint8 andmask = buf[6]; + uint8 nvar = buf[7]; + //uint32 val; + uint16 def; + + grfmsg(GMS_WARN, "SpriteNewSuperset(0x81): Unsupported variable %x. Using default cid.", var); + + //val = (0xff << shiftnum) & andmask; + + //Go for the default. + if (setid >= _spritesset_count) { + _spritesset_count = setid + 1; + _spritesset = realloc(_spritesset, _spritesset_count * sizeof(struct SpriteSuperSet)); + } + buf += 8 + nvar * 4; + def = grf_load_word(&buf); + _spritesset[setid] = _spritesset[def]; + return; + + } else if (numloaded & 0x80) { + grfmsg(GMS_WARN, "SpriteNewSuperset(0x%x): Unsupported special superset.", numloaded); + return; + } + + if (!_spriteset_start) { + grfmsg(GMS_WARN, "SpriteNewSuperset: No sprite set to work on! Skipping."); + return; + } + + if (_spriteset_feature != feature) { + grfmsg(GMS_WARN, "SpriteNewSuperset: Superset feature %x doesn't match set feature %x! Skipping.", feature, _spriteset_feature); + return; + } + + if (setid >= _spritesset_count) { + _spritesset_count = setid + 1; + _spritesset = realloc(_spritesset, _spritesset_count * sizeof(struct SpriteSuperSet)); + } + superset = &_spritesset[setid]; + memset(superset, 0, sizeof(struct SpriteSuperSet)); + superset->sprites_per_set = _spriteset_numents; + + buf += 5; + + for (i = 0; buf < bufend && i < numloaded; i++) { + uint16 spriteset_id = grf_load_word(&buf); + + if (_spritesset[setid].loaded_count > 16) { + grfmsg(GMS_WARN, "SpriteNewSuperset: More than 16 sprites in superset %x, skipping.", setid); + return; + } + superset->loaded[superset->loaded_count++] + = _spriteset_start + spriteset_id * _spriteset_numents; + } + + for (i = 0; buf < bufend && i < numloading; i++) { + uint16 spriteset_id = grf_load_word(&buf); + + if (_spritesset[setid].loading_count > 16) { + grfmsg(GMS_WARN, "SpriteNewSuperset: More than 16 sprites in superset %x, skipping.", setid); + return; + } + superset->loading[superset->loading_count++] = _spriteset_start + spriteset_id * _spriteset_numents; + } + } +} + +static void VehicleMapSpriteSuperset(byte *buf, int len) +{ + byte *bufend = buf + len; + /* <03> ... [ ]... + * + * B feature see action 0 + * B n-id bits 0-6: how many IDs this definition applies to + * bit 7: if set, this is a wagon override definition (see below) + * B ids the IDs for which this definition applies + * B num-cid number of cargo IDs in this definition + * can be zero, in that case the def-cid is used always + * B cargo-type type of this cargo type (e.g. mail=2, wood=7, see below) + * W cid cargo ID for this type of cargo + * W def-cid default cargo ID */ + /* TODO: Only trains supported now. */ + /* TODO: Multiple cargo support could be useful even for trains/cars - + * cargo id 0xff is used for showing images in the build train list. */ + + static byte *last_engines; + static int last_engines_count; + + if (bufend - buf > 6) { + uint8 feature = buf[1]; + uint8 idcount = buf[2] & 0x7f; + int wagover = buf[2] & 0x80; + uint8 cidcount = buf[3 + idcount]; + int c, i; + + if (feature == 4) { + grfmsg(GMS_WARN, "VehicleMapSpriteSuperset: Stations unsupported, skipping."); + return; + } + + // FIXME: Tropicset contains things like: + // 03 00 01 19 01 00 00 00 00 - this is missing one 00 at the end, + // what should we exactly do with that? --pasky + + if (!_spriteset_start || !_spritesset) { + grfmsg(GMS_WARN, "VehicleMapSpriteSuperset: No sprite set to work on! Skipping."); + return; + } + + if (!wagover && last_engines_count != idcount) { + last_engines = realloc(last_engines, idcount); + last_engines_count = idcount; + } + + for (i = 0; i < idcount; i++) { + uint8 engine = buf[3 + i] + _vehshifts[feature]; + byte *bp = &buf[4 + idcount]; + + for (c = 0; c < cidcount; c++) { + uint8 ctype = grf_load_byte(&bp); + uint16 supersetid = grf_load_word(&bp); + + if (supersetid >= _spritesset_count) { + grfmsg(GMS_WARN, "VehicleMapSpriteSuperset: Spriteset %x out of range %x, skipping.", supersetid, _spritesset_count); + return; + } + + if (ctype == 0xff) + ctype = CID_PURCHASE; + + if (wagover) { + // TODO: No multiple cargo types per vehicle yet. --pasky + SetWagonOverrideSprites(engine, &_spritesset[supersetid], last_engines, last_engines_count); + } else { + SetCustomEngineSprites(engine, ctype, &_spritesset[supersetid]); + last_engines[i] = engine; + } + } + } + + { + byte *bp = buf + 4 + idcount + cidcount * 3; + uint16 supersetid = grf_load_word(&bp); + + for (i = 0; i < idcount; i++) { + uint8 engine = buf[3 + i] + _vehshifts[feature]; + + // Don't tell me you don't love duplicated code! + if (supersetid >= _spritesset_count) { + grfmsg(GMS_WARN, "VehicleMapSpriteSuperset: Spriteset %x out of range %x, skipping.", supersetid, _spritesset_count); + return; + } + + if (wagover) { + // TODO: No multiple cargo types per vehicle yet. --pasky + SetWagonOverrideSprites(engine, &_spritesset[supersetid], last_engines, last_engines_count); + } else { + SetCustomEngineSprites(engine, CID_DEFAULT, &_spritesset[supersetid]); + last_engines[i] = engine; + } + } + } + } +} + +static void VehicleNewName(byte *buf, int len) +{ + /* <04> + * + * B veh-type see action 0 + * B language-id language ID with bit 7 cleared (see below) + * B num-veh number of vehicles which are getting a new name + * B offset number of the first vehicle that gets a new name + * S data new texts, each of them zero-terminated, after + * which the next name begins. */ + /* TODO: No support for changing non-vehicle text. Perhaps we shouldn't + * implement it at all, but it could be useful for some "modpacks" + * (completely new scenarios changing all graphics and logically also + * factory names etc). We should then also support all languages (by + * name), not only the original four ones. --pasky */ + + if (len > 5) { + uint8 feature = buf[1]; + uint8 lang = buf[2]; + uint8 id = buf[4] + _vehshifts[feature]; + uint8 endid = id + buf[3]; + + if (lang & 0x80) { + grfmsg(GMS_WARN, "VehicleNewName: No support for changing in-game texts. Skipping."); + return; + } + + if (!(lang & 3)) { + /* XXX: If non-English name, silently skip it. */ + return; + } + + buf += 5, len -= 5; + for (; id < endid && len > 0; id++) { + int ofs = strlen(buf) + 1; + + if (ofs < 128) + SetCustomEngineName(id, buf); + buf += ofs, len -= ofs; + } + } +} + +static void GraphicsNew(byte *buf, int len) +{ + /* <05> + * + * B graphics-type What set of graphics the sprites define. + * B num-sprites How many sprites are in this set? + * V other data Graphics type specific data. Currently unused. */ + /* TODO */ +} + +static void CfgApply(byte *buf, int len) +{ + /* <06> ... + * + * B param-num Number of parameter to substitute (First = "zero") + * Ignored if that parameter was not specified in newgrf.cfg + * B param-size How many bytes to replace. If larger than 4, the + * bytes of the following parameter are used. In that + * case, nothing is applied unless *all* parameters + * were specified. + * B offset Offset into data from beginning of next sprite + * to place where parameter is to be stored. */ + /* TODO */ +} + +static void SkipIf(byte *buf, int len) +{ + /* <07/09> + * + * B param-num + * B param-size + * B condition-type + * V value + * B num-sprites */ + /* TODO: We only support few tests. */ + /* TODO: More params. More condition types. */ + + if (len > 5) { + uint8 param = buf[1]; + uint8 paramsize = buf[2]; + uint8 condtype = buf[3]; + uint8 numsprites = buf[4 + paramsize]; + int val, result; + + if (param == 0x83) { + val = _opt.landscape; + } else { + grfmsg(GMS_WARN, "Unsupported param %x. Ignoring test.", param); + return; + } + + switch (condtype) { + case 2: result = (buf[4] == val); + break; + case 3: result = (buf[4] != val); + break; + default: + grfmsg(GMS_WARN, "Unsupported test %d. Ignoring.", condtype); + return; + } + + if (!result) + return; + + _skip_sprites = numsprites; + if (_skip_sprites == 0) { + /* Zero means there are no sprites to skip, so + * we use -1 to indicate that all further + * sprites should be skipped. */ + _skip_sprites = -1; + } + } +} + +static void GRFInfo(byte *buf, int len) +{ + /* <08> + * + * B version newgrf version, currently 06 + * 4*B grf-id globally unique ID of this .grf file + * S name name of this .grf set + * S info string describing the set, and e.g. author and copyright */ + /* TODO: Check version. (We should have own versioning done somehow.) */ + + if (len > 8) { + uint8 version = buf[1]; + // this is de facto big endian - grf_load_dword() unsuitable + uint32 grfid = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5]; + printf("[%s] Loaded GRFv%d set %08lx - %s:\n%s\n", _cur_grffile, version, grfid, buf+6, buf+6+strlen(buf+6)+1); + } +} + +static void SpriteReplace(byte *buf, int len) +{ + /* <0A> [ ...] + * : + * + * B num-sets How many sets of sprites to replace. + * Each set: + * B num-sprites How many sprites are in this set + * W first-sprite First sprite number to replace */ + /* TODO */ +} + +static void GRFError(byte *buf, int len) +{ + /* <0B> [ 00] [] 00 [] + * + * B severity 00: notice, contine loading grf file + * 01: warning, continue loading grf file + * 02: error, but continue loading grf file, and attempt + * loading grf again when loading or starting next game + * 03: error, abort loading and prevent loading again in + * the future (only when restarting the patch) + * B language-id see action 4, use 1F for built-in error messages + * B message-id message to show, see below + * S message for custom messages (message-id FF), text of the message + * not present for built-in messages. + * V data additional data for built-in (or custom) messages + * B parnum see action 6, only used with built-in message 03 */ + /* TODO: For now we just show the message, sometimes incomplete and never translated. */ + + static const char * const msgstr[4] = { + "Requires at least pseudo-TTDPatch version %s.", + "This file is for %s version of TTD.", + "Designed to be used with %s.", + "Invalid parameter %s.", + }; + + if (len > 5) { + uint8 severity = buf[1]; + uint8 msgid = buf[3]; + + if (msgid == 0xff) { + grfmsg(severity, "%s", buf+4); + } else { + grfmsg(severity, msgstr[msgid], buf+4); + } + } +} + +static void GRFComment(byte *buf, int len) +{ + /* <0C> [] + * + * V ignored Anything following the 0C is ignored */ +} + +static void ParamSet(byte *buf, int len) +{ + /* <0D> [] + * + * B target parameter number where result is stored + * B operation operation to perform, see below + * B source1 first source operand + * B source2 second source operand + * D data data to use in the calculation, not necessary + * if both source1 and source2 refer to actual parameters + * + * Operations + * 00 Set parameter equal to source1 + * 01 Addition, source1 + source2 + * 02 Subtraction, source1 - source2 + * 03 Unsigned multiplication, source1 * source2 (both unsigned) + * 04 Signed multiplication, source1 * source2 (both signed) + * 05 Unsigned bit shift, source1 by source2 (source2 taken to be a + * signed quantity; left shift if positive and right shift if + * negative, source1 is unsigned) + * 06 Signed bit shift, source1 by source2 + * (source2 like in 05, and source1 as well) + */ + /* TODO */ +} + +static void GRFInhibit(byte *buf, int len) +{ + /* <0E> + * + * B num Number of GRFIDs that follow + * D grfids GRFIDs of the files to deactivate */ + /* TODO */ +} + +/* Here we perform initial decoding of some special sprites (as are they + * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very + * partial implementation yet; also, we ignore the stages stuff). */ +/* XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by + * a crafted invalid GRF file. We should tell that to the user somehow, or + * better make this more robust in the future. */ + +void DecodeSpecialSprite(const char *filename, int num, int spriteid) +{ +#define NUM_ACTIONS 0xf + static const SpecialSpriteHandler handlers[NUM_ACTIONS] = { + /* 0x0 */ VehicleChangeInfo, + /* 0x1 */ SpriteNewSet, + /* 0x2 */ SpriteNewSuperset, + /* 0x3 */ VehicleMapSpriteSuperset, + /* 0x4 */ VehicleNewName, + /* 0x5 */ GraphicsNew, + /* 0x6 */ CfgApply, + /* 0x7 */ SkipIf, + /* 0x8 */ GRFInfo, + /* 0x9 */ SkipIf, + /* 0xa */ SpriteReplace, + /* 0xb */ GRFError, + /* 0xc */ GRFComment, + /* 0xd */ ParamSet, + /* 0xe */ GRFInhibit, + }; + byte action; + byte *buf = malloc(num); + int i; + + _cur_grffile = filename; + _cur_spriteid = spriteid; + + for (i = 0; i != num; i++) + buf[i] = FioReadByte(); + + action = buf[0]; + if (action < NUM_ACTIONS) { + handlers[action](buf, num); + } else { + grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action); + } + + free(buf); +#undef NUM_ACTIONS +} diff --git a/gui.h b/gui.h new file mode 100644 --- /dev/null +++ b/gui.h @@ -0,0 +1,118 @@ +#ifndef GUI_H +#define GUI_H + +/* main_gui.c */ +void SetupColorsAndInitialWindow(); +void CcPlaySound10(bool success, uint tile, uint32 p1, uint32 p2); +void PlaceProc_Sign(uint tile); + +/* settings_gui.c */ +void ShowGameOptions(); +void ShowGameDifficulty(); +void ShowPatchesSelection(); + +/* graph_gui.c */ +void ShowOperatingProfitGraph(); +void ShowIncomeGraph(); +void ShowDeliveredCargoGraph(); +void ShowPerformanceHistoryGraph(); +void ShowCompanyValueGraph(); +void ShowCargoPaymentRates(); +void ShowCompanyLeagueTable(); + +/* news_gui.c */ +void ShowLastNewsMessage(); +void ShowMessageOptions(); +void ShowMessageHistory(); + +/* traintoolb_gui.c */ +void ShowBuildRailToolbar(int index, int button); +void PlaceProc_BuyLand(uint tile); + +/* train_gui.c */ +void ShowPlayerTrains(int player); +void ShowTrainViewWindow(Vehicle *v); +void ShowTrainDetailsWindow(Vehicle *v); +void ShowOrdersWindow(Vehicle *v); + +void ShowRoadVehViewWindow(Vehicle *v); + +/* road_gui.c */ +void ShowBuildRoadToolbar(); +void ShowBuildRoadScenToolbar(); +void ShowPlayerRoadVehicles(int player); + +/* dock_gui.c */ +void ShowBuildDocksToolbar(); +void ShowPlayerShips(int player); + +void ShowShipViewWindow(Vehicle *v); + +/* aircraft_gui.c */ +void ShowBuildAirToolbar(); +void ShowPlayerAircraft(int player); + +/* terraform_gui.c */ +void PlaceProc_DemolishArea(uint tile); +void PlaceProc_LowerLand(uint tile); +void PlaceProc_RaiseLand(uint tile); +void PlaceProc_LevelLand(uint tile); +void ShowTerraformToolbar(); + +/* misc_gui.c */ +void PlaceLandBlockInfo(); +void ShowAboutWindow(); +void ShowBuildTreesToolbar(); +void ShowBuildTreesScenToolbar(); +void ShowTownDirectory(); +void ShowIndustryDirectory(); +void ShowSubsidiesList(); +void ShowPlayerStations(int player); +void ShowPlayerFinances(int player); +void ShowPlayerCompany(int player); + +void ShowEstimatedCostOrIncome(int32 cost, int x, int y); +void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y); + +void DrawStationCoverageAreaText(int sx, int sy, uint mask); +void CheckRedrawStationCoverage(Window *w); + +void ShowSmallMap(); +void SetVScrollCount(Window *w, int num); +void SetHScrollCount(Window *w, int num); + +void ShowCheatWindow(); +void AskForNewGameToStart(); + +void DrawEditBox(Window *w, int wid); +void HandleEditBox(Window *w, int wid); + + +/* network gui */ +void ShowNetworkGameWindow(); + + +/* bridge_gui.c */ +void ShowBuildBridgeWindow(uint start, uint end, byte type); + +enum { + ZOOM_IN = 0, + ZOOM_OUT = 1, + ZOOM_NONE = 2, // hack, used to update the button status +}; + +bool DoZoomInOut(int how); +void ShowBuildIndustryWindow(); +void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number); +void ShowMusicWindow(); + +void DrawVehicleProfitButton(Vehicle *v, int x, int y); + +/* main_gui.c */ +VARDEF byte _newspaper_flag; +VARDEF byte _construct_mode; +VARDEF byte _station_show_coverage; +VARDEF PlaceProc *_place_proc; +VARDEF bool _no_button_sound; + +#endif /* GUI_H */ diff --git a/hal.h b/hal.h new file mode 100644 --- /dev/null +++ b/hal.h @@ -0,0 +1,146 @@ +#ifndef HAL_H +#define HAL_H + +typedef struct { + char *(*start)(char **parm); + void (*stop)(); +} HalCommonDriver; + +typedef struct { + const char *(*start)(char **parm); + void (*stop)(); + void (*make_dirty)(int left, int top, int width, int height); + int (*main_loop)(); + bool (*change_resolution)(int w, int h); +} HalVideoDriver; + +enum { + ML_QUIT = 0, + ML_SWITCHDRIVER = 1, +}; + +typedef struct { + char *(*start)(char **parm); + void (*stop)(); +} HalSoundDriver; + +typedef struct { + char *(*start)(char **parm); + void (*stop)(); + + void (*play_song)(const char *filename); + void (*stop_song)(); + bool (*is_song_playing)(); + void (*set_volume)(byte vol); +} HalMusicDriver; + +typedef struct { + const char *name; + const char *longname; + const void *drv; + uint flags; +} DriverDesc; + +enum { + HALERR_OK = 0, + HALERR_ERROR = 1, +}; + +extern const HalMusicDriver _null_music_driver; +extern const HalVideoDriver _null_video_driver; +extern const HalSoundDriver _null_sound_driver; + +VARDEF HalMusicDriver *_music_driver; +VARDEF HalSoundDriver *_sound_driver; +VARDEF HalVideoDriver *_video_driver; + +extern const DriverDesc _video_driver_descs[]; +extern const DriverDesc _sound_driver_descs[]; +extern const DriverDesc _music_driver_descs[]; + +#if defined(WITH_SDL) +extern const HalSoundDriver _sdl_sound_driver; +extern const HalVideoDriver _sdl_video_driver; +#endif + +#if defined(UNIX) +extern const HalMusicDriver _extmidi_music_driver; +#endif + +#if defined(__BEOS__) +extern const HalMusicDriver _bemidi_music_driver; +#endif + +enum DriverType { + VIDEO_DRIVER = 0, + SOUND_DRIVER = 1, + MUSIC_DRIVER = 2, +}; + +extern void GameLoop(); +extern bool _dbg_screen_rect; + +void LoadDriver(int driver, const char *name); + +char *GetDriverParam(char **parm, const char *name); +bool GetDriverParamBool(char **parm, const char *name); +int GetDriverParamInt(char **parm, const char *name, int def); + + + +// Deals with finding savegames +typedef struct { + uint16 id; + byte type; + uint64 mtime; + char title[64]; + char name[256-12-64]; + int old_extension; +} FiosItem; + +// extensions of old savegames, scenarios +static const char* const _old_extensions[] = { + // old savegame types + "ss1", // Transport Tycoon Deluxe preset game + "sv1", // Transport Tycoon Deluxe (Patch) saved game + "sv2", // Transport Tycoon Deluxe (Patch) saved 2-player game + // old scenario game type + "sv0", // Transport Tycoon Deluxe (Patch) scenario + "ss0", // Transport Tycoon Deluxe preset scenario +}; + +enum { + FIOS_TYPE_DRIVE = 0, + FIOS_TYPE_PARENT = 1, + FIOS_TYPE_DIR = 2, + FIOS_TYPE_FILE = 3, + FIOS_TYPE_OLDFILE = 4, + FIOS_TYPE_SCENARIO = 5, + FIOS_TYPE_OLD_SCENARIO = 6, +}; + +// get the name of an oldstyle savegame +void GetOldSaveGameName(char *title, const char *file); +// get the name of an oldstyle scenario +void GetOldScenarioGameName(char *title, const char *file); + +// Get a list of savegames +FiosItem *FiosGetSavegameList(int *num, int mode); +// Get a list of scenarios +FiosItem *FiosGetScenarioList(int *num, int mode); +// Free the list of savegames +void FiosFreeSavegameList(); +// Browse to. Returns a filename w/path if we reached a file. +char *FiosBrowseTo(const FiosItem *item); +// Get descriptive texts. +// Returns a path as well as a +// string describing the path. +StringID FiosGetDescText(char **path); +// Delete a name +void FiosDelete(const char *name); +// Make a filename from a name +void FiosMakeSavegameName(char *buf, const char *name); + +void CreateConsole(); + +#endif /* HAL_H */ diff --git a/industry.h b/industry.h new file mode 100644 --- /dev/null +++ b/industry.h @@ -0,0 +1,74 @@ +#ifndef INDUSTRY_H +#define INDUSTRY_H + +struct Industry { + TileIndex xy; + byte width; /* swapped order of w/h with town */ + byte height; + Town *town; + byte produced_cargo[2]; + uint16 cargo_waiting[2]; + byte production_rate[2]; + byte accepts_cargo[3]; + byte prod_level; + uint16 last_mo_production[2]; + uint16 last_mo_transported[2]; + byte pct_transported[2]; + uint16 total_production[2]; + uint16 total_transported[2]; + uint16 counter; + + byte type; + byte owner; + byte color_map; + byte last_prod_year; + byte was_cargo_delivered; +}; + +VARDEF int _total_industries; // For the AI: the amount of industries active +VARDEF Industry _industries[90]; +#define DEREF_INDUSTRY(i) (&_industries[i]) +VARDEF bool _industry_sort_dirty; +void DeleteIndustry(Industry *is); + +enum { + IT_COAL_MINE = 0, + IT_POWER_STATION = 1, + IT_SAWMILL = 2, + IT_FOREST = 3, + IT_OIL_REFINERY = 4, + IT_OIL_RIG = 5, + IT_FACTORY = 6, + IT_PRINTING_WORKS = 7, + IT_STEEL_MILL = 8, + IT_FARM = 9, + IT_COPPER_MINE = 10, + IT_OIL_WELL = 11, + IT_BANK = 12, + IT_FOOD_PROCESS = 13, + IT_PAPER_MILL = 14, + IT_GOLD_MINE = 15, + IT_BANK_2 = 16, + IT_DIAMOND_MINE = 17, + IT_IRON_MINE = 18, + IT_FRUIT_PLANTATION = 19, + IT_RUBBER_PLANTATION = 20, + IT_WATER_SUPPLY = 21, + IT_WATER_TOWER = 22, + IT_FACTORY_2 = 23, + IT_FARM_2 = 24, + IT_LUMBER_MILL = 25, + IT_COTTON_CANDY = 26, + IT_CANDY_FACTORY = 27, + IT_BATTERY_FARM = 28, + IT_COLA_WELLS = 29, + IT_TOY_SHOP = 30, + IT_TOY_FACTORY = 31, + IT_PLASTIC_FOUNTAINS = 32, + IT_FIZZY_DRINK_FACTORY = 33, + IT_BUBBLE_GENERATOR = 34, + IT_TOFFEE_QUARRY = 35, + IT_SUGAR_MINE = 36, +}; + +#endif diff --git a/industry_cmd.c b/industry_cmd.c new file mode 100644 --- /dev/null +++ b/industry_cmd.c @@ -0,0 +1,1875 @@ +#include "stdafx.h" +#include "ttd.h" +#include "viewport.h" +#include "command.h" +#include "industry.h" +#include "town.h" +#include "vehicle.h" +#include "news.h" +#include "saveload.h" +#include "economy.h" + +byte _industry_sound_ctr; +TileIndex _industry_sound_tile; + +void ShowIndustryViewWindow(int industry); +void BuildOilRig(uint tile); +void DeleteOilRig(uint tile); + +typedef struct DrawIndustryTileStruct { + uint32 sprite_1; + uint32 sprite_2; + + byte subtile_xy; + byte width_height; + byte dz; + byte proc; +} DrawIndustryTileStruct; + + +typedef struct DrawIndustrySpec1Struct { + byte x; + byte image_1; + byte image_2; + byte image_3; +} DrawIndustrySpec1Struct; + +typedef struct DrawIndustrySpec4Struct { + byte image_1; + byte image_2; + byte image_3; +} DrawIndustrySpec4Struct; + + + +#include "table/industry_land.h" + + +typedef struct IndustryTileTable { + TileIndexDiff ti; + byte map5; +} IndustryTileTable; + +typedef struct IndustrySpec { + const IndustryTileTable * const * table; + byte num_table; + byte a,b,c; + byte produced_cargo[2]; + byte production_rate[2]; + byte accepts_cargo[3]; + byte check_proc; +} IndustrySpec; + +#include "table/build_industry.h" + +static const byte _industry_close_mode[37] = { + 1,0,2,1,2,1,2,2,2,1,1,1,0,2,2,1,0,1,1,1,1,1,0,2,1,2,1,2,1,1,0,2,1,2,1,1,1, +}; + +static const StringID _industry_prod_up_strings[] = { + STR_4836_NEW_COAL_SEAM_FOUND_AT, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4837_NEW_OIL_RESERVES_FOUND, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4835_INCREASES_PRODUCTION, + STR_4837_NEW_OIL_RESERVES_FOUND, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4835_INCREASES_PRODUCTION, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4835_INCREASES_PRODUCTION, + STR_4838_IMPROVED_FARMING_METHODS, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, + STR_4835_INCREASES_PRODUCTION, +}; + +static const StringID _industry_prod_down_strings[] = { + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_483A_INSECT_INFESTATION_CAUSES, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, + STR_4839_PRODUCTION_DOWN_BY_50, +}; + +static const StringID _industry_close_strings[] = { + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4834_LACK_OF_NEARBY_TREES_CAUSES, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4833_SUPPLY_PROBLEMS_CAUSE_TO, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE, + STR_4832_ANNOUNCES_IMMINENT_CLOSURE , +}; + + +static void IndustryDrawTileProc1(TileInfo *ti) +{ + const DrawIndustrySpec1Struct *d; + uint32 image; + + if (!(_map_owner[ti->tile] & 0x80)) + return; + + d = &_draw_industry_spec1[_map3_lo[ti->tile]]; + + AddChildSpriteScreen(0x12A7 + d->image_1, d->x, 0); + + if ( (image = d->image_2) != 0) + AddChildSpriteScreen(0x12B0 + image - 1, 8, 41); + + if ( (image = d->image_3) != 0) + AddChildSpriteScreen(0x12AC + image - 1, + _drawtile_proc1_x[image-1], _drawtile_proc1_y[image-1]); +} + +static void IndustryDrawTileProc2(TileInfo *ti) +{ + int x = 0; + + if (_map_owner[ti->tile] & 0x80) { + x = _industry_anim_offs[_map3_lo[ti->tile]]; + if ( (byte)x == 0xFF) + x = 0; + } + + AddChildSpriteScreen(0x129F, 22-x, x+24); + AddChildSpriteScreen(0x129E, 6, 0xE); +} + +static void IndustryDrawTileProc3(TileInfo *ti) +{ + if (_map_owner[ti->tile] & 0x80) { + AddChildSpriteScreen(0x128B, 5, + _industry_anim_offs_2[_map3_lo[ti->tile]]); + } + AddChildSpriteScreen(0x30B928A, 3, 67); +} + +static void IndustryDrawTileProc4(TileInfo *ti) +{ + const DrawIndustrySpec4Struct *d; + + d = &_industry_anim_offs_3[_map3_lo[ti->tile]]; + + if (d->image_1 != 0xFF) { + AddChildSpriteScreen(0x126F, 0x32 - d->image_1 * 2, 0x60 + d->image_1); + } + + if (d->image_2 != 0xFF) { + AddChildSpriteScreen(0x1270, 0x10 - d->image_2*2, 100 + d->image_2); + } + + AddChildSpriteScreen(0x126E, 7, d->image_3); + AddChildSpriteScreen(0x126D, 0, 42); +} + +static void DrawCoalPlantSparkles(TileInfo *ti) +{ + int image = _map_owner[ti->tile]; + if (image & 0x80) { + image = (image >> 2) & 0x1F; + if (image != 0 && image < 7) { + AddChildSpriteScreen(image + 0x806, + _coal_plant_sparkles_x[image-1], + _coal_plant_sparkles_y[image-1] + ); + } + } +} + +typedef void IndustryDrawTileProc(TileInfo *ti); +static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = { + IndustryDrawTileProc1, + IndustryDrawTileProc2, + IndustryDrawTileProc3, + IndustryDrawTileProc4, + DrawCoalPlantSparkles, +}; + +static void DrawTile_Industry(TileInfo *ti) +{ + Industry *ind; + const DrawIndustryTileStruct *dits; + byte z; + uint32 image, ormod; + + /* Pointer to industry */ + ind = DEREF_INDUSTRY(_map2[ti->tile]); + ormod = (ind->color_map+0x307)<<16; + + /* Retrieve pointer to the draw industry tile struct */ + dits = &_industry_draw_tile_data[(ti->map5<<2) | (_map_owner[ti->tile]&3)]; + + image = dits->sprite_1; + if (image&0x8000 && (image & 0xFFFF0000) == 0) + image |= ormod; + + z = ti->z; + /* Add bricks below the industry? */ + if (ti->tileh & 0xF) { + AddSortableSpriteToDraw((ti->tileh & 0xF) + 0x3DD, ti->x, ti->y, 16, 16, 7, z); + AddChildSpriteScreen(image, 0x1F, 1); + z += 8; + } else { + /* Else draw regular ground */ + DrawGroundSprite(image); + } + + /* Add industry on top of the ground? */ + if ((image = dits->sprite_2) != 0) { + + if (image&0x8000 && (image & 0xFFFF0000) == 0) + image |= ormod; + + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + + AddSortableSpriteToDraw(image, + ti->x | (dits->subtile_xy>>4), + ti->y | (dits->subtile_xy&0xF), + (dits->width_height>>4)+1, + (dits->width_height&0xF)+1, + dits->dz, + z); + + if (!(_display_opt & DO_TRANS_BUILDINGS)) + return; + } + + /* TTDBUG: strange code here, return if AddSortableSpriteToDraw failed? */ + { + int proc; + if ((proc=dits->proc-1) >= 0 ) + _industry_draw_tile_procs[proc](ti); + } +} + + +static uint GetSlopeZ_Industry(TileInfo *ti) { + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; +} + +static void GetAcceptedCargo_Industry(uint tile, AcceptedCargo *ac) +{ + int m5 = _map5[tile]; + int a; + + a = _industry_map5_accepts_1[m5]; + if (a >= 0) { + ac->type_1 = a; + ac->amount_1 = (a == 0) ? 1 : 8; + } + + a = _industry_map5_accepts_2[m5]; + if (a >= 0) { + ac->type_2 = a; + ac->amount_2 = 8; + } + + a = _industry_map5_accepts_3[m5]; + if (a >= 0) { + ac->type_3 = a; + ac->amount_3 = 8; + } +} + +static void GetTileDesc_Industry(uint tile, TileDesc *td) +{ + Industry *i = DEREF_INDUSTRY(_map2[tile]); + + td->owner = i->owner; + td->str = STR_4802_COAL_MINE + i->type; + if ((_map_owner[tile] & 0x80) == 0) { + SET_DPARAMX16(td->dparam, 0, td->str); + td->str = STR_2058_UNDER_CONSTRUCTION; + } +} + +static int32 ClearTile_Industry(uint tile, byte flags) +{ + Industry *i = DEREF_INDUSTRY(_map2[tile]); + + if ((_current_player == OWNER_WATER || _game_mode != GM_EDITOR) && !_cheats.magic_bulldozer.value) { + SET_DPARAM16(0, STR_4802_COAL_MINE + i->type); + return_cmd_error(STR_4800_IN_THE_WAY); + } + + if (flags & DC_EXEC) { + DeleteIndustry(i); + } + return 0; +} + +/* p1 index of industry to destroy */ +/* Destroy Industry button costing money removed per request of dominik +int32 CmdDestroyIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + Industry *i = DEREF_INDUSTRY((uint16)p1); + Town *t = ClosestTownFromTile(tile, (uint)-1); // find closest town to penaltize (ALWAYS penaltize) + + // check if you're allowed to remove the industry. Minimum amount + // of ratings to remove the industry depends on difficulty setting + if (!CheckforTownRating(tile, flags, t, INDUSTRY_REMOVE)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DeleteIndustry(i); + CreateEffectVehicleAbove(x + 8,y + 8, 2, EV_DEMOLISH); + ChangeTownRating(t, -1500, -1000); // penalty is 1500 + } + + return (_price.build_industry >> 5) * _industry_type_costs[i->type]*2; +} +*/ + +static const byte _industry_min_cargo[] = { + 5, 5, 5, 30, 5, 5, 5, 5, + 5, 5, 5, 5, 2, 5, 5, 5, + 5, 5, 5, 15, 15, 5, 5, 5, + 5, 5, 30, 5, 30, 5, 5, 5, + 5, 5, 5, 5, 5, +}; + +void TransportIndustryGoods(uint tile) +{ + Industry *i; + int type; + uint cw, am; + byte m5; + + i = DEREF_INDUSTRY(_map2[tile]); + + type = i->type; + cw = min(i->cargo_waiting[0], 255); + if (cw > _industry_min_cargo[type]/* && i->produced_cargo[0] != 0xFF*/) { + i->cargo_waiting[0] -= cw; + + /* fluctuating economy? */ + if (_economy.fluct <= 0) cw = (cw + 1) >> 1; + + i->last_mo_production[0] += cw; + + am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[0], cw); + i->last_mo_transported[0] += am; + if (am != 0 && (m5 = _industry_produce_map5[_map5[tile]]) != 0xFF) { + _map5[tile] = m5; + _map_owner[tile] = 0x80; + MarkTileDirtyByTile(tile); + } + } + + type = i->type; + cw = min(i->cargo_waiting[1], 255); + if (cw > _industry_min_cargo[type]) { + i->cargo_waiting[1] -= cw; + + if (_economy.fluct <= 0) cw = (cw + 1) >> 1; + + i->last_mo_production[1] += cw; + + am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[1], cw); + i->last_mo_transported[1] += am; + } +} + + +static void AnimateTile_Industry(uint tile) +{ + byte m,n; + + switch(_map5[tile]) { + case 174: + if ((_tick_counter & 1) == 0) { + m = _map3_lo[tile] + 1; + + switch(m & 7) { + case 2: SndPlayTileFx(45, tile); break; + case 6: SndPlayTileFx(41, tile); break; + } + + if (m >= 96) { + m = 0; + DeleteAnimatedTile(tile); + } + _map3_lo[tile] = m; + + MarkTileDirtyByTile(tile); + } + break; + + case 165: + if ((_tick_counter & 3) == 0) { + m = _map3_lo[tile]; + + if (_industry_anim_offs[m] == 0xFF) { + SndPlayTileFx(48, tile); + } + + if (++m >= 70) { + m = 0; + DeleteAnimatedTile(tile); + } + _map3_lo[tile] = m; + + MarkTileDirtyByTile(tile); + } + break; + + case 162: + if ((_tick_counter&1) == 0) { + m = _map3_lo[tile]; + + if (++m >= 40) { + m = 0; + DeleteAnimatedTile(tile); + } + _map3_lo[tile] = m; + + MarkTileDirtyByTile(tile); + } + break; + + // Sparks on a coal plant + case 10: + if ((_tick_counter & 3) == 0) { + m = _map_owner[tile]; + if ((m & (31<<2)) == (6 << 2)) { + _map_owner[tile] = m&~(31<<2); + DeleteAnimatedTile(tile); + } else { + _map_owner[tile] = m + (1<<2); + MarkTileDirtyByTile(tile); + } + } + break; + + case 143: + if ((_tick_counter & 1) == 0) { + m = _map3_lo[tile] + 1; + + if (m == 1) { + SndPlayTileFx(44, tile); + } else if (m == 23) { + SndPlayTileFx(43, tile); + } else if (m == 28) { + SndPlayTileFx(42, tile); + } + + if (m >= 50 && (m=0,++_map3_hi[tile] >= 8)) { + _map3_hi[tile] = 0; + DeleteAnimatedTile(tile); + } + _map3_lo[tile] = m; + MarkTileDirtyByTile(tile); + } + break; + + case 148: case 149: case 150: case 151: + case 152: case 153: case 154: case 155: + if ((_tick_counter & 3) == 0) { + m = _map5[tile] + 1; + if (m == 155+1) m = 148; + _map5[tile] = m; + + MarkTileDirtyByTile(tile); + } + break; + + case 30: case 31: case 32: + if ((_tick_counter & 7) == 0) { + bool b = CHANCE16(1,7); + m = _map_owner[tile]; + m = (m & 3) + 1; + n = _map5[tile]; + if (m == 4 && (m=0,++n) == 32+1 && (n=30,b)) { + _map_owner[tile] = 0x83; + _map5[tile] = 29; + DeleteAnimatedTile(tile); + } else { + _map5[tile] = n; + _map_owner[tile] = (_map_owner[tile] & ~3) | m; + MarkTileDirtyByTile(tile); + } + } + break; + + case 88: + case 48: + case 1: { + int state = _tick_counter & 0x7FF; + + if ((state -= 0x400) < 0) + return; + + if (state < 0x1A0) { + if (state < 0x20 || state >= 0x180) { + if (! (_map_owner[tile] & 0x40)) { + _map_owner[tile] |= 0x40; + SndPlayTileFx(9, tile); + } + if (state & 7) + return; + } else { + if (state & 3) + return; + } + m = (_map_owner[tile] + 1) | 0x40; + if (m > 0xC2) m = 0xC0; + _map_owner[tile] = m; + MarkTileDirtyByTile(tile); + } else if (state >= 0x200 && state < 0x3A0) { + int i; + i = (state < 0x220 || state >= 0x380) ? 7 : 3; + if (state & i) + return; + + m = (_map_owner[tile] & 0xBF) - 1; + if (m < 0x80) m = 0x82; + _map_owner[tile] = m; + MarkTileDirtyByTile(tile); + } + } break; + } +} + +static void MakeIndustryTileBiggerCase8(uint tile) +{ + TileInfo ti; + FindLandscapeHeight(&ti, GET_TILE_X(tile)*16, GET_TILE_Y(tile)*16); + CreateEffectVehicle(ti.x + 15, ti.y + 14, ti.z + 59 + (ti.tileh != 0 ? 8 : 0), EV_INDUSTRYSMOKE); +} + +static void MakeIndustryTileBigger(uint tile, byte size) +{ + byte b = (byte)((size + (1<<2)) & (3<<2)); + + if (b != 0) { + _map_owner[tile] = b | (size & 3); + return; + } + + size = (size + 1) & 3; + if (size == 3) size |= 0x80; + _map_owner[tile] = size | b; + + MarkTileDirtyByTile(tile); + + if (!(_map_owner[tile] & 0x80)) + return; + + switch(_map5[tile]) { + case 8: + MakeIndustryTileBiggerCase8(tile); + break; + + case 24: + if (_map5[tile + TILE_XY(0,1)] == 24) { + BuildOilRig(tile); + } + break; + + case 143: + case 162: + case 165: + _map3_lo[tile] = 0; + _map3_hi[tile] = 0; + break; + + case 148: case 149: case 150: case 151: + case 152: case 153: case 154: case 155: + AddAnimatedTile(tile); + break; + } +} + + + +static void TileLoopIndustryCase161(uint tile) +{ + int dir; + Vehicle *v; + static const int8 _tileloop_ind_case_161[12] = { + 11, 0, -4, -14, + -4, -10, -4, 1, + 49, 59, 60, 65, + }; + + SndPlayTileFx(46, tile); + + dir = Random() & 3; + + v = CreateEffectVehicleAbove( + GET_TILE_X(tile)*16 + _tileloop_ind_case_161[dir + 0], + GET_TILE_Y(tile)*16 + _tileloop_ind_case_161[dir + 4], + _tileloop_ind_case_161[dir + 8], + EV_INDUSTRY_SMOKE + ); + + if (v != NULL) + v->u.special.unk2 = dir; +} + +static void TileLoop_Industry(uint tile) +{ + byte n; + + if (!(_map_owner[tile] & 0x80)) { + MakeIndustryTileBigger(tile, _map_owner[tile]); + return; + } + + if (_game_mode == GM_EDITOR) + return; + + TransportIndustryGoods(tile); + + n = _industry_map5_animation_next[_map5[tile]]; + if (n != 255) { + _map5[tile] = n; + _map_owner[tile] = 0; + MarkTileDirtyByTile(tile); + return; + } + +#define SET_AND_ANIMATE(tile,a,b) { _map5[tile]=a; _map_owner[tile]=b; AddAnimatedTile(tile); } +#define SET_AND_UNANIMATE(tile,a,b) { _map5[tile]=a; _map_owner[tile]=b; DeleteAnimatedTile(tile); } + + switch(_map5[tile]) { + case 0: + if (!(_tick_counter & 0x400) && CHANCE16(1,2)) + SET_AND_ANIMATE(tile,1,0x80); + break; + + case 47: + if (!(_tick_counter & 0x400) && CHANCE16(1,2)) + SET_AND_ANIMATE(tile,0x30,0x80); + break; + + case 79: + if (!(_tick_counter & 0x400) && CHANCE16(1,2)) + SET_AND_ANIMATE(tile,0x58,0x80); + break; + + case 29: + if (CHANCE16(1,6)) + SET_AND_ANIMATE(tile,0x1E,0x80); + break; + + case 1: + if (!(_tick_counter & 0x400)) + SET_AND_UNANIMATE(tile, 0, 0x83); + break; + + case 48: + if (!(_tick_counter & 0x400)) + SET_AND_UNANIMATE(tile, 0x2F, 0x83); + break; + + case 88: + if (!(_tick_counter & 0x400)) + SET_AND_UNANIMATE(tile, 0x4F, 0x83); + break; + + case 10: + if (CHANCE16(1,3)) { + SndPlayTileFx(10, tile); + AddAnimatedTile(tile); + } + break; + + case 49: { + CreateEffectVehicleAbove(GET_TILE_X(tile)*16 + 6, GET_TILE_Y(tile)*16 + 6, 43, EV_SMOKE_3); + } break; + + + case 143: { + Industry *i = DEREF_INDUSTRY(_map2[tile]); + if (i->was_cargo_delivered) { + i->was_cargo_delivered = false; + if ((_map3_hi[tile]|_map3_lo[tile]) != 0) + _map3_hi[tile] = 0; + AddAnimatedTile(tile); + } + } + break; + + case 161: + TileLoopIndustryCase161(tile); + break; + + case 165: + AddAnimatedTile(tile); + break; + + case 174: + if (CHANCE16(1,3)) { + AddAnimatedTile(tile); + } + break; + } +} + + +static void ClickTile_Industry(uint tile) +{ + ShowIndustryViewWindow(_map2[tile]); +} + +static uint32 GetTileTrackStatus_Industry(uint tile, int mode) +{ + return 0; +} + +static void GetProducedCargo_Industry(uint tile, byte *b) +{ + Industry *i = DEREF_INDUSTRY(_map2[tile]); + b[0] = i->produced_cargo[0]; + b[1] = i->produced_cargo[1]; +} + +static void ChangeTileOwner_Industry(uint tile, byte old_player, byte new_player) +{ + /* not used */ +} + +void DeleteIndustry(Industry *i) +{ + int index = i - _industries; + + BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy); + if (IS_TILETYPE(tile_cur, MP_INDUSTRY)) { + if (_map2[tile_cur] == (byte)index) { + DoClearSquare(tile_cur); + } + } else if (IS_TILETYPE(tile_cur, MP_STATION) && _map5[tile_cur] == 0x4B) { + DeleteOilRig(tile_cur); + } + END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); + + i->xy = 0; + _industry_sort_dirty = true; + DeleteSubsidyWithIndustry(index); + DeleteWindowById(WC_INDUSTRY_VIEW, index); + InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); +} + +static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6}; + +static bool IsBadFarmFieldTile(uint tile) +{ + if (IS_TILETYPE(tile,MP_CLEAR)) { + byte m5 = _map5[tile] & 0x1C; + if (m5 == 0xC || m5 == 0x10) + return true; + return false; + } else if (IS_TILETYPE(tile,MP_TREES)) { + return false; + } else { + return true; + } +} + +static bool IsBadFarmFieldTile2(uint tile) +{ + if (IS_TILETYPE(tile,MP_CLEAR)) { + byte m5 = _map5[tile] & 0x1C; + if (m5 == 0x10) + return true; + return false; + } else if (IS_TILETYPE(tile,MP_TREES)) { + return false; + } else { + return true; + } +} + +static void SetupFarmFieldFence(uint tile, int size, byte type, int direction) +{ + byte or, and; + + do { + tile = TILE_MASK(tile); + + if (IS_TILETYPE(tile, MP_CLEAR) || IS_TILETYPE(tile, MP_TREES)) { + + or = type; + if (or == 1 && (uint16)Random() <= 9362) or = 2; + + or <<= 2; + and = (byte)~0x1C; + if (direction) { + or <<= 3; + and = (byte)~0xE0; + } + _map3_hi[tile] = (_map3_hi[tile] & and) | or; + } + + tile += direction ? TILE_XY(0,1) : TILE_XY(1,0); + } while (--size); +} + +static void PlantFarmField(uint tile) +{ + uint size_x, size_y; + uint32 r; + int count; + int type, type2; + + if (_opt.landscape == LT_HILLY) { + if (GetTileZ(tile) >= (_opt.snow_line - 16)) + return; + } + + /* determine field size */ + r = (Random() & 0x303) + 0x404; + if (_opt.landscape == LT_HILLY) r += 0x404; + size_x = (byte)r; + size_y = r >> 8; + + /* offset tile to match size */ + tile = tile - TILE_XY(size_x>>1, size_y>>1); + + /* check the amount of bad tiles */ + count = 0; + BEGIN_TILE_LOOP(cur_tile, size_x, size_y, tile) + cur_tile = TILE_MASK(cur_tile); + count += IsBadFarmFieldTile(cur_tile); + END_TILE_LOOP(cur_tile, size_x, size_y, tile) + if ((uint)(count * 2) >= size_x * size_y) + return; + + /* determine type of field */ + r = Random(); + type = ((r & 0xE0) | 0xF); + type2 = ((byte)(r >> 8) * 9) >> 8; + + /* make field */ + BEGIN_TILE_LOOP(cur_tile, size_x, size_y, tile) + cur_tile = TILE_MASK(cur_tile); + if (!IsBadFarmFieldTile2(cur_tile)) { + ModifyTile(cur_tile, + MP_SETTYPE(MP_CLEAR) | + MP_MAP2_CLEAR | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAPOWNER | MP_MAP5, + type2, /* map3_lo */ + OWNER_NONE, /* map_owner */ + type); /* map5 */ + } + END_TILE_LOOP(cur_tile, size_x, size_y, tile) + + type = 3; + if (_opt.landscape != LT_HILLY && _opt.landscape != LT_DESERT) { + type = _plantfarmfield_type[Random() & 0xF]; + } + + SetupFarmFieldFence(tile-TILE_XY(1,0), size_y, type, 1); + SetupFarmFieldFence(tile-TILE_XY(0,1), size_x, type, 0); + SetupFarmFieldFence(tile+TILE_XY(1,0) * (size_x-1), size_y, type, 1); + SetupFarmFieldFence(tile+TILE_XY(0,1) * (size_y-1), size_x, type, 0); +} + +static void MaybePlantFarmField(Industry *i) +{ + uint tile; + if (CHANCE16(1,8)) { + tile = TileAddWrap(i->xy, TILE_XY(i->width>>1, i->height>>1) + (Random()&TILE_XY(31,31))-TILE_XY(16,16)); + if (tile != TILE_WRAPPED) + PlantFarmField(tile); + } +} + +static void ChopLumberMillTrees(Industry *i) +{ + static const TileIndexDiff _chop_dir[4] = { TILE_XY(0,1), TILE_XY(1,0), TILE_XY(0,-1), TILE_XY(-1,0) }; + + uint tile = i->xy; + int dir, a, j; + + if ((_map_owner[tile] & 0x80) == 0) + return; + + /* search outwards as a rectangular spiral */ + for(a=1; a!=41; a+=2) { + for(dir=0; dir!=4; dir++) { + j = a; + do { + tile = TILE_MASK(tile); + if (IS_TILETYPE(tile, MP_TREES)) { + /* found a tree */ + + _current_player = OWNER_NONE; + _industry_sound_ctr = 1; + _industry_sound_tile = tile; + SndPlayTileFx(56, tile); + + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + SetMapExtraBits(tile, 0); + + i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + 45); + return; + } + tile += _chop_dir[dir]; + } while (--j); + } + tile -= TILE_XY(1,1); + } +} + +static const byte _industry_sounds[37][2] = { + {0}, + {0}, + {1,38}, + {0}, + {0}, + {0}, + {1,1}, + {1,1}, + {0}, + {3,34}, + {0}, + {0}, + {0}, + {0}, + {1,38}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {1,1}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {1,51}, + {0}, + {0}, + {0}, + {0}, +}; + + +static void ProduceIndustryGoods(Industry *i) +{ + uint32 r; + uint num; + + /* play a sound? */ + if ((i->counter & 0x3F) == 0) { + if (CHANCE16R(1,14,r) && (num=_industry_sounds[i->type][0]) != 0) { + SndPlayTileFx( + _industry_sounds[i->type][1] + (((r >> 16) * num) >> 16), + i->xy); + } + } + + i->counter--; + + /* produce some cargo */ + if ((i->counter & 0xFF) == 0) { + i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + i->production_rate[0]); + i->cargo_waiting[1] = min(0xffff, i->cargo_waiting[1] + i->production_rate[1]); + + if (i->type == IT_FARM) + MaybePlantFarmField(i); + else if (i->type == IT_LUMBER_MILL && (i->counter & 0x1FF) == 0) + ChopLumberMillTrees(i); + } +} + +void OnTick_Industry() +{ + Industry *i; + + if (_industry_sound_ctr != 0) { + _industry_sound_ctr++; + + if (_industry_sound_ctr == 75) { + SndPlayTileFx(55, _industry_sound_tile); + } else if (_industry_sound_ctr == 160) { + _industry_sound_ctr = 0; + SndPlayTileFx(54, _industry_sound_tile); + } + } + + if (_game_mode == GM_EDITOR) + return; + + for(i=_industries; i != endof(_industries); i++) { + if (i->xy != 0) + ProduceIndustryGoods(i); + } +} + + +static bool CheckNewIndustry_NULL(uint tile, int type) +{ + return true; +} + +static bool CheckNewIndustry_Forest(uint tile, int type) +{ + if (_opt.landscape == LT_HILLY) { + if (GetTileZ(tile) < (_opt.snow_line + 16) ) { + _error_message = STR_4831_FOREST_CAN_ONLY_BE_PLANTED; + return false; + } + } + return true; +} + +static bool CheckNewIndustry_Oilwell(uint tile, int type) +{ + int x,y; + if (type != IT_OIL_RIG && _game_mode == GM_EDITOR) + return true; + + x = GET_TILE_X(tile); + y = GET_TILE_Y(tile); + + if ( x < 15 || y < 15 || x > 238 || y > 238) + return true; + + _error_message = STR_483B_CAN_ONLY_BE_POSITIONED; + return false; +} + +static bool CheckNewIndustry_Farm(uint tile, int type) +{ + if (_opt.landscape == LT_HILLY) { + if (GetTileZ(tile) >= (_opt.snow_line - 16)) { + _error_message = STR_0239_SITE_UNSUITABLE; + return false; + } + } + return true; +} + +static bool CheckNewIndustry_Plantation(uint tile, int type) +{ + if (GetMapExtraBits(tile) == 1) { + _error_message = STR_0239_SITE_UNSUITABLE; + return false; + } + + return true; +} + +static bool CheckNewIndustry_Water(uint tile, int type) +{ + if (GetMapExtraBits(tile) != 1) { + _error_message = STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT; + return false; + } + + return true; +} + +static bool CheckNewIndustry_Lumbermill(uint tile, int type) +{ + if (GetMapExtraBits(tile) != 2) { + _error_message = STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST; + return false; + } + return true; +} + +static bool CheckNewIndustry_BubbleGen(uint tile, int type) +{ + if (GetTileZ(tile) > 32) { + return false; + } + return true; +} + +typedef bool CheckNewIndustryProc(uint tile, int type); +static CheckNewIndustryProc * const _check_new_industry_procs[] = { + CheckNewIndustry_NULL, + CheckNewIndustry_Forest, + CheckNewIndustry_Oilwell, + CheckNewIndustry_Farm, + CheckNewIndustry_Plantation, + CheckNewIndustry_Water, + CheckNewIndustry_Lumbermill, + CheckNewIndustry_BubbleGen, +}; + +static bool CheckSuitableIndustryPos(uint tile) +{ + int x = GET_TILE_X(tile); + int y = GET_TILE_Y(tile); + + if ( x < 2 || y < 2 || x > TILE_X_MAX - 3 || y > TILE_Y_MAX - 3) { + _error_message = STR_0239_SITE_UNSUITABLE; + return false; + } + + return true; +} + +static Town *CheckMultipleIndustryInTown(uint tile, int type) +{ + Town *t; + Industry *i; + + t = ClosestTownFromTile(tile, (uint)-1); + + if (_patches.multiple_industry_per_town) + return t; + + for(i=_industries; i != endof(_industries); i++) { + if (i->xy != 0 && + i->type == (byte)type && + i->town == t) { + _error_message = STR_0287_ONLY_ONE_ALLOWED_PER_TOWN; + return NULL; + } + } + + return t; +} + +static const byte _industry_map5_bits[] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 4, 2, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 4, 2, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, +}; + +static bool CheckIfIndustryTilesAreFree(uint tile, const IndustryTileTable *it, int type, Town *t) +{ + TileInfo ti; + uint cur_tile; + + _error_message = STR_0239_SITE_UNSUITABLE; + + do { + cur_tile = tile + it->ti; + if (!IsValidTile(cur_tile)) { + if (it->map5 == 0xff) + continue; + return false; + } + + FindLandscapeHeightByTile(&ti, cur_tile); + + if (it->map5 == 0xFF) { + if (ti.type != MP_WATER || ti.tileh != 0) + return false; + } else { + if (!EnsureNoVehicle(cur_tile)) + return false; + + if (type == IT_OIL_RIG) { + if (ti.type != MP_WATER || ti.map5 != 0) + return false; + } else { + if (ti.type == MP_WATER && ti.map5 == 0) + return false; + if (ti.tileh & 0x10) + return false; + + if (ti.tileh != 0) { + int t; + byte bits = _industry_map5_bits[it->map5]; + + if (bits & 0x10) + return false; + + t = ~ti.tileh; + + if (bits & 1 && (t & (1+8))) + return false; + + if (bits & 2 && (t & (4+8))) + return false; + + if (bits & 4 && (t & (1+2))) + return false; + + if (bits & 8 && (t & (2+4))) + return false; + } + + if (type == IT_BANK) { + if (ti.type != MP_HOUSE || t->population < 1200) { + _error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS; + return false; + } + } else if (type == IT_BANK_2) { + if (ti.type != MP_HOUSE) { + _error_message = STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS; + return false; + } + } else if (type == IT_TOY_SHOP) { + if (GetTileDist1D(t->xy, cur_tile) > 9) + return false; + if (ti.type != MP_HOUSE) goto do_clear; + } else if (type == IT_WATER_TOWER) { + if (ti.type != MP_HOUSE) { + _error_message = STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS; + return false; + } + } else { +do_clear: + if (DoCommandByTile(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return false; + } + } + } + } while ( (++it)->ti != -0x8000); + + return true; +} + +static bool CheckIfTooCloseToIndustry(uint tile, int type) +{ + Industry *i; + const IndustrySpec *spec; + spec = &_industry_spec[type]; + + // accepting industries won't be close, not even with patch + if (_patches.same_industry_close && (spec->accepts_cargo[0] == 0xFF) ) + return true; + + for(i=_industries; i != endof(_industries); i++) { + // check if an industry that accepts the same goods is nearby + if (i->xy != 0 && + (GetTileDist1D(tile, i->xy) <= 14) && + spec->accepts_cargo[0] != 0xFF && + spec->accepts_cargo[0] == i->accepts_cargo[0]) { + _error_message = STR_INDUSTRY_TOO_CLOSE; + return false; + } + + // check "not close to" field. + if (i->xy != 0 && + (i->type == spec->a || i->type == spec->b || i->type == spec->c) && + GetTileDist1D(tile, i->xy) <= 14) { + _error_message = STR_INDUSTRY_TOO_CLOSE; + return false; + } + } + return true; +} + +static Industry *AllocateIndustry() +{ + Industry *i; + + for(i=_industries; i != endof(_industries); i++) { + if (i->xy == 0) { + int index = i - _industries; + if (index > _total_industries) _total_industries++; + return i; + } + } + return NULL; +} + +static void DoCreateNewIndustry(Industry *i, uint tile, int type, const IndustryTileTable *it, Town *t, byte owner) +{ + const IndustrySpec *spec; + uint32 r; + uint cur_tile; + int j; + + i->xy = tile; + i->width = i->height = 0; + i->type = type; + + spec = &_industry_spec[type]; + + i->produced_cargo[0] = spec->produced_cargo[0]; + i->produced_cargo[1] = spec->produced_cargo[1]; + i->accepts_cargo[0] = spec->accepts_cargo[0]; + i->accepts_cargo[1] = spec->accepts_cargo[1]; + i->accepts_cargo[2] = spec->accepts_cargo[2]; + i->production_rate[0] = spec->production_rate[0]; + i->production_rate[1] = spec->production_rate[1]; + + if (_patches.smooth_economy) { + i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8 , 255); + i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8 , 255); + } + + i->town = t; + i->owner = owner; + + r = Random() & 0xFFF; + i->color_map = (byte)(r >> 8); + i->counter = (uint16)r; + i->cargo_waiting[0] = 0; + i->cargo_waiting[1] = 0; + i->last_mo_production[0] = 0; + i->last_mo_production[1] = 0; + i->last_mo_transported[0] = 0; + i->last_mo_transported[1] = 0; + i->pct_transported[0] = 0; + i->pct_transported[1] = 0; + i->total_transported[0] = 0; + i->total_transported[1] = 0; + i->was_cargo_delivered = false; + i->last_prod_year = _cur_year; + i->total_production[0] = i->production_rate[0] * 8; + i->total_production[1] = i->production_rate[1] * 8; + + if (_generating_world == 0) + i->total_production[0] = i->total_production[1] = 0; + + i->prod_level = 0x10; + + do { + cur_tile = tile + it->ti; + + if (it->map5 != 0xFF) { + byte size; + + size = GET_TILE_X((TileIndex)it->ti); + if (size > i->width) i->width = size; + size = GET_TILE_Y((TileIndex)it->ti); + if (size > i->height)i->height = size; + + DoCommandByTile(cur_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + + _map_type_and_height[cur_tile] = (_map_type_and_height[cur_tile]&~0xF0) | (MP_INDUSTRY<<4); + _map5[cur_tile] = it->map5; + _map2[cur_tile] = i - _industries; + _map_owner[cur_tile] = _generating_world ? 0x1E : 0; /* maturity */ + } + } while ( (++it)->ti != -0x8000); + + i->width++; + i->height++; + + if (i->type == IT_FARM || i->type == IT_FARM_2) { + tile = i->xy + TILE_XY((i->width >> 1), (i->height >> 1)); + for(j=0; j!=50; j++) { + uint new_tile = TileAddWrap(tile, (Random() & TILE_XY(31,31)) - TILE_XY(16,16)); + if (new_tile != TILE_WRAPPED) + PlantFarmField(new_tile); + } + } + _industry_sort_dirty = true; + InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); +} + +/* p1 = industry type 0-36 */ +int32 CmdBuildIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + Town *t; + int num; + const IndustryTileTable * const *itt; + const IndustryTileTable *it; + Industry *i; + const IndustrySpec *spec; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + + if (!CheckSuitableIndustryPos(tile)) + return CMD_ERROR; + + spec = &_industry_spec[p1]; + + if (!_check_new_industry_procs[spec->check_proc](tile, p1)) + return CMD_ERROR; + + if ((t=CheckMultipleIndustryInTown(tile, p1)) == NULL) + return CMD_ERROR; + + num = spec->num_table; + itt = spec->table; + + do { + if (--num < 0) + return_cmd_error(STR_0239_SITE_UNSUITABLE); + } while (!CheckIfIndustryTilesAreFree(tile, it=itt[num], p1, t)); + + + if (!CheckIfTooCloseToIndustry(tile, p1)) + return CMD_ERROR; + + if ( (i = AllocateIndustry()) == NULL) + return CMD_ERROR; + + if (flags & DC_EXEC) + DoCreateNewIndustry(i, tile, p1, it, t, 0x10); + + return (_price.build_industry >> 5) * _industry_type_costs[p1]; +} + + +Industry *CreateNewIndustry(uint tile, int type) +{ + Town *t; + const IndustryTileTable *it; + Industry *i; + + const IndustrySpec *spec; + + if (!CheckSuitableIndustryPos(tile)) + return NULL; + + spec = &_industry_spec[type]; + + if (!_check_new_industry_procs[spec->check_proc](tile, type)) + return NULL; + + if (!(t=CheckMultipleIndustryInTown(tile, type))) + return NULL; + + /* pick a random layout */ + it = spec->table[(spec->num_table * (uint16)Random()) >> 16]; + + if (!CheckIfIndustryTilesAreFree(tile, it, type, t)) + return NULL; + + if (!CheckIfTooCloseToIndustry(tile, type)) + return NULL; + + if ( (i = AllocateIndustry()) == NULL) + return NULL; + + DoCreateNewIndustry(i, tile, type, it, t, 0x10); + + return i; +} + +static const byte _numof_industry_table[3][12] = { + {0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + {0, 2, 3, 4, 6, 7, 8, 9, 10, 10, 10}, +}; + +static void PlaceInitialIndustry(byte type, int amount) +{ + int num = _numof_industry_table[_opt.diff.number_industries][amount]; + + assert(num > 0); + + do { + int i = 2000; + do { + if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL) + break; + } while (--i != 0); + } while (--num); +} + +void GenerateIndustries() +{ + const byte *b; + + b = _industry_create_table[_opt.landscape]; + do { + PlaceInitialIndustry(b[1], b[0]); + } while ( (b+=2)[0] != 0); +} + +static void ExtChangeIndustryProduction(Industry *i) +{ + bool closeit; + int j; + + if (_industry_close_mode[i->type] == 0) return; + + closeit = true; + + if (_industry_close_mode[i->type] == 2) { + if ( (byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1,180)) + closeit = false; + } else { + for (j=0; j != 2 && i->produced_cargo[j]!=255; j++){ + uint32 r; + int change,percent,old; + int mag; + + change = old = i->production_rate[j]; + if (CHANCE16R(20,1024,r))change -= ((RandomRange(50) + 10)*old) >> 8; + if (CHANCE16I(20+(i->pct_transported[j]*20>>8),1024,r>>16)) change += ((RandomRange(50) + 10)*old) >> 8; + + // make sure it doesn't exceed 255 or goes below 0 + change = clamp(change, 0, 255); + if (change == old) { + closeit = false; + continue; + } + + percent = change*100/old - 100; + i->production_rate[j] = change; + + if (change >= _industry_spec[i->type].production_rate[j]/4) + closeit = false; + + mag = abs(percent); + if (mag >= 10) { + SET_DPARAM16(3, mag); + SET_DPARAM16(0,_cargoc.names_s[i->produced_cargo[j]]); + SET_DPARAM16(1, i->town->index); + SET_DPARAM16(2, i->type + STR_4802_COAL_MINE); + AddNewsItem(percent>=0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN, + NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), + i->xy + TILE_XY(1,1), 0); + } + } + } + + if (closeit) { + i->prod_level = 0; + SET_DPARAM16(1, i->type + STR_4802_COAL_MINE); + SET_DPARAM16(0, i->town->index); + AddNewsItem(_industry_close_strings[i->type], NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), i->xy + TILE_XY(1,1), 0); + } +} + + +static void UpdateIndustryStatistics(Industry *i) +{ + byte pct; + + if (i->produced_cargo[0] != 0xFF) { + pct = 0; + if (i->last_mo_production[0] != 0) { + i->last_prod_year = _cur_year; + pct = min(i->last_mo_transported[0] * 256 / i->last_mo_production[0],255); + } + i->pct_transported[0] = pct; + + i->total_production[0] = i->last_mo_production[0]; + i->last_mo_production[0] = 0; + + i->total_transported[0] = i->last_mo_transported[0]; + i->last_mo_transported[0] = 0; + } + + if (i->produced_cargo[1] != 0xFF) { + pct = 0; + if (i->last_mo_production[1] != 0) { + i->last_prod_year = _cur_year; + pct = min(i->last_mo_transported[1] * 256 / i->last_mo_production[1],255); + } + i->pct_transported[1] = pct; + + i->total_production[1] = i->last_mo_production[1]; + i->last_mo_production[1] = 0; + + i->total_transported[1] = i->last_mo_transported[1]; + i->last_mo_transported[1] = 0; + } + + + if ( i->produced_cargo[0] != 0xFF || i->produced_cargo[1] != 0xFF ) + InvalidateWindow(WC_INDUSTRY_VIEW, i - _industries); + + if (i->prod_level == 0) + DeleteIndustry(i); + else if (_patches.smooth_economy) + ExtChangeIndustryProduction(i); +} + +static const byte _new_industry_rand[4][32] = { + {12,12,12,12,12,12,12, 0, 0, 6, 6, 9, 9, 3, 3, 3,18,18, 4, 4, 2, 2, 5, 5, 5, 5, 5, 5, 1, 1, 8, 8}, + {16,16,16, 0, 0, 0, 9, 9, 9, 9,13,13, 3, 3, 3, 3,15,15,15, 4, 4,11,11,11,11,11,14,14, 1, 1, 7, 7}, + {21,21,21,24,22,22,22,22,23,23,12,12,12, 4, 4,19,19,19,13,13,20,20,20,11,11,11,17,17,17,10,10,10}, + {30,30,30,36,36,31,31,31,27,27,27,28,28,28,26,26,26,34,34,34,35,35,35,29,29,29,32,32,32,33,33,33}, +}; + +static void MaybeNewIndustry(uint32 r) +{ + int type; + int j; + Industry *i; + + type = _new_industry_rand[_opt.landscape][(r >> 16) & 0x1F]; + if (type == IT_OIL_WELL && _date > 10958) + return; + + if (type == IT_OIL_RIG && _date < 14610) + return; + + j = 2000; + _current_player = OWNER_NONE; + for(;;) { + i = CreateNewIndustry(TILE_MASK(Random()), type); + if (i != NULL) + break; + if (--j == 0) + return; + } + + SET_DPARAM16(0, type + STR_4802_COAL_MINE); + SET_DPARAM16(1, i->town->index); + AddNewsItem( STR_482D_NEW_UNDER_CONSTRUCTION + (type == IT_FOREST), NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ECONOMY,0), i->xy, 0); +} + +static void MaybeCloseIndustry(Industry *i) +{ + uint32 r; + StringID str; + int type = i->type; + + if (_industry_close_mode[type] == 1) { + /* decrease or increase */ + if (type == IT_OIL_WELL && _opt.landscape == LT_NORMAL) goto decrease_production; + if (CHANCE16I(1,3,r=Random())) { + if ((i->pct_transported[0] > 153) ^ CHANCE16I(1,3,r>>16)) { + +/* Increase production */ + if (i->prod_level != 0x80) { + byte b; + + i->prod_level <<= 1; + + b = i->production_rate[0]*2; + if (i->production_rate[0] >= 128) b=255; + i->production_rate[0] = b; + b = i->production_rate[1]*2; + if (i->production_rate[1] >= 128) b=255; + i->production_rate[1] = b; + + str = _industry_prod_up_strings[type]; + goto add_news; + } + } else { +decrease_production: + +/* Decrease production */ + if (i->prod_level == 4) goto close_industry; + i->prod_level>>=1; + i->production_rate[0] = (i->production_rate[0]+1) >> 1; + i->production_rate[1] = (i->production_rate[1]+1) >> 1; + + str = _industry_prod_down_strings[type]; + goto add_news; + } + } + } else if (_industry_close_mode[type] > 1) { + /* maybe close */ + if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) { +close_industry: + i->prod_level = 0; + str = _industry_close_strings[type]; +add_news: + SET_DPARAM16(1, type + STR_4802_COAL_MINE); + SET_DPARAM16(0, i->town->index); + AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), i->xy + TILE_XY(1,1), 0); + } + } +} + +void IndustryMonthlyLoop() +{ + Industry *i; + + for(i=_industries; i != endof(_industries); i++) { + if (i->xy != 0) + UpdateIndustryStatistics(i); + } + + i = DEREF_INDUSTRY(RandomRange(lengthof(_industries))); + + if (i->xy == 0) { + uint32 r; + if (CHANCE16I(1,9,r=Random())) + MaybeNewIndustry(r); + } else if (!_patches.smooth_economy) { + MaybeCloseIndustry(i); + } + // production-change + _industry_sort_dirty = true; + InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); +} + + +void InitializeIndustries() +{ + memset(_industries, 0, sizeof(_industries)); + _total_industries = 0; + _industry_sort_dirty = true; +} + +const TileTypeProcs _tile_type_industry_procs = { + DrawTile_Industry, /* draw_tile_proc */ + GetSlopeZ_Industry, /* get_slope_z_proc */ + ClearTile_Industry, /* clear_tile_proc */ + GetAcceptedCargo_Industry, /* get_accepted_cargo_proc */ + GetTileDesc_Industry, /* get_tile_desc_proc */ + GetTileTrackStatus_Industry,/* get_tile_track_status_proc */ + ClickTile_Industry, /* click_tile_proc */ + AnimateTile_Industry, /* animate_tile_proc */ + TileLoop_Industry, /* tile_loop_proc */ + ChangeTileOwner_Industry, /* change_tile_owner_proc */ + GetProducedCargo_Industry, /* get_produced_cargo_proc */ + NULL, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; + +static const byte _industry_desc[] = { + SLE_VAR(Industry,xy, SLE_UINT16), + SLE_VAR(Industry,width, SLE_UINT8), + SLE_VAR(Industry,height, SLE_UINT8), + SLE_REF(Industry,town, REF_TOWN), + SLE_ARR(Industry,produced_cargo, SLE_UINT8, 2), + SLE_ARR(Industry,cargo_waiting, SLE_UINT16, 2), + SLE_ARR(Industry,production_rate, SLE_UINT8, 2), + SLE_ARR(Industry,accepts_cargo, SLE_UINT8, 3), + SLE_VAR(Industry,prod_level, SLE_UINT8), + SLE_ARR(Industry,last_mo_production,SLE_UINT16, 2), + SLE_ARR(Industry,last_mo_transported,SLE_UINT16, 2), + SLE_ARR(Industry,pct_transported,SLE_UINT8, 2), + SLE_ARR(Industry,total_production,SLE_UINT16, 2), + SLE_ARR(Industry,total_transported,SLE_UINT16, 2), + + SLE_VAR(Industry,counter, SLE_UINT16), + + SLE_VAR(Industry,type, SLE_UINT8), + SLE_VAR(Industry,owner, SLE_UINT8), + SLE_VAR(Industry,color_map, SLE_UINT8), + SLE_VAR(Industry,last_prod_year, SLE_UINT8), + SLE_VAR(Industry,was_cargo_delivered,SLE_UINT8), + + // reserve extra space in savegame here. (currently 32 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 4, 2, 255), + + SLE_END() +}; + +static void Save_INDY() +{ + Industry *ind; + int i; + // Write the vehicles + for(ind=_industries,i=0; i!=lengthof(_industries); ind++,i++) { + if (ind->xy != 0) { + SlSetArrayIndex(i); + SlObject(ind, _industry_desc); + } + } +} + +static void Load_INDY() +{ + int index; + _total_industries = 0; + while ((index = SlIterateArray()) != -1) { + SlObject(DEREF_INDUSTRY(index), _industry_desc); + if (index + 1 > _total_industries) + _total_industries = index + 1; + } +} + +const ChunkHandler _industry_chunk_handlers[] = { + { 'INDY', Save_INDY, Load_INDY, CH_ARRAY | CH_LAST}, +}; + diff --git a/industry_gui.c b/industry_gui.c new file mode 100644 --- /dev/null +++ b/industry_gui.c @@ -0,0 +1,590 @@ +#include "stdafx.h" +#include "ttd.h" +//#include "gui.h" +#include "window.h" +#include "gfx.h" +#include "command.h" +#include "viewport.h" +#include "industry.h" +#include "town.h" + +static const byte _build_industry_types[4][12] = { + { 1, 2, 4, 6, 8, 0, 3, 5, 9, 11, 18 }, + { 1, 14, 4, 13, 7, 0, 3, 9, 11, 15 }, + { 25, 13, 4, 23, 22, 11, 17, 10, 24, 19, 20, 21 }, + { 27, 30, 31, 33, 26, 28, 29, 32, 34, 35, 36 }, +}; + +extern const byte _industry_type_costs[37]; + +static void BuildIndustryWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + if (_thd.place_mode == 1 && _thd.window_class == WC_BUILD_INDUSTRY) { + int ind_type = _build_industry_types[_opt.landscape][WP(w,def_d).data_1]; + + SET_DPARAM32(0, (_price.build_industry >> 5) * _industry_type_costs[ind_type]); + DrawStringCentered(85, w->height - 21, STR_482F_COST, 0); + } + break; + + case WE_CLICK: { + int wid = e->click.widget; + if (wid >= 3) { + if (HandlePlacePushButton(w, wid, 0xFF1, 1, NULL)) + WP(w,def_d).data_1 = wid - 3; + } + } break; + + case WE_PLACE_OBJ: + if (DoCommandP(e->place.tile, _build_industry_types[_opt.landscape][WP(w,def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY))) + ResetObjectToPlace(); + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + break; + } +} + +static const Widget _build_industry_land0_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0,0}, +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_0242_SAWMILL,STR_0264_CONSTRUCT_SAWMILL}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY,STR_0268_CONSTRUCT_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL,STR_0269_CONSTRUCT_STEEL_MILL}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land1_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0,0}, +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS,STR_0270_CONSTRUCT_PRINTING_WORKS}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land2_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0,0}, +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL,STR_0273_CONSTRUCT_LUMBER_MILL_TO}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY,STR_0268_CONSTRUCT_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER,STR_0277_CONSTRUCT_WATER_TOWER_CAN}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land3_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 115, 0x0,0}, +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY,STR_027B_CONSTRUCT_CANDY_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP,STR_027E_CONSTRUCT_TOY_SHOP}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY,STR_027F_CONSTRUCT_TOY_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY,STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land0_widgets_extra[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 187, 0x0,0}, + +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_0242_SAWMILL,STR_0264_CONSTRUCT_SAWMILL}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY,STR_0268_CONSTRUCT_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0247_STEEL_MILL,STR_0269_CONSTRUCT_STEEL_MILL}, + +{ WWT_CLOSEBOX, 14, 2, 167, 84, 95, STR_0240_COAL_MINE, STR_CONSTRUCT_COAL_MINE_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 97, 108, STR_0243_FOREST, STR_CONSTRUCT_FOREST_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 110, 121, STR_0245_OIL_RIG, STR_CONSTRUCT_OIL_RIG_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 123, 134, STR_0248_FARM, STR_CONSTRUCT_FARM_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 136, 147, STR_024A_OIL_WELLS, STR_CONSTRUCT_OIL_WELLS_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 149, 160, STR_0249_IRON_ORE_MINE, STR_CONSTRUCT_IRON_ORE_MINE_TIP}, + +{ WWT_LAST}, +}; + +static const Widget _build_industry_land1_widgets_extra[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 174, 0x0,0}, + +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0241_POWER_STATION,STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_024E_PRINTING_WORKS,STR_0270_CONSTRUCT_PRINTING_WORKS}, + +{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_0240_COAL_MINE,STR_CONSTRUCT_COAL_MINE_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_0243_FOREST,STR_CONSTRUCT_FOREST_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_0248_FARM,STR_CONSTRUCT_FARM_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_024A_OIL_WELLS,STR_CONSTRUCT_OIL_WELLS_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_024F_GOLD_MINE,STR_CONSTRUCT_GOLD_MINE_TIP}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land2_widgets_extra[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 200, 0x0,0}, + +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0250_LUMBER_MILL,STR_0273_CONSTRUCT_LUMBER_MILL_TO}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_024D_FOOD_PROCESSING_PLANT,STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_0244_OIL_REFINERY,STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_0246_FACTORY,STR_0268_CONSTRUCT_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 68, 79, STR_0254_WATER_TOWER,STR_0277_CONSTRUCT_WATER_TOWER_CAN}, + +{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_024A_OIL_WELLS,STR_CONSTRUCT_OIL_WELLS_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_0255_DIAMOND_MINE,STR_CONSTRUCT_DIAMOND_MINE_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_0256_COPPER_ORE_MINE,STR_CONSTRUCT_COPPER_ORE_MINE_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_0248_FARM,STR_CONSTRUCT_FARM_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_0251_FRUIT_PLANTATION,STR_CONSTRUCT_FRUIT_PLANTATION_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 146+3, 157+3, STR_0252_RUBBER_PLANTATION,STR_CONSTRUCT_RUBBER_PLANTATION_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 159+3, 170+3, STR_0253_WATER_SUPPLY,STR_CONSTRUCT_WATER_SUPPLY_TIP}, +{ WWT_LAST}, +}; + +static const Widget _build_industry_land3_widgets_extra[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_0314_FUND_NEW_INDUSTRY,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 169, 14, 187, 0x0,0}, + +{ WWT_CLOSEBOX, 14, 2, 167, 16, 27, STR_0258_CANDY_FACTORY,STR_027B_CONSTRUCT_CANDY_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 29, 40, STR_025B_TOY_SHOP,STR_027E_CONSTRUCT_TOY_SHOP}, +{ WWT_CLOSEBOX, 14, 2, 167, 42, 53, STR_025C_TOY_FACTORY,STR_027F_CONSTRUCT_TOY_FACTORY}, +{ WWT_CLOSEBOX, 14, 2, 167, 55, 66, STR_025E_FIZZY_DRINK_FACTORY,STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY}, + +{ WWT_CLOSEBOX, 14, 2, 167, 68+3, 79+3, STR_0257_COTTON_CANDY_FOREST,STR_CONSTRUCT_COTTON_CANDY_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 81+3, 92+3, STR_0259_BATTERY_FARM,STR_CONSTRUCT_BATTERY_FARM_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 94+3, 105+3, STR_025A_COLA_WELLS,STR_CONSTRUCT_COLA_WELLS_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 107+3, 118+3, STR_025D_PLASTIC_FOUNTAINS,STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 120+3, 131+3, STR_025F_BUBBLE_GENERATOR,STR_CONSTRUCT_BUBBLE_GENERATOR_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 133+3, 144+3, STR_0260_TOFFEE_QUARRY,STR_CONSTRUCT_TOFFEE_QUARRY_TIP}, +{ WWT_CLOSEBOX, 14, 2, 167, 146+3, 157+3, STR_0261_SUGAR_MINE,STR_CONSTRUCT_SUGAR_MINE_TIP}, +{ WWT_LAST}, +}; + + +static const WindowDesc _build_industry_land0_desc = { + -1, -1, 170, 116, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land0_widgets, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land1_desc = { + -1, -1, 170, 116, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land1_widgets, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land2_desc = { + -1, -1, 170, 116, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land2_widgets, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land3_desc = { + -1, -1, 170, 116, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land3_widgets, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land0_desc_extra = { + -1, -1, 170, 188, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land0_widgets_extra, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land1_desc_extra = { + -1, -1, 170, 175, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land1_widgets_extra, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land2_desc_extra = { + -1, -1, 170, 201, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land2_widgets_extra, + BuildIndustryWndProc +}; + +static const WindowDesc _build_industry_land3_desc_extra = { + -1, -1, 170, 188, + WC_BUILD_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_industry_land3_widgets_extra, + BuildIndustryWndProc +}; + +static const WindowDesc * const _industry_window_desc[2][4] = { + { + &_build_industry_land0_desc, + &_build_industry_land1_desc, + &_build_industry_land2_desc, + &_build_industry_land3_desc, + }, + { + &_build_industry_land0_desc_extra, + &_build_industry_land1_desc_extra, + &_build_industry_land2_desc_extra, + &_build_industry_land3_desc_extra, + }, +}; + +void ShowBuildIndustryWindow() +{ + AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt.landscape],0); +} + +static void IndustryViewWndProc(Window *w, WindowEvent *e) +{ + Industry *i; + StringID str; + + switch(e->event) { + case WE_PAINT: + // in editor, use bulldoze to destroy industry + // Destroy Industry button costing money removed per request of dominik + //w->disabled_state = (_patches.extra_dynamite && !_networking && _game_mode != GM_EDITOR) ? 0 : (1 << 6); + i = DEREF_INDUSTRY(w->window_number); + SET_DPARAM16(0, i->town->index); + SET_DPARAM16(1, i->type + STR_4802_COAL_MINE); + DrawWindowWidgets(w); + + if (i->accepts_cargo[0] != 0xFF) { + SET_DPARAM16(0, _cargoc.names_s[i->accepts_cargo[0]]); + str = STR_4827_REQUIRES; + if (i->accepts_cargo[1] != 0xFF) { + SET_DPARAM16(1, _cargoc.names_s[i->accepts_cargo[1]]); + str++; + if (i->accepts_cargo[2] != 0xFF) { + SET_DPARAM16(2, _cargoc.names_s[i->accepts_cargo[2]]); + str++; + } + } + DrawString(2, 107, str, 0); + } + + if (i->produced_cargo[0] != 0xFF) { + DrawString(2, 117, STR_482A_PRODUCTION_LAST_MONTH, 0); + + SET_DPARAM16(1, i->total_production[0]); + SET_DPARAM16(0, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5)); + SET_DPARAM16(2, i->pct_transported[0] * 100 >> 8); + DrawString(4, 127, STR_482B_TRANSPORTED, 0); + + if (i->produced_cargo[1] != 0xFF) { + SET_DPARAM16(1, i->total_production[1]); + SET_DPARAM16(0, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5)); + SET_DPARAM16(2, i->pct_transported[1] * 100 >> 8); + DrawString(4, 137, STR_482B_TRANSPORTED, 0); + } + } + + DrawWindowViewport(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 5: + i = DEREF_INDUSTRY(w->window_number); + ScrollMainWindowToTile(i->xy + TILE_XY(1,1)); + break; + case 6: + // Destroy Industry button costing money removed per request of dominik + //i = DEREF_INDUSTRY(w->window_number); + /* passing only i->xy is not safe if industry has a weird shape like: + _ X X + X X X + _ <--- grass, no industry, but i->xy points there (first top-left tile)!, + so passing i->xy to destroy industry will fail in called procedure + */ + //DoCommandP(i->xy, w->window_number, 0, CcPlaySound10, CMD_DESTROY_INDUSTRY | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + break; + } + break; + } +} + +static const Widget _industry_view_widgets[] = { +{ WWT_TEXTBTN, 9, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 9, 11, 259, 0, 13, STR_4801, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 9, 0, 259, 14, 105, 0x0}, +{ WWT_6, 9, 2, 257, 16, 103, 0x0}, +{ WWT_IMGBTN, 9, 0, 259, 106, 147, 0x0}, +{ WWT_PUSHTXTBTN, 9, 0, 129, 148, 159, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON}, +{ WWT_IMGBTN, 9, 130, 259, 148, 159, 0x0, 0}, +// Destroy Industry button costing money removed per request of dominik +//{ WWT_PUSHTXTBTN, 9, 130, 259, 148, 159, STR_INDUSTRYDIR_DESTROY, STR_482C_DESTROY_INDUSTRY}, +{ WWT_LAST}, +}; + +static const WindowDesc _industry_view_desc = { + -1, -1, 260, 160, + WC_INDUSTRY_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _industry_view_widgets, + IndustryViewWndProc +}; + +void ShowIndustryViewWindow(int industry) +{ + Window *w; + Industry *i; + + w = AllocateWindowDescFront(&_industry_view_desc, industry); + if (w) { + w->flags4 |= WF_DISABLE_VP_SCROLL; + i = DEREF_INDUSTRY(w->window_number); + AssignWindowViewport(w, 3, 17, 0xFE, 0x56, i->xy + TILE_XY(1,1), 1); + } +} + +static const Widget _industry_directory_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 507, 0, 13, STR_INDUSTRYDIR_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 13, 0, 100, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 13, 101, 200, 14, 25, STR_SORT_BY_TYPE, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 13, 201, 300, 14, 25, STR_SORT_BY_PRODUCTION, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 13, 301, 400, 14, 25, STR_SORT_BY_TRANSPORTED, STR_SORT_TIP}, +{ WWT_PANEL, 13, 401, 496, 14, 25, 0x0, 0}, +{ WWT_IMGBTN, 13, 0, 496, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME}, +{ WWT_SCROLLBAR, 13, 497, 507, 14, 189, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static byte _industry_sort[lengthof(_industries)]; +static uint _num_industry_sort; + +static char _bufcache[96]; +static byte _last_industry_idx; + +static byte _industry_sort_order; + +static int CDECL IndustrySorter(const void *a, const void *b) +{ + char buf1[96]; + Industry *i, *j; + byte val; + int r = 0; + + i = DEREF_INDUSTRY(*(byte*)a); + j = DEREF_INDUSTRY(*(byte*)b); + + switch (_industry_sort_order >> 1) { + case 0: + r = 0; + break; + case 1: /* Case 1, sort by type */ + r = i->type - j->type; + break; + case 2: /* Case 2, sort by production */ + if (i->produced_cargo[0] != 0xFF && j->produced_cargo[0] != 0xFF) { //producing any cargo? + if (i->produced_cargo[1] == 0xFF) //producing one or two things? + r = j->total_production[0] - i->total_production[0]; + else + r = (j->total_production[0] + j->total_production[1]) / 2 - (i->total_production[0] + i->total_production[1]) / 2; + } else if (i->produced_cargo[0] == 0xFF && j->produced_cargo[0] == 0xFF) //None of them producing anything, let them go to the name-sorting + r = 0; + else if (i->produced_cargo[0] == 0xFF) //Non-producers, end up last/first in list + r = 1; + else + r = -1; + break; + case 3: /* Case 3, sort by transportation */ + if (i->produced_cargo[0] != 0xFF && j->produced_cargo[0] != 0xFF) { //producing any cargo? + if (i->produced_cargo[1] == 0xFF) //producing one or two things? + r = (j->pct_transported[0] * 100 >> 8) - (i->pct_transported[0] * 100 >> 8); + else + r = ((j->pct_transported[0] * 100 >> 8) + (j->pct_transported[1] * 100 >> 8)) / 2 - ((i->pct_transported[0] * 100 >> 8) + (i->pct_transported[1] * 100 >> 8)) / 2; + } else if (i->produced_cargo[0] == 0xFF && j->produced_cargo[0] == 0xFF) //None of them producing anything, let them go to the name-sorting + r = 0; + else if (i->produced_cargo[0] == 0xFF) //Non-producers, end up last/first in list + r = 1; + else + r = -1; + break; + } + + // default to string sorting if they are otherwise equal + if (r == 0) { + SET_DPARAM32(0, i->town->townnameparts); + GetString(buf1, i->town->townnametype); + + if ( (val=*(byte*)b) != _last_industry_idx) { + _last_industry_idx = val; + SET_DPARAM32(0, j->town->townnameparts); + GetString(_bufcache, j->town->townnametype); + } + r = strcmp(buf1, _bufcache); + } + + if (_industry_sort_order & 1) + r = -r; + + return r; +} + +static void MakeSortedIndustryList() +{ + Industry *i; + int n = 0, index = 0; + + for(i=_industries; i != endof(_industries); i++) { + if(i->xy) _industry_sort[n++] = index; + index++; + } + _num_industry_sort = n; + _last_industry_idx = 255; // used for "cache" + + qsort(_industry_sort, n, 1, IndustrySorter); +} + + +static void IndustryDirectoryWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int n; + uint p; + Industry *i; + static const uint16 _indicator_positions[4] = {88, 187, 284, 387}; + + if (_industry_sort_dirty) { + _industry_sort_dirty = false; + MakeSortedIndustryList(); + } + + w->vscroll.count = _num_industry_sort; + + DrawWindowWidgets(w); + DoDrawString(_industry_sort_order & 1 ? "\xAA" : "\xA0", _indicator_positions[_industry_sort_order>>1], 15, 0x10); + + p = w->vscroll.pos; + n = 0; + + while (p < _num_industry_sort) { + i = DEREF_INDUSTRY(_industry_sort[p]); + SET_DPARAM16(0, i->town->index); + SET_DPARAM16(1, i->type + STR_4802_COAL_MINE); + if (i->produced_cargo[0] != 0xFF) { + SET_DPARAM16(3, i->total_production[0] * 100 >> 8); + SET_DPARAM16(2, _cargoc.names_long_s[i->produced_cargo[0]] + ((i->total_production[0]!=1)<<5)); + + if (i->produced_cargo[1] != 0xFF) { + SET_DPARAM16(5, i->total_production[1] * 100 >> 8); + SET_DPARAM16(4, _cargoc.names_long_s[i->produced_cargo[1]] + ((i->total_production[1]!=1)<<5)); + SET_DPARAM16(6, i->pct_transported[0] * 100 >> 8); + SET_DPARAM16(7, i->pct_transported[1] * 100 >> 8); + DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM_TWO, 0); + } else { + SET_DPARAM16(4, i->pct_transported[0] * 100 >> 8); + DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM, 0); + } + } else { + DrawString(4, 28+n*10, STR_INDUSTRYDIR_ITEM_NOPROD, 0); + } + p++; + if (++n == 16) + break; + } + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { + _industry_sort_order = _industry_sort_order==0 ? 1 : 0; + _industry_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 3: { + _industry_sort_order = _industry_sort_order==2 ? 3 : 2; + _industry_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 4: { + _industry_sort_order = _industry_sort_order==4 ? 5 : 4; + _industry_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 5: { + _industry_sort_order = _industry_sort_order==6 ? 7 : 6; + _industry_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 7: { + int y = (e->click.pt.y - 28) / 10; + byte p; + Industry *c; + + if (!IS_INT_INSIDE(y, 0, 16)) + return; + p = y + w->vscroll.pos; + if (p < _num_industry_sort) { + c = DEREF_INDUSTRY(_industry_sort[p]); + ScrollMainWindowToTile(c->xy); + } + } break; + } + break; + + case WE_4: + SetWindowDirty(w); + break; + } +} + + +/* Industry List */ +static const WindowDesc _industry_directory_desc = { + -1, -1, 508, 190, + WC_INDUSTRY_DIRECTORY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _industry_directory_widgets, + IndustryDirectoryWndProc +}; + + + +void ShowIndustryDirectory() +{ + /* Industry List */ + Window *w; + + w = AllocateWindowDescFront(&_industry_directory_desc, 0); + if (w) { + w->vscroll.cap = 16; + SetWindowDirty(w); + } +} diff --git a/intro_gui.c b/intro_gui.c new file mode 100644 --- /dev/null +++ b/intro_gui.c @@ -0,0 +1,277 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "player.h" +#include "command.h" + +extern void MakeNewGame(); +extern void StartScenario(); + +/* +static void ShowSelectTutorialWindow() +{ +} +*/ + +static const Widget _select_game_widgets[] = { +{ WWT_CAPTION, 13, 0, 335, 0, 13, STR_0307_TRANSPORT_TYCOON_DELUXE}, +{ WWT_IMGBTN, 13, 0, 335, 14, 196, 0x0}, +{ WWT_PUSHTXTBTN, 12, 10, 167, 22, 33, STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME}, +{ WWT_PUSHTXTBTN, 12, 168, 325, 22, 33, STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME_FROM}, +//{ WWT_PUSHTXTBTN, 12, 10, 167, 177, 188, STR_0142_TUTORIAL_DEMONSTRATION, STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS}, +{ WWT_PUSHTXTBTN, 12, 10, 167, 177, 188, STR_CONFIG_PATCHES, STR_CONFIG_PATCHES_TIP}, +{ WWT_PUSHTXTBTN, 12, 10, 167, 40, 51, STR_0220_CREATE_SCENARIO, STR_02FE_CREATE_A_CUSTOMIZED_GAME}, +{ WWT_PUSHTXTBTN, 12, 10, 167, 136, 147, STR_SINGLE_PLAYER, STR_02FF_SELECT_SINGLE_PLAYER_GAME}, +{ WWT_PUSHTXTBTN, 12, 168, 325, 136, 147, STR_MULTIPLAYER, STR_0300_SELECT_TWO_PLAYER_GAME}, +{ WWT_PUSHTXTBTN, 12, 10, 167, 159, 170, STR_0148_GAME_OPTIONS, STR_0301_DISPLAY_GAME_OPTIONS}, +{ WWT_PUSHTXTBTN, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY,STR_0302_DISPLAY_DIFFICULTY_OPTIONS}, +{ WWT_PUSHTXTBTN, 12, 168, 325, 40, 51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING}, +{ WWT_PUSHTXTBTN, 12, 168, 325, 177, 188, STR_0304_QUIT, STR_0305_LEAVE_TRANSPORT_TYCOON}, +{ WWT_PANEL_2, 12, 10, 85, 69, 122, 0x1312, STR_030E_SELECT_TEMPERATE_LANDSCAPE}, +{ WWT_PANEL_2, 12, 90, 165, 69, 122, 0x1314, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE}, +{ WWT_PANEL_2, 12, 170, 245, 69, 122, 0x1316, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE}, +{ WWT_PANEL_2, 12, 250, 325, 69, 122, 0x1318, STR_0311_SELECT_TOYLAND_LANDSCAPE}, +{ WWT_LAST}, +}; + +static void SelectGameWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + w->click_state = (w->click_state & ~(0xC0) & ~(0xF << 12)) | (1 << (_new_opt.landscape+12)) | (!_networking?(1<<6):(1<<7)); + w->disabled_state = _networking ? 0x30 : 0; + SET_DPARAM16(0, STR_6801_EASY + _new_opt.diff_level); + DrawWindowWidgets(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: DoCommandP(0, 0, 0, NULL, CMD_START_NEW_GAME); break; + case 3: ShowSaveLoadDialog(SLD_LOAD_GAME); break; + case 4: ShowPatchesSelection(); break; + case 5: DoCommandP(0, InteractiveRandom(), 0, NULL, CMD_CREATE_SCENARIO); break; + case 6: + if (_networking) + DoCommandP(0, 0, 0, NULL, CMD_SET_SINGLE_PLAYER); + break; + case 7: + ShowNetworkGameWindow(); + break; + case 8: ShowGameOptions(); break; + case 9: ShowGameDifficulty(); break; + case 10:ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; + case 11:AskExitGame(); break; + case 12: case 13: case 14: case 15: + DoCommandP(0, e->click.widget - 12, 0, NULL, CMD_SET_NEW_LANDSCAPE_TYPE); + break; + } + break; + } +} + +static const WindowDesc _select_game_desc = { + WDP_CENTER, WDP_CENTER, 336, 197, + WC_SELECT_GAME,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _select_game_widgets, + SelectGameWndProc +}; + +void ShowSelectGameWindow() +{ + AllocateWindowDesc(&_select_game_desc); +} + + +// p1 = mode +// 0 - start new game +// 1 - close new game dialog + +int32 CmdStartNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (!(flags & DC_EXEC)) + return 0; + + switch(p1) { + case 0: // show select game window + AskForNewGameToStart(); + break; + case 1: // close select game window + DeleteWindowById(WC_SAVELOAD, 0); + break; + } + + return 0; +} + +int32 CmdGenRandomNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (!(flags & DC_EXEC)) + return 0; + + // this forces stuff into test mode. + _docommand_recursive = 0; + + _random_seed_1 = p1; + _random_seed_2 = p2; + + if (_networking) { NetworkStartSync(); } + + MakeNewGame(); + return 0; +} + +int32 CmdLoadGame(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (!(flags & DC_EXEC)) + return 0; + +// ShowSaveLoadDialog(0); + return 0; +} + +int32 CmdCreateScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (!(flags & DC_EXEC)) + return 0; + + _switch_mode = SM_EDITOR; + return 0; +} + +int32 CmdSetSinglePlayer(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + printf("CmdSetSinglePlayer\n"); + return 0; +} + +int32 CmdStartScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (!(flags & DC_EXEC)) + return 0; + + // this forces stuff into test mode. + _docommand_recursive = 0; + + _random_seed_1 = p1; + _random_seed_2 = p2; + + if (_networking) { NetworkStartSync(); } + + StartScenario(); + return 0; +} + + +static const Widget _ask_abandon_game_widgets[] = { +{ WWT_TEXTBTN, 4, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 4, 11, 179, 0, 13, STR_00C7_QUIT}, +{ WWT_IMGBTN, 4, 0, 179, 14, 91, 0x0}, +{ WWT_TEXTBTN, 12, 25, 84, 72, 83, STR_00C9_NO}, +{ WWT_TEXTBTN, 12, 95, 154, 72, 83, STR_00C8_YES}, +{ WWT_LAST}, +}; + +static void AskAbandonGameWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); +#if defined(_WIN32) + SET_DPARAM16(0, STR_0133_WINDOWS); +#elif defined(__APPLE__) + SET_DPARAM16(0, STR_0135_OSX); +#elif defined(__BEOS__) + SET_DPARAM16(0, STR_OSNAME_BEOS); +#elif defined(__MORPHOS__) + SET_DPARAM16(0, STR_OSNAME_MORPHOS); +#else + SET_DPARAM16(0, STR_0134_UNIX); +#endif + DrawStringMultiCenter(0x5A, 0x26, STR_00CA_ARE_YOU_SURE_YOU_WANT_TO, 178); + return; + + case WE_CLICK: + switch(e->click.widget) { + case 3: + DeleteWindow(w); + break; + case 4: + _exit_game = true; + break; + } + break; + } +} + +static const WindowDesc _ask_abandon_game_desc = { + WDP_CENTER, WDP_CENTER, 180, 92, + WC_ASK_ABANDON_GAME,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _ask_abandon_game_widgets, + AskAbandonGameWndProc +}; + +void AskExitGame() +{ + AllocateWindowDescFront(&_ask_abandon_game_desc, 0); +} + + +static const Widget _ask_quit_game_widgets[] = { +{ WWT_TEXTBTN, 4, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 4, 11, 179, 0, 13, STR_0161_QUIT_GAME}, +{ WWT_IMGBTN, 4, 0, 179, 14, 91, 0x0}, +{ WWT_TEXTBTN, 12, 25, 84, 72, 83, STR_00C9_NO}, +{ WWT_TEXTBTN, 12, 95, 154, 72, 83, STR_00C8_YES}, +{ WWT_LAST}, +}; + +static void AskQuitGameWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + DrawStringMultiCenter(0x5A, 0x26, + _game_mode != GM_EDITOR ? STR_0160_ARE_YOU_SURE_YOU_WANT_TO : + STR_029B_ARE_YOU_SURE_YOU_WANT_TO, + 178); + return; + + case WE_CLICK: + switch(e->click.widget) { + case 3: + DeleteWindow(w); + break; + case 4: + _switch_mode = SM_MENU; + break; + } + break; + } +} + +static const WindowDesc _ask_quit_game_desc = { + WDP_CENTER, WDP_CENTER, 180, 92, + WC_QUIT_GAME,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _ask_quit_game_widgets, + AskQuitGameWndProc +}; + + +void AskExitToGameMenu() +{ + AllocateWindowDescFront(&_ask_quit_game_desc, 0); +} + +int32 CmdSetNewLandscapeType(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + // XXX: some stuff + _new_opt.landscape = p1; + InvalidateWindowClasses(WC_SELECT_GAME); + } + return 0; +} diff --git a/landscape.c b/landscape.c new file mode 100644 --- /dev/null +++ b/landscape.c @@ -0,0 +1,727 @@ +#include "stdafx.h" +#include "ttd.h" +#include +#include "gfx.h" +#include "viewport.h" +#include "command.h" +#include "vehicle.h" + +byte _map_type_and_height[TILES_X * TILES_Y]; +byte _map5[TILES_X * TILES_Y]; +byte _map3_lo[TILES_X * TILES_Y]; +byte _map3_hi[TILES_X * TILES_Y]; +byte _map_owner[TILES_X * TILES_Y]; +byte _map2[TILES_X * TILES_Y]; +byte _map_extra_bits[TILES_X * TILES_Y/4]; + +extern const TileTypeProcs + _tile_type_clear_procs, + _tile_type_rail_procs, + _tile_type_road_procs, + _tile_type_town_procs, + _tile_type_trees_procs, + _tile_type_station_procs, + _tile_type_water_procs, + _tile_type_dummy_procs, + _tile_type_industry_procs, + _tile_type_tunnelbridge_procs, + _tile_type_unmovable_procs; + +const TileTypeProcs * const _tile_type_procs[16] = { + &_tile_type_clear_procs, + &_tile_type_rail_procs, + &_tile_type_road_procs, + &_tile_type_town_procs, + &_tile_type_trees_procs, + &_tile_type_station_procs, + &_tile_type_water_procs, + &_tile_type_dummy_procs, + &_tile_type_industry_procs, + &_tile_type_tunnelbridge_procs, + &_tile_type_unmovable_procs, +}; + +/* landscape slope => sprite */ +const byte _tileh_to_sprite[32] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0, + 0,0,0,0,0,0,0,16,0,0,0,17,0,15,18,0, +}; + +uint GetTileSlope(uint tile, int *h) +{ + uint a,b,c,d,min; + int r; + + if (GET_TILE_X(tile) == TILE_X_MAX || GET_TILE_Y(tile) == TILE_Y_MAX) { + if (h) + *h = 0; + return 0; + } + + assert(tile < TILES_X * TILES_Y && GET_TILE_X(tile) != TILE_X_MAX && GET_TILE_Y(tile) != TILE_Y_MAX); + + min = a = _map_type_and_height[tile] & 0xF; + b = _map_type_and_height[tile+TILE_XY(1,0)] & 0xF; + if (min >= b) min = b; + c = _map_type_and_height[tile+TILE_XY(0,1)] & 0xF; + if (min >= c) min = c; + d = _map_type_and_height[tile+TILE_XY(1,1)] & 0xF; + if (min >= d) min = d; + + r = 0; + if ((a-=min)!=0) { r += (--a << 4) + 8; } + if ((c-=min)!=0) { r += (--c << 4) + 4; } + if ((d-=min)!=0) { r += (--d << 4) + 2; } + if ((b-=min)!=0) { r += (--b << 4) + 1; } + + if (h != 0) + *h = min * 8; + + return r; +} + +int GetTileZ(uint tile) +{ + int h; + GetTileSlope(tile, &h); + return h; +} + +void FindLandscapeHeightByTile(TileInfo *ti, uint tile) +{ + if (GET_TILE_X(tile) == TILE_X_MAX || + GET_TILE_Y(tile) == TILE_Y_MAX) { + ti->tileh = 0; + ti->type = MP_STRANGE; + ti->tile = 0; + ti->map5 = 0; + ti->z = 0; + return; + } + + ti->tile = tile; + ti->map5 = _map5[tile]; + ti->type = GET_TILETYPE(tile); + ti->tileh = GetTileSlope(tile, &ti->z); +// ti->z = min * 8; +} + +/* find the landscape height for the coordinates x y */ +void FindLandscapeHeight(TileInfo *ti, uint x, uint y) +{ + int tile; + + ti->x = x; + ti->y = y; + + if (x >= TILE_X_MAX*16-1 || y >= TILE_Y_MAX*16-1) { + ti->tileh = 0; + ti->type = MP_STRANGE; + ti->tile = 0; + ti->map5 = 0; + ti->z = 0; + return; + } + + tile = TILE_FROM_XY(x,y); + FindLandscapeHeightByTile(ti, tile); +} + +uint GetPartialZ(int x, int y, int corners) +{ + int z = 0; + + switch(corners) { + case 1: + if (x - y >= 0) + z = (x - y) >> 1; + break; + + case 2: + y^=0xF; + if ( (x - y) >= 0) + z = (x - y) >> 1; + break; + + case 3: + z = (x>>1) + 1; + break; + + case 4: + if (y - x >= 0) + z = (y - x) >> 1; + break; + + case 5: + case 10: + case 15: + z = 4; + break; + + case 6: + z = (y>>1) + 1; + break; + + case 7: + z = 8; + y^=0xF; + if (x - y < 0) + z += (x - y) >> 1; + break; + + case 8: + y ^= 0xF; + if (y - x >= 0) + z = (y - x) >> 1; + break; + + case 9: + z = (y^0xF)>>1; + break; + + case 11: + z = 8; + if (x - y < 0) + z += (x - y) >> 1; + break; + + case 12: + z = (x^0xF)>>1; + break; + + case 13: + z = 8; + y ^= 0xF; + if (y - x < 0) + z += (y - x) >> 1; + break; + + case 14: + z = 8; + if (y - x < 0) + z += (y - x) >> 1; + break; + + case 23: + z = 1 + ((x+y)>>1); + break; + + case 27: + z = 1 + ((x+(y^0xF))>>1); + break; + + case 29: + z = 1 + (((x^0xF)+(y^0xF))>>1); + break; + + case 30: + z = 1 + (((x^0xF)+(y^0xF))>>1); + break; + } + + return z; +} + +uint GetSlopeZ(int x, int y) +{ + TileInfo ti; +// int z; + + FindLandscapeHeight(&ti, x, y); + +/* + z = ti.z; + x &= 0xF; + y &= 0xF; + + + assert(z < 256); +*/ + + return _tile_type_procs[ti.type]->get_slope_z_proc(&ti); +} + +void DrawFoundation(TileInfo *ti, uint f) +{ + if (f < 15) { + // leveled foundation + AddSortableSpriteToDraw(f + 0x3DE - 1, ti->x, ti->y, 16, 16, 7, ti->z); + ti->z += 8; + ti->tileh = 0; + OffsetGroundSprite(31, 1); + } else { + // inclined foundation + + AddSortableSpriteToDraw( + HASBIT( (1<<1) | (1<<2) | (1<<4) | (1<<8), ti->tileh) ? (SPR_OPENTTD_BASE+17) + (f - 15) : ti->tileh + 0x3DE - 1, + ti->x, ti->y, 1, 1, 1, ti->z + ); + + ti->tileh = _inclined_tileh[f - 15]; + OffsetGroundSprite(31, 9); + } +} + +void DoClearSquare(uint tile) +{ + ModifyTile(tile, + MP_SETTYPE(MP_CLEAR) | + MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAPOWNER | MP_MAP5, + OWNER_NONE, /* map_owner */ + _generating_world ? 3 : 0 /* map5 */ + ); +} + +uint32 GetTileTrackStatus(uint tile, int mode) +{ + return _tile_type_procs[GET_TILETYPE(tile)]->get_tile_track_status_proc(tile, mode); +} + +void ChangeTileOwner(uint tile, byte old_player, byte new_player) +{ + _tile_type_procs[GET_TILETYPE(tile)]->change_tile_owner_proc(tile, old_player, new_player); +} + +void GetAcceptedCargo(uint tile, AcceptedCargo *ac) +{ + memset(ac, 0, sizeof(AcceptedCargo)); + _tile_type_procs[GET_TILETYPE(tile)]->get_accepted_cargo_proc(tile, ac); +} + +void AnimateTile(uint tile) +{ + _tile_type_procs[GET_TILETYPE(tile)]->animate_tile_proc(tile); +} + +void ClickTile(uint tile) +{ + _tile_type_procs[GET_TILETYPE(tile)]->click_tile_proc(tile); +} + +void DrawTile(TileInfo *ti) +{ + _tile_type_procs[ti->type]->draw_tile_proc(ti); +} + +void GetTileDesc(uint tile, TileDesc *td) +{ + _tile_type_procs[GET_TILETYPE(tile)]->get_tile_desc_proc(tile, td); +} + +/* Clear a piece of landscape + * p1 = 0, + * p2 = 0 + */ + +int32 CmdLandscapeClear(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + return _tile_type_procs[GET_TILETYPE(tile)]->clear_tile_proc(tile, flags); +} + +// p1 = end tile +int32 CmdClearArea(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) +{ + int32 cost,ret, money; + int sx,sy; + int x,y; + bool success = false; + + // make sure sx,sy are smaller than ex,ey + sx = GET_TILE_X(p1)*16; + sy = GET_TILE_Y(p1)*16; + if (ex < sx) intswap(ex, sx); + if (ey < sy) intswap(ey, sy); + + money = GetAvailableMoneyForCommand(); + cost = 0; + + for(x=sx; x<=ex; x+=16) { + for(y=sy; y<=ey; y+=16) { + ret = DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags &~DC_EXEC, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) continue; + cost += ret; + success = true; + + if (flags & DC_EXEC) { + if ( ret>0 && (money -= ret) < 0) { + _additional_cash_required = ret; + return cost - ret; + } + DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags, CMD_LANDSCAPE_CLEAR); + + // draw explosion animation... + if ((x==sx || x==ex) && (y==sy || y==ey)) { + // big explosion in each corner, or small explosion for single tiles + CreateEffectVehicleAbove(x + 8,y + 8, 2, sy==ey && sx==ex ? EV_DEMOLISH : EV_CRASHED_SMOKE); + } + } + } + } + + if (!success) + cost = CMD_ERROR; + return cost; +} + + +/* utility function used to modify a tile */ +void CDECL ModifyTile(uint tile, uint flags, ...) +{ + va_list va; + int i; + + va_start(va, flags); + + if ((i = (flags >> 8) & 0xF) != 0) { + _map_type_and_height[tile] = (_map_type_and_height[tile]&~0xF0)|((i-1) << 4); + } + + if (flags & (MP_MAP2_CLEAR | MP_MAP2)) { + int x = 0; + if (flags & MP_MAP2) x = va_arg(va, int); + _map2[tile] = x; + } + + if (flags & (MP_MAP3LO_CLEAR | MP_MAP3LO)) { + int x = 0; + if (flags & MP_MAP3LO) x = va_arg(va, int); + _map3_lo[tile] = x; + } + + if (flags & (MP_MAP3HI_CLEAR | MP_MAP3HI)) { + int x = 0; + if (flags & MP_MAP3HI) x = va_arg(va, int); + _map3_hi[tile] = x; + } + + if (flags & (MP_MAPOWNER|MP_MAPOWNER_CURRENT)) { + byte x = _current_player; + if (flags & MP_MAPOWNER) x = va_arg(va, int); + _map_owner[tile] = x; + } + + if (flags & MP_MAP5) { + _map5[tile] = va_arg(va, int); + } + + va_end(va); + + if (!(flags & MP_NODIRTY)) + MarkTileDirtyByTile(tile); +} + +void SetMapExtraBits(uint tile, byte bits) +{ + _map_extra_bits[tile >> 2] &= ~(3 << ((tile&3)*2)); + _map_extra_bits[tile >> 2] |= (bits&3) << ((tile&3)*2); +} + +uint GetMapExtraBits(uint tile) +{ + return (_map_extra_bits[tile >> 2] >> (tile&3)*2)&3; +} + +#define TILELOOP_BITS 4 +#define TILELOOP_SIZE (1 << TILELOOP_BITS) +#define TILELOOP_ASSERTMASK ((TILELOOP_SIZE-1) + ((TILELOOP_SIZE-1) << TILE_X_BITS)) +#define TILELOOP_CHKMASK (((1 << (TILE_X_BITS - TILELOOP_BITS))-1) << TILELOOP_BITS) + +void RunTileLoop() +{ + uint tile; + uint count; + + tile = _cur_tileloop_tile; + + assert( (tile & ~TILELOOP_ASSERTMASK) == 0); + count = (TILES_X/TILELOOP_SIZE) * (TILES_Y/TILELOOP_SIZE); + do { + _tile_type_procs[GET_TILETYPE(tile)]->tile_loop_proc(tile); + + if ( GET_TILE_X(tile) < TILES_X - TILELOOP_SIZE) { + tile += TILELOOP_SIZE; /* no overflow */ + } else { + tile = TILE_MASK(tile - TILELOOP_SIZE * (TILES_X/TILELOOP_SIZE-1) + TILE_XY(0, TILELOOP_SIZE)); /* x would overflow, also increase y */ + } + } while (--count); + assert( (tile & ~TILELOOP_ASSERTMASK) == 0); + + tile += 9; + if (tile & TILELOOP_CHKMASK) + tile = (tile + TILES_X) & TILELOOP_ASSERTMASK; + _cur_tileloop_tile = tile; +} + +void InitializeLandscape() +{ + int i; + + memset(_map_owner, OWNER_NONE, sizeof(_map_owner)); + memset(_map2, 0, sizeof(_map2)); + memset(_map3_lo, 0, sizeof(_map3_lo)); + memset(_map3_hi, 0, sizeof(_map3_hi)); + memset(_map_extra_bits, 0, sizeof(_map_extra_bits)); + memset(_map_type_and_height, MP_WATER << 4, sizeof(_map_type_and_height)); + + for(i=0; i!=TILES_Y-1; i++) + memset(_map_type_and_height + i*TILES_X, 0, TILES_X-1); + + memset(_map5, 3, sizeof(_map5)); +} + +void ConvertGroundTilesIntoWaterTiles() +{ + uint tile = 0; + int h; + + while(true) { + if (IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h == 0) { + _map_type_and_height[tile] = MP_WATER << 4; + _map5[tile] = 0; + _map_owner[tile] = OWNER_WATER; + } + tile++; + if (GET_TILE_X(tile) == TILE_X_MAX) { + tile += TILE_XY(-TILE_X_MAX, 1); + if (GET_TILE_Y(tile) == TILE_Y_MAX) + break; + } + } +} + +static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 }; +static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 }; + +static void GenerateTerrain(int type, int flag) +{ + uint32 r; + int x,y; + int w,h; + byte *p,*tile; + byte direction; + + r = Random(); + p = GetSpritePtr((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845); + + x = r & TILE_X_MAX; + y = (r >> TILE_X_BITS) & TILE_Y_MAX; + + + if (x < 2 || y < 2) + return; + + direction = (byte)(r >> 22) & 3; + w = p[2]; + h = p[1]; + if (direction & 1) { w = p[1]; h = p[2]; } + p += 8; + + if (flag & 4) { + if (!(flag & 2)) { + if (!(flag & 1)) { + if (x + y > 190) + return; + } else { + if (y < 30 + x) + return; + } + } else { + if (!(flag & 1)) { + if (x + y < 256) + return; + } else { + if (x < 30 + y) + return; + } + } + } + + if (x + w >= TILE_X_MAX-1) + return; + + if (y + h >= TILE_Y_MAX-1) + return; + + tile = &_map_type_and_height[TILE_XY(x,y)]; + + if (direction == 0) { + do { + int w_cur = w; + byte *tile_cur = tile; + do { + if (*p >= *tile_cur) *tile_cur = *p; + p++; + tile_cur++; + } while (--w_cur != 0); + tile += TILE_XY(0,1); + } while (--h != 0); + } else if (direction == 1) { + do { + int h_cur = h; + byte *tile_cur = tile; + do { + if (*p >= *tile_cur) *tile_cur = *p; + p++; + tile_cur+=TILE_XY(0,1); + } while (--h_cur != 0); + tile++; + } while (--w != 0); + } else if (direction == 2) { + tile += w - 1; + do { + int w_cur = w; + byte *tile_cur = tile; + do { + if (*p >= *tile_cur) *tile_cur = *p; + p++; + tile_cur--; + } while (--w_cur != 0); + tile += TILE_XY(0,1); + } while (--h != 0); + } else { + tile += (h - 1) * TILE_XY(0,1); + do { + int h_cur = h; + byte *tile_cur = tile; + do { + if (*p >= *tile_cur) *tile_cur = *p; + p++; + tile_cur-=TILE_XY(0,1); + } while (--h_cur != 0); + tile++; + } while (--w != 0); + } +} + + +#include "table/genland.h" + +static void CreateDesertOrRainForest() +{ + uint tile; + const TileIndexDiff *data; + byte mt; + int i; + + tile = 0; + do { + data = _make_desert_or_rainforest_data; + do { + if ((i = *data++) == MDORD_LAST) { + SetMapExtraBits(tile, 1); + break; + } + mt = _map_type_and_height[tile + i]; + } while ((mt & 0xC) == 0 && (mt >> 4) != MP_WATER); + } while (++tile != TILES_X*TILES_Y); + + for(i=0; i!=256; i++) + RunTileLoop(); + + tile = 0; + do { + data = _make_desert_or_rainforest_data; + do { + if ((i = *data++) == MDORD_LAST) { + SetMapExtraBits(tile, 2); + break; + } + } while ( !IS_TILETYPE(tile+i, MP_CLEAR) || (_map5[tile + i]&0x1C) != 0x14); + } while (++tile != TILES_X*TILES_Y); +} + +void GenerateLandscape() +{ + int i,flag; + uint32 r; + + if (_opt.landscape == LT_HILLY) { + i = ((Random() & 0x7F) + 950) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(2, 0); + } while (--i); + + r = Random(); + flag = (r & 3) | 4; + i = (((r >> 16) & 0x7F) + 450) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(4, flag); + } while (--i); + } else if (_opt.landscape == LT_DESERT) { + i = ((Random()&0x7F) + 170) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(0, 0); + } while (--i); + + r = Random(); + flag = (r & 3) | 4; + i = (((r >> 16) & 0xFF) + 1700) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(0, flag); + } while (--i); + + flag ^= 2; + + i = ((Random() & 0x7F) + 410) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(3, flag); + } while (--i); + } else { + i = ((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes)*256 + 100) * LANDSCAPE_SIZE_FACTOR; + do { + GenerateTerrain(_opt.diff.terrain_type, 0); + } while (--i); + } + + ConvertGroundTilesIntoWaterTiles(); + + if (_opt.landscape == LT_DESERT) + CreateDesertOrRainForest(); +} + +void OnTick_Town(); +void OnTick_Trees(); +void OnTick_Station(); +void OnTick_Industry(); + +void OnTick_Players(); +void OnTick_Train(); + +void CallLandscapeTick() +{ + OnTick_Town(); + OnTick_Trees(); + OnTick_Station(); + OnTick_Industry(); + + OnTick_Players(); + OnTick_Train(); +} + +TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng) +{ + int rn = rng; + uint32 r = Random(); + + return TILE_XY( + GET_TILE_X(a) + ((byte)r * rn * 2 >> 8) - rn, + GET_TILE_Y(a) + ((byte)(r>>8) * rn * 2 >> 8) - rn + ); +} + +uint TileAddWrap(TileIndex tile, int add) +{ + uint t = tile + add; + if (t < TILES_X * TILE_Y_MAX && GET_TILE_X(t) != TILE_X_MAX) + return t; + return TILE_WRAPPED; +} + +bool IsValidTile(uint tile) +{ + return (tile < TILES_X * TILE_Y_MAX && GET_TILE_X(tile) != TILE_X_MAX); +} diff --git a/lang/czech.txt b/lang/czech.txt new file mode 100644 --- /dev/null +++ b/lang/czech.txt @@ -0,0 +1,2456 @@ +##name Czech +##ownname Cesky + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Mimo okraj mapy +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Prilis blizko k okraji mapy +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Nedostatek penez - je potreba {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Je potreba plocha zeme +STR_0008_WAITING :{BLACK}Ceka: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (na ceste z +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Prijima: {WHITE} +STR_000D_ACCEPTS :{BLACK}Prijima: {GOLD} +STR_000E : +STR_000F_PASSENGERS :cestujici +STR_0010_COAL :uhli +STR_0011_MAIL :posta +STR_0012_OIL :ropa +STR_0013_LIVESTOCK :dobytek +STR_0014_GOODS :zbozi +STR_0015_GRAIN :zrni +STR_0016_WOOD :drevo +STR_0017_IRON_ORE :zelezna ruda +STR_0018_STEEL :ocel +STR_0019_VALUABLES :ceniny +STR_001A_COPPER_ORE :medena ruda +STR_001B_MAIZE :kukurice +STR_001C_FRUIT :ovoce +STR_001D_DIAMONDS :diamanty +STR_001E_FOOD :jidlo +STR_001F_PAPER :papir +STR_0020_GOLD :zlato +STR_0021_WATER :voda +STR_0022_WHEAT :psenice +STR_0023_RUBBER :kaucuk +STR_0024_SUGAR :cukr +STR_0025_TOYS :hracky +STR_0026_CANDY :bonbony +STR_0027_COLA :cola +STR_0028_COTTON_CANDY :cukrova vata +STR_0029_BUBBLES :bubliny +STR_002A_TOFFEE :karamel +STR_002B_BATTERIES :baterie +STR_002C_PLASTIC :plast +STR_002D_FIZZY_DRINKS :limonada +STR_002E : +STR_002F_PASSENGER :cestujici +STR_0030_COAL :uhli +STR_0031_MAIL :posta +STR_0032_OIL :ropa +STR_0033_LIVESTOCK :dobytek +STR_0034_GOODS :zbozi +STR_0035_GRAIN :zrni +STR_0036_WOOD :drevo +STR_0037_IRON_ORE :zelezna ruda +STR_0038_STEEL :ocel +STR_0039_VALUABLES :cenniny +STR_003A_COPPER_ORE :medena ruda +STR_003B_MAIZE :kukurice +STR_003C_FRUIT :ovoce +STR_003D_DIAMOND :diamanty +STR_003E_FOOD :jidlo +STR_003F_PAPER :papir +STR_0040_GOLD :zlato +STR_0041_WATER :voda +STR_0042_WHEAT :psenice +STR_0043_RUBBER :kaucuk +STR_0044_SUGAR :cukr +STR_0045_TOY :hracky +STR_0046_CANDY :bonbony +STR_0047_COLA :kola +STR_0048_COTTON_CANDY :cukrova vata +STR_0049_BUBBLE :bubliny +STR_004A_TOFFEE :karamel +STR_004B_BATTERY :baterie +STR_004C_PLASTIC :plast +STR_004D_FIZZY_DRINK :limonada +STR_004E : +STR_004F_PASSENGER :{COMMA16} cestujici +STR_0050_TON_OF_COAL :{COMMA16} tuna uhli +STR_0051_BAG_OF_MAIL :{COMMA16} balik posty +STR_0052_OF_OIL :{VOLUME} ropy +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} kus dobytka +STR_0054_CRATE_OF_GOODS :{COMMA16} krabice zbozi +STR_0055_TON_OF_GRAIN :{COMMA16} tuna zrni +STR_0056_TON_OF_WOOD :{COMMA16} tuna dreva +STR_0057_TON_OF_IRON_ORE :{COMMA16} tuna zelezne rudy +STR_0058_TON_OF_STEEL :{COMMA16} tuna oceli +STR_0059_BAG_OF_VALUABLES :{COMMA16} balik cenin +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tuna medene rudy +STR_005B_TON_OF_MAIZE :{COMMA16} tuna kukurice +STR_005C_TON_OF_FRUIT :{COMMA16} tuna ovoce +STR_005D_BAG_OF_DIAMONDS :{COMMA16} balik diamantu +STR_005E_TON_OF_FOOD :{COMMA16} tuna jidla +STR_005F_TON_OF_PAPER :{COMMA16} tuna papiru +STR_0060_BAG_OF_GOLD :{COMMA16} balik posty +STR_0061_OF_WATER :{VOLUME} vody +STR_0062_TON_OF_WHEAT :{COMMA16} tuna kukurice +STR_0063_OF_RUBBER :{VOLUME} kaucuku +STR_0064_TON_OF_SUGAR :{COMMA16} tuna cukru +STR_0065_TOY :{COMMA16} hracka +STR_0066_BAG_OF_CANDY :{COMMA16} bonboniera +STR_0067_OF_COLA :{VOLUME} coly +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tuna cukrove vaty +STR_0069_BUBBLE :{COMMA16} bublin +STR_006A_TON_OF_TOFFEE :{COMMA16} tuna karamelu +STR_006B_BATTERY :{COMMA16} baterie +STR_006C_OF_PLASTIC :{VOLUME} plastu +STR_006D_FIZZY_DRINK :{COMMA16} limonad +STR_006E : +STR_006F_PASSENGERS :{COMMA16} cestujicich +STR_0070_TONS_OF_COAL :{COMMA16} tun uhli +STR_0071_BAGS_OF_MAIL :{COMMA16} baliku posty +STR_0072_OF_OIL :{VOLUME} ropy +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} kusu dobytka +STR_0074_CRATES_OF_GOODS :{COMMA16} krabic zbozi +STR_0075_TONS_OF_GRAIN :{COMMA16} tun zrni +STR_0076_TONS_OF_WOOD :{COMMA16} tun dreva +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tun zelezne rudy +STR_0078_TONS_OF_STEEL :{COMMA16} tun oceli +STR_0079_BAGS_OF_VALUABLES :{COMMA16} baliku cennin +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tun medene rudy +STR_007B_TONS_OF_MAIZE :{COMMA16} tun kukurice +STR_007C_TONS_OF_FRUIT :{COMMA16} tun ovoce +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} baliku diamantu +STR_007E_TONS_OF_FOOD :{COMMA16} tun jidla +STR_007F_TONS_OF_PAPER :{COMMA16} tun papiru +STR_0080_BAGS_OF_GOLD :{COMMA16} baliku zlata +STR_0081_OF_WATER :{VOLUME} vody +STR_0082_TONS_OF_WHEAT :{COMMA16} psenice +STR_0083_OF_RUBBER :{VOLUME} kaucuku +STR_0084_TONS_OF_SUGAR :{COMMA16} tun cukru +STR_0085_TOYS :{COMMA16} hracek +STR_0086_BAGS_OF_CANDY :{COMMA16} bonbonier +STR_0087_OF_COLA :{VOLUME} koly +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tun cukrove vaty +STR_0089_BUBBLES :{COMMA16} bublin +STR_008A_TONS_OF_TOFFEE :{COMMA16} tun karamelu +STR_008B_BATTERIES :{COMMA16} baterii +STR_008C_OF_PLASTIC :{VOLUME} plastu +STR_008D_FIZZY_DRINKS :{COMMA16} limonad +STR_008E : +STR_008F_PS :{TINYFONT}CS +STR_0090_CL :{TINYFONT}UH +STR_0091_ML :{TINYFONT}PT +STR_0092_OL :{TINYFONT}RP +STR_0093_LV :{TINYFONT}DB +STR_0094_GD :{TINYFONT}ZB +STR_0095_GR :{TINYFONT}ZN +STR_0096_WD :{TINYFONT}DR +STR_0097_OR :{TINYFONT}ZR +STR_0098_ST :{TINYFONT}OC +STR_0099_VL :{TINYFONT}CN +STR_009A_CO :{TINYFONT}MD +STR_009B_MZ :{TINYFONT}KU +STR_009C_FT :{TINYFONT}OV +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}JD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}ZL +STR_00A1_WR :{TINYFONT}VD +STR_00A2_WH :{TINYFONT}PS +STR_00A3_RB :{TINYFONT}KA +STR_00A4_SG :{TINYFONT}CU +STR_00A5_TY :{TINYFONT}HR +STR_00A6_SW :{TINYFONT}BO +STR_00A7_CL :{TINYFONT}KL +STR_00A8_CF :{TINYFONT}CV +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}KR +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}LI +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Mapa - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Moznosti hry +STR_00B2_MESSAGE :{YELLOW}Zprava +STR_00B3_MESSAGE_FROM :{YELLOW}Zprava od {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Tohle neumuzes udelat... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Nemuzes vycistit tuto oblast... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Copyright {COPYRIGHT} 1995 Chris Sawyer, vsechna prava vyhrazena +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}Verze OpenTTD {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Puvodni design: Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafika: Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 Tym OpenTTD + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Konec +STR_00C8_YES :{BLACK}Ano +STR_00C9_NO :{BLACK}Ne +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jsi si jisty, ze chces opustit tuto hru a odejit do {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nic +STR_00D1_DARK_BLUE :Tmavomodra +STR_00D2_PALE_GREEN :Svetlezelena +STR_00D3_PINK :Ruzova +STR_00D4_YELLOW :Zluta +STR_00D5_RED :Cervena +STR_00D6_LIGHT_BLUE :Bledemodra +STR_00D7_GREEN :Zelena +STR_00D8_DARK_GREEN :Tmavozelena +STR_00D9_BLUE :Modra +STR_00DA_CREAM :Kremova +STR_00DB_MAUVE :Lila +STR_00DC_PURPLE :Purpurova +STR_00DD_ORANGE :Oranzova +STR_00DE_BROWN :Hneda +STR_00DF_GREY :Seda +STR_00E0_WHITE :Bila +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Prilis mnoho vozidel ve hre +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Umisteni +STR_00E5_CONTOURS :Profil +STR_00E6_VEHICLES :Dopravni prostredky +STR_00E7_INDUSTRIES :Prumysl +STR_00E8_ROUTES :Trate +STR_00E9_VEGETATION :Vegetace +STR_00EA_OWNERS :Vlastnici +STR_00EB_ROADS :{BLACK}{TINYFONT}Silnice +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Zeleznice +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stanice/Letiste/Pristavy +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Budovy/Prumysl +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vozidla +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Vlaky +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Silnicni vozidla +STR_00F7_SHIPS :{BLACK}{TINYFONT}Lode +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Letadla +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Dopravni cesty +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Uhelny dul +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Elektrarna +STR_00FC_FOREST :{BLACK}{TINYFONT}Les +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Pila +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Ropna rafinerie +STR_00FF_FARM :{BLACK}{TINYFONT}Farma +STR_0100_FACTORY :{BLACK}{TINYFONT}Tovarna +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Tiskarna +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Ropny vrt +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Dul na medenou rudu +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Ocelarna +STR_0105_BANK :{BLACK}{TINYFONT}Banka +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papirna +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Dul na zlato +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Tovarna na zpracovani potravin +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamantovy dul +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Dul na medenou rudu +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Ovocna plantaz +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kaucukova plantaz +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Zdroj vody +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vodojem +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Pila +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Les cukrove vaty +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Tovarna na sladkosti +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Farma na baterie +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Colove studny +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Hrackarstvi +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Tovarna na hracky +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastove fontany +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Stacirna limonad +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Generator bublin +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamelolom +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Cukerny dul +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Nadrazi +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Nakladaci plosina +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Autobusova zastavka +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Letiste/Heliport +STR_011F_DOCK :{BLACK}{TINYFONT}Pristavy +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Hrbolata zem +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Travnata zem +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Prazdna zem +STR_0123_FIELDS :{BLACK}{TINYFONT}Pole +STR_0124_TREES :{BLACK}{TINYFONT}Stromy +STR_0125_ROCKS :{BLACK}{TINYFONT}Kameny +STR_0126_WATER :{BLACK}{TINYFONT}Voda +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Zadny vlastnik +STR_0128_TOWNS :{BLACK}{TINYFONT}Mesta +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Tovarny +STR_012A_DESERT :{BLACK}{TINYFONT}Poust +STR_012B_SNOW :{BLACK}{TINYFONT}Snih +STR_012C_MESSAGE :{WHITE}Zprava +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Zrusit +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Prejmenovat +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Definovano prilis mnoho jmen +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Zvolene jmeno se jiz pouziva + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperialni (mile) +STR_013A_METRIC_KILOMETERS :Metricke (kilometry) +STR_013B_OWNED_BY :{WHITE}...vlastneno {STRING} +STR_013C_CARGO :{BLACK}Naklad +STR_013D_INFORMATION :{BLACK}Informace +STR_013E_CAPACITIES :{BLACK}Kapacity +STR_013E_TOTAL_CARGO :{BLACK}Celkovy naklad +STR_013F_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Celkova kapacita tohoto vlaku: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nova hra +STR_0141_LOAD_GAME :{BLACK}Nahrat hru +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Ukazka +STR_SINGLE_PLAYER :{BLACK}1 hrac +STR_MULTIPLAYER :{BLACK}Vice hracu + +STR_0148_GAME_OPTIONS :{BLACK}Moznosti hry + +STR_0150_SOMEONE :nekdo{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Mapa sveta +STR_0152_TOWN_DIRECTORY :Seznam mest +STR_0153_SUBSIDIES :Dotace + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Graf provozniho zisku +STR_0155_INCOME_GRAPH :Graf prijmu +STR_0156_DELIVERED_CARGO_GRAPH :Graf doruceneho zbozi +STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf historie vykonu +STR_0158_COMPANY_VALUE_GRAPH :Graf hodnoty spolecnosti +STR_0159_CARGO_PAYMENT_RATES :Graf ceny plateb +STR_015A_COMPANY_LEAGUE_TABLE :Tabulka spolecnosti +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Ulozit hru +STR_015D_LOAD_GAME :Nacist hru +STR_015E_QUIT_GAME :Ukoncit hru +STR_015F_QUIT :Ukoncit program +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Opravdu chces ukoncit tuto hru? +STR_0161_QUIT_GAME :{WHITE}Konec hry + +############ range for months starts +STR_0162_JAN :led +STR_0163_FEB :uno +STR_0164_MAR :bre +STR_0165_APR :dub +STR_0166_MAY :kve +STR_0167_JUN :cer +STR_0168_JUL :cnc +STR_0169_AUG :srp +STR_016A_SEP :zar +STR_016B_OCT :rij +STR_016C_NOV :lis +STR_016D_DEC :pro +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pauza +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Ulozit hru, opustit hru, ukoncit +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Zobrazit seznam stanic spolecnosti +STR_0174_DISPLAY_MAP :{BLACK}Zobrazit mapu +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Zobrazit mapu a seznam mest +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Zobrazit seznam mest +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Zobrazit financni informace o spolecnosti +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Zobrazit obecne informace o spolecnosti +STR_0179_DISPLAY_GRAPHS :{BLACK}Zobrazit grafy +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Zobrazit tabulku spolecnosti +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Zobrazit seznam vlaku spolecnosti +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Zobrazit seznam automobilu spolecnosti +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Zobrazit seznam lodi spolecnosti +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Zobrazit seznam letadel spolecnosti +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Priblizit pohled +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Oddalit pohled +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Stavet koleje +STR_0182_BUILD_ROADS :{BLACK}Stavet silnice +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Stavet doky +STR_0184_BUILD_AIRPORTS :{BLACK}Stavet letiste +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Zasadit stromy, umistit cedule, atd.. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Informace o zemi +STR_0187_OPTIONS :{BLACK}Moznosti +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Nelze zmenit interval oprav... +STR_018B_CLOSE_WINDOW :{BLACK}Zavrit okno +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Titulek okna - tahej pro posun okna +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Demolice budov, atd. +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Snizit roh zeme +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Zvysit roh zeme +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Posuvnik - posouva vypisem nahoru a dolu +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Zobrazit na mape relief krajiny +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Zobrazit na mape dopravni prostredky +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Zobrazit na mape prumysl +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Zobrazit na mape dopravni cesty +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Zobrazit na mape vegetaci +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Zobrazit na mape vlastniky pudy +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Zobrazovat na mape jmena mest +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Zisk tento rok: {CURRENCY} (minuly rok: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} rok ({COMMA16}) +STR_019A_YEARS :{COMMA16} let ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} let ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Automobil +STR_019D_AIRCRAFT :Letadlo +STR_019E_SHIP :Lod +STR_019F_TRAIN :Vlak +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} je stare +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} je velmi stare +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} je velmi stare a potrebuje nahradit +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informace o uzemi +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Cena za vycisteni: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Cena za vycisteni: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Vlastnik: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Mistni sprava: {LTBLUE}{STRING} +STR_01A9_NONE :Nic +STR_01AA_NAME :{BLACK}Jmeno +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1. +STR_01AD_2ND :2. +STR_01AE_3RD :3. +STR_01AF_4TH :4. +STR_01B0_5TH :5. +STR_01B1_6TH :6. +STR_01B2_7TH :7. +STR_01B3_8TH :8. +STR_01B4_9TH :9. +STR_01B5_10TH :10. +STR_01B6_11TH :11. +STR_01B7_12TH :12. +STR_01B8_13TH :13. +STR_01B9_14TH :14. +STR_01BA_15TH :15. +STR_01BB_16TH :16. +STR_01BC_17TH :17. +STR_01BD_18TH :18. +STR_01BE_19TH :19. +STR_01BF_20TH :20. +STR_01C0_21ST :21. +STR_01C1_22ND :22. +STR_01C2_23RD :23. +STR_01C3_24TH :24. +STR_01C4_25TH :25. +STR_01C5_26TH :26. +STR_01C6_27TH :27. +STR_01C7_28TH :28. +STR_01C8_29TH :29. +STR_01C9_30TH :30. +STR_01CA_31ST :31. +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Prepnout velkou/malou mapu +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Zvolit Tutorial/Ukazka + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Prijimane zbozi: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Prijimane zbozi: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Prijimane zbozi: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jukebox +STR_01D3_SOUND_MUSIC :Zvuk/Hudba +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Ukazat zvukove/hudebni okno +STR_01D5_ALL :{TINYFONT}Vse +STR_01D6_OLD_STYLE :{TINYFONT}Stare +STR_01D7_NEW_STYLE :{TINYFONT}Nove +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Volba 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Volba 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Hlasitost hudby +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Hlasitost efektu +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Skocit na predchozi skladbu ve vyberu +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Skocit na dalsi skladbu ve vyberu +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Zastavit prehravani hudby +STR_01E1_START_PLAYING_MUSIC :{BLACK}Zacit prehravat hudbu +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Tahej posouvatka pro nastaveni hlasitosti hudby a zvukovych efektu +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Skladba{SETX 88}Nazev +STR_01E9_SHUFFLE :{TINYFONT}Nahodne +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Volba programu hudby +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Index skladeb +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Vymazat +STR_01F1_SAVE :{TINYFONT}{BLACK}Ulozit +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Momentalni program skladeb +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Zvolit program 'vsechny skladby' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Zvolit program 'stare skladby' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Zvolit program 'nove skladby' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Zvolit program 'Volba 1' (uzivatelsky nastaveny) +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Zvolit program 'Volba 2' (uzivatelsky nastaveny) +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Vymaz aktualni program ( Jen Volba 1 a Volba 2 ) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Ulozit nastaveni hudby na disk +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Stiskni nazev skladby pro pridani do momentalniho programu ( Volba 1 nebo Volba 2 ) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Zapnout/vypnout nahodne opakovani skladeb +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Ukaz skladbu ve vyberovem okne +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klepni na dotaci pro zobrazeni mesta/prumyslu +STR_01FE_DIFFICULTY :{BLACK}Obtiznost ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Posledni zprava/clanek: +STR_0201_MESSAGE_SETTINGS :Nastaveni zprav +STR_MESSAGE_HISTORY_MENU :Historie zprav +STR_0202_SEND_MESSAGE :Poslat zpravu +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Ukazat posledni zpravu/clanek, ukazat moznosti zprav. +STR_0204_MESSAGE_OPTIONS :{WHITE}Moznosti zprav +STR_0205_MESSAGE_TYPES :{BLACK}Typy zprav: +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prijezd prvniho vozidla do hracovy stanice +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prijezd prvniho vozidla do konkurencni stanice +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Nehody / katastrofy +STR_0209_COMPANY_INFORMATION :{YELLOW}Informace o spolecnosti +STR_020A_ECONOMY_CHANGES :{YELLOW}Zmeny v ekonomice +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Rady / informace o hracovych vozidlech +STR_020C_NEW_VEHICLES :{YELLOW}Nove vozidlo +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Zmeny prijmu zbozi +STR_020E_SUBSIDIES :{YELLOW}Dotace +STR_020F_GENERAL_INFORMATION :{YELLOW}Obecne informace +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...prilis daleko od predchazejiciho cile +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Nejlepsi spolecnosti, ktere dosahly roku 2050{}(Uroven {STRING}) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Obchodnik +STR_0214_ENTREPRENEUR :Manazer +STR_0215_INDUSTRIALIST :Tovarnik +STR_0216_CAPITALIST :Kapitalista +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Velemagnat +STR_0219_TYCOON_OF_THE_CENTURY :Magnat stoleti +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} dosahuje hodnosti '{STRING}' ! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} z {STRING} dosahuje hodnosti '{STRING}' ! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Vytvorit mapu +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Editor mapy +STR_0223_LAND_GENERATION :{WHITE}Generovat zemi +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Nahodna zeme +STR_0227_RESET_LAND :{BLACK}Vymaz zemi +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Zvetsit oblast zeme pro snizeni/zvyseni +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Zmensit oblast zeme pro snizeni/zvyseni +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Generovat nahodnou zemi +STR_022B_RESET_LANDSCAPE :{BLACK}Smazat krajinu +STR_022C_RESET_LANDSCAPE :{WHITE}Smazat krajinu +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Jsi si jist, ze chces smazat krajinu? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Generovani krajiny +STR_022F_TOWN_GENERATION :{BLACK}Generovani mest +STR_0230_INDUSTRY_GENERATION :{BLACK}Generovani prumyslu +STR_0231_ROAD_CONSTRUCTION :{BLACK}Konstrukce silnic +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetace a dalsi objekty +STR_0233_TOWN_GENERATION :{WHITE}Generovani mest +STR_0234_NEW_TOWN :{BLACK}Nove mesto +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Vytvor nove mesto +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Tady nemohu postavit mesto... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...prilis blizko k okraji mapy +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...prilis blizko k jinemu mestu +STR_0239_SITE_UNSUITABLE :{WHITE}...nepouzitelne misto +STR_023A_TOO_MANY_TOWNS :{WHITE}...prilis mnoho mest +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Zvetsit velikost mesta +STR_023C_EXPAND :{BLACK}Rozsirit +STR_023D_RANDOM_TOWN :{BLACK}Nahodne mesto +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Vybuduj mesto na nahodne pozici +STR_023F_INDUSTRY_GENERATION :{WHITE}Generovani prumyslu +STR_0240_COAL_MINE :{BLACK}Uhelny dul +STR_0241_POWER_STATION :{BLACK}Elektrarna +STR_0242_SAWMILL :{BLACK}Pila +STR_0243_FOREST :{BLACK}Les +STR_0244_OIL_REFINERY :{BLACK}Ropny vrt +STR_0245_OIL_RIG :{BLACK}Rafinerie +STR_0246_FACTORY :{BLACK}Tovarna +STR_0247_STEEL_MILL :{BLACK}Ocelarna +STR_0248_FARM :{BLACK}Farma +STR_0249_IRON_ORE_MINE :{BLACK}Dul na zeleznou rudu +STR_024A_OIL_WELLS :{BLACK}Ropny vrt +STR_024B_BANK :{BLACK}Banka +STR_024C_PAPER_MILL :{BLACK}Papirna +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Tovarna na zpracovani potravin +STR_024E_PRINTING_WORKS :{BLACK}Tiskarna +STR_024F_GOLD_MINE :{BLACK}Dul na zlato +STR_0250_LUMBER_MILL :{BLACK}Pila +STR_0251_FRUIT_PLANTATION :{BLACK}Ovocna plantaz +STR_0252_RUBBER_PLANTATION :{BLACK}Kaucukova plantaz +STR_0253_WATER_SUPPLY :{BLACK}Zdroj vody +STR_0254_WATER_TOWER :{BLACK}Vodojem +STR_0255_DIAMOND_MINE :{BLACK}Diamantovy dul +STR_0256_COPPER_ORE_MINE :{BLACK}Dul na medenou rudu +STR_0257_COTTON_CANDY_FOREST :{BLACK}Les cukrove vaty +STR_0258_CANDY_FACTORY :{BLACK}Tovarna na sladkosti +STR_0259_BATTERY_FARM :{BLACK}Farma na baterky +STR_025A_COLA_WELLS :{BLACK}Colove studny +STR_025B_TOY_SHOP :{BLACK}Hrackarstvi +STR_025C_TOY_FACTORY :{BLACK}Tovarna na hracky +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastove fontany +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Stacirna limonad +STR_025F_BUBBLE_GENERATOR :{BLACK}Generator bublin +STR_0260_TOFFEE_QUARRY :{BLACK}Karamelolom +STR_0261_SUGAR_MINE :{BLACK}Cukerny dul +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Postavit uhelny dul +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Postavit elektrarnu +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Postavit pilu +STR_0265_PLANT_FOREST :{BLACK}Vysadit les +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Postavit rafinerii +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Postavit ropnou plosinu (lze vybudovat jen u okraju mapy) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Postavit tovarnu +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Postavit ocelarnu +STR_026A_CONSTRUCT_FARM :{BLACK}Zalozit farmu +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Postavit dul na zeleznou rudu +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Postavit ropne vrty +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Postavit banku (lze vybudovat jen ve mestech s polulaci vetsi nez 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Postavit papirnu +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Postavit tovarnu na zpracovani potravin +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Postavit tiskarnu +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Postavit zlaty dul +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Postavit banku (lze vybudovat pouze ve mestech) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Postavit pilu (kaci stromy v pralese a produkuje drevo) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Vysadit ovocnou plantaz +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Vysadit kaucukovou plantaz +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Navrtat studnu +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Postavit vodojem (lze budovat pouze ve mestech) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Postavit diamantovy dul +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Postavit dul na medenou rudu +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Vysadit les cukrove vaty +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Postavit tovarnu na sladkosti +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Postavit farmu na baterie +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Vyvrtat colove studny +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Postavit hrackarstvi +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Postavit tovarnu na hracky +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Postavit plastove fontany +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Postavit stacirnu limonad +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Postavit generator bublin +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Postavit karamelolom +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Postavit cukerny dul +STR_0285_CAN_T_BUILD_HERE :{WHITE}Nemuzes zde stavet {STRING} ... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...musis postavit nejprve mesto +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...povolena jen jedna na mesto +STR_0288_PLANT_TREES :{BLACK}Vysadit stromy +STR_0289_PLACE_SIGN :{BLACK}Umistit napis +STR_028A_RANDOM_TREES :{BLACK}Nahodne stromy +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Umistit stromy nahodne po krajine +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Umistit kamenita uzemi po mape +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Umistit majak +STR_028E_PLACE_TRANSMITTER :{BLACK}Umistit vysilac +STR_028F_DEFINE_DESERT_AREA :{BLACK}Vytvorit poustni oblast +STR_0290_DELETE :{BLACK}Smaz +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Smazat cele toto mesto +STR_0292_SAVE_SCENARIO :Ulozit mapu +STR_0293_LOAD_SCENARIO :Otevrit mapu +STR_0294_QUIT_EDITOR :Ukoncit editor +STR_0295 : +STR_0296_QUIT :Ukoncit +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Ulozit mapu, otevrit mapu, opustit editor map, ukoncit... +STR_0298_LOAD_SCENARIO :{WHITE}Otevrit mapu +STR_0299_SAVE_SCENARIO :{WHITE}Ulozit mapu +STR_029A_PLAY_SCENARIO :{BLACK}Hrat mapu +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jste si jisty, ze chces opustit toto mapu? +STR_029C_QUIT_EDITOR :{WHITE}Ukoncit editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...muze byt vybudovano jen ve mestech s populaci 1200 lidi nebo vice +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Posunout startovni rok o rok zpet +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Posunout startovni rok o rok vpred +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...oba konce mostu musi byt na zemi +STR_02A1_SMALL :{BLACK}Male +STR_02A2_MEDIUM :{BLACK}Stredni +STR_02A3_LARGE :{BLACK}Velke +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Zvol velikost mesta: +STR_02A5_TOWN_SIZE :{YELLOW}Velikost mesta: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Ukazat posledni zpravu nebo clanek +STR_02B8_SUMMARY :{BLACK}Shrnuti +STR_02B9_FULL :{BLACK}Plna +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Seznam mest +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Nazvy dopravnich prostredku +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Zakladni +STR_02BF_CUSTOM :Uzivatelske +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Ulozit uzivatelske nazvy na disk +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Vyber nazvu dopravnich prostredku +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Ulozit uzivatelske nazvy dopravnich prostredku na disk + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Moznosti hry +STR_02C4_GAME_OPTIONS :Moznosti hry +STR_02C5_DIFFICULTY_SETTINGS :Nastaveni obtiznosti +STR_02C6_DIFFICULTY_SETTINGS :Nastaveni obtiznosti +STR_02C7_CONFIG_PATCHES :Nastaveni patchu +STR_02C8_CONFIG_PATCHES :Nastaveni patchu +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazeni jmen mest +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Zobrazeni jmen mest +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazeni jmen stanic +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Zobrazeni jmen stanic +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazeni napisu +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Zobrazeni napisu +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazeni kontrolnich bodu +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Zobrazeni kontrolnich bodu +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Plne animace +STR_02D0_FULL_ANIMATION :{SETX 12}Plne animace +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Plne detaily +STR_02D2_FULL_DETAIL :{SETX 12}Plne detaily +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Pruhledne budovy +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Pruhledne budovy +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Informace o zemi +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Screenshot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Obrovsky screenshot (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :O 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}Zapnuto +STR_02DB_OFF :{BLACK}Vypnuto +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Zobrazit nabidky dotaci +STR_02DD_SUBSIDIES :Dotace +STR_02DE_MAP_OF_WORLD :Mapa sveta +STR_02DF_TOWN_DIRECTORY :Seznam mest +STR_02E0_CURRENCY_UNITS :{BLACK}Jednotky meny +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Vyber jednotek meny +STR_02E3_DISTANCE_UNITS :{BLACK}Jednotky vzdalenosti +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Vyber jednotek vzdalenosti +STR_02E6_ROAD_VEHICLES :{BLACK}Automobily jezdi +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Vyber strany na ktere jezdi silnicni vozidla +STR_02E9_DRIVE_ON_LEFT :Vlevo +STR_02EA_DRIVE_ON_RIGHT :Vpravo +STR_02EB_TOWN_NAMES :{BLACK}Jmena mest +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Vyber stylu jmen mest + +STR_02F4_AUTOSAVE :{BLACK}Automaticke ukladani +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Volba intervalu mezi automatickym ukladanim hry +STR_02F7_OFF :Vypnuto +STR_02F8_EVERY_3_MONTHS :Kazde 3 mesice +STR_02F9_EVERY_6_MONTHS :Kazdych 6 mesicu +STR_02FA_EVERY_12_MONTHS :Kazdych 12 mesicu +STR_02FB_START_A_NEW_GAME :{BLACK}Zalozit novou hru +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Otevrit ulozenou hru z disku +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Prohlednout ukazky/tutorialy +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Vytvorit uzivatelsky svet/scenario +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Vybrat hru pro jednoho hrace +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Vybrat hru pro dva hrace +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Zobrazit moznosti hry +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Zobrazit nastaveni obtiznosti +STR_0303_START_A_NEW_GAME_USING :{BLACK}Zalozit novou hru, pouzit uzivatelske scenario +STR_0304_QUIT :{BLACK}Ukoncit +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Opustit 'OpenTTD' a ukoncit +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Prohlednout ukazku/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD{REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...muze byt staveno jen ve mestech +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Zvolit krajinu 'mirne pasmo' +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Zvolit 'subarctickou' krajinu +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Zvolit 'subtropickou' krajinu +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Zvolit krajinu 'zeme hracek' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Investovat do noveho prumyslu + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Investovat do prumyslu +STR_INDUSTRY_DIR :Seznam prumyslu +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Investovat do prumyslu +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...muze byt budovano jen ve mestech +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...muze but budovano jen v pralesech +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...muze but budovano jen v poustich +STR_0319_PAUSED :{YELLOW}* * PAUZA * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot uspesne ulozen jako '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot neulozen! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Zakoupit zemi pro budouci uziti +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Udrzby automobilu +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Udrzby vlaku +STR_032C_3_AIR_SERVICE :{BLACK}3: Udrzby letadel +STR_032D_4_SHIP_SERVICE :{BLACK}4: Udrzby lodi +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Udrzby vlaku ( rozsirene ) +STR_032F_AUTOSAVE :{RED}Automaticke ukladani +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Zvolit 'Ezy Street style music' program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Anglicka +STR_TOWNNAME_FRENCH :Francouzska +STR_TOWNNAME_GERMAN :Nemecka +STR_TOWNNAME_AMERICAN :Americka +STR_TOWNNAME_LATIN_AMERICAN :Jihoamericka +STR_TOWNNAME_SILLY :Legracni (anglicka) +STR_TOWNNAME_SWEDISH :Svedska +STR_TOWNNAME_DUTCH :Holandska +STR_TOWNNAME_FINNISH :Finska +STR_TOWNNAME_POLISH :Polska +STR_TOWNNAME_SLOVAKISH :Slovenska +STR_TOWNNAME_HUNGARIAN :Madarska +STR_TOWNNAME_AUSTRIAN :Australska +############ end of townname region + +STR_CURR_POUNDS :Anglicke libry ({POUNDSIGN}) +STR_CURR_DOLLARS :Americke dolary ($) +STR_CURR_FF :Francouzske franky (FF) +STR_CURR_DM :Nemecke marky (DM) +STR_CURR_YEN :Japonske jeny ({YENSIGN}) +STR_CURR_PT :Spanelske pesety (Pt) +STR_CURR_FT :Madarske forinty (Ft) +STR_CURR_ZL :Polske zlote (zl) +STR_CURR_ATS :Rakouske silinky (ATS) +STR_CURR_BEF :Belgicke franky (BEF) +STR_CURR_DKK :Danske koruny (DKK) +STR_CURR_FIM :Finske marky (FIM) +STR_CURR_GRD :Recke drachmy (GRD) +STR_CURR_CHF :Svycarske franky (CHF) +STR_CURR_NLG :Holandske guldeny (NLG) +STR_CURR_ITL :Italske liry (ITL) +STR_CURR_SEK :Svedske koruny (SEK) +STR_CURR_RUR :Ruske rubly (RUR) +STR_CURR_CZK :Ceske koruny (CZK) +STR_CURR_ISK :Islandske koruny (ISK) +STR_CURR_NOK :Norske koruny (NOK) +STR_CURR_EUR :Eura (€) + +STR_OPTIONS_LANG :{BLACK}Jazyk +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Zvolit jazyk uzivatelskeho rozhrani + +STR_OPTIONS_RES :{BLACK}Rozliseni obrazovky +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Zvolit rozliseni obrazovky + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Format screenshotu +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Zvolit format screenshotu + +STR_AUTOSAVE_1_MONTH :Kazdy mesic +STR_AUTOSAVE_FAILED :{WHITE}Automaticke ulozeni selhalo + +STR_MONTH_JAN :Leden +STR_MONTH_FEB :unor +STR_MONTH_MAR :Brezen +STR_MONTH_APR :Duben +STR_MONTH_MAY :Kveten +STR_MONTH_JUN :Cerven +STR_MONTH_JUL :Cervenec +STR_MONTH_AUG :Srpen +STR_MONTH_SEP :Zari +STR_MONTH_OCT :Rijen +STR_MONTH_NOV :Listopad +STR_MONTH_DEC :Prosinec + +STR_HEADING_FOR_STATION :{LTBLUE}Mirim do {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Mirim do {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Bez prikazu +STR_NO_ORDERS_VEL :{LTBLUE}Bez prikazu, {VELOCITY} + +STR_PASSENGERS :cestujicich +STR_BAGS :pytlu +STR_TONS :tun +STR_LITERS :litru +STR_ITEMS :kus +STR_CRATES :krabic +STR_RES_OTHER :jine +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Nemuzu sdilet seznam prikazu... +STR_CANT_COPY_ORDER_LIST :{WHITE}Nemohu kopirovat seznam prikazu... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Konec sdilenych prikazu - - + +STR_TRAIN_IS_LOST :{WHITE}Vlak {COMMA16} je ztracen. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Zisk vlaku {COMMA16} za posledni rok byl {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Nastavit patche +STR_CONFIG_PATCHES_TIP :{BLACK}Nastavit patche +STR_CONFIG_PATCHES_CAPTION :{WHITE}Nastavit patche + +STR_CONFIG_PATCHES_OFF :Vypnuto +STR_CONFIG_PATCHES_ON :Zapnuto +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Ukazovat rychlost vozidla ve stavove liste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Povolit vystavbu na kopcich a pobrezich: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Povolit ruseni vice mestskych silnic, mostu, tunelu, atp.: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Povolit stavbu dlouhych vlaku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Zapnout realisticke zrychlovani vlaku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Spojovat stanice postavene vedle sebe: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Odjet kdyz je plne nalozen jakykoli naklad pri 'nalozit': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflace: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Vypnout automatickou udrzbu vlaku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Vozit zbozi do stanice jen pokud je poptavka: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Povolit stavbu velmi dlouhych mostu: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Povolit prikaz 'jed do depa': {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Povolit konstrukci prumyslu teziciho surovy material: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Povolit vice stejneho prumyslu kolem jednoho mesta: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Prumysl stejneho druhu muze byt budovan pobliz sebe: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Ukazovat vzdy dlouhe datum ve stavove liste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Ukazovat semafory na strane kde jezdi automobily: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Ukazovat financni okno na konci kazdeho roku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}Pouziti prikazu 'bez zastaveni' jako v TTDPatch: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Automobily stoji fronty (s kvantovym efektem): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Posouvat okno kdyz je mys na okraji: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Povolit uplatek mistni sprave: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Nove vyhledavani dep: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Nejednolite stanice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Novy algoritmus pro hledani cesty vlaku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Povolit stavbu pri pauze: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Povolit stavbu malych letist kdykoliv : {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Vlak se povazuje za ztraceny pokud nedojede do {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Varovat pokud vlak prodelava: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES :{LTBLUE}Vozidlum se nikdy nezastavi vyroba: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Automaticky obnovit dopravni prostredek kdyz je stary +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Doba trvani chybove zpravy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Vyska snehove cary: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Nejvetsi rozsah stanice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Udrzba vrtulniku na heliportech: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maximum vlaku na hrace: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maximum automobilu na hrace: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maximum letadel na hrace: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maximum lodi na hrace: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Zakazat pocitaci vlaky: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Zakazat pocitaci automobily: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Zakazat pocitaci letadla: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Zakazat pocitaci lode: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Zakladni servisni interval pro vlaky: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Zakladni servisni interval pro automobily: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Zakladni servisni interval pro letadla: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Zakladni servisni interval pro lode: {ORANGE}{STRING} dni + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Barevne noviny se objevi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Pocatecni datum: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Plynule zmeny ekonomiky (vice mensich zmen) + +STR_CONFIG_PATCHES_GUI :{BLACK}Ovladani +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstrukce +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Dop. prostredky +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stanice +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Ekonomika + +STR_CONFIG_PATCHES_DISABLED :vypnuto +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Zmenit hodnotu nastaveni + + +STR_CHEATS :{WHITE}Cheaty +STR_CHEATS_TIP :{BLACK}Zaskrtavaci policka indikuji jestli jsi tento cheat jiz pouzil. +STR_CHEATS_WARNING :{BLACK}Varovani! Chystas se podvest ostatni soutezici. Pamatuj si, ze tento podly cin nebude nikdy zapomenut! +STR_CHEAT_MONEY :{LTBLUE}Navysit penize o {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Hrajes jako hrac: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magicky buldozer (odstrani prumysl a neodstranitelne predmety): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunely se mohou krizit: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Jmeno +STR_TOWNDIR_POPULATION :{BLACK}Populace +STR_TOWNDIR_SORT_TIP :{BLACK}Zvolit zpusob razeni + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Mirim do {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Mirim do {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Jet pres {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Kontrolni bod {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Kontrolni bod {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Kontrolni bod + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Zmenit jmeno kontrolniho bodu + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Nemohu zmenit jmeno kontrolniho bodu... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Zmenit koleje v kontrolni bod +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Nemohu zde vybudovat zeleznicni kontrolni bod... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Nemohu zde zrusit zeleznicni kontrolni bod... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Budovat koleje pouzitim rezimu Autokoleje + +STR_NO_TOWN_IN_SCENARIO :{WHITE}... v tomto scenari neni ani jedno mesto + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Opravdu chcete vytvorit novy nahodny teren? +STR_MANY_RANDOM_TOWNS :{BLACK}Hodne nahodnych mest +STR_RANDOM_TOWNS_TIP :{BLACK}Pokryje krajinu mnoha nahodnymi mesty +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Hodne nahodneho prumyslu +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Pokryje krajinu nahodnym prumyslem +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemuzu generovat prumysl... + +STR_LANDSCAPING_TOOLBAR :{WHITE}Upravy krajiny +STR_LEVEL_LAND_TOOLTIP :{BLACK}Srovnat teren + + +STR_TREES_RANDOM_TYPE :{BLACK}Ruzne stromy +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Umistit nahodne stromy + +STR_CANT_BUILD_CANALS :{WHITE}Nemohu zde postavit kanal... +STR_BUILD_CANALS_TIP :{BLACK}Stavet kanal +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Nemohu zde postavit zdymadlo... +STR_BUILD_LOCKS_TIP :{BLACK}Stavet zdymadlo +STR_LANDINFO_LOCK :Zdymadlo + +STR_LANDINFO_COORDS :{BLACK}Souradnice: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Nemohu odstranit cast stanice... +STR_CANT_CONVERT_RAIL :{WHITE}Nemohu zde zmenit typ koleji... +STR_CONVERT_RAIL_TIP :{BLACK}Zmenit/Vylepsit typ koleji + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Potahni sem lokomotivu pro prodani celeho vlaku + +STR_DRAG_DROP :{BLACK}Tahni a pust +STR_STATION_DRAG_DROP :{BLACK}Stavet stanice pomoci tahani mysi + +STR_FAST_FORWARD :{BLACK}Zrychlit beh hry +STR_MESSAGE_HISTORY :{WHITE}Historie zprav +STR_MESSAGE_HISTORY_TIP :{BLACK}Seznam predeslych zprav +STR_MESSAGES_DISABLE_ALL :{BLACK}Vypnout vsechny +STR_MESSAGES_ENABLE_ALL :{BLACK}Zapnout vsechny + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Vyhloubit uhelny dul +STR_CONSTRUCT_FOREST_TIP :{BLACK}Vysadit les +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Postavit ropnou plosinu +STR_CONSTRUCT_FARM_TIP :{BLACK}Zalozit farmu +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Vyhloubit medeny dul +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Vyvrtat ropny vrt +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Postavit zlaty dul +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Postavit diamantovy dul +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Postavir dul na zeleznou rudu +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Zalozit ovocnou plantaz +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Zalozit kaucukovou plantaz +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Vyvrtat studnu +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Vysadit cukrovou vatu +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Zalozit farmu na baterky +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Vyvrtat kolovou studnu +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Zalozit plastove fontany +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Vybudovat generator bublin +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Vyhloubit karamelolom +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Vyhloubit cukrovy dul + +STR_INDUSTRYDIR_NAME :{BLACK}Jmeno +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produkce +STR_INDUSTRYDIR_TYPE :{BLACK}Typ +STR_INDUSTRYDIR_TRANSPORTED :{BLACK}Prepraveno +STR_INDUSTRYDIR_CAPTION :{WHITE}Prumysl +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}){YELLOW} ({COMMA16}% prepraveno) +STR_INDUSTRYDIR_ITEM_TWO :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}/{STRING}){YELLOW} ({COMMA16}%/{COMMA16}% prepraveno) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...prilis blizko k jinemu prumyslu + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Prestavet vlak pro prevoz jineho typu nakladu +STR_RAIL_REFIT :{WHITE}{STRING} (Prestavet) +STR_RAIL_REFIT_VEHICLE :{BLACK}Prestavet vlak +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Zvolit typ nakladu na ktery vlak prestavet +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Prestavet vlak na oznaceny typ nakladu +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Nelze prestavet vlak... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}Sitove rozhrani jeste nefunguje! + +STR_NETWORK_MULTIPLAYER :{WHITE}Multiplayer + +STR_NETWORK_FIND_SERVER :{BLACK}Najit server +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Hledat server v siti +STR_NETWORK_DIRECT_CONNECT :{BLACK}Pripojit se primo +STR_NETWORK_ENTER_IP :{BLACK}Vloz IP addresu serveru +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Pripojit se na urcitou IP adresu +STR_NETWORK_START_SERVER :{BLACK}Spustit server +STR_NETWORK_START_SERVER_TIP :{BLACK}Spusti tvuj vlastni server + +STR_NETWORK_PLAYER_NAME :{BLACK}Jmeno hrace: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}Podle tohoto jmena te ostatni hraci poznaji + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Vyber typ pripojeni: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Vyber si hru na internetu nebo v mistni siti +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Nazev +STR_NETWORK_GAME_NAME_TIP :{BLACK}Nazev hry +STR_NETWORK_PLAYERS :{BLACK}#/# +STR_NETWORK_PLAYERS_TIP :{BLACK}Kolik je ted ve hre hracu / Maximum hracu ve hre +STR_NETWORK_MAP_SIZE :{BLACK}Velikost +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Velikost mapy +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Jazyk, verze serveru, atd. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Hru vyberes kliknutim do seznamu + +STR_NETWORK_JOIN_GAME :{BLACK}Pridat se + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Zacit novou hru + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Jmeno hry: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}Jmeno hry se zobrazi ostatnim hracum v menu, kde si vybiraji sitovou hru +STR_NETWORK_PASSWORD :{BLACK}Heslo: +STR_NETWORK_PASSWORD_TIP :{BLACK}Svoji hru si muzes ochranit heslem, kdyz nechces, aby se ti do ni hlasili jini lide +STR_NETWORK_SELECT_MAP :{BLACK}Vyber mapu: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}Ve ktere mape si chces zahrat? +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Pocet hracu: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Zvol maximalni pocet hracu. Nemusis vybirat maximalni pocet. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 hraci +STR_NETWORK_3_PLAYERS :{BLACK}3 hraci +STR_NETWORK_4_PLAYERS :{BLACK}4 hraci +STR_NETWORK_5_PLAYERS :{BLACK}5 hracu +STR_NETWORK_6_PLAYERS :{BLACK}6 hracu +STR_NETWORK_7_PLAYERS :{BLACK}7 hracu +STR_NETWORK_8_PLAYERS :{BLACK}8 hracu +STR_NETWORK_START_GAME :{BLACK}Zacit hru + + +STR_NETWORK_GAME_LOBBY :{WHITE}Vstupni mistnost do multiplayerove hry + +STR_NETWORK_SEND :{BLACK}Poslat +STR_NETWORK_SEND_TIP :{BLACK}Polat zpravu ostatnim hracum +STR_NETWORK_COMPANY_NAME :{BLACK}Jmeno spolecnosti: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Muzes zmenit jmeno tve spolecnosti. Enterem potvrdis zmeny +STR_NETWORK_SPECTATE_GAME :{BLACK}Navstivit hru +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Koukat na hru jako divak +STR_NETWORK_NEW_COMPANY :{BLACK}Nova spolecnost +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Zalozit novou spolecnost +STR_NETWORK_READY :{BLACK}Pripraven + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Cena: {CURRENCY} +STR_0801_COST :{RED}Cena: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Prijem: {CURRENCY} +STR_0803_INCOME :{GREEN}Prijem: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Odhadovana cena: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Odhadovana cena: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Odhadovany prijem: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Odhadovany prijem: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Nemohu zde zvednout zemi... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Nemohu zde snizit zemi... +STR_080A_ROCKS :Kameni +STR_080B_ROUGH_LAND :Hrbolata zeme +STR_080C_BARE_LAND :Prazdna zeme +STR_080D_GRASS :Travnata zeme +STR_080E_FIELDS :Pole +STR_080F_SNOW_COVERED_LAND :Zasnezena zeme +STR_0810_DESERT :Poust + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Zeme sklonena nespravnym smerem +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nemozna kombinace koleji +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Uprava terenu by poskodila tunel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Jiz na urovni more +STR_1004_TOO_HIGH :{WHITE}Prilis vysoko +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Zadne pouzitelne koleje +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Vlak v depu +STR_1007_ALREADY_BUILT :{WHITE}...jiz vystaveno +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Musis nejprve odstranit koleje +STR_1009_TOO_MANY_DEPOTS :{WHITE}Prilis mnoho dep +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Vystavba koleji +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Vystavba monorailu +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Vystavba Maglevu +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Zvolit zeleznicni most +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Zde nemohu postavit depo... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Zde nemohu postavit nadrazi... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Zde nemohu postavit semafory... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Zde nemohu postavit koleje... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nemohu odsud odstranit koleje... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nemohu odsud odstranit semafory... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Orientace vlakoveho depa +STR_1015_RAILROAD_CONSTRUCTION :Vystavba koleji +STR_1016_MONORAIL_CONSTRUCTION :Vystavba monorailu +STR_1017_MAGLEV_CONSTRUCTION :Vystavba Maglevu +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Polozit koleje +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Postavit zeleznicni depo ( pro nakup a servis vlaku ) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Postavit nadrazi +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Postavit semafory +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Postavit zeleznicni most +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Postavit zeleznicni tunel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Prepnout rezim stavba/odstraneni pro koleje a semafory +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Vyber mostu - stiskni vybrany typ mostu pro vystavbu +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Zvalit orientaci zeleznicniho depa +STR_1021_RAILROAD_TRACK :Koleje +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Koleje se semaforem +STR_1023_RAILROAD_TRAIN_DEPOT :Zeleznicni depo +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...uzemi vlastni jina spolecnost +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Zeleznicni trat s normalnimy signaly +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Zeleznicni trat s predsignaly +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Zeleznicni trat s vystupnimy signaly +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Zeleznicni trat s kombinovanymy signaly + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Nespravny sklon zeme pro silnici +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Musis nejprve odstranit silnici +STR_1802_ROAD_CONSTRUCTION :{WHITE}Vystavba silnic +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Zvolit silnicni most +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Zde nemohu postavit silnici... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nemohu odsud odstranit silnici +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientace garaze +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nemohu zde postavit garaz +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Nemohu postavit autobusovou zastavku... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemohu postavit nakladovou rampu... +STR_180A_ROAD_CONSTRUCTION :Vystavba silnic +STR_180B_BUILD_ROAD_SECTION :{BLACK}Postavit silnici +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Postavit garaz (pro nakup a servis vozidel) +STR_180D_BUILD_BUS_STATION :{BLACK}Postavit autobusovou zastavku +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Postavit nakladovou rampu +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Postavit silnicni most +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Postavit silnicni tunel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Prepnout stavba/odstraneni silnice +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Vyber mostu - stiskni vybrany typ most pro stavbu +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Vyber orientace garaze +STR_1814_ROAD :Silnice +STR_1815_ROAD_WITH_STREETLIGHTS :Silnice s poulicnimy lampamy +STR_1816_TREE_LINED_ROAD :Silnice s aleji +STR_1817_ROAD_VEHICLE_DEPOT :Garaz +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Zeleznicni prejezd + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Mesta +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Budova musi byt nejprve znicena +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Populace: {ORANGE}{COMMA32}{BLACK} Domu: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Prejmenovat mesto +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Nemohu prejmenovat mesto: +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}Mistni sprava mesta {TOWN} toto odmita povolit. +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Jmena mest - stiskni na jmenu mesta pro pohled na mesto +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Umistit pohled na mesto +STR_200C_CHANGE_TOWN_NAME :{BLACK}Zmenit jmeno mesta +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Cestujici minuly mesic: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Posta minuly mesic: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Vysoky kancelarsky blok +STR_2010_OFFICE_BLOCK :Kancelarsky blok +STR_2011_SMALL_BLOCK_OF_FLATS :Male bytovky +STR_2012_CHURCH :Kostel +STR_2013_LARGE_OFFICE_BLOCK :Velky kancelarsky blok +STR_2014_TOWN_HOUSES :Mestske domy +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Socha +STR_2017_FOUNTAIN :Fontana +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kancelarsky blok +STR_201A_SHOPS_AND_OFFICES :Obchody a kancelare +STR_201B_MODERN_OFFICE_BUILDING :Moderni kancelarsky blok +STR_201C_WAREHOUSE :Vyrobni hala +STR_201D_OFFICE_BLOCK :Kancelarsky blok +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Stare domy +STR_2020_LOCAL_AUTHORITY :{BLACK}Mistni sprava +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Ukazat informace o mistni sprave +STR_2022_LOCAL_AUTHORITY :{WHITE}Mistni sprava mesta {TOWN} +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Hodnoceni spolecnosti: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Dotace +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Nabidnute dotace pro sluzbu: +STR_2027_FROM_TO :{ORANGE}{STRING} z {STRING} do {STRING} +STR_2028_BY :{YELLOW} (do {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Nic +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Jiz priznane dotace: +STR_202C_FROM_TO :{ORANGE}{STRING} z {STATION} do {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, do {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Nabidka dotace prepravy vyprsela:{}{}Dotace dopravy {STRING} z {STRING} do {STRING} nebude dale nabizena. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Ukonceni dotovani dopravy:{}{}Dotace pro {STRING} z {STATION} do {STATION} jiz nebude dale poskytovana. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Nabidka dotace:{}{}Doprava {STRING} z {STRING} do {STRING} bude jeden rok dotovana mistni spravou! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotace pridelena {STRING} .{}{}Za dopravu {STRING} z {STATION} do {STATION} bude dostavat bonus v podobe 150% ceny. +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotace pridelena {STRING} .{}{}Za dopravu {STRING} z {STATION} do {STATION} bude dostavat bonus v podobe dvojnasobku ceny! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotace pridelena {STRING} .{}{}Za dopravu {STRING} z {STATION} do {STATION} bude dostavat bonus v podobe trojnasobku ceny! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotace pridelena {STRING} .{}{}Za dopravu {STRING} z {STATION} do {STATION} bude dostavat bonus v podobe ctyrnasobku ceny! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}Mistni sprava mesta {TOWN} zakazuje stavbu dalsiho letiste v tomto meste. +STR_2036_COTTAGES :Chatky +STR_2037_HOUSES :Domy +STR_2038_FLATS :Byty +STR_2039_TALL_OFFICE_BLOCK :Vysoky kancelarsky blok +STR_203A_SHOPS_AND_OFFICES :Obchody a kancelare +STR_203B_SHOPS_AND_OFFICES :Obchody a kancelare +STR_203C_THEATER :Divadlo +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Kancelare +STR_203F_HOUSES :Domy +STR_2040_CINEMA :Kino +STR_2041_SHOPPING_MALL :Nakupni stredisko +STR_2042_DO_IT :{BLACK}Udelej to +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Seznam vsech veci ktere lze delat v tomto meste - stiskni na cinnosti pro vice detailu: +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Proved oznacenou cinnost z vyse uvedeneho seznamu. +STR_2045_ACTIONS_AVAILABLE :{BLACK}Mozne cinnosti: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Mala reklamni kampan +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Stredni reklamni kampan +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Velka reklamni kampan +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Dotovat rekonstrukci mistnich silnic +STR_204A_BUILD_STATUE_OF_COMPANY :Postavit sochu majitele spolecnosti +STR_204B_FUND_NEW_BUILDINGS :Dotovat nove budovy +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Koupit vyhradni pravo k preprave +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Podplatit mistni spravu +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Zahajit malou reklamni kampan, ktera prilaka vice cestujicich a nakladu.{} Cena: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Zahajit stredne velkou reklamni kampan, ktera prilaka vice cestujicich a nakladu.{} Cena: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Zahajit velkou reklamni kampan, ktera prilaka vice cestujicich a nakladu.{} Cena: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Dotovat rekonstrukci mistni poulicni site. Zpusobi problemy v doprave po dobu 6 mesicu.{} Cena: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Postavit sochu vlastnika jako poctu tve spolecnosti.{} Cena: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Dotovat stavbu novych obchodnich budov ve meste.{} Cena: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Koupit vyhradni prava k preprave zbozi z tohoto mesta po dobu jednoho roku. Mistni sprava dovoli cestujicim a nakladu pouzivat pouze stanice tve spolecnosti.{} Cena: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Podplatit mistni spravu pro zvyseni hodnoceni spolecnosti. Riziko trestu v pripade pristizeni.{} Cena: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Toto nemuzes udelat... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Dopravni chaos v {TOWN}!{}{}Program prestavby ulic sponzorovany {STRING} prinasi motoristum 6 mesicu utrpeni! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (ve vystavbe) +STR_2059_IGLOO :Iglu +STR_205A_TEPEES :Teepee +STR_205B_TEAPOT_HOUSE :Dum Konvicka +STR_205C_PIGGY_BANK :Banka Prasatko + +##id 0x2800 +STR_LANDSCAPING :Upravy krajiny +STR_2800_PLANT_TREES :Vysadit stromy +STR_2801_PLACE_SIGN :Umistit napis +STR_2802_TREES :{WHITE}Stromy +STR_2803_TREE_ALREADY_HERE :{WHITE}...strom zde jiz je +STR_2804_SITE_UNSUITABLE :{WHITE}...nepouzitelne misto +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Zde nemuzes vysadit strom... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...prilis mnoho napisu +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Zde nemuzes umistit napis... +STR_280A_SIGN :Napis +STR_280B_EDIT_SIGN_TEXT :{WHITE}Upravit text napis +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nemuzes zmenit jmeno napisu... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Zvol typ stromu na vysazeni +STR_280E_TREES :Stromy +STR_280F_RAINFOREST :Tropicky prales +STR_2810_CACTUS_PLANTS :Kaktusy + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Vyber nadrazi +STR_3001_AIRPORT_SELECTION :{WHITE}Vyber letiste +STR_3002_ORIENTATION :{BLACK}Orientace +STR_3003_NUMBER_OF_TRACKS :{BLACK}Pocet nastupist +STR_3004_PLATFORM_LENGTH :{BLACK}Delka nastupiste +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Prilis blizko jinemu nadrazi +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Spojuje vice jak jedno existujici nadrazi/nakladovou rampu... +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Prilis mnoho nadrazi/nakladovych ramp v tomto meste +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Prilis mnoho nadrazi/nakladovych ramp +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Prilis blizko k jinemu nadrazi/nakladove rampe +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Musis nejprve znicit stanici +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Prilis blizko k jinemu letisti +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Musis nejprve znicit letiste + +STR_3030_RENAME_STATION_LOADING :Prejmenovat stanici +STR_3031_CAN_T_RENAME_STATION :{WHITE}Nemohu prejmenovat stanici... +STR_3032_RATINGS :{BLACK}Hodnoceni +STR_3033_ACCEPTS :{BLACK}Prijima +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Mistni hodnoceni dopravni sluzby: + +############ range for rating starts +STR_3035_APPALLING :Priserne +STR_3036_VERY_POOR :Velmi slabe +STR_3037_POOR :Slabe +STR_3038_MEDIOCRE :Prumerne +STR_3039_GOOD :Dobre +STR_303A_VERY_GOOD :Velmi dobre +STR_303B_EXCELLENT :Vynikajici +STR_303C_OUTSTANDING :Uzasne +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} jiz vice neprijima {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} jiz vice neprijima {STRING} nebo {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} nyni prijima {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} nyni prijima {STRING} a {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Orientace autobusove zastavky. +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Orientace nakladove rampy. +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Prilis blizko k jine autobusove zastavce +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Prilis blizko k jine nakladove rampe +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Musis nejprve znicit autobusovou zastavku +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Musis nejprve znicit nakladovou rampu +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} stanic +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Nic - +STR_304B_SITE_UNSUITABLE :{WHITE}...nepouzitelne misto +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Prilis blizko k jinemu doku +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Musis nejprve znicit dok +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Zvolit orientaci nadrazi +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Zvolit pocet nastupist pro nadrazi +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Zvolit delku nadrazi +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Zvolit orientaci autobusove zastavky +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Zvolit orientaci nakladove rampy +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Vycentrovat pohled na umisteni stanice +STR_3054_SHOW_STATION_RATINGS :{BLACK}Ukazat hodnoceni spolecnosti +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Zmenit jmeno stanice +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Ukazat seznam prijimaneho zbozi +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Jmena stanic - stiskni jmeno pro vycentrovani obrazu na stanici +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Zvol velikost/typ letiste +STR_3059_SMALL :{BLACK}Male +STR_305A_LARGE :{BLACK}Mestske +STR_305AA_LARGE :{BLACK}Metropolitni +STR_305AB_LARGE :{BLACK}Mezinarodni +STR_305B_SIZE :{BLACK}Velikost +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Nadrazi +STR_305F_AIRCRAFT_HANGAR :Hangar +STR_3060_AIRPORT :Letiste +STR_3061_TRUCK_LOADING_AREA :Nakladova rampa +STR_3062_BUS_STATION :Autobusova zastavka +STR_3063_SHIP_DOCK :Dok +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Zvyraznit oblast pokryti +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Nezvyraznovat oblast pokryti +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Zvyraznit oblast pokryti +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Vyber nadrazi pro jednokolejku. +STR_3068_DOCK :{WHITE}Pristav +STR_3069_BUOY :Bojka +STR_306A_BUOY_IN_THE_WAY :{WHITE}...bojka v ceste +STR_306B_HELIPORT :{BLACK}Heliport +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stanice prilis rozlozena + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orientace sucheho doku +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...musi byt postaven na vode +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Zde nemuzes postavit suchy dok... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Zvolit orientaci sucheho doku +STR_3804_WATER :Voda +STR_3805_COAST_OR_RIVERBANK :Pobrezi nebo breh +STR_3806_SHIP_DEPOT :Suchy dok +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...nemohu stavet na vode + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Ulozit hru +STR_4001_LOAD_GAME :{WHITE}Otevrit hru +STR_4002_SAVE :{BLACK}Ulozit +STR_4003_DELETE :{BLACK}Smazat +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} MB volnych +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Nemohu cist jednotku +STR_4007_GAME_SAVE_FAILED :{WHITE}Ulozeni hry selhalo +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Nemohu smazat soubor +STR_4009_GAME_LOAD_FAILED :{WHITE}Nemohu otevrit hru +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Seznam jednotek, adresaru a ulozenych her +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Zvolene jmeno ulozene hry +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Smazat oznacenou ulozenou hru +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Ulozit aktualni hru se zvolenym jmenem +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Zvolit novy typ hry +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Zvolit scenario (zelena), prednastavenou hru (modra), nebo nahodnou novou hru +STR_4010_GENERATE_RANDOM_NEW_GAME :Vytvorit nahodnou novou hru + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} v ceste +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Uhelny dul +STR_4803_POWER_STATION :Elektrarna +STR_4804_SAWMILL :Pila +STR_4805_FOREST :Les +STR_4806_OIL_REFINERY :Rafinerie +STR_4807_OIL_RIG :Ropna plosina +STR_4808_FACTORY :Tovarna +STR_4809_PRINTING_WORKS :Tiskarna +STR_480A_STEEL_MILL :Ocelarna +STR_480B_FARM :Farma +STR_480C_COPPER_ORE_MINE :Medeny dul +STR_480D_OIL_WELLS :Ropne vrty +STR_480E_BANK :Banka +STR_480F_FOOD_PROCESSING_PLANT :Tovarna na zpracovani jidla +STR_4810_PAPER_MILL :Papirna +STR_4811_GOLD_MINE :Zlaty dul +STR_4812_BANK :Banka +STR_4813_DIAMOND_MINE :Diamantovy dul +STR_4814_IRON_ORE_MINE :Dul na zeleznou rudu +STR_4815_FRUIT_PLANTATION :Ovocna plantaz +STR_4816_RUBBER_PLANTATION :Kaucukova plantaz +STR_4817_WATER_SUPPLY :Zdroj vody +STR_4818_WATER_TOWER :Vodojem +STR_4819_FACTORY :Tovarna +STR_481A_FARM :Farma +STR_481B_LUMBER_MILL :Pila +STR_481C_COTTON_CANDY_FOREST :Les cukrove vaty +STR_481D_CANDY_FACTORY :Tovarna na sladkosti +STR_481E_BATTERY_FARM :Farma na baterky +STR_481F_COLA_WELLS :Kolove studny +STR_4820_TOY_SHOP :Hrackarstvi +STR_4821_TOY_FACTORY :Tovarna na hracky +STR_4822_PLASTIC_FOUNTAINS :Plastove fontany +STR_4823_FIZZY_DRINK_FACTORY :Sodovkarna +STR_4824_BUBBLE_GENERATOR :Generator bublin +STR_4825_TOFFEE_QUARRY :Karamelolom +STR_4826_SUGAR_MINE :Cukrovy dul + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Vyzaduje: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Vyzaduje: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Vyzaduje: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produkce minuly mesic: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% prepraveno) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Nastavit pohled na prumysl +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}{STRING} v konstrukci pobliz mesta {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Novy {STRING} je vysazen pobliz mesta {TOWN}! +STR_482F_COST :{BLACK}Cena: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Tento druh prumyslu zde nemohu postavit... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...lesy lze vysadit jen nad snehovou lini +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} ohlasuje okamzite uzavreni! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Zasobovaci problemy zpusobily uzavreni {TOWN} {STRING}! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Nedostatek stromu zpusobil uzavreni {TOWN} {STRING}! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} zvysuje produkci! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nove lozisko uhli nalezene v {TOWN} {STRING}!{}zdvojnasobi produkci! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nove zasoby ropy nalezene v {TOWN} {STRING}!{}zdvojnasobi produkci! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Lepsi metody pestovani {TOWN} {STRING} zdvojnasobi produkci! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} produkce poklesla o 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Zamoreni skudci v {TOWN} {STRING}!{}Produkce poklesla o 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...muze byt umisteno pouze pobliz okraju mapy +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}Produkce {STRING} v {TOWN} {STRING} vzrostla o {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}Produkce {STRING} v {TOWN} {STRING} poklesla o {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Vlak v tunelu +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Silnicni vozidlo v tunelu +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}V ceste je jiny tunel +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Nemohu vyrovnat zemi na druhem konci tunelu +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Nutno nejprve znicit tunel +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Nutno nejprve znicit most +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nelze zacit a skoncit na stejnem miste +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Pod mostem je nutna rovna zeme nebo voda +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Zacatek a konec musi byt v jedne vysce +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Misto nevhodne pro vjezd do tunelu +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Zaveseny, Ocelovy +STR_500F_GIRDER_STEEL :Tramovy, Ocelovy +STR_5010_CANTILEVER_STEEL :Konzolovy, Ocelovy +STR_5011_SUSPENSION_CONCRETE :Zaveseny, Betonovy +STR_5012_WOODEN :Dreveny +STR_5013_CONCRETE :Betonovy +STR_5014_TUBULAR_STEEL :Potrubni, Ocelovy +STR_BRIDGE_TUBULAR_SILICON :Potrubni, Kremikovy +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Zde nelze postavit most... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Zde nelze postavit most... +STR_5017_RAILROAD_TUNNEL :Zeleznicni tunel +STR_5018_ROAD_TUNNEL :Silnicni tunel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Ocelovy zaveseny zeleznicni most +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Ocelovy tramovy zeleznicni most +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Ocelovy konzolovy zeleznicni most +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Zpevneny betonovy zaveseny zeleznicni most +STR_501F_WOODEN_RAIL_BRIDGE :Dreveny zeleznicni most +STR_5020_CONCRETE_RAIL_BRIDGE :Betonovy zeleznicni most +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Ocelovy zaveseny silnicni most +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Ocelovy tramovy silnicni most +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Ocelovy konzolovy silnicni most +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Zpevneny betonovy zaveseny silnicni most +STR_5025_WOODEN_ROAD_BRIDGE :Dreveny silnicni most +STR_5026_CONCRETE_ROAD_BRIDGE :Betonovy silnicni most +STR_5027_TUBULAR_RAIL_BRIDGE :Potrubni zeleznicni most +STR_5028_TUBULAR_ROAD_BRIDGE :Potrubni silnicni most +STR_5029_STEEL :Ocelovy + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}V ceste je objekt +STR_5801_TRANSMITTER :Vysilac +STR_5802_LIGHTHOUSE :Majak +STR_5803_COMPANY_HEADQUARTERS :Reditelstvi spolecnosti +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...v ceste je reditelstvi spolecnosti +STR_5805_COMPANY_OWNED_LAND :Puda vlastnena spolecnosti +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Nelze zakoupit tento pozemek... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...jiz ji vlastnis! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Beze jmena{SKIP} +STR_SV_TRAIN_NAME :Vlak {COMMA16} +STR_SV_ROADVEH_NAME :Silnicni vozidlo {COMMA16} +STR_SV_SHIP_NAME :Lod {COMMA16} +STR_SV_AIRCRAFT_NAME :Letadlo {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} sever +STR_SV_STNAME_SOUTH :{STRING} jih +STR_SV_STNAME_EAST :{STRING} vychod +STR_SV_STNAME_WEST :{STRING} zapad +STR_SV_STNAME_CENTRAL :{STRING} stred +STR_SV_STNAME_TRANSFER :{STRING} prestupni +STR_SV_STNAME_HALT :{STRING} zastavka +STR_SV_STNAME_VALLEY :{STRING} udoli +STR_SV_STNAME_HEIGHTS :{STRING} vysina +STR_SV_STNAME_WOODS :{STRING} polesi +STR_SV_STNAME_LAKESIDE :{STRING} jezero +STR_SV_STNAME_EXCHANGE :{STRING} centrala +STR_SV_STNAME_AIRPORT :{STRING} letiste +STR_SV_STNAME_OILFIELD :{STRING} ropna plosina +STR_SV_STNAME_MINES :{STRING} doly +STR_SV_STNAME_DOCKS :{STRING} pristav +STR_SV_STNAME_BUOY_1 :{STRING} bojka 1 +STR_SV_STNAME_BUOY_2 :{STRING} bojka 2 +STR_SV_STNAME_BUOY_3 :{STRING} bojka 3 +STR_SV_STNAME_BUOY_4 :{STRING} bojka 4 +STR_SV_STNAME_BUOY_5 :{STRING} bojka 5 +STR_SV_STNAME_BUOY_6 :{STRING} bojka 6 +STR_SV_STNAME_BUOY_7 :{STRING} bojka 7 +STR_SV_STNAME_BUOY_8 :{STRING} bojka 8 +STR_SV_STNAME_BUOY_9 :{STRING} bojka 9 +STR_SV_STNAME_ANNEXE :{STRING} pripojne +STR_SV_STNAME_SIDINGS :{STRING} odstavne +STR_SV_STNAME_BRANCH :{STRING} odbocka +STR_SV_STNAME_UPPER :horni {STRING} +STR_SV_STNAME_LOWER :dolni {STRING} +STR_SV_STNAME_HELIPORT :{STRING} heliport +STR_SV_STNAME_FOREST :{STRING} les + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Obtiznost +STR_OPTIONS_SAVE_CHANGES :{BLACK}Ulozit + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Lehka +STR_6802_MEDIUM :{BLACK}Stredni +STR_6803_HARD :{BLACK}Tezka +STR_6804_CUSTOM :{BLACK}Uzivatelska +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maximalni pocet protivniku: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Cas startu protivniku: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Mnozstvi mest: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Mnozstvi prumyslu: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maximalni pocatecni dluh: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Pocatecni urokova sazba: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Cena provozu vozidel: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Rychlost stavby protivnika: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Inteligence protivniku: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Poruchy vozidel: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Cinitel dotaci: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Cena konstrukce: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Typ krajiny: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Kvantita jezer/mori: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Ekonomika: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Otaceni vlaku: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katastrofy: {ORANGE}{STRING} +STR_16816_CITY_APPROVAL :{LTBLUE}Postoj mistni rady k upravam kolem mesta (terennim): {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :nizke +STR_6817_NORMAL :stredni +STR_6818_HIGH :vysoke +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :velmi nizka +STR_681C_SLOW :nizka +STR_681D_MEDIUM :stredne vysoka +STR_681E_FAST :vysoka +STR_681F_VERY_FAST :velmi vysoka +STR_VERY_LOW :velmi nizka +STR_6820_LOW :nizka +STR_6821_MEDIUM :stredni +STR_6822_HIGH :vysoka +STR_6823_NONE :zadne +STR_6824_REDUCED :snizene +STR_6825_NORMAL :bezne +STR_6826_X1_5 :1,5x +STR_6827_X2 :2x +STR_6828_X3 :3x +STR_6829_X4 :4x +STR_682A_VERY_FLAT :velmi plocha +STR_682B_FLAT :plocha +STR_682C_HILLY :kopcovita +STR_682D_MOUNTAINOUS :hornata +STR_682E_STEADY :stabilni +STR_682F_FLUCTUATING :promenliva +STR_6830_IMMEDIATE :okamzite +STR_6831_3_MONTHS_AFTER_PLAYER :3 mesice po hraci +STR_6832_6_MONTHS_AFTER_PLAYER :6 mesicu po hraci +STR_6833_9_MONTHS_AFTER_PLAYER :9 mesicu po hraci +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :na konci trate a ve stanicich +STR_6835_AT_END_OF_LINE_ONLY :pouze na konci trate +STR_6836_OFF :zapnuty +STR_6837_ON :vypnuty +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Zobraz tabulku nejlepsich vysledku +STR_6839_PERMISSIVE :nezaujaty +STR_683A_TOLERANT :tolerantni +STR_683B_HOSTILE :zaujaty + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Hrac 1) +STR_7003_PLAYER_2 : (Hrac 2) +STR_7004_NEW_FACE :{BLACK}Novy oblicej +STR_7005_COLOR_SCHEME :{BLACK}Barva: +STR_7006_COLOR_SCHEME :{GOLD}Barevne schema: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nove barevne schema +STR_7008_COMPANY_NAME :{BLACK}Spolecnost +STR_7009_PRESIDENT_NAME :{BLACK}Prezident +STR_700A_COMPANY_NAME :Jmeno spolecnosti +STR_700B_PRESIDENT_S_NAME :Jmeno prezidenta +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Nemohu zmenit jmeno spolecnosti.. +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Nemohu zmenit jmeno prezidenta... +STR_700E_FINANCES :{WHITE}{STRING} Finance{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Vydaje/Prijmy +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Vystavba +STR_7012_NEW_VEHICLES :{GOLD}Nove dopravni prostredky +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Provoz vlaku +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Provoz silnicnich vozidel +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Provoz letadel +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Provoz lodi +STR_7017_PROPERTY_MAINTENANCE :{GOLD}udrzba +STR_7018_TRAIN_INCOME :{GOLD}Prijmy vlaku +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Prijmy silnicnich vozidel +STR_701A_AIRCRAFT_INCOME :{GOLD}Prijmy letadel +STR_701B_SHIP_INCOME :{GOLD}Prijmy lodi +STR_701C_LOAN_INTEREST :{GOLD}uroky z pujcek +STR_701D_OTHER :{GOLD}Dalsi +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Celkem: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Graf prijmu +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graf provozniho zisku +STR_7026_BANK_BALANCE :{WHITE}Stav konta +STR_7027_LOAN :{WHITE}Pujcka +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Pujcit {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Vratit {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...Maximalni dovolena velikost pujcky je {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemohu pujcit vice penez... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...zadny dluh ke splaceni +STR_702E_REQUIRED :{WHITE}...{CURRENCY} potreba +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Nemohu zaplatit dluh. +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Zvol novy oblicej prezidenta +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Zvol novy nater vozidel spolecnosti +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Zmenit jmeno prezidenta +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Zmenit jmeno spolecnosti +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Stiskni vybrane barevne schema +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Pujcit si vice +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Splatit cast dluhu +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Prezident) +STR_7038_INAUGURATED :{GOLD}Zalozeno: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Vozidla: +STR_703A_TRAIN :{WHITE}{COMMA16} vlak +STR_703B_TRAINS :{WHITE}{COMMA16} vlaku +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} silnicni vozidlo +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} silnicnich vozidel +STR_703E_AIRCRAFT :{WHITE}{COMMA16} letadlo +STR_703F_AIRCRAFT :{WHITE}{COMMA16} letadel +STR_7040_SHIP :{WHITE}{COMMA16} lod +STR_7041_SHIPS :{WHITE}{COMMA16} lodi +STR_7042_NONE :{WHITE}Nic +STR_7043_FACE_SELECTION :{WHITE}Volba tvare +STR_7044_MALE :{BLACK}Muz +STR_7045_FEMALE :{BLACK}Zena +STR_7046_NEW_FACE :{BLACK}Novy oblicej +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Zrusit volbu noveho obliceje +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Potvrdit vyber obliceje +STR_7049_SELECT_MALE_FACES :{BLACK}Zvolit muzske obliceje +STR_704A_SELECT_FEMALE_FACES :{BLACK}Zvolit zenske obliceje +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Vytvorit nahodnou novou tvar +STR_704C_KEY :{BLACK}Legenda +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Ukazat legendu ke grafum +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Legenda ke grafum spolecnosti +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Stiskni zde pro prepnuti zobrazeni spolecnosti na grafu +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Doruceno jednotek zbozi +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Hodnoceni spolecnosti (nejvyssi hodnoceni=1000) +STR_7052_COMPANY_VALUES :{WHITE}Hodnota spolecnosti +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Tabulka poradi spolecnosti +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Dopravni spolecnost ma problemy! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} bude prodana nebo vyhlasi bankrot pokud se brzy nezvysi vykonnost! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Prezident) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Sjednoceni dopravnich spolecnosti! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} byla prodana {STRING} za {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Hledame transporni spolecnost ktera prevezme nasi spolecnost{}{}Chcete zakoupit {STRING} za {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrot! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} byla zavrena veritely a podily byly prodany! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nova spolecnost zalozena! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} zacina stavet pobliz {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Nemohu koupit spolecnost... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Ceny za prepravu zbozi +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Delka prepravy +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Platna za doruceni 10 tun (nebo 10000 litru) zbozi do vzdalenosti 20 ctverecku +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Zapnout/Vypnout graf pro zbozi +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Strojvudce +STR_7067_TRAFFIC_MANAGER :Manazer dopravy +STR_7068_TRANSPORT_COORDINATOR :Koordinator dopravy +STR_7069_ROUTE_SUPERVISOR :Vedouci trasy +STR_706A_DIRECTOR :Reditel +STR_706B_CHIEF_EXECUTIVE :Vykonny reditel +STR_706C_CHAIRMAN :Predseda +STR_706D_PRESIDENT :Prezident +STR_706E_TYCOON :Magnat +STR_706F_BUILD_HQ :{BLACK}Reditelstvi +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Vybudovat reditelstvi spolecnosti / ukazat reditelstvi spolecnosti +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Nemohu postavit reditelstvi spolecnosti +STR_7072_VIEW_HQ :{BLACK}Reditelstvi +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Svetova recese!{}{}Financni experti se obavaji nejhorsiho! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Konec recese!{}{}Zvyseni obchodu dava prumyslu duveru o tom, ze ekonomika posiluje! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Prepnout velke/male okno +STR_7076_COMPANY_VALUE :{GOLD}Hodnota spolecnosti: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Koupit 25% podil ve spolecnosti +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Prodat 25% podil ve spolecnosti +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Koupit 25% podil v teto spolecnosti +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Prodat 25% podil v teto spolecnosti +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemohu koupit 25% podil v teto spolecnosti... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Nemohu prodat 25% podil v teto spolecnosti... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% vlastneno {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% vlastneno {STRING}{} {COMMA16}% vlastneno {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} byla prevzata {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Parni) +STR_8001_MJS_250_DIESEL :MJS 250 (Dieselova) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut (Dieselova) +STR_8006_POWERNAUT_DIESEL :Powernaut (Dieselova) +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Parni) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Parni) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Parni) +STR_800A_SH_8P_STEAM :SH '8P' (Parni) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Dieselova) +STR_800C_DASH_DIESEL :'Dash' (Dieselova) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Dieselova) +STR_800E_UU_37_DIESEL :UU '37' (Dieselova) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Dieselova) +STR_8010_CS_4000_DIESEL :CS 4000 (Dieselova) +STR_8011_CS_2400_DIESEL :CS 2400 (Dieselova) +STR_8012_CENTENNIAL_DIESEL :Centennial (Dieselova) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Dieselova) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Dieselova) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Dieselova) +STR_8016_SH_125_DIESEL :SH '125' (Dieselova) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektricka) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektricka) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektricka) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Electricka) +STR_801B_PASSENGER_CAR :Osobni vagon (Cestujici) +STR_801C_MAIL_VAN :Postovni vagon (Posta) +STR_801D_COAL_CAR :Otevreny vagon (Uhli) +STR_801E_OIL_TANKER :Cisterna (Ropa) +STR_801F_LIVESTOCK_VAN :Uzavreny vagon (Dobytek) +STR_8020_GOODS_VAN :Uzavreny vagon (Zbozi) +STR_8021_GRAIN_HOPPER :Nasypny vagon (Zrni) +STR_8022_WOOD_TRUCK :Vagon (Drevo) +STR_8023_IRON_ORE_HOPPER :Nasypny vagon (Zel. ruda) +STR_8024_STEEL_TRUCK :Vagon (Ocel) +STR_8025_ARMORED_VAN :Obrneny Vagon (Cenniny) +STR_8026_FOOD_VAN :Chlazeny vagon (Ovoce) +STR_8027_PAPER_TRUCK :Vagon (Papir) +STR_8028_COPPER_ORE_HOPPER :Nasypny vagon (Med. ruda) +STR_8029_WATER_TANKER :Cisterna (Voda) +STR_802A_FRUIT_TRUCK :Chlazeny vagon (Ovoce) +STR_802B_RUBBER_TRUCK :Otevreny vagon (Kaucuk) +STR_802C_SUGAR_TRUCK :Vagon na cukr +STR_802D_COTTON_CANDY_HOPPER :Nasypny vagon na cukrovou vatu +STR_802E_TOFFEE_HOPPER :Nasypny vagon na karamel +STR_802F_BUBBLE_VAN :Vagon na bubliny +STR_8030_COLA_TANKER :Cisterna na kolu +STR_8031_CANDY_VAN :Vagon na bonbony +STR_8032_TOY_VAN :Vagon na hracky +STR_8033_BATTERY_TRUCK :Vagon na baterie +STR_8034_FIZZY_DRINK_TRUCK :Vagon na limonady +STR_8035_PLASTIC_TRUCK :Vagon na plasty +STR_8036_X2001_ELECTRIC :'X2001' (Elektricka) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektricka) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Osobni vagon +STR_803A_MAIL_VAN :Postovni vagon +STR_803B_COAL_CAR :Vahon na uhli +STR_803C_OIL_TANKER :Cisterna na ropu +STR_803D_LIVESTOCK_VAN :Vagon na dobytek +STR_803E_GOODS_VAN :Vagon na zbozi +STR_803F_GRAIN_HOPPER :Nasypny vagon na zrni +STR_8040_WOOD_TRUCK :Vagon na drevo +STR_8041_IRON_ORE_HOPPER :Nasypny vagon na zeleznou rudu +STR_8042_STEEL_TRUCK :Vagon na ocel +STR_8043_ARMORED_VAN :Obrneny vagon +STR_8044_FOOD_VAN :Vagon na jidlo +STR_8045_PAPER_TRUCK :Vagon na papir +STR_8046_COPPER_ORE_HOPPER :Nasypny vagon na medenou rudu +STR_8047_WATER_TANKER :Cisterna na vodu +STR_8048_FRUIT_TRUCK :Vagon na ovoce +STR_8049_RUBBER_TRUCK :Vagon na kaucuk +STR_804A_SUGAR_TRUCK :Vagon na cukr +STR_804B_COTTON_CANDY_HOPPER :Nasypny vagon na cukrovou vatu +STR_804C_TOFFEE_HOPPER :Nasypny vagon na karamel +STR_804D_BUBBLE_VAN :Vagon na bubliny +STR_804E_COLA_TANKER :Cisterna na kolu +STR_804F_CANDY_VAN :Vagon na bonbony +STR_8050_TOY_VAN :Vagon na hracky +STR_8051_BATTERY_TRUCK :Vagon na baterky +STR_8052_FIZZY_DRINK_TRUCK :Vagon na limonady +STR_8053_PLASTIC_TRUCK :Vagon na plast +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektricka) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektricka) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektricka) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektricka) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Osobni vagon +STR_805A_MAIL_VAN :Postovni vagon +STR_805B_COAL_CAR :Vagon na uhli +STR_805C_OIL_TANKER :Cisterna na ropu +STR_805D_LIVESTOCK_VAN :Vagon na dobytek +STR_805E_GOODS_VAN :Vagon na zbozi +STR_805F_GRAIN_HOPPER :Nasypny vagon na zrni +STR_8060_WOOD_TRUCK :Vagon na drevo +STR_8061_IRON_ORE_HOPPER :Nasypny vagon na zeleznou rudu +STR_8062_STEEL_TRUCK :Vagon na ocel +STR_8063_ARMORED_VAN :Obrneny vagon +STR_8064_FOOD_VAN :Vagon na jidlo +STR_8065_PAPER_TRUCK :Vagon na papir +STR_8066_COPPER_ORE_HOPPER :Nasypny vagon na medenou rudu +STR_8067_WATER_TANKER :Cisterna na vodu +STR_8068_FRUIT_TRUCK :Vagon na jidlo +STR_8069_RUBBER_TRUCK :Vagon na kaucuk +STR_806A_SUGAR_TRUCK :Vagon na cukr +STR_806B_COTTON_CANDY_HOPPER :Nasypny vagon na cukrovou vatu +STR_806C_TOFFEE_HOPPER :Nasypny vagon na karamel +STR_806D_BUBBLE_VAN :Vagon na bubliny +STR_806E_COLA_TANKER :Cisterna na kolu +STR_806F_CANDY_VAN :Vagon na bonbony +STR_8070_TOY_VAN :Vagon na hracky +STR_8071_BATTERY_TRUCK :Vagon na baterie +STR_8072_FIZZY_DRINK_TRUCK :Vagon na limonady +STR_8073_PLASTIC_TRUCK :Vagon na plasty +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Vuz na uhli +STR_807C_UHL_COAL_TRUCK :Uhl Vuz na uhli +STR_807D_DW_COAL_TRUCK :DW Vuz na uhli +STR_807E_MPS_MAIL_TRUCK :MPS Postovni vuz +STR_807F_REYNARD_MAIL_TRUCK :Reynard Postovni vuz +STR_8080_PERRY_MAIL_TRUCK :Perry Postovni vuz +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postovni vuz +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Postovni vuz +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Postovni vuz +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Cisterna na ropu +STR_8085_FOSTER_OIL_TANKER :Foster Cisterna na ropu +STR_8086_PERRY_OIL_TANKER :Perry Cisterna na ropu +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Vuz na dobytek +STR_8088_UHL_LIVESTOCK_VAN :Uhl Vuz na dobytek +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Vuz na dobytek +STR_808A_BALOGH_GOODS_TRUCK :Balogh Vuz na zbozi +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Vuz na zbozi +STR_808C_GOSS_GOODS_TRUCK :Goss Vuz na zbozi +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Vuz na zrni +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Vuz na zrni +STR_808F_GOSS_GRAIN_TRUCK :Goss Vuz na zrni +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Vuz na drevo +STR_8091_FOSTER_WOOD_TRUCK :Foster Vuz na drevo +STR_8092_MORELAND_WOOD_TRUCK :Moreland Vuz na drevo +STR_8093_MPS_IRON_ORE_TRUCK :MPS Vuz na zeleznou rudu +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Vuz na zeleznou rudu +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Vuz na zeleznou rudu +STR_8096_BALOGH_STEEL_TRUCK :Balogh Vuz na ocel +STR_8097_UHL_STEEL_TRUCK :Uhl Vuz na ocel +STR_8098_KELLING_STEEL_TRUCK :Kelling Vuz na ocel +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Obrneny vuz +STR_809A_UHL_ARMORED_TRUCK :Uhl Obrneny vuz +STR_809B_FOSTER_ARMORED_TRUCK :Foster Obrneny vuz +STR_809C_FOSTER_FOOD_VAN :Foster Vuz na jidlo +STR_809D_PERRY_FOOD_VAN :Perry Vuz na jidlo +STR_809E_CHIPPY_FOOD_VAN :Chippy Vuz na jidlo +STR_809F_UHL_PAPER_TRUCK :Uhl Vuz na papir +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Vuz na papir +STR_80A1_MPS_PAPER_TRUCK :MPS Vuz na papir +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Vuz na medenou rudu +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Vuz na medenou rudu +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Vuz na medenou rudu +STR_80A5_UHL_WATER_TANKER :Uhl Cisterna na vodu +STR_80A6_BALOGH_WATER_TANKER :Balogh Cisterna na vodu +STR_80A7_MPS_WATER_TANKER :MPS Cisterna na vodu +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Vuz na ovoce +STR_80A9_UHL_FRUIT_TRUCK :Uhl Vuz na ovoce +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Vuz na ovoce +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Vuz na kaucuk +STR_80AC_UHL_RUBBER_TRUCK :Uhl Vuz na kaucuk +STR_80AD_RMT_RUBBER_TRUCK :RMT Vuz na kaucuk +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Vuz na cukr +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Vuz na cukr +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Vuz na cukr +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Cisterna na kolu +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Cisterna na kolu +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Cisterna na kolu +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Vuz na cukrovou vatu +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Vuz na cukrovou vatu +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Vuz na cukrovou vatu +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Vuz na karamel +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Vuz na karamel +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Vuz na karamel +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Vuz na hracky +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Vuy na hracky +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Vuz na hracky +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Vuz na bonbony +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Vuz na bonbony +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Vuz na bonbony +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Vuz na baterky +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Vuz na baterky +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Vuz na baterky +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Vuz na limonady +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Vuz na limonady +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Vuz na limonady +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Vuz na plast +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Vuz na plast +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Vuz na plast +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Vuz na bubliny +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Vuz na bubliny +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Vuz na bubliny +STR_80CC_MPS_OIL_TANKER :MPS Ropny tanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Ropny tanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Trajekt pro cestujici +STR_80CF_FFP_PASSENGER_FERRY :FFP Trajekt pro cestujici +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Vznasedlo +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Trajekt pro cestujici +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Trajekt pro cestujici +STR_80D3_YATE_CARGO_SHIP :Yate Nakladni lod +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Nakladni lod +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Nakladni lod +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Nakladni lod +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Vrtulnik Tricairo +STR_80FE_GURU_X2_HELICOPTER :Vrtulnik Guru X2 +STR_80FF_POWERNAUT_HELICOPTER :Vrtulnik Powernaut +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Zprava od vyrobce dopravnich prostredku +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Prave jsme vyvinuli nove (novou) {STRING} - mel bys zajem o rocni vyhradni pravo na pouzivani tohoto dopravniho prostredku, abychom ho mohli otestovat pred zavedenim do provozu? +STR_8102_RAILROAD_LOCOMOTIVE :lokomotivu +STR_8103_ROAD_VEHICLE :automobil +STR_8104_AIRCRAFT :letadlo +STR_8105_SHIP :lod +STR_8106_MONORAIL_LOCOMOTIVE :lokomotivu pro jednokolejku +STR_8107_MAGLEV_LOCOMOTIVE :lokomotivu pro maglev + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}Zeleznicni depo {TOWN} +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Obyvatele oslavuji...{}Prvni vlak dorazil do {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Detaily) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}V ceste je vlak +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Jet do {STATION} +STR_8807_GO_TO_UNLOAD :Jet do {STATION} (Vylozit) +STR_8808_GO_TO_LOAD :Jet do {STATION} (Nalozit) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Jet bez zastaveni do {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Jet bez zastaveni do {STATION} (Vylozit) +STR_880C_GO_NON_STOP_TO_LOAD :Jet bez zastaveni do {STATION} (Nalozit) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Jet do zeleznicniho depa {TOWN} +STR_SERVICE_AT_TRAIN_DEPOT :Udrzba v zeleznicnim depu {TOWN} +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Jet bez zastaveni do zelezniho depa {TOWN} +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Udrzba bez zastaveni v zeleznicnim depu {TOWN} + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Mirim do zeleznicniho depa {TOWN} +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Mirim do zeleznichiho depa {TOWN}, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Prazdny +STR_8813_FROM :{LTBLUE}{CARGO} z {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Vlak {COMMA16} ceka v depu +STR_8815_NEW_VEHICLES :{BLACK}Nova vozidla +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Hmotnost: {GOLD}{COMMA16}t{}{BLACK}Rychlost: {GOLD}{VELOCITY}{BLACK} Vykon: {GOLD}{COMMA16}koni{}{BLACK}Provoz stoji: {GOLD}{CURRENCY}/rok{}{BLACK}Kapacita: {GOLD}{STRING}{}{BLACK}Vyvinuto: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} let{}{BLACK}Max. spolehlivost: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informace +STR_8819_TRAIN_TOO_LONG :{WHITE}Prilis dlouhy vlak +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Vlaky lze menit pouze pokud stoji uvnitr depa +STR_881B_TRAINS :{WHITE}{STRING} - Vlaky +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nove lokomotivy a vagony +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nove lokomotivy a vagony pro jednokolejku +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nove lokomotivy a vagony pro maglev +STR_881F_BUILD_VEHICLE :{BLACK}Koupit vuz +STR_8820_RENAME :{BLACK}Prejmenovat +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Cena: {GOLD}{CURRENCY}{}{BLACK}Hmotnost: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapacita: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Preskocit +STR_8824_DELETE :{BLACK}Smazat +STR_8825_NON_STOP :{BLACK}Nonstop +STR_8826_GO_TO :{BLACK}Jet do +STR_8827_FULL_LOAD :{BLACK}Nalozit +STR_8828_UNLOAD :{BLACK}Vylozit +STR_8829_ORDERS :{WHITE}{STRING} (Prikazy) +STR_882A_END_OF_ORDERS :{SETX 10}- - Konec prikazu - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Udrzba +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Nemohu koupit vagon/lokomotivu... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Koupeno: {LTBLUE}{NUMU16}{BLACK} Hodnota: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Hodnota: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Nakladani / Vykladani +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Nelze poslat vlak do depa... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Nedostatek prostoru na prikazy +STR_8832_TOO_MANY_ORDERS :{WHITE}Prilis mnoho prikazu +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Nemohu vlozit novy prikaz +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Nemohu tento prikaz smazat... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Nemohu tento prikaz zmenit... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Musis nejprve postavit depo +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Nemohu presunout vozidlo... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Nemohu prodat vagon/lokomotivu... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Nemohu najit cestu do mistniho depa... +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Nemohu rozjet/zastavit vlak... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Interval servisu: {LTBLUE}{COMMA16}dni{BLACK} Posledni servis: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaky - stiskni na vlaku pro informace +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Kupovat nove vlaky (vyzaduje vlakove depo) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaky - stiskni na vlaku pro info, presun vagon pro pridani ci odebrani z vlaku +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Koupit novy vagon/lokomotivu +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Presun sem vagon pro prodej +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Nastav pohled na vlakove depo +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Seznam vlaku - stiskni na vlaku pro informace +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Kup oznaceny vagon/lokomotivu +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Prejmenovat typ vlaku +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Momentalni akce vlaku - stiskni pro zastaveni/rozjeti vlaku +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Ukaz prikazy vlaku +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Nastav pohled na vlak +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Posli vlak do depa +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Donut vlak prokracovat bez cekani na povoleni od semaforu +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Otocit vlak +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Ukazat detaily vlaku +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Zvysit interval servisu +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Snizit interval servisu +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Ukazat detaily prepravovaneho zbozi +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Ukazat detaily jednotlivych vagonu +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Ukazat kapacity jednotlivych vagonu +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Ukazat celkovou kapacitu vlaku, rozdelenou dle nakladu +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Seznam prikazu - stiskni prikaz pro oznaceni +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Preskocit prikaz a jit na dalsi +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Smazat oznaceny prikaz +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Provest oznaceny prikaz bez zastaveni +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Vlozit novy prikaz pred oznaceny prikaz nebo na konec seznamu +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Oznaceny prikaz provadet do plneho nalozeni +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Oznaceny prikaz vylozi vozidlo +STR_SERVICE_HINT :{BLACK}Preskoc tento cil pokud neni potreba pravidelna udrzba +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nyni k dispozici dalsi {STRING} ! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cena: {CURRENCY} Hmotnost: {COMMA16}t{}Rychlost: {VELOCITY} Vykon: {COMMA16}koni{}Cena provozu: {CURRENCY}/rok{}Kapacita: {STRING} +STR_885C_BROKEN_DOWN :{RED}Porucha +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena provozu: {LTBLUE}{CURRENCY}/rok +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Hmotnost: {LTBLUE}{COMMA16}t {BLACK}Vykon: {LTBLUE}{COMMA32}koni{BLACK} Max. rychlost: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Prijem tento rok: {LTBLUE}{CURRENCY} (minuly rok: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Spolehlivost: {LTBLUE}{COMMA8}% {BLACK}Poruch od posledniho serivisu: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Zastaveno +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemohu vlak nechat projet semafory v nebezpeci... +STR_8863_CRASHED :{RED}Nehoda! + +STR_8865_NAME_TRAIN :{WHITE}Pojmenovat vlak +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Nelze pojmenovat vlak... +STR_8867_NAME_TRAIN :{BLACK}Pojmenovat vlak +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Vlakove nestesti!{}{COMMA16} lidi zemrelo po srazce v plamenech +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Nemohu zmenit smer vlaku... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Prejmenovat typ zeleznicniho vozidla +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Nemohu prejmenovat typ zeleznicniho vozidla... + +STR_TRAIN_STOPPING :{RED}Zastavuje +STR_TRAIN_STOPPING_VEL :{RED}Zastavuje, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Automobil v ceste +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Automobily +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}Garaze pro automobily {TOWN} +STR_9004_NEW_VEHICLES :{BLACK}Nove automobily +STR_9005_INFORMATION :{BLACK}Informace +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nove automobily +STR_9007_BUILD_VEHICLE :{BLACK}Koupit automobil +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Cena provozu: {GOLD}{CURRENCY}/rok{}{BLACK}Kapacita: {GOLD}{STRING}{}{BLACK}Vyvinuto: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} let{}{BLACK}Max. spolehlivost: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nemohu koupit novy automobil... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Musis nejprve postavit garaze +STR_900B_ORDERS :{WHITE}{STRING} (Prikazy) +STR_900C_DETAILS :{WHITE}{STRING} (Detaily) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena provozu: {LTBLUE}{CURRENCY}/yr +STR_900E_MAX_SPEED :{BLACK}Max. rychlost: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Prijem tento rok: {LTBLUE}{CURRENCY} (minuly rok): {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Spolehlivost: {LTBLUE}{COMMA8}% {BLACK}Poruch od posledniho servisu: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Koupen: {LTBLUE}{NUMU16}{BLACK} Cena: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...musi byt zastaven v garazi +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Nemohu prodat automobil... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Nemohu zastavit/rozjet automobil... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Automobil {COMMA16} ceka v garazi +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Mirim do garaze {TOWN} +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Mirim do garaze {TOWN} , {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Nemohu poslat automobil do garaze... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nemohu najit mistni garaz +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Automobily - stiskni vozidlo pro informace +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Koupit nove automobily (vyzaduje garaze) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Momentalni akce automobilu - stiskni pro zastaveni/rozjeti vozidla +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Ukaz prikazy vozidla +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Nastav pohled na vozidlo +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Posli vozidlo do garaze +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Otoc vozidlo +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Ukaz detaily automobilu +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Vozidla - stiskni vozidlo pro informace +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Koupit novy automobil +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Presun sem automobil k prodeji +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Nastav pohled na garaz +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Seznam automobilu - stiskni vozidlo pro informace +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Koupit oznacene vozidlo +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Novy automobil k dispozici! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Cena: {CURRENCY}{}Rychlost: {VELOCITY}{}Cena provozu: {CURRENCY}/rok{}Kapacita: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Prejmenovat automobil +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Nelze prejmenovat automobil... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Prejmenovat automobil +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Obyvatele oslavuji . . .{}Prvni autobus prijel do {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Obyvatele oslavuji . . .{}Prvni nakladni vuz prijel do {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Dopravni nehoda!{}Ridic zemrel v plamenech po srazce s vlakem +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Dopravni nehoda!{}{COMMA16} lidi zemrelo v plamenech po srazce s vlakem +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Nelze otocit vozidlo... +STR_9034_RENAME :{BLACK}Prejmenovat +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Prejmenovat typ automobilu +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Prejmenovat typ automobilu +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Nelze prejmenovat typ automobilu... +STR_9038_GO_TO_ROADVEH_DEPOT :Jet do garaze {TOWN} +STR_SERVICE_AT_ROADVEH_DEPOT :Udrzba v garazi {TOWN} + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Konstrukce pristavu +STR_9801_DOCK_CONSTRUCTION :{WHITE}Konstrukce pristavu +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Zde nelze postavit pristav... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Suchy dok +STR_9804_NEW_SHIPS :{BLACK}Nove lode +STR_9805_SHIPS :{WHITE}{STRING} - Lode +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Nemohu koupit lod... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Nejprve musis postavit suchy dok +STR_9808_NEW_SHIPS :{WHITE}Nove lode +STR_9809_BUILD_SHIP :{BLACK}Koupit lod +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Kapacita: {GOLD}{STRING} {STRING}{}{BLACK}Cena provozu: {GOLD}{CURRENCY}/rok{}{BLACK}Vyvinuto: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} let{}{BLACK}Max. Spolehlivost: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Lod musi byt zastavena v doku +STR_980C_CAN_T_SELL_SHIP :{WHITE}Nelze prodat lod... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Nelze koupit lod... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Lod v ceste +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Prikazy) +STR_9811_DETAILS :{WHITE}{STRING} (Detaily) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena provozu: {LTBLUE}{CURRENCY}/rok +STR_9813_MAX_SPEED :{BLACK}Max. rychlost: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Prijem tento rok: {LTBLUE}{CURRENCY} (minuly rok: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Spolehlivost: {LTBLUE}{COMMA8}% {BLACK}Poruch od posledniho servisu: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Koupeno: {LTBLUE}{NUMU16}{BLACK} Cena: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Nelze rozjet/zastavit lod... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Nelze poslat lod do doku... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nemohu najit mistni dok +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Mirim do doku {TOWN} +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Mirim do doku {TOWN}, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Lod {COMMA16} ceka v doku +STR_981D_BUILD_SHIP_DOCK :{BLACK}Postavit pristavni molo +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Postavit suchy dok ( pro nakup a servis lodi ) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Lode - stiskni lod pro informace +STR_9820_BUILD_NEW_SHIP :{BLACK}Koupit novou lod +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Pretahnout lod sem pro prodej +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Nastavit pohled na suchy dok +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Lode - stiskni lod pro informace +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Koupit nove lode ( vyzaduje suchy dok ) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Seznam lodi - stiskni lod pro informace +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Koupit oznacenou lod +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Cinnost lodi - stiskni pro rozjeti/zastaveni lodi +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Ukazat prikazy lodi +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Nastavit pohled na lod +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Poslad lod do doku +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Ukazat detaily lodi +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nova lod k dispozici! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. rychlost: {VELOCITY}{}Kapacita: {STRING}{}Cena provozu: {CURRENCY}/rok +STR_982F_NAME_SHIP :{BLACK}Prejmenovat lod + +STR_9831_NAME_SHIP :{WHITE}Prejemnovat lod +STR_9832_CAN_T_NAME_SHIP :{WHITE}Nelze prejmenovat lod... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Obyvatele oslavuji . . .{}Prvni lod pristala v {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Umistit bojku, kterou lze pouzit jako navigacni bod +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Zde nelze umistit bojku... +STR_9836_RENAME :{BLACK}Prejmenovat +STR_9837_RENAME_SHIP_TYPE :{BLACK}Prejmenovat typ lodi +STR_9838_RENAME_SHIP_TYPE :{WHITE}Prejmenovat typ lodi +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Nelze prejmenovat typ lodi... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Prestavet pro prevazeni jineho druhu nakladu +STR_983B_REFIT :{WHITE}{STRING} (Prestavet) +STR_983C_REFIT_SHIP :{BLACK}Prestavet +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Zvolit druh nakladu ktery bude lod prevazet +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Prestavet pro prevoz oznaceneho nakladu +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Zvolit druh nakladu:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova kapacita: {GOLD}{STRING}{}{BLACK}Cena prestavby: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Nelze prestavet lod... +STR_9842_REFITTABLE :(lze prestavet) +STR_GO_TO_SHIP_DEPOT :Poslat do doku {TOWN} +SERVICE_AT_SHIP_DEPOT :Udrzba v doku {TOWN} + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Stavba letiste. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Zde nelze postavit letiste... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Letistni hangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nove letadlo +STR_A004_INFORMATION :{BLACK}Informace +STR_A005_NEW_AIRCRAFT :{WHITE}Nove letadlo +STR_A006_BUILD_AIRCRAFT :{BLACK}Koupit letadlo +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Kapacita: {GOLD}{COMMA16} cestujicich, {COMMA16} baliku posty{}{BLACK}Cena provozu: {GOLD}{CURRENCY}/rok{}{BLACK}Vyvinuto: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} let{}{BLACK}Max. Spolehlivost: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Nelze koupit letadlo... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Letadlo +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Prikazy) +STR_A00C_DETAILS :{WHITE}{STRING} (Detaily) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena provozu: {LTBLUE}{CURRENCY}/rok +STR_A00E_MAX_SPEED :{BLACK}Max. rychlost: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Prijem tento rok: {LTBLUE}{CURRENCY} (minuly rok: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Spolehlivost: {LTBLUE}{COMMA8}% {BLACK}Poruch od posledniho servisu: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Koupeno: {LTBLUE}{NUMU16}{BLACK} Cena: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Nelze poslat letadlo do hangaru... +STR_HEADING_FOR_HANGAR :{LTBLUE}Mirim do hangaru {STATION} +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Mirim do hangaru {STATION} , {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Letadlo {COMMA16} ceka v hangaru +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Letadlo v ceste +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Nemohu rozjet/zastavit letadlo... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Letadlo leti +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Musis nejprve postavit letiste +STR_A019_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Letadlo musi byt zastaveno v hangaru +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Nelze prodat letadlo... +STR_A01D_AIRPORT_CONSTRUCTION :Stavba letiste +STR_A01E_BUILD_AIRPORT :{BLACK}Postavit letiste +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Letadlo - stiskni letadlo pro informace +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Koupit nove letadlo (vyzaduje letiste s hangarem) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Letadlo - stiskni letadlo pro informace +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Koupit nove letadlo +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Presun sem letadlo k prodeji +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Nastavit pohled na hangar +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Seznam letadel - stiskni letadlo pro informace +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Koupit oznacene letadlo +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Cinnost letadla - stiskni pro rozjeti/zastaveni letadla +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Ukazat prikazy letadla +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Nastavit pohled na letadlo +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Poslat letadlo do hangaru +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Ukazat detaily letadla +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nove letadlo k dispozici! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. rychlost: {VELOCITY}{}Kapacita: {COMMA16} cestujicich, {COMMA16} baliku posty{}Cena provozu: {CURRENCY}/rok + +STR_A030_NAME_AIRCRAFT :{WHITE}Prejmenovat letadlo +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Nelze prejmenovat letadlo +STR_A032_NAME_AIRCRAFT :{BLACK}Prejmenovat letadlo +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Obyvatele oslavuji . . .{}Prvni letadlo pristalo v {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Pad letadla!{}{COMMA16} zemrelo v plamenech v {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Cile: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Prejmenovat +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Prejmenovat typ letadla +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Prejmenovat typ letadla +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Nelze prejmenovat typ letadla... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Prestavet letadlo pro prevoz jineho typu nakladu +STR_A03C_REFIT :{WHITE}{STRING} (Prestavet) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Prestavet letadlo +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Zvolit typ nakladu pro letadlo +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Prestavet letadlo pro prevoz oznaceneho typu nakladu +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Zvolit typ nakladu pro prevoz:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova kapacita: {GOLD}{STRING}{}{BLACK}Cena prestavby: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Nelze prestavet letadlo.... +STR_A043_REFITTABLE :(lze prestavet) +STR_GO_TO_AIRPORT_HANGAR :Poslat do hangaru {STATION} +SERVICE_AT_AIRPORT_HANGAR :Udrzba v hangaru {STATION} + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin se zritil v {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Silnicni vozidlo zniceno pri srazce s UFO! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Vybuch ropne rafinerie pobliz {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Za podezrelych okolnosti byla znicena tovarna pobliz {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}UFO pristalo pobliz {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Pokles terenu u uhelneho dolu {TOWN} zpusobil velke skody! + +STR_BRIBE_FAILED :{WHITE}Tvuj pokus o uplatek byl +STR_BRIBE_FAILED_2 :{WHITE}odhalen mistnim vysetrovatelem. diff --git a/lang/danish.txt b/lang/danish.txt new file mode 100644 --- /dev/null +++ b/lang/danish.txt @@ -0,0 +1,2356 @@ +##name Danish +##ownname Dansk + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Ude over kanten af kortet +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}For tæt på kanten af kortet +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Ikke nok penge - kræver {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Landet skal være flat +STR_0008_WAITING :{BLACK}Venter: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (på vej fra +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accepterer: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accepterer: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passagerer +STR_0010_COAL :Kul +STR_0011_MAIL :Post +STR_0012_OIL :Olie +STR_0013_LIVESTOCK :Kvæg +STR_0014_GOODS :Stykgods +STR_0015_GRAIN :Korn +STR_0016_WOOD :Træ +STR_0017_IRON_ORE :Jern Malm +STR_0018_STEEL :Stål +STR_0019_VALUABLES :Værdigendstande +STR_001A_COPPER_ORE :Kobber Malm +STR_001B_MAIZE :Majs +STR_001C_FRUIT :Frugt +STR_001D_DIAMONDS :Diamands +STR_001E_FOOD :Mad +STR_001F_PAPER :Papir +STR_0020_GOLD :Guld +STR_0021_WATER :Vand +STR_0022_WHEAT :Hvede +STR_0023_RUBBER :Gummi +STR_0024_SUGAR :Sukker +STR_0025_TOYS :Legetøj +STR_0026_CANDY :Slik +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Candyfloss +STR_0029_BUBBLES :Bobler +STR_002A_TOFFEE :Karamel +STR_002B_BATTERIES :Batterier +STR_002C_PLASTIC :Plastik +STR_002D_FIZZY_DRINKS :Brusende Drinks +STR_002E : +STR_002F_PASSENGER :Passager +STR_0030_COAL :Kul +STR_0031_MAIL :Post +STR_0032_OIL :Olie +STR_0033_LIVESTOCK :Kvæg +STR_0034_GOODS :Stykgods +STR_0035_GRAIN :Korn +STR_0036_WOOD :Træ +STR_0037_IRON_ORE :Jern Malm +STR_0038_STEEL :Stål +STR_0039_VALUABLES :Værdigendstand +STR_003A_COPPER_ORE :Kobber Malm +STR_003B_MAIZE :Majs +STR_003C_FRUIT :Frugt +STR_003D_DIAMOND :Diamand +STR_003E_FOOD :Mad +STR_003F_PAPER :Papir +STR_0040_GOLD :Guld +STR_0041_WATER :Vand +STR_0042_WHEAT :Hvede +STR_0043_RUBBER :Gummi +STR_0044_SUGAR :Sukker +STR_0045_TOY :Legetøj +STR_0046_CANDY :Slik +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Candyfloss +STR_0049_BUBBLE :Boble +STR_004A_TOFFEE :Karamel +STR_004B_BATTERY :Batteri +STR_004C_PLASTIC :Plastik +STR_004D_FIZZY_DRINK :Brusende Drink +STR_004E : +STR_004F_PASSENGER :{COMMA16} passager +STR_0050_TON_OF_COAL :{COMMA16} ton kul +STR_0051_BAG_OF_MAIL :{COMMA16} sæk post +STR_0052_OF_OIL :{VOLUME} olie +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} stk. kvæg +STR_0054_CRATE_OF_GOODS :{COMMA16} kasse gods +STR_0055_TON_OF_GRAIN :{COMMA16} ton korn +STR_0056_TON_OF_WOOD :{COMMA16} ton træ +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton jern malm +STR_0058_TON_OF_STEEL :{COMMA16} ton stål +STR_0059_BAG_OF_VALUABLES :{COMMA16} sæk værdigendstande +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tons kobber malm +STR_005B_TON_OF_MAIZE :{COMMA16} ton majs +STR_005C_TON_OF_FRUIT :{COMMA16} ton frugt +STR_005D_BAG_OF_DIAMONDS :{COMMA16} sæk diamanter +STR_005E_TON_OF_FOOD :{COMMA16} ton mad +STR_005F_TON_OF_PAPER :{COMMA16} ton papir +STR_0060_BAG_OF_GOLD :{COMMA16} sæk guld +STR_0061_OF_WATER :{VOLUME} vand +STR_0062_TON_OF_WHEAT :{COMMA16} ton hvede +STR_0063_OF_RUBBER :{VOLUME} gummi +STR_0064_TON_OF_SUGAR :{COMMA16} ton sukker +STR_0065_TOY :{COMMA16} legetøj +STR_0066_BAG_OF_CANDY :{COMMA16} sæk slik +STR_0067_OF_COLA :{VOLUME} cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton candyfloss +STR_0069_BUBBLE :{COMMA16} boble +STR_006A_TON_OF_TOFFEE :{COMMA16} ton karamel +STR_006B_BATTERY :{COMMA16} batteri +STR_006C_OF_PLASTIC :{VOLUME} plastik +STR_006D_FIZZY_DRINK :{COMMA16} sodavand +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passagerer +STR_0070_TONS_OF_COAL :{COMMA16} tons kul +STR_0071_BAGS_OF_MAIL :{COMMA16} sække post +STR_0072_OF_OIL :{VOLUME} olie +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} stk. kvæg +STR_0074_CRATES_OF_GOODS :{COMMA16} kasser gods +STR_0075_TONS_OF_GRAIN :{COMMA16} tons korn +STR_0076_TONS_OF_WOOD :{COMMA16} tons træ +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tons jern malm +STR_0078_TONS_OF_STEEL :{COMMA16} tons stål +STR_0079_BAGS_OF_VALUABLES :{COMMA16} sække værdigendstande +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tons kobber malm +STR_007B_TONS_OF_MAIZE :{COMMA16} tons majs +STR_007C_TONS_OF_FRUIT :{COMMA16} tons frugt +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} sække diamanter +STR_007E_TONS_OF_FOOD :{COMMA16} tons mad +STR_007F_TONS_OF_PAPER :{COMMA16} tons papir +STR_0080_BAGS_OF_GOLD :{COMMA16} sække guld +STR_0081_OF_WATER :{VOLUME} vand +STR_0082_TONS_OF_WHEAT :{COMMA16} tons hvede +STR_0083_OF_RUBBER :{VOLUME} gummi +STR_0084_TONS_OF_SUGAR :{COMMA16} tons sukker +STR_0085_TOYS :{COMMA16} legetøj +STR_0086_BAGS_OF_CANDY :{COMMA16} sække slik +STR_0087_OF_COLA :{VOLUME} cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tons candyfloss +STR_0089_BUBBLES :{COMMA16} bobler +STR_008A_TONS_OF_TOFFEE :{COMMA16} tons karamel +STR_008B_BATTERIES :{COMMA16} batterier +STR_008C_OF_PLASTIC :{VOLUME} plastik +STR_008D_FIZZY_DRINKS :{COMMA16} sodavand +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Kort - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Spilindstillinger +STR_00B2_MESSAGE :{YELLOW}Besked +STR_00B3_MESSAGE_FROM :{YELLOW}Besked Fra {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Det kan jeg ikke.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kan ikke rydde området.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, Alle retigheder reserveret +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Originalt design af Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafik af Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Afslut +STR_00C8_YES :{BLACK}Ja +STR_00C9_NO :{BLACK}Nej +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil afslutte dette spil og returnere til {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Ingenting +STR_00D1_DARK_BLUE :Mørk Blå +STR_00D2_PALE_GREEN :Lys Grøn +STR_00D3_PINK :Lyserød +STR_00D4_YELLOW :Gul +STR_00D5_RED :Rød +STR_00D6_LIGHT_BLUE :Lys Blå +STR_00D7_GREEN :Grøn +STR_00D8_DARK_GREEN :Mørk Grøn +STR_00D9_BLUE :Blå +STR_00DA_CREAM :Lys Brun +STR_00DB_MAUVE :Mauve +STR_00DC_PURPLE :Lilla +STR_00DD_ORANGE :Orange +STR_00DE_BROWN :Brun +STR_00DF_GREY :Grå +STR_00E0_WHITE :Hvid +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}For mange køretøjer i spillet +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Placering +STR_00E5_CONTOURS :Konturer +STR_00E6_VEHICLES :Køretøjer +STR_00E7_INDUSTRIES :Industrier +STR_00E8_ROUTES :Router +STR_00E9_VEGETATION :Vegetation +STR_00EA_OWNERS :Ejere +STR_00EB_ROADS :{BLACK}{TINYFONT}Veje +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Jernbaner +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stationer/Lufthavne/Havne +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Bygninger/Industrier +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Køretøjer +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Toge +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Lastbiler +STR_00F7_SHIPS :{BLACK}{TINYFONT}Skibe +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Fly +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transport Router +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kulmine +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Kraftværk +STR_00FC_FOREST :{BLACK}{TINYFONT}Skov +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Savværk +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Olieraffinaderi +STR_00FF_FARM :{BLACK}{TINYFONT}Bondegård +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabrik +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Trykkeri +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Olieboring +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Jernmalmsmine +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Stålværk +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papirmølle +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Guldmine +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Fødevareindustri +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamandmine +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kobbermalmsmine +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Frugtplantage +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Gummiplantage +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vandforsyning +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vandtårn +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Træfabrik +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Candyfloss skov +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Slikfabrik +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batterigård +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Colabrønd +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Legetøjsforretning +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Legetøjsfabrik +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastikspringvand +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Sodavandsfabrik +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Boblegenerator +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamelbrud +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Sukkermine +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Togstation +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Lasteplads +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Rutebilsstation +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Lufthavn/Helikopterplads +STR_011F_DOCK :{BLACK}{TINYFONT}Havn +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Hårdt terræn +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Grass +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Bart terræn +STR_0123_FIELDS :{BLACK}{TINYFONT}Marker +STR_0124_TREES :{BLACK}{TINYFONT}Træer +STR_0125_ROCKS :{BLACK}{TINYFONT}Klipper +STR_0126_WATER :{BLACK}{TINYFONT}Vand +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Ingen Ejer +STR_0128_TOWNS :{BLACK}{TINYFONT}Byer +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrier +STR_012A_DESERT :{BLACK}{TINYFONT}Ørken +STR_012B_SNOW :{BLACK}{TINYFONT}Sne +STR_012C_MESSAGE :{WHITE}Besked +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Annuler +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Omdøb +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}For mange navne defineret +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Valgte navn er allerede i brug + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (miles) +STR_013A_METRIC_KILOMETERS :Meter (kilometer) +STR_013B_OWNED_BY :{WHITE}...ejes af {STRING} +STR_013C_CARGO :{BLACK}Last +STR_013D_INFORMATION :{BLACK}Information +STR_013E_CAPACITIES :{BLACK}Lasteevner +STR_013E_TOTAL_CARGO :{BLACK}Samlet last +STR_013F_CAPACITY :{BLACK}Lasteevne: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Samlet last (lasteevne) på dette tog: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nyt Spil +STR_0141_LOAD_GAME :{BLACK}Hent Spil +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demonstration +STR_0143_1_PLAYER :{BLACK}1 Spiller +STR_0144_2_PLAYERS :{BLACK}2 Spillere + +STR_0148_GAME_OPTIONS :{BLACK}Spilindstillinger + +STR_0150_SOMEONE :en eller anden{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Kort over verden +STR_0152_TOWN_DIRECTORY :Byoversigt +STR_0153_SUBSIDIES :Special aftaler + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Graf over profit +STR_0155_INCOME_GRAPH :Graf over indkomster +STR_0156_DELIVERED_CARGO_GRAPH :Graf over afleveret last +STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf over præstation +STR_0158_COMPANY_VALUE_GRAPH :Graf over selskabsværdi +STR_0159_CARGO_PAYMENT_RATES :Graf over last udbetalingsrater +STR_015A_COMPANY_LEAGUE_TABLE :Selskabsoversigt +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Gem Spil +STR_015D_LOAD_GAME :Hent Spil +STR_015E_QUIT_GAME :Afslut Spil +STR_015F_QUIT :Afslut +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil afslutte dette spil ? +STR_0161_QUIT_GAME :{WHITE}Afslut Spil + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :Maj +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Oct +STR_016C_NOV :Nov +STR_016D_DEC :Dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pause spillet +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Gem spillet, afslut spillet, afslut +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis en liste over selskabets stationer +STR_0174_DISPLAY_MAP :{BLACK}Vis kortet +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Vis kortet, byoversigt +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Vis byoversigten +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Vis selskabets finans information +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Vis general selskabsinformation +STR_0179_DISPLAY_GRAPHS :{BLACK}Vis grafer +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Vis selskabsoversigten +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over selskabets tog +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over selskabets lastbiler +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over selskabets skibe +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over selskabets fly +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Zoom skærmen ind +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Zoom skærmen ud +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Byg jernbanespor +STR_0182_BUILD_ROADS :{BLACK}Byg veje +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Byg havne +STR_0184_BUILD_AIRPORTS :{BLACK}Byg lufthavne +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plant træer, placer skilte osv. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Landområde information +STR_0187_OPTIONS :{BLACK}Indstillinger +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Kan ikke ændre service interval... +STR_018B_CLOSE_WINDOW :{BLACK}Luk vindue +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Vindue title - træk her for at flytte vindue +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}nedriver bygning osv. på et stykke land +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Sænk et hjørne af landet +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Hæv et hjørne af landet +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scroll bar - scroller listen op/ned +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Vis land konturer på kortet +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Vis køretøjer på kortet +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Vis industrier på kortet +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Vis transportruter på kortet +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Vis vegetation på kortet +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Vis land ejere på kortet +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Tænd/Sluk bynavne +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Dette års profit: {CURRENCY} (sidste år: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} år ({COMMA16}) +STR_019A_YEARS :{COMMA16} år ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} år ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Lastbil +STR_019D_AIRCRAFT :Fly +STR_019E_SHIP :Skibe +STR_019F_TRAIN :Tog +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} er ved at være for gammel +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} er alt for gammel +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} er alt for gammel og burde blive udskiftet straks +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Land område information +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Pris for at rydde: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Pris for at rydde: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Ejer: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Lokal myndighed: {LTBLUE}{STRING} +STR_01A9_NONE :Ingen +STR_01AA_NAME :{BLACK}Navn +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1. +STR_01AD_2ND :2. +STR_01AE_3RD :3. +STR_01AF_4TH :4. +STR_01B0_5TH :5. +STR_01B1_6TH :6. +STR_01B2_7TH :7. +STR_01B3_8TH :8. +STR_01B4_9TH :9. +STR_01B5_10TH :10. +STR_01B6_11TH :11. +STR_01B7_12TH :12. +STR_01B8_13TH :13. +STR_01B9_14TH :14. +STR_01BA_15TH :15. +STR_01BB_16TH :16. +STR_01BC_17TH :17. +STR_01BD_18TH :18. +STR_01BE_19TH :19. +STR_01BF_20TH :20. +STR_01C0_21ST :21. +STR_01C1_22ND :22. +STR_01C2_23RD :23. +STR_01C3_24TH :24. +STR_01C4_25TH :25. +STR_01C5_26TH :26. +STR_01C6_27TH :27. +STR_01C7_28TH :28. +STR_01C8_29TH :29. +STR_01C9_30TH :30. +STR_01CA_31ST :31. +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Skift mellem stor/lille kort størrelse +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Vælg Tutorial/Demonstration + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Accepteret last: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Accepteret last: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Accepteret last: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Lyd/Musik +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Vis lyd/musik vindue +STR_01D5_ALL :{TINYFONT}Alle +STR_01D6_OLD_STYLE :{TINYFONT}Old Style +STR_01D7_NEW_STYLE :{TINYFONT}New Style +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Custom 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Custom 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Musik lydstyrke +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Effekt lydstyrke +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAKS +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Hop til forrige nummer +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Hop til næste nummer +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Stop med at spille musik +STR_01E1_START_PLAYING_MUSIC :{BLACK}Start musikken +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Flyt slideren for at justere musik og effekt lydstyrken +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Nummer{SETX 88}Titel +STR_01E9_SHUFFLE :{TINYFONT}Bland +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programmer +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Musik Program Valg +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Nummer Index +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Ryd +STR_01F1_SAVE :{TINYFONT}{BLACK}Gem +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Nuværende musikprogram valg +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Vælg 'Alle numre' programmet +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Vælg 'Old style musik' programmet +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Vælg 'New style musik' programmet +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Vælg 'Custom 1' (brugerdefineret) programmet +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select 'Custom 2' (brugerdefineret) programmet +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Ryd det valgte program (Gælder kun Custom1/Custom2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Gem musik indstillinger til disken +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klik på et musiknummer for at tilføje det til programlisten (Kun for Custom1/Custom2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Skift mellem tilfældig afspilning af/på +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vis musiknummer valg vinduet +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klik på servicen for at centrere skærmen over industrien/byen +STR_01FE_DIFFICULTY :{BLACK}Sværhedsgrad ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Sidste Besked/Nyheds rapport +STR_0201_MESSAGE_SETTINGS :Besked Indstillinger +STR_MESSAGE_HISTORY_MENU :Tidligere beskeder +STR_0202_SEND_MESSAGE :Send besked +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Vis sidste besked/nyheds rapport, vis besked indstillinger +STR_0204_MESSAGE_OPTIONS :{WHITE}Besked Indstillinger +STR_0205_MESSAGE_TYPES :{BLACK}Besked typer:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Andkomst af første køretøj til spillerens station +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Andkomst af første køretøj til modstanderens station +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Uheld / katastrofer +STR_0209_COMPANY_INFORMATION :{YELLOW}Firma information +STR_020A_ECONOMY_CHANGES :{YELLOW}Økonomi ændringer +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Rådgivning / information om spillerens køretøjer +STR_020C_NEW_VEHICLES :{YELLOW}Nye køretøjer +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Ændring i accepteret last +STR_020E_SUBSIDIES :{YELLOW}Special aftaler +STR_020F_GENERAL_INFORMATION :{YELLOW}General information +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...for langt fra forrige destination +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Bedste firmaer der nåede til år 2050{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Forretningsmand +STR_0214_ENTREPRENEUR :Entreprenør +STR_0215_INDUSTRIALIST :Industrialist +STR_0216_CAPITALIST :Kapitalist +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Århundredes Matador +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} opnår '{STRING}' status! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} af {STRING} opnår '{STRING}' status! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Lav et scenarie +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Scenarieeditor +STR_0223_LAND_GENERATION :{WHITE}Land Generation +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Tilfældig Land +STR_0227_RESET_LAND :{BLACK}Nulstil Land +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Forstår området af land der skal sænkes/hæves +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Formindsk området af land der skal sænkes/hæves +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Generer tilføldig land +STR_022B_RESET_LANDSCAPE :{BLACK}Nulstil landskab +STR_022C_RESET_LANDSCAPE :{WHITE}Nulstil Landskab +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Er du sikker på du vil nulstille landskabet? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Landskabs generering +STR_022F_TOWN_GENERATION :{BLACK}By generering +STR_0230_INDUSTRY_GENERATION :{BLACK}Industri generering +STR_0231_ROAD_CONSTRUCTION :{BLACK}Bygning af vej +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetation og andre objekter +STR_0233_TOWN_GENERATION :{WHITE}By Generering +STR_0234_NEW_TOWN :{BLACK}Ny By +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Byg en ny by +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Kan ikke bygge en by her... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...for tæt på kanten af kortet +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...for tæt på en anden by +STR_0239_SITE_UNSUITABLE :{WHITE}...ikke brugbar placering +STR_023A_TOO_MANY_TOWNS :{WHITE}...for mange byer +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Forøg størrelsen af byen +STR_023C_EXPAND :{BLACK}Udvid +STR_023D_RANDOM_TOWN :{BLACK}Tilføldig by +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Byg en by på en tilfældig placering +STR_023F_INDUSTRY_GENERATION :{WHITE}Industri Generering +STR_0240_COAL_MINE :{BLACK}Kulmine +STR_0241_POWER_STATION :{BLACK}kraftværk +STR_0242_SAWMILL :{BLACK}Savværk +STR_0243_FOREST :{BLACK}Skov +STR_0244_OIL_REFINERY :{BLACK}Olieraffinaderi +STR_0245_OIL_RIG :{BLACK}Boreplatform +STR_0246_FACTORY :{BLACK}Fabrik +STR_0247_STEEL_MILL :{BLACK}Stålværk +STR_0248_FARM :{BLACK}Bondegård +STR_0249_IRON_ORE_MINE :{BLACK}Jernmalmsmine +STR_024A_OIL_WELLS :{BLACK}Olieborring +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Papirmølle +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Fødevareindustri +STR_024E_PRINTING_WORKS :{BLACK}Trykkeri +STR_024F_GOLD_MINE :{BLACK}Guldmine +STR_0250_LUMBER_MILL :{BLACK}Træfabrik +STR_0251_FRUIT_PLANTATION :{BLACK}Frugtplantage +STR_0252_RUBBER_PLANTATION :{BLACK}Gummiplantage +STR_0253_WATER_SUPPLY :{BLACK}Vandforsyning +STR_0254_WATER_TOWER :{BLACK}Vandtårn +STR_0255_DIAMOND_MINE :{BLACK}Diamandmine +STR_0256_COPPER_ORE_MINE :{BLACK}Kobbermalmsmine +STR_0257_COTTON_CANDY_FOREST :{BLACK}Candyfloss Skov +STR_0258_CANDY_FACTORY :{BLACK}Slikfabrik +STR_0259_BATTERY_FARM :{BLACK}Batterigård +STR_025A_COLA_WELLS :{BLACK}Cola Brånd +STR_025B_TOY_SHOP :{BLACK}Legetøjsforretning +STR_025C_TOY_FACTORY :{BLACK}Legetøjsfabrik +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastikspringvand +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Sodavandsfabrik +STR_025F_BUBBLE_GENERATOR :{BLACK}Boblegenerator +STR_0260_TOFFEE_QUARRY :{BLACK}Karamelbrud +STR_0261_SUGAR_MINE :{BLACK}Sukkermine +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Byg Kulmine +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Byg Kraftværk +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Byg Savværk +STR_0265_PLANT_FOREST :{BLACK}Plant Skov +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Byg Olieraffinaderi +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Byg Boreplatform (Kan kun bygges tæt på kanten af kortet) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Byg Fabrik +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Byg Stålværk +STR_026A_CONSTRUCT_FARM :{BLACK}Byg Bondegårg +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Byg Jernmalmsmine +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Byg Olieborring +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Byg Bank (Kan kun bygges i en by med mere en 1200 indbyggere) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Byg Papirmølle +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Byg Fødevareindustri +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Byg Trykkeri +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Byg Guldmine +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Byg Bank (Kan kun bygges i en by) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Byg Træfabrik (for at ryde regnskoven og producere træ) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plant Frugtplantage +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plant Gummiplantage +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Byg Vandforsyning +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Byg Vandtårn (Kan kun bygges i byer) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Byg Diamandmine +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Byg Kobbermalmsmine +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plant Candyfloss Skov +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Byg Slikfabrik +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Byg Batterigård +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Byg Colabrønd +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Byg Legetøjsforretning +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Byg Legetøjsfabrik +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Byg Plastikspringvand +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Byg Sodavandsfabrik +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Byg Boblegenerator +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Byg Karamelbrud +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Byg Sukkermine +STR_0285_CAN_T_BUILD_HERE :{WHITE}Kan ikke bygge {STRING} her... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...det er nødvendigt at bygge en by først +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...kun en tilladt per by +STR_0288_PLANT_TREES :{BLACK}Plant træer +STR_0289_PLACE_SIGN :{BLACK}Placer skilt +STR_028A_RANDOM_TREES :{BLACK}Tilfældige Træer +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Plant træer tilfældigt på landskabet +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Placer klippeområder på landskabet +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Placer fyrtårn +STR_028E_PLACE_TRANSMITTER :{BLACK}Placer transmitter +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definer ørkenområde +STR_0290_DELETE :{BLACK}Slet +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Slet denne by fuldstændigt +STR_0292_SAVE_SCENARIO :Gem scenarie +STR_0293_LOAD_SCENARIO :Hent scenarie +STR_0294_QUIT_EDITOR :Afslut editoren +STR_0295 : +STR_0296_QUIT :Afslut +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Gem scenarie, hent scenarie, forlad scenarie editoren, aflsut +STR_0298_LOAD_SCENARIO :{WHITE}Hent et scenarie +STR_0299_SAVE_SCENARIO :{WHITE}Gem scenarie +STR_029A_PLAY_SCENARIO :{BLACK}Spil et scenarie +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil afslutte dette scenarie ? +STR_029C_QUIT_EDITOR :{WHITE}Afslut Editoren +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan kun bygges i byer med mindst 1200 indbyggere +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Flyt start datoen tilbage 1 år +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Flyt start datoen frem 1 år +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...begge ender af en bro skal være på land +STR_02A1_SMALL :{BLACK}Lille +STR_02A2_MEDIUM :{BLACK}Mellem +STR_02A3_LARGE :{BLACK}Stor +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Vælg bystørrelse +STR_02A5_TOWN_SIZE :{YELLOW}Bystørrelse: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Vis sidste besked eller nyheds rapport +STR_02B8_SUMMARY :{BLACK}Resume +STR_02B9_FULL :{BLACK}Fuldt +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Byoversigt +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Køretøjsdesignnavne +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Standard +STR_02BF_CUSTOM :Brugerdefineret +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Gem brugerdefinerede navne til disken +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Køretøjsdesignnavne valg +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Gem brugerdefinerede køretøjsdesignnavne til disken + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Spilidstillinger +STR_02C4_GAME_OPTIONS :Spilindstillinger +STR_02C5_DIFFICULTY_SETTINGS :Sværhedsgrad +STR_02C6_DIFFICULTY_SETTINGS :Sværhedsgrad +STR_02C7_CONFIG_PATCHES :Indstil patches +STR_02C8_CONFIG_PATCHES :Indstil patches +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Bynavne vist +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Bynavne vist +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Stationsnavne vist +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Stationsnavne vist +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Skilte vist +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Skilte vist +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Checkpoints vist +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Checkpoints vist +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Fuld animation +STR_02D0_FULL_ANIMATION :{SETX 12}Fuld animation +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Fuld detalje +STR_02D2_FULL_DETAIL :{SETX 12}Fuld detalje +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Gennemsigtige bygninger +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Gennemsigtige bygninger +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Landområde information +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Screenshot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Kæmpe Screenshot (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Om 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}Til +STR_02DB_OFF :{BLACK}Fra +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Vis specialaftaler +STR_02DD_SUBSIDIES :Specialaftaler +STR_02DE_MAP_OF_WORLD :Kort over verden +STR_02DF_TOWN_DIRECTORY :Byoversigt +STR_02E0_CURRENCY_UNITS :{BLACK}Valutaenhed +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Valutaenhed selection +STR_02E3_DISTANCE_UNITS :{BLACK}Afstandsenhed +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Afstandsenhed selection +STR_02E6_ROAD_VEHICLES :{BLACK}Lastbiler +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Vælg den side lsatbiler skal køre i +STR_02E9_DRIVE_ON_LEFT :Kør i venstre side +STR_02EA_DRIVE_ON_RIGHT :Kør i højre side +STR_02EB_TOWN_NAMES :{BLACK}Bynavne +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Vælg bynavne stil + +STR_02F4_AUTOSAVE :{BLACK}Autogem +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Vælg interval imellem automatisk gemning +STR_02F7_OFF :Off +STR_02F8_EVERY_3_MONTHS :Hver 3. måned +STR_02F9_EVERY_6_MONTHS :Hver 6. måned +STR_02FA_EVERY_12_MONTHS :Hver 12. måned +STR_02FB_START_A_NEW_GAME :{BLACK}Start et nyt spil +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Hent et gemt spil fra disken +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Se demonstrationer/tutorials +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Lav en brugerdefineret verden/scenarie +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Vælg singleplayer spil +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Vælg tospiller spil +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Vis spilindstillinger +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Vis sværhedsgrad indstillinger +STR_0303_START_A_NEW_GAME_USING :{BLACK}Start et nyt spil, med et brugerdefineret scenarie +STR_0304_QUIT :{BLACK}Afslut +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Forlad 'OpenTTD', og aflsut +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Se demonstration/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan kun bygges i byer +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Select 'tempereret' landskab +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Select 'sub-arktisk' landskab +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Select 'sub-tropisk' landskab +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Select 'legetøjsland' landskab +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Betal for bygningen af nye industrier + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Opfør en ny industri +STR_INDUSTRY_DIR :Industrioversigt +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Opfør ny industri +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan kun bygges i byer +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...kan kun bygges i regnskovsområder +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kan kun bygges i ørkenområder +STR_0319_PAUSED :{YELLOW}* * PAUSE * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot gemt '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Fejl under tagning af screenshot! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Køb land til senere brug +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Lastbilsservice +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Togservice +STR_032C_3_AIR_SERVICE :{BLACK}3: Flyservice +STR_032D_4_SHIP_SERVICE :{BLACK}4: Skibsservice +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Togservice (avanceret) +STR_032F_AUTOSAVE :{RED}AUTOSAVE +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Vælg 'Ezy Street musik' program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Engelske +STR_TOWNNAME_FRENCH :Franske +STR_TOWNNAME_GERMAN :Tyske +STR_TOWNNAME_AMERICAN :Amerikanske +STR_TOWNNAME_LATIN_AMERICAN :Latin-Amerikanske +STR_TOWNNAME_SILLY :Fjollede +STR_TOWNNAME_SWEDISH :Svenske +STR_TOWNNAME_DUTCH :Hollandske +STR_TOWNNAME_FINNISH :Finske +STR_TOWNNAME_POLISH :Polske +STR_TOWNNAME_SLOVAKISH :Slovakiske +STR_TOWNNAME_HUNGARIAN :Ungarske +STR_TOWNNAME_AUSTRIAN :Østrigske +############ end of townname region + +STR_CURR_POUNDS :Pund ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollar ($) +STR_CURR_FF :Franc (FF) +STR_CURR_DM :Deutschmark (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseta (Pt) +STR_CURR_FT :Ungarsk Forint (Ft) +STR_CURR_ZL :Polsk Zloty (zl) +STR_CURR_ATS :Østrisk Shilling (ATS) +STR_CURR_BEF :Belgisk Franc (BEF) +STR_CURR_DKK :Danske Kroner (DKK) +STR_CURR_FIM :Finske Markka (FIM) +STR_CURR_GRD :Græske Drachmer (GRD) +STR_CURR_CHF :Sweiziske Franc (CHF) +STR_CURR_NLG :Hollandske Guilder (NLG) +STR_CURR_ITL :Italienske Lire (ITL) +STR_CURR_SEK :Svenske Kroner (SEK) +STR_CURR_RUR :Russiske Rubel (rur) +STR_CURR_CZK :Tjekkiske Koruna (CZK) +STR_CURR_ISK :Islandske Kroner (ISK) +STR_CURR_NOK :Norske Kroner (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Sprog +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Vælg sprog til brugerfladen + +STR_OPTIONS_RES :{BLACK}Skærmopløsning +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Vælg skørmopløsning + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Screenshot format +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Vælg det format til screenshots + +STR_AUTOSAVE_1_MONTH :Hver måned +STR_AUTOSAVE_FAILED :{WHITE}Fejl under autogem + +STR_MONTH_JAN :Januar +STR_MONTH_FEB :Februar +STR_MONTH_MAR :Marts +STR_MONTH_APR :April +STR_MONTH_MAY :Maj +STR_MONTH_JUN :Juni +STR_MONTH_JUL :Juli +STR_MONTH_AUG :August +STR_MONTH_SEP :September +STR_MONTH_OCT :Oktober +STR_MONTH_NOV :November +STR_MONTH_DEC :December + +STR_HEADING_FOR_STATION :{LTBLUE}Retning mod {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Retning mod {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Ingen ordre +STR_NO_ORDERS_VEL :{LTBLUE}Ingen ordre, {VELOCITY} + +STR_PASSENGERS :passagerer +STR_BAGS :sække +STR_TONS :ton +STR_LITERS :liter +STR_ITEMS :stykker +STR_CRATES :kasser +STR_RES_OTHER :andet +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Kan ikke dele ordreliste... +STR_CANT_COPY_ORDER_LIST :{WHITE}Kan ikke kopiere ordreliste... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Slut på delt ordreliste - - + +STR_TRAIN_IS_LOST :{WHITE}Tog {COMMA16} er faret vild. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Tog {COMMA16}'s profit sidste år var {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Indstil Patches +STR_CONFIG_PATCHES_TIP :{BLACK}Indstil Patchesne +STR_CONFIG_PATCHES_CAPTION :{WHITE}Indstil Patches + +STR_CONFIG_PATCHES_OFF :Fra +STR_CONFIG_PATCHES_ON :Til +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Vis køretøjets fart i statusbaren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Tillad bygning på skråninger og kyster: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Tillad nedriving af industribygninger, flere veje, osv: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Aktiver bygning af meget lange tog: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Aktiver realistisk acceleration af tog: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Foren togstationer der bygges ved siden af hinanden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Forlad stationen hvis en slags last bliver fyldt, hvis 'fuld last': {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Ingen automatisk servicering af tog: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Aflever kun last til en station hvis der er en forespørgsel: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Tillad bygning af meget lange broer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Tillad go til depot ordrer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Tillad opførslen af råmateriale industrier: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Tillad flere af samme slags industri per by: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Tillad at flere af samme slags industri kan være tæt på hinanden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Vis altid lang dato i statusbaren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Vis signaler i kørselssiden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Vis finansvinduet i slutningen af året: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch kombatibel nonstop håndtering: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Kø dannelse af lastbiler (med kvante effekt): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Pannorer vindue når musen er ved kanten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Tillad bestikkelse af de lokale myndigheder: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Find nyt depot: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Ikke uniforme stationer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Ny stifindingsalgoritme til tog: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Tillad at bygge mens pause er aktiveret: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Tillad altid små lufthavne: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Et tog er væk hvis der ikke forekommer fremskridt inden for: {ORANGE}{STRING} dage +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Advar hvis et tog har underskud: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Automatisk udskiftning af køretøjer, når de bliver gamle +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Levetid for fejlmeddelser: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Snelinjehøjden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maks stations spredning: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Automatisk service på helikopterlandingspladser: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maks antal tog per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maks antal lastbiler per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maks antal fly per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maks antal skibe per spiller: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Deaktiver tog for computeren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Deaktiver lastbiler for computeren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Deaktiver fly for computeren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Deaktiver skibe for computeren: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Standard serviceinterval for tog: {ORANGE}{STRING} dage +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Standard serviceinterval for lastbiler: {ORANGE}{STRING} dage +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Standard serviceinterval for fly: {ORANGE}{STRING} dage +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Standard serviceinterval for skibe: {ORANGE}{STRING} dage + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Farvede nyheder dukker op i: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Start dato: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Aktiver rolig økonomi (flere små ændringer) + +STR_CONFIG_PATCHES_GUI :{BLACK}Brugerflade +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstruktion +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Køretøjer +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stationer +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Økonomi + +STR_CONFIG_PATCHES_DISABLED :deaktiveret +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Skift indstillingsværdi + +STR_CHEATS :{WHITE}Snydefunktioner +STR_CHEATS_TIP :{BLACK}Checkboxes viser om du bruger denne snydefunktion before +STR_CHEATS_WARNING :{BLACK}Advarsel! Du er ved at forråde dine modstandere. Husk at dette vil blive husket i al evighed. +STR_CHEAT_MONEY :{LTBLUE}Forøg kassebeholdning med {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Spil som spiller: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magisk bulldozer (nedriv ting, som normalt ikke kan fjernes): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunneler kan krydse hinanden: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Navn +STR_TOWNDIR_POPULATION :{BLACK}Indbyggertal +STR_TOWNDIR_SORT_TIP :{BLACK}Vælg sorteringsrækkefølge + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Retning mod {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Retning mod {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Via {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Checkpoint {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Checkpoint {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Checkpoint + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Ændrer checkpointets navn + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Kan ikke ændre checkpointets navn... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Konverter togskinner til checkpoint +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Kan ikke bygge et togcheckpoint her... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Kan ikke fjerne et togcheckpoint her... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Byg togskinner ved hjælp af autotogskinner mode + +STR_TREES_RANDOM_TYPE :{BLACK}Træer af tilfældig type +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Placer træer af tilfældig type + +STR_CANT_BUILD_CANALS :{WHITE}Kan ikke bygge en kanal her... +STR_BUILD_CANALS_TIP :{BLACK}Byg kanaler +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Kan ikke bygge en sluse her... +STR_BUILD_LOCKS_TIP :{BLACK}Byg sluser +STR_LANDINFO_LOCK :Sluse + +STR_LANDINFO_COORDS :{BLACK}Koordinater: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Kan ikke fjerne en del af en station... +STR_CANT_CONVERT_RAIL :{WHITE}Kan ikke konvertere togskinnetype her... +STR_CONVERT_RAIL_TIP :{BLACK}Konverter/Opgrader typen af togskinner + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Træk lokomotivet her for at sælge hele toget + +STR_DRAG_DROP :{BLACK}Træk & slip +STR_STATION_DRAG_DROP :{BLACK}Byg en station via træk & slip + +STR_FAST_FORWARD :{BLACK}Kør spillet hurtigere +STR_MESSAGE_HISTORY :{WHITE}Tidligere beskeder + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Byg Kulmine +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plant Skov +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Byg Boreplatform +STR_CONSTRUCT_FARM_TIP :{BLACK}Opfør en bondegård +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Byg Kobbermalmsmine +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Bor efter olie +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Byg Guldmine +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Byg Diamandmine +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Byg Jernmalmsmine +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Opfør Frugtplantage +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Opfør Gummiplantage +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Opfør Vandforsyning +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plant Candyfloss Skov +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Opfør Batterigård +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Bor efter Cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Opfør Plastikspringvand +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Byg Boblegenerator +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Opfør Karamelbrud +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Byg Sukkermine + +STR_INDUSTRYDIR_NAME :{BLACK}Navn +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produktion +STR_INDUSTRYDIR_TYPE :{BLACK}Type +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrier +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...for tæt på en anden industribygning + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Ombyg toget til at køre med en anden slags last +STR_RAIL_REFIT :{WHITE}{STRING} (Ombyg) +STR_RAIL_REFIT_VEHICLE :{BLACK}Ombyg toget +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vælg den slags last toget skal køre med +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Ombyg toget til at køre med den markerede slags last +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Kan ikke ombygge toget... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Pris: {CURRENCY} +STR_0801_COST :{RED}Pris: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Indkomst: {CURRENCY} +STR_0803_INCOME :{GREEN}Indkomst: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Andslået Pris: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Andslået Pris: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Andslået Indkomst: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Andslået Indkomst: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Kan ikke hæve landet her... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Kan ikke sænke landet her... +STR_080A_ROCKS :Klipper +STR_080B_ROUGH_LAND :Barskt land +STR_080C_BARE_LAND :Bart land +STR_080D_GRASS :Gras +STR_080E_FIELDS :Marker +STR_080F_SNOW_COVERED_LAND :Snedækket land +STR_0810_DESERT :Ørken + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Landet hælder i den forkerte retning +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Umulig sporkombination +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Udgravning ville skade en tunnel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Allerede ved havoverfladen +STR_1004_TOO_HIGH :{WHITE}For højt +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Ingen brugbare togskinner +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Der er et tog i remisen +STR_1007_ALREADY_BUILT :{WHITE}...allerede bygget +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Det er nødvendigt at fjerne togskinnerne først +STR_1009_TOO_MANY_DEPOTS :{WHITE}For mange depoter +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Togskinne Konstruktion +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Monorail Konstruktion +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Magnetskinnetog Konstruktion +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Vælg togbro +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Kan ikke bygge en remise her... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Kan ikke bygge en togstation her... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Kan ikke bygge signaler her... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Kan ikke bygge togskinner her... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Kan ikke fjerne togksinner herfra... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Kan ikke fjerne signaler herfra... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Retning for remise +STR_1015_RAILROAD_CONSTRUCTION :Togskinne konstruktion +STR_1016_MONORAIL_CONSTRUCTION :Monorail Konstruktion +STR_1017_MAGLEV_CONSTRUCTION :Magnetskinnetog konstruktion +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Byg togskinner +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Byg en remise (til at bygge og servicere tog) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Byg togstation +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Byg signaler +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Byg bro +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Byg tunnel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Skift mellem bygning/fjerning af togskinner og signaler +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Valg af bro - klik på den valgte bro for at bygge den +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Vælg orientering af remise +STR_1021_RAILROAD_TRACK :Togskinner +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Togskinner med signaler +STR_1023_RAILROAD_TRAIN_DEPOT :Remise +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...området ejes af et andet firma +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Togskinner med almindelige signaler +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Togskinner med indkørselssignaler +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Togskinner med udkørselssignaler +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Togskinner med kombineret ind- og udkørselssignaler + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Landet hælder i en forkert retning til byggning af vej +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Det er nødvendigt at fjerne vejen først +STR_1802_ROAD_CONSTRUCTION :{WHITE}Vej Konstruktion +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Vælg vejbro +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Kan ikke bygge vej her... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Kan ikke fjerne vej herfra... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientering af lastbilsdepot +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan ikke bygge lastbilsdepot her... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Kan ikke bygge rutebilsstation... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kan ikke bygge lasteplads... +STR_180A_ROAD_CONSTRUCTION :Vej konstruktion +STR_180B_BUILD_ROAD_SECTION :{BLACK}Byg en sektion vej +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Byg lastbilsdepot (til servicering og bygning af lastbiler) +STR_180D_BUILD_BUS_STATION :{BLACK}Byg rutebilsstation +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Byg lasteplads +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Byg bro +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Byg tunnel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Skift mellem bygning/fjerning af veje +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Valg af bro - klik på en brotype for at bygge den +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Vælg erienteringen af lastbilsdepot +STR_1814_ROAD :Vej +STR_1815_ROAD_WITH_STREETLIGHTS :Vej med gadelygter +STR_1816_TREE_LINED_ROAD :Alle +STR_1817_ROAD_VEHICLE_DEPOT :Lastbilsdepot +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Jernbaneoverskærring + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Byer +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Det er nødvendigt at nedrive bygningen først +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Indbyggere: {ORANGE}{COMMA32}{BLACK} Huse: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Omdøb Byen +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Kan ikke omdøbe byen... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} de lokale myndigheder nægter at tillade dette +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Bynavne - klik på et navn for at centrere skærmen over byen +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrer skærmen over byens placering +STR_200C_CHANGE_TOWN_NAME :{BLACK}Ændrer navnet på byen +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagerer sidste måned: {ORANGE}{COMMA16}{BLACK} maks: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Post sidste måned: {ORANGE}{COMMA16}{BLACK} maks: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Høj kontorbygning +STR_2010_OFFICE_BLOCK :Kontorbygning +STR_2011_SMALL_BLOCK_OF_FLATS :Lille lejlighedskomplex +STR_2012_CHURCH :Kirke +STR_2013_LARGE_OFFICE_BLOCK :Stor kontorbygning +STR_2014_TOWN_HOUSES :Villaer +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Statue +STR_2017_FOUNTAIN :Springvand +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kontorbygning +STR_201A_SHOPS_AND_OFFICES :Forretninger og kontorer +STR_201B_MODERN_OFFICE_BUILDING :Moderne kontorbygning +STR_201C_WAREHOUSE :Varehus +STR_201D_OFFICE_BLOCK :Kontorbygning +STR_201E_STADIUM :Stadium +STR_201F_OLD_HOUSES :Gamle huse +STR_2020_LOCAL_AUTHORITY :{BLACK}Lokale myndigheder +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Vis information omkring de lokale myndigheder +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} lokal myndighed +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Transportselskabsbedømmelse: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Specialaftaler +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Specialaftaler til udlicitering:- +STR_2027_FROM_TO :{ORANGE}{STRING} fra {STRING} til {STRING} +STR_2028_BY :{YELLOW} (inden {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Ingen +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Specialaftaler der allerede er vundet:- +STR_202C_FROM_TO :{ORANGE}{STRING} fra {STATION} til {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, indtil {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Specialaftale udløbet:{}{}{STRING} fra {STRING} til {STRING} vil ikke længere udløse en bonus. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Tilbud om specialaftale tilbagetrukket:{}{}{STRING} fragt fra {STATION} til {STATION} er ikke længere til udlicitering. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Tilbud om specialaftale:{}{}Første {STRING} fragt fra {STRING} til {STRING} vil udløse et års bonus kontrakt med de lokale myndigheder! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Specialaftale tildelt {STRING}!{}{}{STRING} fragt fra {STATION} til {STATION} vil give 50% mere i de næste 12 måneder! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Specialaftale tildelt {STRING}!{}{}{STRING} fragt fra {STATION} til {STATION} vil give dobbelt udbytte i de næste 12 måneder! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Specialaftale tildelt {STRING}!{}{}{STRING} fragt fra {STATION} til {STATION} vil give tredobbelt udbytte i de næste 12 måneder! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Specialaftale tildelt {STRING}!{}{}{STRING} fragt fra {STATION} til {STATION} vil give firedobbelt udbytte i de næste 12 måneder! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} de lokale myndigheder nægter at der bliver bygget en lufthavn mere i byen +STR_2036_COTTAGES :Hytter +STR_2037_HOUSES :Huse +STR_2038_FLATS :Lejligheder +STR_2039_TALL_OFFICE_BLOCK :Høj kontorbygning +STR_203A_SHOPS_AND_OFFICES :Forretninger og kontorer +STR_203B_SHOPS_AND_OFFICES :Forretninger og kontorer +STR_203C_THEATER :Teater +STR_203D_STADIUM :Stadium +STR_203E_OFFICES :Kontorer +STR_203F_HOUSES :Huse +STR_2040_CINEMA :Biograf +STR_2041_SHOPPING_MALL :Indkøbscenter +STR_2042_DO_IT :{BLACK}Gør det +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Liste af ting der kan gøres i denne by - klik på en ting for yderligere detaljer +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Udfør den markerede ting i listen ovenover +STR_2045_ACTIONS_AVAILABLE :{BLACK}Handlinger til Rådighed: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Lille reklamekampagne +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Mellem reklamekampagne +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Stor reklamekampagne +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Betal for lokal vejfornyelse +STR_204A_BUILD_STATUE_OF_COMPANY :Byg en statue af selskabets ejer +STR_204B_FUND_NEW_BUILDINGS :Betal for opførslen af nye bygninger +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Køb eksklusive transport rettigheder i byen +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Bestik de lokale myndigheder +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en lille reklamekampagne, for at tiltrække flere passagerer og last til dine stationer.{} Pris: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en mellem reklamekampagne, for at tiltrække flere passagerer og last til dine stationer.{} Pris: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en stor reklamekampagne, for at tiltrække flere passagerer og last til dine stationer.{} Pris: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Betal for vejfornyelse i midtbyen. Laver stor forstyrrelse af vejnettet i de næste 6 måneder.{} Pris: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Byg en statue til ære for dit firma.{} Pris: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Betal for bygning af kommercielle bygninger i byen.{} Pris: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Køb et års eksklusive rettigheder til transport i byen. De lokale myndigheder vil kun tillade passagerer og last at bruge dine stationer.{} Prist: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Bestik de lokale myndigheder til at høve din bedømmelse, med sandsynlighed for en stor straf hvis det bliver opdaget.{} Pris: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Kan ikke gøre dette... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Trafikkaos i byen {TOWN}!{}{}Vejfornyelse betalt af {STRING} bringer 6 måneders kaos for trafikken! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (under konstruktion) +STR_2059_IGLOO :Iglo +STR_205A_TEPEES :Tipi +STR_205B_TEAPOT_HOUSE :Tepottehus +STR_205C_PIGGY_BANK :Sparegris + +##id 0x2800 +STR_2800_PLANT_TREES :Plant træer +STR_2801_PLACE_SIGN :Placer skilt +STR_2802_TREES :{WHITE}Træer +STR_2803_TREE_ALREADY_HERE :{WHITE}...der er allerede træer her +STR_2804_SITE_UNSUITABLE :{WHITE}...placeringen er ikke egnet +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Kan ikke plante træer her... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...for mange skilte +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Kan ikke placere skilt her... +STR_280A_SIGN :Skilt +STR_280B_EDIT_SIGN_TEXT :{WHITE}Ændre skiltets tekst +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Kan ikke ændre navnet på skiltet... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Vælg typen af træer der skal plantes +STR_280E_TREES :Træer +STR_280F_RAINFOREST :Regnskov +STR_2810_CACTUS_PLANTS :Kaktusplanter + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Valg af togstation +STR_3001_AIRPORT_SELECTION :{WHITE}Valg af lufthavn +STR_3002_ORIENTATION :{BLACK}Orientering +STR_3003_NUMBER_OF_TRACKS :{BLACK}Antal spor +STR_3004_PLATFORM_LENGTH :{BLACK}Længden af platformen +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}For tæt på en anden togstation +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grænser op til mere end en eksisterende station/lasteplads +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}For mange stationer/lastepladser i denne by +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}For mange stationer/lastepladser +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}For tæt på en anden station/lasteplads +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Det er nødvendigt at rive stationen ned først +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}For tæt på en anden lufthavn +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Det er nødvendigt at rive lufthavnen ned først + +STR_3030_RENAME_STATION_LOADING :Omdøb stationen/lastepladsen +STR_3031_CAN_T_RENAME_STATION :{WHITE}Kan ikke omdøbe stationen... +STR_3032_RATINGS :{BLACK}Bedømmelse +STR_3033_ACCEPTS :{BLACK}Accepterer +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Lokal bedømmelse af transportservice: + +############ range for rating starts +STR_3035_APPALLING :Rædselsfuld +STR_3036_VERY_POOR :Meget Dårlig +STR_3037_POOR :Dårlig +STR_3038_MEDIOCRE :Middel +STR_3039_GOOD :God +STR_303A_VERY_GOOD :Meget God +STR_303B_EXCELLENT :Fortrinlig +STR_303C_OUTSTANDING :Enestående +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} accepterer ikke længere {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} accepterer ikke længere {STRING} eller {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} accepterer nu {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} accepterer nu {STRING} og {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Rutebilsstation Orientering +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Lastbilslasteplads Orientering. +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}For tæt på en anden rutebilsstation +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}For tæt på en anden lastbilslasteplads +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Det er nødvendigt at rive rutebilsstationen ned først +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Det er nødvendigt at rive lastbilslastepladsen ned først +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stationer +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Ingen - +STR_304B_SITE_UNSUITABLE :{WHITE}...placeringen er uegnet +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}For tæt på en anden havn +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Det er nødvendigt at rive havnen ned først +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Vælg orienteringen af togstationen +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Vælg antallet af platforme togstationen har +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Vælg længden af togstationen +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Vælg orienteringen af rutebilsstationen +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Vælg orienteringen af lastbilslastepladsen +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centrer skærmen over stationens placering +STR_3054_SHOW_STATION_RATINGS :{BLACK}Vis stationens bedømmelse +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Ændrer stationens navn +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Vis liste over accepteret last +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Stationsnavne - klik på et navn for at centrere skærmen over stationen +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Vælg lufthavnens størrelse/type +STR_3059_SMALL :{BLACK}Lille +STR_305A_LARGE :{BLACK}Stor +STR_305AA_LARGE :{BLACK}National lufthavn +STR_305AB_LARGE :{BLACK}International lufthavn +STR_305B_SIZE :{BLACK}Størrelse +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Togstation +STR_305F_AIRCRAFT_HANGAR :Lufthavnshangar +STR_3060_AIRPORT :Lufthavn +STR_3061_TRUCK_LOADING_AREA :Lastbilslasteplads +STR_3062_BUS_STATION :Rutebilsstation +STR_3063_SHIP_DOCK :Havn +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Marker dækningsområdet af den foreslåede placering +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Marker ikke dækningsområdet af den foreslåede placering +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Markering af dækningsområdet +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Valg af Monorail Station +STR_3068_DOCK :{WHITE}Havn +STR_3069_BUOY :Bøje +STR_306A_BUOY_IN_THE_WAY :{WHITE}...der er en bøje i vejen +STR_306B_HELIPORT :{BLACK}Helikopterplads +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stationen er for spredt + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Skibsdepot Orientering +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...skal bygges på vand +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Kan ikke bygge et skibsdepot her... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Vælg orienteringen af skibsdepotet +STR_3804_WATER :Vand +STR_3805_COAST_OR_RIVERBANK :Kyst eller flodbred +STR_3806_SHIP_DEPOT :Skibsdepot +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...kan ikke bygge på vand + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Gem Spil +STR_4001_LOAD_GAME :{WHITE}Hent Spil +STR_4002_SAVE :{BLACK}Gem +STR_4003_DELETE :{BLACK}Slet +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes fri +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Kan ikke læse drevet +STR_4007_GAME_SAVE_FAILED :{WHITE}Fejl under gemning af spil +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Kan ikke slette fil +STR_4009_GAME_LOAD_FAILED :{WHITE}Fejl under hentning af spil +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Liste over drev, biblioteker og gemte spilfiler +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Nuværende gemte spils navn +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Slet det valgte gemte spil +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Gem det nuværende spil, med det valgte navn +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Vælg Spiltype til Nyt Spil +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Vælg scenarie (grøn), predefineret spil (blå), eller nyt tilfældigt spil +STR_4010_GENERATE_RANDOM_NEW_GAME :Generer nyt tilfældigt spil + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} i vejen +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kulmine +STR_4803_POWER_STATION :Kraftværk +STR_4804_SAWMILL :Savværk +STR_4805_FOREST :Skov +STR_4806_OIL_REFINERY :Olieraffinaderi +STR_4807_OIL_RIG :Boreplatform +STR_4808_FACTORY :Fabrik +STR_4809_PRINTING_WORKS :Trykkeri +STR_480A_STEEL_MILL :Stålværk +STR_480B_FARM :Bondegård +STR_480C_COPPER_ORE_MINE :Kobbermalmsmine +STR_480D_OIL_WELLS :Olieborring +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Fødevareindustri +STR_4810_PAPER_MILL :Papirmølle +STR_4811_GOLD_MINE :Guldmine +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamandmine +STR_4814_IRON_ORE_MINE :Jernmalmsmine +STR_4815_FRUIT_PLANTATION :Frugtplantage +STR_4816_RUBBER_PLANTATION :Gummiplantage +STR_4817_WATER_SUPPLY :Vandforsyning +STR_4818_WATER_TOWER :Vandtårn +STR_4819_FACTORY :Fabrik +STR_481A_FARM :Bondegård +STR_481B_LUMBER_MILL :Træfabrik +STR_481C_COTTON_CANDY_FOREST :Candyfloss Skov +STR_481D_CANDY_FACTORY :Slikfabrik +STR_481E_BATTERY_FARM :Batterigård +STR_481F_COLA_WELLS :Colabrønd +STR_4820_TOY_SHOP :Legetøjsforretning +STR_4821_TOY_FACTORY :Legetøjsfabrik +STR_4822_PLASTIC_FOUNTAINS :Plastikspringvand +STR_4823_FIZZY_DRINK_FACTORY :Sodavandsfabrik +STR_4824_BUBBLE_GENERATOR :Boblegenerator +STR_4825_TOFFEE_QUARRY :Karamelbrud +STR_4826_SUGAR_MINE :Sukkermine + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Kræver: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Kræver: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Kræver: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produktion sidste måned: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transporteret) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrer skærmen over placeringen af industrien +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Ny {STRING} under konstruktion tæt på {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Ny {STRING} bliver plantet tæt på {TOWN}! +STR_482F_COST :{BLACK}Pris: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Kan ikke bygge denne industritype her... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...skov kan kun plantes over snelinjen +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} rapporterer om øjeblikkelig nedlukning! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Forsyningsproblemer foresager {TOWN} {STRING} til at meddele om øjeblikkelig lukning! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Mangel på træer i nærheden får {TOWN} {STRING} til at lukke omgående! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} øger produktionen! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Ny kulåre fundet tæt på {TOWN} {STRING}!{}Produktionen forventes at fordobles! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nye oliereserver fundet tæt ved {TOWN} {STRING}!{}Produktionen forventes at fordoble! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Forbedrede landbrugsmetoder ved {TOWN} {STRING} gør at produktionen forventes fordoblet! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} produktion er faldet med 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insekter foresager kaos ved {TOWN} {STRING}!{}Produktionen er faldet med 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...kan kun placeres nær kanten af kortet +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} produktionen på {TOWN} {STRING} vokser med {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} produktionen på {TOWN} {STRING} sænkes med {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Der er et tog i tunnelen +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Der er en lastbil i tunnelen +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}En anden tunnel er i vejen +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Det er umuligt at lave en udgravning til tunnelen i den anden ende +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Det er nødvendigt at rive tunnelen ned først +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Det er nødvendigt at rive broen ned først +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan ikke starte og slutte på samme position +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Der skal være flat land eller vand under broen +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start og slut position skal være på linje +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Dette sted er ikke brugbart til starten af en tunnel +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Hængebro, Stål +STR_500F_GIRDER_STEEL :Bjælkebro, Stål +STR_5010_CANTILEVER_STEEL :Cantileverbro, Stål +STR_5011_SUSPENSION_CONCRETE :Hængebro, Beton +STR_5012_WOODEN :Træ +STR_5013_CONCRETE :Beton +STR_5014_TUBULAR_STEEL :Rørformet bro, Stål +STR_BRIDGE_TUBULAR_SILICON :Rørformet bro, Silicium +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Kan ikke bygge en bro her... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan ikke bygge en tunnel her... +STR_5017_RAILROAD_TUNNEL :Jernbanetunnel +STR_5018_ROAD_TUNNEL :Tunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Jernbanehængebro af stål +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Jernbanebjælkebro af stål +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Jernbanecantileverbro af stål +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Forstærket jernbanehængebro af beton +STR_501F_WOODEN_RAIL_BRIDGE :Jernbanebro af træ +STR_5020_CONCRETE_RAIL_BRIDGE :Jernbanebro af beton +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Hængebro af stål +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Bjælkebro af stål +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Cantileverbro af stål +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Forstærket hængebro af beton +STR_5025_WOODEN_ROAD_BRIDGE :Bro af træ +STR_5026_CONCRETE_ROAD_BRIDGE :Bro af beton +STR_5027_TUBULAR_RAIL_BRIDGE :Rørformet jernbanebro +STR_5028_TUBULAR_ROAD_BRIDGE :Rørformet bro +STR_5029_STEEL :Stål + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Der er et objekt i vejen +STR_5801_TRANSMITTER :Sender +STR_5802_LIGHTHOUSE :Fyrtårn +STR_5803_COMPANY_HEADQUARTERS :Selskabets hovedkontor +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...selskabets hovedkontor i vejen +STR_5805_COMPANY_OWNED_LAND :Land ejet af selskabet +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Kan ikke købe dette stykke land... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...du ejer det allerede! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Ikke navngivet{SKIP} +STR_SV_TRAIN_NAME :Tog {COMMA16} +STR_SV_ROADVEH_NAME :Lastbil {COMMA16} +STR_SV_SHIP_NAME :Skib {COMMA16} +STR_SV_AIRCRAFT_NAME :Fly {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Nord +STR_SV_STNAME_SOUTH :{STRING} Syd +STR_SV_STNAME_EAST :{STRING} Øst +STR_SV_STNAME_WEST :{STRING} Vest +STR_SV_STNAME_CENTRAL :{STRING} Hovedbanegård +STR_SV_STNAME_TRANSFER :{STRING} Centrum +STR_SV_STNAME_HALT :{STRING} Stop +STR_SV_STNAME_VALLEY :{STRING} Dalen +STR_SV_STNAME_HEIGHTS :{STRING} Bakke +STR_SV_STNAME_WOODS :{STRING} Park +STR_SV_STNAME_LAKESIDE :{STRING} Sø +STR_SV_STNAME_EXCHANGE :{STRING} Marked +STR_SV_STNAME_AIRPORT :{STRING} Lufthavn +STR_SV_STNAME_OILFIELD :{STRING} Oliefelt +STR_SV_STNAME_MINES :{STRING} Miner +STR_SV_STNAME_DOCKS :{STRING} Havn +STR_SV_STNAME_BUOY_1 :{STRING} Bøje 1 +STR_SV_STNAME_BUOY_2 :{STRING} Bøje 2 +STR_SV_STNAME_BUOY_3 :{STRING} Bøje 3 +STR_SV_STNAME_BUOY_4 :{STRING} Bøje 4 +STR_SV_STNAME_BUOY_5 :{STRING} Bøje 5 +STR_SV_STNAME_BUOY_6 :{STRING} Bøje 6 +STR_SV_STNAME_BUOY_7 :{STRING} Bøje 7 +STR_SV_STNAME_BUOY_8 :{STRING} Bøje 8 +STR_SV_STNAME_BUOY_9 :{STRING} Bøje 9 +STR_SV_STNAME_ANNEXE :{STRING} Forstad +STR_SV_STNAME_SIDINGS :{STRING} Sidespor +STR_SV_STNAME_BRANCH :{STRING} Torv +STR_SV_STNAME_UPPER :Øvre {STRING} +STR_SV_STNAME_LOWER :Nedre {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Helicopterplads +STR_SV_STNAME_FOREST :{STRING} Skov + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Sværhedsgrad + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Nem +STR_6802_MEDIUM :{BLACK}Mellem +STR_6803_HARD :{BLACK}Svær +STR_6804_CUSTOM :{BLACK}Speciel +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maksimalt antal modstandere: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Modstandernes starttidspunkt: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Antal byer: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Antal industrier: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maksimalt startlån: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Startrenten: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Køretøjers kørselsomkostning: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Byggehastighed for modstandere: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Modstandernes inteligens: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Nedbrud af køretøjer: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Specialaftale bonus: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Konstruktionspris: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Terræntype: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Antal søer/floder: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Økonomi: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Tog vender: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katastrofer: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Lav +STR_6817_NORMAL :Normal +STR_6818_HIGH :Høj +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Meget Langsom +STR_681C_SLOW :Langsom +STR_681D_MEDIUM :Mellem +STR_681E_FAST :Hurtig +STR_681F_VERY_FAST :Meget Hurtig +STR_VERY_LOW :Meget Lavt +STR_6820_LOW :Lavt +STR_6821_MEDIUM :Middel +STR_6822_HIGH :Højt +STR_6823_NONE :Ingen +STR_6824_REDUCED :Reduceret +STR_6825_NORMAL :Normal +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Meget Fladt +STR_682B_FLAT :Fladt +STR_682C_HILLY :Bakket +STR_682D_MOUNTAINOUS :Bjergrigt +STR_682E_STEADY :Rolig +STR_682F_FLUCTUATING :Svingende +STR_6830_IMMEDIATE :Med det samme +STR_6831_3_MONTHS_AFTER_PLAYER :3 måneder efter spilleren +STR_6832_6_MONTHS_AFTER_PLAYER :6 måneder efter spilleren +STR_6833_9_MONTHS_AFTER_PLAYER :9 måneder efter spilleren +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Ved slutningen af jernbanespor, og ved stationer +STR_6835_AT_END_OF_LINE_ONLY :Kun ved slutningen af jernbanespor +STR_6836_OFF :Fra +STR_6837_ON :Til +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Vis higscoreliste + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 :(Spiller 1) +STR_7003_PLAYER_2 :(Spiller 2) +STR_7004_NEW_FACE :{BLACK}Nyt Ansigt +STR_7005_COLOR_SCHEME :{BLACK}Farvetema +STR_7006_COLOR_SCHEME :{GOLD}Farvetema: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nyt Farvetema +STR_7008_COMPANY_NAME :{BLACK}Firmanavn +STR_7009_PRESIDENT_NAME :{BLACK}Direktørnavn +STR_700A_COMPANY_NAME :Firmanavn +STR_700B_PRESIDENT_S_NAME :Direktørens Navn +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Kan ikke ændre firmaets navn... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Kan ikke ændre direktørens navn... +STR_700E_FINANCES :{WHITE}{STRING} Finanser{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Udgifter/Indkomst +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Konstruktion +STR_7012_NEW_VEHICLES :{GOLD}Nye Køretøjer +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Togkørselsudgift +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Lastbilskørselsudgift +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Flykørselsudgift +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Skibskørselsudgift +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Vedligeholdelse af ejendom +STR_7018_TRAIN_INCOME :{GOLD}Togindkomst +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Lastbilsindkomst +STR_701A_AIRCRAFT_INCOME :{GOLD}Flyindkomst +STR_701B_SHIP_INCOME :{GOLD}Skibsindkomst +STR_701C_LOAN_INTEREST :{GOLD}Renter +STR_701D_OTHER :{GOLD}Andet +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Total: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Indkomst Graf +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Profit Garf +STR_7026_BANK_BALANCE :{WHITE}Bank Balance +STR_7027_LOAN :{WHITE}Lån +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Lån {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Tilbagebetal {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maksimale størrelse af lån er {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Kan ikke låne felere penge... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...ingen lån at tilbagebetale +STR_702E_REQUIRED :{WHITE}...{CURRENCY} krævet +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Kan ikke tilbagebetale lån... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Vælg nyt ansigt til direktøren +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Ændrer firmaets køretøjers farve +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Ændrer direktørens navn +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Ændrer firmaets navn +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Klik på det nye farvetema +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Forøg lånet +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Tilbagebetal en del af lånet +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Direktør) +STR_7038_INAUGURATED :{GOLD}Inaugurated: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Køretøjer: +STR_703A_TRAIN :{WHITE}{COMMA16} tog +STR_703B_TRAINS :{WHITE}{COMMA16} tog +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} lastbil +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} lastbiler +STR_703E_AIRCRAFT :{WHITE}{COMMA16} fly +STR_703F_AIRCRAFT :{WHITE}{COMMA16} fly +STR_7040_SHIP :{WHITE}{COMMA16} skib +STR_7041_SHIPS :{WHITE}{COMMA16} skibe +STR_7042_NONE :{WHITE}Ingen +STR_7043_FACE_SELECTION :{WHITE}Ansigtsvalg +STR_7044_MALE :{BLACK}Mand +STR_7045_FEMALE :{BLACK}Kvinde +STR_7046_NEW_FACE :{BLACK}Nyt Ansigt +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Annuler nyt valg af ansigt +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Accepter nyt ansigtsvalg +STR_7049_SELECT_MALE_FACES :{BLACK}Vælg mandlige ansigter +STR_704A_SELECT_FEMALE_FACES :{BLACK}Vælg kvindelige ansigter +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Generer nyt tilfældigt ansigt +STR_704C_KEY :{BLACK}Nøgle +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Viser nøglen til grafen +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Nøgle til firmagraf +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Klik her for at vise/gemme firmaets graf +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Afleveret last +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Firmaets ydelsesrate (maksimal=1000) +STR_7052_COMPANY_VALUES :{WHITE}Selskabsværdier +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Selskabsoversigt +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transportfirma i vanskeligheder! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} vil blive erklæret bankerupt eller solgt hvis ikke ydelsen stiger snart! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Direktør) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Fussion mellem transportfirmaer! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} er blevet solgt til {STRING} for {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Vi leder efter et selskab til at overtage vores{}{}Vil du købe {STRING} for {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankerupt! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} er blevet lukket af kreditorerne og alle ejendomme er solgt! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nyt transportselskab er startet! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} starter konstruktion i nærheden af {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Kan ikke købe selskab... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Lastudbetalingsrater +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Antal dage undervejs +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Betaling for at transportere 10 enheder (eller 10,000 liter) last en distance på 20 enheder. +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Skift grafen for denne lasttype til/fra +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingeniør +STR_7067_TRAFFIC_MANAGER :Trafikbestyrrer +STR_7068_TRANSPORT_COORDINATOR :Trafikkoordinator +STR_7069_ROUTE_SUPERVISOR :Routesuperviser +STR_706A_DIRECTOR :Direktør +STR_706B_CHIEF_EXECUTIVE :Administrende Direktør +STR_706C_CHAIRMAN :Formand +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Matador +STR_706F_BUILD_HQ :{BLACK}Byg HK +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Byg firmaets hovedkvarter / centrer over hovedkvarteret +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Kan ikke bygge firmaets hovedkvarter... +STR_7072_VIEW_HQ :{BLACK}Vis HK +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Lavkonjuktur over hele verden!{}{}Vismændende frygter det værste, økonomien skrumper! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Økonomisk krise overvundet!{}{}Stigning i forbrug giver industrien selvtilliden tilbage, produktionen øges! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Skift mellem stort/lille vindue +STR_7076_COMPANY_VALUE :{GOLD}Selskabsværdi: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Køb 25% aktier i firmaet +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Sælg 25% aktier i firmaet +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kæb 25% aktier i dette firma +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Sælg 25% aktier i dette firma +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Kan ikke købe 25% aktier i dette firma... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Kan ikke sælge 25% aktier i dette firma... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% ejes af {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% ejes af {STRING}{} {COMMA16}% ejes af {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} er blevet overtaget af {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Damp) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Damp) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Damp) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Damp) +STR_800A_SH_8P_STEAM :SH '8P' (Damp) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektrisk) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektrisk) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektrisk) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektrisk) +STR_801B_PASSENGER_CAR :Personvogn +STR_801C_MAIL_VAN :Postvogn +STR_801D_COAL_CAR :Kulvogn +STR_801E_OIL_TANKER :Olievogn +STR_801F_LIVESTOCK_VAN :Kreaturvogn +STR_8020_GOODS_VAN :Stykgodsvogn +STR_8021_GRAIN_HOPPER :Kornvogn +STR_8022_WOOD_TRUCK :Trævogn +STR_8023_IRON_ORE_HOPPER :Jernmalmsvogn +STR_8024_STEEL_TRUCK :Stålvogn +STR_8025_ARMORED_VAN :Pansret vogn +STR_8026_FOOD_VAN :Fødevarevogn +STR_8027_PAPER_TRUCK :Papirvogn +STR_8028_COPPER_ORE_HOPPER :Kobbermalmsvogn +STR_8029_WATER_TANKER :Vandtanksvogn +STR_802A_FRUIT_TRUCK :Frugtvogn +STR_802B_RUBBER_TRUCK :Gummivogn +STR_802C_SUGAR_TRUCK :Sukkervogn +STR_802D_COTTON_CANDY_HOPPER :Candyflossvogn +STR_802E_TOFFEE_HOPPER :Karamelvogn +STR_802F_BUBBLE_VAN :Boblevogn +STR_8030_COLA_TANKER :Colatankvogn +STR_8031_CANDY_VAN :Slikvogn +STR_8032_TOY_VAN :Legetøjsvogn +STR_8033_BATTERY_TRUCK :Batterivogn +STR_8034_FIZZY_DRINK_TRUCK :Sodavandsvogn +STR_8035_PLASTIC_TRUCK :Plastikvogn +STR_8036_X2001_ELECTRIC :'X2001' (Elektrisk) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektrisk) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Personvogn +STR_803A_MAIL_VAN :Postvogn +STR_803B_COAL_CAR :Kulvogn +STR_803C_OIL_TANKER :Olietank +STR_803D_LIVESTOCK_VAN :Kreaturvogn +STR_803E_GOODS_VAN :Stykgodsvogn +STR_803F_GRAIN_HOPPER :Kornvogn +STR_8040_WOOD_TRUCK :Trævogn +STR_8041_IRON_ORE_HOPPER :Jernmalmsvogn +STR_8042_STEEL_TRUCK :Stålvogn +STR_8043_ARMORED_VAN :Pansret vogn +STR_8044_FOOD_VAN :Fødevarevogn +STR_8045_PAPER_TRUCK :Papirvogn +STR_8046_COPPER_ORE_HOPPER :Kobbermalmsvogn +STR_8047_WATER_TANKER :Vandtanksvogn +STR_8048_FRUIT_TRUCK :Frugtvogn +STR_8049_RUBBER_TRUCK :Gummivogn +STR_804A_SUGAR_TRUCK :Sukkervogn +STR_804B_COTTON_CANDY_HOPPER :Candyflossvogn +STR_804C_TOFFEE_HOPPER :Karamelvogn +STR_804D_BUBBLE_VAN :Boblevogn +STR_804E_COLA_TANKER :Colatankvogn +STR_804F_CANDY_VAN :Slikvogn +STR_8050_TOY_VAN :Legetøjsvogn +STR_8051_BATTERY_TRUCK :Batterivogn +STR_8052_FIZZY_DRINK_TRUCK :Sodavandsvogn +STR_8053_PLASTIC_TRUCK :Plastikvogn +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektrisk) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektrisk) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektrisk) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektrisk) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Personvogn +STR_805A_MAIL_VAN :Postvogn +STR_805B_COAL_CAR :Kulvogn +STR_805C_OIL_TANKER :Olietank +STR_805D_LIVESTOCK_VAN :Kreaturvogn +STR_805E_GOODS_VAN :Stykgodsvogn +STR_805F_GRAIN_HOPPER :Kornvogn +STR_8060_WOOD_TRUCK :Trævogn +STR_8061_IRON_ORE_HOPPER :Jernmalmsvogn +STR_8062_STEEL_TRUCK :Stålvogn +STR_8063_ARMORED_VAN :Pansret vogn +STR_8064_FOOD_VAN :Fødevarevogn +STR_8065_PAPER_TRUCK :Papirvogn +STR_8066_COPPER_ORE_HOPPER :Kobbermalmsvogn +STR_8067_WATER_TANKER :Vandtanksvogn +STR_8068_FRUIT_TRUCK :Frugtvogn +STR_8069_RUBBER_TRUCK :Gummivogn +STR_806A_SUGAR_TRUCK :Sukkervogn +STR_806B_COTTON_CANDY_HOPPER :Candyflossvogn +STR_806C_TOFFEE_HOPPER :Karamelvogn +STR_806D_BUBBLE_VAN :Boblevogn +STR_806E_COLA_TANKER :Colatankvogn +STR_806F_CANDY_VAN :Slikvogn +STR_8070_TOY_VAN :Legetøjsvogn +STR_8071_BATTERY_TRUCK :Batterivogn +STR_8072_FIZZY_DRINK_TRUCK :Sodavandsvogn +STR_8073_PLASTIC_TRUCK :Plastikvogn +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Kullastbil +STR_807C_UHL_COAL_TRUCK :Uhl Kullastbil +STR_807D_DW_COAL_TRUCK :DW Kullastbil +STR_807E_MPS_MAIL_TRUCK :MPS Postlastbil +STR_807F_REYNARD_MAIL_TRUCK :Reynard Postlastbil +STR_8080_PERRY_MAIL_TRUCK :Perry Postlastbil +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postlastbil +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Postlastbil +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Postlastbil +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Olietanklastbil +STR_8085_FOSTER_OIL_TANKER :Foster Olietanklastbil +STR_8086_PERRY_OIL_TANKER :Perry Olietanklastbil +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Kreaturlastbil +STR_8088_UHL_LIVESTOCK_VAN :Uhl Kreaturlastbil +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Kreaturlastbil +STR_808A_BALOGH_GOODS_TRUCK :Balogh Stykgodslastbil +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Stykgodslastbil +STR_808C_GOSS_GOODS_TRUCK :Goss Stykgodslastbil +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Kornlastbil +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Kornlastbil +STR_808F_GOSS_GRAIN_TRUCK :Goss Kornlastbil +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Trælastbil +STR_8091_FOSTER_WOOD_TRUCK :Foster Trælastbil +STR_8092_MORELAND_WOOD_TRUCK :Moreland Trælastbil +STR_8093_MPS_IRON_ORE_TRUCK :MPS Jernmalmslastbil +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Jernmalmslastbil +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Jernmalmslastbil +STR_8096_BALOGH_STEEL_TRUCK :Balogh Stållastbil +STR_8097_UHL_STEEL_TRUCK :Uhl Stållastbil +STR_8098_KELLING_STEEL_TRUCK :Kelling Stållastbil +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Pansret Bil +STR_809A_UHL_ARMORED_TRUCK :Uhl Pansret Bil +STR_809B_FOSTER_ARMORED_TRUCK :Foster Pansret Bil +STR_809C_FOSTER_FOOD_VAN :Foster Fødevarelastbil +STR_809D_PERRY_FOOD_VAN :Perry Fødevarelastbil +STR_809E_CHIPPY_FOOD_VAN :Chippy Fødevarelastbil +STR_809F_UHL_PAPER_TRUCK :Uhl Papirlastbil +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Papirlastbil +STR_80A1_MPS_PAPER_TRUCK :MPS Papirlastbil +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Kobbermalmslastbil +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Kobbermalmslastbil +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Kobbermalmslastbil +STR_80A5_UHL_WATER_TANKER :Uhl Vandtankslastbil +STR_80A6_BALOGH_WATER_TANKER :Balogh Vandtankslastbil +STR_80A7_MPS_WATER_TANKER :MPS Vandtankslastbil +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Frugtlastbil +STR_80A9_UHL_FRUIT_TRUCK :Uhl Frugtlastbil +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Frugtlastbil +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Gummilastbil +STR_80AC_UHL_RUBBER_TRUCK :Uhl Gummilastbil +STR_80AD_RMT_RUBBER_TRUCK :RMT Gummilastbil +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Sukkerlastbil +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Sukkerlastbil +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Sukkerlastbil +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Colalastbil +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Colalastbil +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Colalastbil +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Candyflosslastbil +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Candyflosslastbil +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Candyflosslastbil +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Karamellastbil +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Karamellastbil +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Karamellastbil +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Legetøjslastbil +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Legetøjslastbil +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Legetøjslastbil +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Sliklastbil +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Sliklastbil +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Sliklastbil +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Batterilastbil +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Batterilastbil +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Batterilastbil +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Sodavandslastbil +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Sodavandslastbil +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Sodavandslastbil +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastiklastbil +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastiklastbil +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastiklastbil +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Bublelastlastbil +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Bublelastlastbil +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Bublelastlastbil +STR_80CC_MPS_OIL_TANKER :MPS Olietanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Olietanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Passagerfærge +STR_80CF_FFP_PASSENGER_FERRY :FFP Passagerfærge +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Luftpudebåd +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passagerfærge +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passagerfærge +STR_80D3_YATE_CARGO_SHIP :Yate Fragtskib +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Fragtskib +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Fragtskib +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Fragtskib +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helikopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helikopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helikopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Besked fra køretøjsfabrikken +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Vi har lige designet en ny {STRING} - er du interesseret i et års ekslusiv testkørsel, så vi kan se hvordan den klarer sig inden vi gør den frit tilgængelig ? +STR_8102_RAILROAD_LOCOMOTIVE :jernbanelokomotiv +STR_8103_ROAD_VEHICLE :lastbil +STR_8104_AIRCRAFT :fly +STR_8105_SHIP :skib +STR_8106_MONORAIL_LOCOMOTIVE :monoraillokomotiv +STR_8107_MAGLEV_LOCOMOTIVE :magnetskinnelokomotiv + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} remise +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Indbyggerene fester . . .{}Første tog ankommer til {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Detaljer) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Tog i vejen +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Gå til {STATION} +STR_8807_GO_TO_UNLOAD :Gå til {STATION} (Aflæsse) +STR_8808_GO_TO_LOAD :Gå til {STATION} (Læsse) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Gå uden stop til {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Gå uden stop til {STATION} (Aflæsse) +STR_880C_GO_NON_STOP_TO_LOAD :Gå uden stop til {STATION} (Læsse) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Gå til {TOWN} remise +STR_SERVICE_AT_TRAIN_DEPOT :Service i {TOWN} remise +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Gå uden stop til {TOWN} remise +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Service non-stop i {TOWN} remise + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Retning mod {TOWN} remise +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Retning mod {TOWN} remise, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Tom +STR_8813_FROM :{LTBLUE}{CARGO} fra {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Tog {COMMA16} Venter i depot +STR_8815_NEW_VEHICLES :{BLACK}Nye køretøjer +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Pris: {GOLD}{CURRENCY}{BLACK} Vægt: {GOLD}{COMMA16}t{}{BLACK}Hastighed: {GOLD}{VELOCITY}{BLACK} Styrke: {GOLD}{COMMA16}hp{}{BLACK}Kørselsomkostninger: {GOLD}{CURRENCY}/år{}{BLACK}Kapacitet: {GOLD}{STRING}{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Levetid: {GOLD}{COMMA16} år{}{BLACK}Maks pålidelighed: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Information +STR_8819_TRAIN_TOO_LONG :{WHITE}Toget er for langt +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Tog kan kun ændres når de er stoppet i en remise +STR_881B_TRAINS :{WHITE}{STRING} - Tog +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nye Jernbanekøretøjer +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nye Monorailkøretøjer +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nye Magnetskinne køretøjer +STR_881F_BUILD_VEHICLE :{BLACK}Byg Køretøj +STR_8820_RENAME :{BLACK}Omdøb +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Pris: {GOLD}{CURRENCY}{}{BLACK}Vægt: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapacitet: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Spring over +STR_8824_DELETE :{BLACK}Slet +STR_8825_NON_STOP :{BLACK}Uden stop +STR_8826_GO_TO :{BLACK}Gå til +STR_8827_FULL_LOAD :{BLACK}Fuld Last +STR_8828_UNLOAD :{BLACK}Aflæs +STR_8829_ORDERS :{WHITE}{STRING} (Ordre) +STR_882A_END_OF_ORDERS :{SETX 10}- - Slut på ordre - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Service +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Kan ikke bygge jernbanekøretøj... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Værdi: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Værdi: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Læsser / Aflæsser +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Kan ikke sende toget til remise... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ikke mere plads til flere ordre +STR_8832_TOO_MANY_ORDERS :{WHITE}For mange ordre +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Kan ikke indsætte ny ordre... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Kan ikke slette denne ordre... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Kan ikke ændre denne ordre... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Det er nødvendigt at bygge en remise først +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Kan ikke flytte køretøjet... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Kan ikke sælge jernbanekøretøjet... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Kan ikke finde en route til en lokal remise +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Kan ikke stoppe/starte toget... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Serviceinterval: {LTBLUE}{COMMA16}dage{BLACK} Sidste Service: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tog - klik på et tog for information +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Byg nye tog (kræver en remise) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tog - klik på et tog for information., træk vogn/lokomotiv for at fjerne/tilføje det til toget +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Byg nyt tog/togvogn +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Træk tog/togvogn her hend for at sælge +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrer skærmen over placeringen af remisen +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Tog valgsliste - klik på et køretøj for mere information +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Byg det markerede lokomotiv/togvogn +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Omdøb tog-/togvognstypen +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Nuværende opførsel - klik her for at starte/stoppe toget +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Vis togets ordre +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrer skærmen over togets placering +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Send toget til depot +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Tving toget til at fortsætte uden at vente på at signalet skifter til grønt +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Vend retningen af toget +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Vis detaljer om toget +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Forøg serviceintervallet +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Sænk serviceintervallet +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Vis detaljer omkring den last der medbringes +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Vis detaljer omkring toget/vognene +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Vis kapaciteten af hver togvogn +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Vis total lasteevne på toget, fordelt på lasttyper +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Ordreliste - klik på en ordre for at markere den +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Spring over den nuværende ordre og gå til den næste +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Slet den markerede ordre +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Lav den markerede ordre til en "uden stop" ordre +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Indsæt en ny ordre før den markerede eller ved slutningen af ordrelisten +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Få den markerede ordre til at tvinge toget til at vente på en fuld last +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Få den markerede ordre til at tvinge toget til at aflæsse +STR_SERVICE_HINT :{BLACK}Spring denne ordre over hvis der ikke er behov for service +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Ny {STRING} tilgængelig nu! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Pris: {CURRENCY} Vægt: {COMMA16}t{}Hastighed: {VELOCITY} Styrke: {COMMA16}hp{}Kørselsomkostning: {CURRENCY}/år{}Kapacitet: {STRING} +STR_885C_BROKEN_DOWN :{RED}Gået i stykker +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Vægt: {LTBLUE}{COMMA16}t {BLACK}Styrke: {LTBLUE}{COMMA32}hp{BLACK} Maks hastighed: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed {LTBLUE}{COMMA8}% {BLACK}nedbrud siden sidste service: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Stoppet +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan ikke få toget til at passere signalet... +STR_8863_CRASHED :{RED}Forulykket! + +STR_8865_NAME_TRAIN :{WHITE}Giv toget et navn +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Kan ikke give toget navn... +STR_8867_NAME_TRAIN :{BLACK}Giv toget et navn +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Tog forulykket!{}{COMMA16} døde i flammerne efter kollision +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Kan ikke vende retningen af toget... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Omdøb tog-/togvognstypen +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Kan ikke omdøbe tog-/togvognstypen... + +STR_TRAIN_STOPPING :{RED}Stopper +STR_TRAIN_STOPPING_VEL :{RED}Stopper, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Lastbil i vejen +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Lastbiler +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Lastbilsdepot +STR_9004_NEW_VEHICLES :{BLACK}Nye køretøjer +STR_9005_INFORMATION :{BLACK}Information +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nye lastbiler +STR_9007_BUILD_VEHICLE :{BLACK}Byg køretøj +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Pris: {GOLD}{CURRENCY}{BLACK} Hastighed: {GOLD}{VELOCITY}{}{BLACK}Kørselsomkostning: {GOLD}{CURRENCY}/år{}{BLACK}Kapacitet: {GOLD}{STRING}{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Livstid: {GOLD}{COMMA16} år{}{BLACK}Maks Pålidelighed: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan ikke bygge lastbil... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Det er nødvendigt at bygge lastbilsdepot først +STR_900B_ORDERS :{WHITE}{STRING} (Ordre) +STR_900C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år +STR_900E_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA8}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Værdi: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...skal være stoppet inde i et depot først +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Kan ikke sælge lastbil... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Kan ikke stoppe/starte lastbil... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Lastbil {COMMA16} venter i depot +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Retning mod {TOWN} Lastbilsdepot +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Retning mod {TOWN} Lastbilsdepot, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kan ikke sende køretøj i depot... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finde lokalt depot +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Lastlastbiler - klik på et køretøj for information +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Byg nye lastbiler (kræver et lastbilsdepot) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Nuværende opførsel - klik her for at stoppe/starte lastbilen +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Vis køretøjets ordrer +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centrer skærmen over placeringen af køretøjet +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Send køretøjet i depot +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Tving køretøjet til at vende +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Vis lastbilens detaljer +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Køretøjer - klik på et køretøj for mere information +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Byg ny lastbil +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Træk lastbilen herhend for at sælge +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centrer skærmen over placeringen af lastbilsdepotet +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Liste over lastbilstyper - klik på køretøj for information +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Byg den markerede lastbil +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Ny lastbil er tilgængelig! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Pris: {CURRENCY}{}Hastighed: {VELOCITY}{}Kørselsomkostning: {CURRENCY}/år{}Kapacitet: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Giv lastbilen et navn +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Kan ikke give lastbilen et navn... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Giv lastbilen et navn +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Indbyggerne fester . . .{}Første bus ankommer til {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Indbyggerne fester . . .{}Første lastbil ankommer til {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Lastbil forulykket!{}Chaufføren død i flammerne efter at være kollideret med et tog! +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Bus forulykket!{}{COMMA16} dør i flammerne efter kollision med et tog +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Kan ikke få køretøjet til at vende... +STR_9034_RENAME :{BLACK}Omdøb +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Omdøb lastbilstypen +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Omdøb lastbilstypen +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Kan ikke omdøbe lastbilstypen... +STR_9038_GO_TO_ROADVEH_DEPOT :Gå til {TOWN} Lastbilsdepot +STR_SERVICE_AT_ROADVEH_DEPOT :Service i {TOWN} Lastbilsdepot + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Havnekonstruktion +STR_9801_DOCK_CONSTRUCTION :{WHITE}Havnekonstruktion +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Kan ikke bygge en havn her... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Skibsdepot +STR_9804_NEW_SHIPS :{BLACK}Nye skibe +STR_9805_SHIPS :{WHITE}{STRING} - Skibe +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Kan ikke bygge skibe... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Det er nødvendigt at bygge et skibsdepot først +STR_9808_NEW_SHIPS :{WHITE}Nye skibe +STR_9809_BUILD_SHIP :{BLACK}Byg skib +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Pris: {GOLD}{CURRENCY}{BLACK} Hastighed: {GOLD}{VELOCITY}{}{BLACK}Kapacitet: {GOLD}{STRING} {STRING}{}{BLACK}Kørselsomkostning: {GOLD}{CURRENCY}/år{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Livetid: {GOLD}{COMMA16} år{}{BLACK}Maks Pålidelighed: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Skibet skal være stoppet i et depot +STR_980C_CAN_T_SELL_SHIP :{WHITE}Kan ikke sælge skibet... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Kan ikke bygge skibet... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Der er et skib i vejen +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Ordre) +STR_9811_DETAILS :{WHITE}{STRING} (Detaljer) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år +STR_9813_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA8}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Værdi: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Kan ikke stoppe/starte skibet... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Kan ikke sende skibet til depot... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finde lokalt depot +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Retning mod {TOWN} Skibsdepot +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Retning mod {TOWN} Skibsdepot, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Skib {COMMA16} venter i depot +STR_981D_BUILD_SHIP_DOCK :{BLACK}Byg havn +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Byg skibsdepot (til bygning og servicering af skibe) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skibe - klik på et skib for information +STR_9820_BUILD_NEW_SHIP :{BLACK}Byg nyt skib +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Træk det her for at sælge det +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrer skærmen over placeringen af skibsdepotet +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skibe - klik på et skib for information +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Byg nye skibe (kræver et skibsdepot) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Skibstypeliste - klik på skibstype for information +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Byg det markerede skib +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Nuværende opførsel - klik her for at starte/stoppe skibet +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Vis skibets ordrer +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrer skærmen over skibets placering +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Send skibet til depot +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Vis detaljer omkring skibet +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nyt skib er tilgængeligt! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks Hastighed: {VELOCITY}{}Kapacitet: {STRING}{}Kørselsomkostning: {CURRENCY}/år +STR_982F_NAME_SHIP :{BLACK}Giv skibet et navn + +STR_9831_NAME_SHIP :{WHITE}Giv skibet et navn +STR_9832_CAN_T_NAME_SHIP :{WHITE}Kan ikke give skibet et navn... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Indbyggere fester . . .{}Første skib ankommer til {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Potitionsbøje, kan bruges som yderligere navigationspunkt +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Kan ikke placere en bøje her... +STR_9836_RENAME :{BLACK}Omdøb +STR_9837_RENAME_SHIP_TYPE :{BLACK}Omdøb skibstypen +STR_9838_RENAME_SHIP_TYPE :{WHITE}Omdøb skibstypen +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Kan ikke omdøbe skibstypen... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Ombyg skibet til at sejle med en anden slags last +STR_983B_REFIT :{WHITE}{STRING} (Ombyg) +STR_983C_REFIT_SHIP :{BLACK}Ombyg skibet +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vælg den slags last skibet skal sejle med +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Ombyg skibet til den markerede slags last +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Vælg den lasttype der skal sejles med:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapacitet: {GOLD}{STRING}{}{BLACK}Pris for ombyggelse: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Kan ikke ombygge skib... +STR_9842_REFITTABLE :(ombygning mulig) +STR_GO_TO_SHIP_DEPOT :Sejl til {TOWN} Skip Depot +SERVICE_AT_SHIP_DEPOT :Service i {TOWN} Skip Depot + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Lufthavnskonstruktion. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Kan ikke bygge en lufthavn her... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Flyhangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nyt fly +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}Nyt fly +STR_A006_BUILD_AIRCRAFT :{BLACK}Byg et fly +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Pris: {GOLD}{CURRENCY}{BLACK} Hastighed: {GOLD}{VELOCITY}{}{BLACK}Kapacitet: {GOLD}{COMMA16} passagerer, {COMMA16} sække post{}{BLACK}Kørselsomkostning: {GOLD}{CURRENCY}/år{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Livstid: {GOLD}{COMMA16} år{}{BLACK}Maks Pålidelighed: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Kan ikke bygge fly... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Fly +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Ordre) +STR_A00C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Kørselsomkostning: {LTBLUE}{CURRENCY}/år +STR_A00E_MAX_SPEED :{BLACK}Maks hastighed: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Dette års profit: {LTBLUE}{CURRENCY} (sidste år: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Pålidelighed: {LTBLUE}{COMMA8}% {BLACK}Nedbrud siden sidste service: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Værdi: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Kan ikke sende flyet til en hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Retning mod {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Retning mod {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Fly {COMMA16} venter i flyhangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Fly i vejen +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Kan ikke stoppe/starte fly... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Flyet er i luften +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Det er nødvendigt at bygge en lufthavn først +STR_A019_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Flyet skal være stoppet i en flyhangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Kan ikke sælge flyet... +STR_A01D_AIRPORT_CONSTRUCTION :Lufthavnskonstruktion +STR_A01E_BUILD_AIRPORT :{BLACK}Byg en lufthavn +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Fly - klik på et fly for information +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Byg nyt fly (kræver en lufthavn med hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Fly - klik på et fly for information +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Byg nyt fly +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Træk fly herhend for at sælge +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centrer skærmen over placeringen af hangaren +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Flytypeliste - klik på en flytype for mere information +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Byg det markerede fly +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Nuværende opførsel - klik her for at starte/stoppe flyet +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Vis flyets ordre +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centrer skærmen over placeringen af flyet +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Send flyet til en hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Vis detaljet omkring flyet +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nyt fly tilgængeligt! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Pris: {CURRENCY} Maks hastighed: {VELOCITY}{}Kapacitet: {COMMA16} passagerer, {COMMA16} sække post{}Kørselsomkostning: {CURRENCY}/år + +STR_A030_NAME_AIRCRAFT :{WHITE}Navngiv flyet +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kan ikke navngive flyet... +STR_A032_NAME_AIRCRAFT :{BLACK}Navngiv fluet +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Indbyggerene fester . . .{}Første fly ankommer til{STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Flystyrt!{}{COMMA16} dør i flammerne ved {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinationer: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Omdøb +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Ømdøb flytypen +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Ømdøb flytypen +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Kan ikke omdøbe flytypen... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Ombyg flyet til at flyve med en anden slags last +STR_A03C_REFIT :{WHITE}{STRING} (Ombyg) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Ombyg fly +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vælg den type last flyet skal flyve med +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Ombyg flyet til at flyve med den markerede slags last +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Vælg den type last der skal flyves med:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapacitet: {GOLD}{STRING}{}{BLACK}Ombygningspris: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Kan ikke ombygge fly... +STR_A043_REFITTABLE :(ombygning mulig) +STR_GO_TO_AIRPORT_HANGAR :Flyv til {STATION} hangar +SERVICE_AT_AIRPORT_HANGAR :Service i {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin katastrofe ved {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Lastbil ødelagt i kollision med en UFO +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Eksplosion af olieraffinaderi ved {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabrik ødelagt under mystiske omstændigheder ved {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}En UFO lander tæt på {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Sammenstyrtning af kulmine efterlader et spor af katastrofe ved {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Dit forsøg på bestikkelse er blevet +STR_BRIBE_FAILED_2 :{WHITE}opdaget af en inspektør. diff --git a/lang/dutch.txt b/lang/dutch.txt new file mode 100644 --- /dev/null +++ b/lang/dutch.txt @@ -0,0 +1,2449 @@ +##name Dutch (not complete) +##ownname Nederlands (niet volledig) + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Buiten de kaart +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Te dicht bij de rand van de kaart +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Niet genoeg geld - {CURRENCY} nodig +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Vlak land nodig +STR_0008_WAITING :{BLACK}Wachtend: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (Onderweg uit +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accepteert: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accepteert: {GOLD} +STR_000E : +STR_000F_PASSENGERS : +STR_0010_COAL :Kolen +STR_0011_MAIL :Post +STR_0012_OIL :Olie +STR_0013_LIVESTOCK : +STR_0014_GOODS : +STR_0015_GRAIN : +STR_0016_WOOD : +STR_0017_IRON_ORE : +STR_0018_STEEL :Staal +STR_0019_VALUABLES :Kostbaarheden +STR_001A_COPPER_ORE :Kopererts +STR_001B_MAIZE :Maïs +STR_001C_FRUIT :Fruit +STR_001D_DIAMONDS :Diamanten +STR_001E_FOOD :Voedsel +STR_001F_PAPER :Papier +STR_0020_GOLD :Goud +STR_0021_WATER :Water +STR_0022_WHEAT :Tarwe +STR_0023_RUBBER :Rubber +STR_0024_SUGAR :Suiker +STR_0025_TOYS :Speelgoed +STR_0026_CANDY :Snoep +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Suikerspinnen +STR_0029_BUBBLES :Bellen +STR_002A_TOFFEE :Toffee +STR_002B_BATTERIES :Batterijen +STR_002C_PLASTIC :Plastic +STR_002D_FIZZY_DRINKS :Frisdrank +STR_002E : +STR_002F_PASSENGER :Passagier +STR_0030_COAL :Kolen +STR_0031_MAIL :Post +STR_0032_OIL :Olie +STR_0033_LIVESTOCK :Vee +STR_0034_GOODS :Goederen +STR_0035_GRAIN :Graan +STR_0036_WOOD :Hout +STR_0037_IRON_ORE :IJzererts +STR_0038_STEEL :Staal +STR_0039_VALUABLES :Kostbaarheden +STR_003A_COPPER_ORE :Kopererts +STR_003B_MAIZE :Maïs +STR_003C_FRUIT :Fruit +STR_003D_DIAMOND :Diamant +STR_003E_FOOD :Voedsel +STR_003F_PAPER :Papier +STR_0040_GOLD :Goud +STR_0041_WATER :Water +STR_0042_WHEAT :Tarwe +STR_0043_RUBBER :Rubber +STR_0044_SUGAR :Suiker +STR_0045_TOY :Speelgoed +STR_0046_CANDY :Snoep +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Suikerspin +STR_0049_BUBBLE :Bel +STR_004A_TOFFEE :Toffee +STR_004B_BATTERY :Batterij +STR_004C_PLASTIC :Plastic +STR_004D_FIZZY_DRINK :Frisdrank +STR_004E : +STR_004F_PASSENGER :{COMMA16} passagier +STR_0050_TON_OF_COAL :{COMMA16} ton kolen +STR_0051_BAG_OF_MAIL :{COMMA16} zak post +STR_0052_OF_OIL :{VOLUME} olie +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} stuk vee +STR_0054_CRATE_OF_GOODS :{COMMA16} pallet goederen +STR_0055_TON_OF_GRAIN :{COMMA16} ton graan +STR_0056_TON_OF_WOOD :{COMMA16} ton hout +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton ijzererts +STR_0058_TON_OF_STEEL :{COMMA16} ton staal +STR_0059_BAG_OF_VALUABLES :{COMMA16} zak kostbaarheden +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton kopererts +STR_005B_TON_OF_MAIZE :{COMMA16} ton maïs +STR_005C_TON_OF_FRUIT :{COMMA16} ton fruit +STR_005D_BAG_OF_DIAMONDS :{COMMA16} zak diamanten +STR_005E_TON_OF_FOOD :{COMMA16} ton voedsel +STR_005F_TON_OF_PAPER :{COMMA16} ton papier +STR_0060_BAG_OF_GOLD :{COMMA16} zak goud +STR_0061_OF_WATER :{VOLUME} water +STR_0062_TON_OF_WHEAT :{COMMA16} ton tarwe +STR_0063_OF_RUBBER :{VOLUME} rubber +STR_0064_TON_OF_SUGAR :{COMMA16} ton suiker +STR_0065_TOY :{COMMA16} speelgoed +STR_0066_BAG_OF_CANDY :{COMMA16} zak snoep +STR_0067_OF_COLA :{VOLUME} cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton suikerspinnen +STR_0069_BUBBLE :{COMMA16} bel +STR_006A_TON_OF_TOFFEE :{COMMA16} ton toffee +STR_006B_BATTERY :{COMMA16} batterij +STR_006C_OF_PLASTIC :{VOLUME} plastic +STR_006D_FIZZY_DRINK :{COMMA16} blikje frisdrank +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passagiers +STR_0070_TONS_OF_COAL :{COMMA16} ton kolen +STR_0071_BAGS_OF_MAIL :{COMMA16} zakken post +STR_0072_OF_OIL :{VOLUME} olie +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} stuks vee +STR_0074_CRATES_OF_GOODS :{COMMA16} pallets goederen +STR_0075_TONS_OF_GRAIN :{COMMA16} ton graan +STR_0076_TONS_OF_WOOD :{COMMA16} ton hout +STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton ijzererts +STR_0078_TONS_OF_STEEL :{COMMA16} ton staal +STR_0079_BAGS_OF_VALUABLES :{COMMA16} zakken kostbaarheden +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton kopererts +STR_007B_TONS_OF_MAIZE :{COMMA16} ton maïs +STR_007C_TONS_OF_FRUIT :{COMMA16} ton fruit +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} zakken diamanten +STR_007E_TONS_OF_FOOD :{COMMA16} ton voedsel +STR_007F_TONS_OF_PAPER :{COMMA16} ton papier +STR_0080_BAGS_OF_GOLD :{COMMA16} zakken goud +STR_0081_OF_WATER :{VOLUME} water +STR_0082_TONS_OF_WHEAT :{COMMA16} ton tarwe +STR_0083_OF_RUBBER :{VOLUME} rubber +STR_0084_TONS_OF_SUGAR :{COMMA16} ton suiker +STR_0085_TOYS :{COMMA16} speelgoed +STR_0086_BAGS_OF_CANDY :{COMMA16} zakken snoep +STR_0087_OF_COLA :{VOLUME} cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton suikerspinnen +STR_0089_BUBBLES :{COMMA16} bellen +STR_008A_TONS_OF_TOFFEE :{COMMA16} ton toffee +STR_008B_BATTERIES :{COMMA16} batterijen +STR_008C_OF_PLASTIC :{VOLUME} plastic +STR_008D_FIZZY_DRINKS :{COMMA16} blikjes frisdrank +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}KL +STR_0091_ML :{TINYFONT}PT +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}VE +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}HT +STR_0097_OR :{TINYFONT}IJ +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}KB +STR_009A_CO :{TINYFONT}KE +STR_009B_MZ :{TINYFONT}MS +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}VD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}TW +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SK +STR_00A5_TY :{TINYFONT}SP +STR_00A6_SW :{TINYFONT}SN +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}SS +STR_00A9_BU :{TINYFONT}BE +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FR +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Kaart - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Spelopties +STR_00B2_MESSAGE :{YELLOW}Bericht +STR_00B3_MESSAGE_FROM :{YELLOW}Bericht van {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Kan dit niet uitvoeren.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kan gebied niet ontruimen.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Origineel copyright {COPYRIGHT} 1995 Chris Sawyer, Alle rechten voorbehouden +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD versie {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Origineel ontworpen door Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafisch door Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 Het OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Afsluiten +STR_00C8_YES :{BLACK}Ja +STR_00C9_NO :{BLACK}Nee +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Weet u zeker dat u dit spel wilt verlaten en terug wilt keren naar {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Niets +STR_00D1_DARK_BLUE :Donkerblauw +STR_00D2_PALE_GREEN :Lichtgroen +STR_00D3_PINK :Rose +STR_00D4_YELLOW :Geel +STR_00D5_RED :Rood +STR_00D6_LIGHT_BLUE :Lichtblauw +STR_00D7_GREEN :Groen +STR_00D8_DARK_GREEN :Donkergroen +STR_00D9_BLUE :Blauw +STR_00DA_CREAM :Crème +STR_00DB_MAUVE :Mauve +STR_00DC_PURPLE :Paars +STR_00DD_ORANGE :Oranje +STR_00DE_BROWN :Bruin +STR_00DF_GREY :Grijs +STR_00E0_WHITE :Wit +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Te veel voertuigen in het spel +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Locatie +STR_00E5_CONTOURS :Randen +STR_00E6_VEHICLES :Voertuigen +STR_00E7_INDUSTRIES :Industrieën +STR_00E8_ROUTES :Routes +STR_00E9_VEGETATION :Begroeiïng +STR_00EA_OWNERS :Eigenaren +STR_00EB_ROADS :{BLACK}{TINYFONT}Wegen +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Spoorwegen +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stations/vliegvelden/havens +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Gebouwen/industrieën +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Voertuigen +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Treinen +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Wagens +STR_00F7_SHIPS :{BLACK}{TINYFONT}Schepen +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Vliegtuig +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transportroutes +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kolenmijn +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Energiecentrale +STR_00FC_FOREST :{BLACK}{TINYFONT}Bos +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Houtzagerij +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Olieraffinaderij +STR_00FF_FARM :{BLACK}{TINYFONT}Boerderij +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabriek +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Drukkerij +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Oliebron +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}IJzermijn +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Hoogoven +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papierfabriek +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Goudmijn +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Voedselverwerkings fabriek +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamantmijn +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kopermijn +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Fruitplantage +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Rubberplantage +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Waterbron +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Watertoren +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Houtkapperij +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Suikerspinbos +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Snoepfabriek +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batterijplantage +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Colabronnen +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Speelgoedwinkel +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Speelgoedfabriek +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plasticfonteinen +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Frisdrankfabriek +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Bellenblazer +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Toffeegroeve +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Suikermijn +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Station +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Laadstation +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Busstation +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Vliegveld +STR_011F_DOCK :{BLACK}{TINYFONT}Haven +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Woestenij +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Grasland +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Braakliggend land +STR_0123_FIELDS :{BLACK}{TINYFONT}Velden +STR_0124_TREES :{BLACK}{TINYFONT}Bomen +STR_0125_ROCKS :{BLACK}{TINYFONT}Rotsen +STR_0126_WATER :{BLACK}{TINYFONT}Water +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Geen eigenaar +STR_0128_TOWNS :{BLACK}{TINYFONT}Steden +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrieën +STR_012A_DESERT :{BLACK}{TINYFONT}Woestijn +STR_012B_SNOW :{BLACK}{TINYFONT}Sneeuw +STR_012C_MESSAGE :{WHITE}Bericht +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Annuleren +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Hernoem +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Te veel namen in gebruik +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Deze naam is al in gebruik + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperiaal (mijlen) +STR_013A_METRIC_KILOMETERS :S.I. (kilometers) +STR_013B_OWNED_BY :{WHITE}...is van {STRING} +STR_013C_CARGO :{BLACK}Lading +STR_013D_INFORMATION :{BLACK}Informatie +STR_013E_CAPACITIES :{BLACK}Capaciteiten +STR_013E_TOTAL_CARGO :{BLACK}Totale lading +STR_013F_CAPACITY :{BLACK}Capaciteit: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Totale lading (capaciteit) van deze trein: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nieuw spel +STR_0141_LOAD_GAME :{BLACK}Laad spel +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Uitleg / demonstratie +STR_SINGLE_PLAYER :{BLACK}Single player +STR_MULTIPLAYER :{BLACK}Multiplayer + +STR_0148_GAME_OPTIONS :{BLACK}Spel Opties + +STR_0150_SOMEONE :iemand{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Wereldkaart +STR_0152_TOWN_DIRECTORY :Stedenlijst +STR_0153_SUBSIDIES :Subsidies + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Winstgrafiek +STR_0155_INCOME_GRAPH :Inkomenstegrafiek +STR_0156_DELIVERED_CARGO_GRAPH :Afgeleverde lading-grafiek +STR_0157_PERFORMANCE_HISTORY_GRAPH :Prestatiegrafiek +STR_0158_COMPANY_VALUE_GRAPH :Bedrijfswaardegrafiek +STR_0159_CARGO_PAYMENT_RATES :Ladingsprijzen +STR_015A_COMPANY_LEAGUE_TABLE :Bedrijfscompetitietabel +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Spel opslaan +STR_015D_LOAD_GAME :Spel laden +STR_015E_QUIT_GAME :Spel stoppen +STR_015F_QUIT :Afsluiten +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Weet u zeker dat u dit spel wilt afsluiten? +STR_0161_QUIT_GAME :{WHITE}Spel stoppen + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mrt +STR_0165_APR :Apr +STR_0166_MAY :Mei +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Okt +STR_016C_NOV :Nov +STR_016D_DEC :Dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pauseer spel +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Spel opslaan, spel stoppen, afsluiten +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Toon lijst met stations van het bedrijf +STR_0174_DISPLAY_MAP :{BLACK}Toon kaart +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Toon kaart, stedenlijst +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Toon stedenlijst +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Toon financiële informatie van het bedrijf +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Toon algemene informatie van het bedrijf +STR_0179_DISPLAY_GRAPHS :{BLACK}Toon grafieken +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Toon bedrijfscompetitietabel +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Toon lijst met treinen van het bedrijf +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Toon lijst met voertuigen van het bedrijf +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Toon lijst met schepen van het bedrijf +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Toon lijst met vliegtuigen van het bedrijf +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Inzoomen +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Uitzoomen +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Bouw rails +STR_0182_BUILD_ROADS :{BLACK}Bouw wegen +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Bouw havens +STR_0184_BUILD_AIRPORTS :{BLACK}Bouw vliegvelden +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plaats bomen, borden, etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Landinformatie +STR_0187_OPTIONS :{BLACK}Opties +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Kan onderhoudsinterval niet aanpassen... +STR_018B_CLOSE_WINDOW :{BLACK}Sluit scherm +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Vensternaam - sleep om venster te verplaatsen +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Sloop gebouwen etc. op een stuk land +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Verlaag een hoek van het land +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Verhoog een hoek van het land +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scrollbalk - scroll door de lijst +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Toon landranden op de kaart +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Toon voertuigen op de kaart +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Toon industrieën op de kaart +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Toon transportroutes op de kaart +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Toon begroeiïng op de kaart +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Toon landeigenaren op de kaart +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Plaatsnamen op de kaart aan/uit +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Winst dit jaar: {CURRENCY} (vorig jaar: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} jaar ({COMMA16}) +STR_019A_YEARS :{COMMA16} jaren ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} jaren ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Voertuig +STR_019D_AIRCRAFT :Vliegtuig +STR_019E_SHIP :Schip +STR_019F_TRAIN :Trein +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} wordt oud +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} wordt erg oud +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} wordt erg oud en is aan vervanging toe +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Landinformatie +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Sloopkosten: {LTBLUE}niet mogelijk +STR_01A5_COST_TO_CLEAR :{BLACK}Sloopkosten: {LTBLUE}{CURRENCY} +STR_01A6_N_A :(geen) +STR_01A7_OWNER :{BLACK}Eigenaar: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Gemeente: {LTBLUE}{STRING} +STR_01A9_NONE :Geen +STR_01AA_NAME :{BLACK}Naam +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1 +STR_01AD_2ND :2 +STR_01AE_3RD :3 +STR_01AF_4TH :4 +STR_01B0_5TH :5 +STR_01B1_6TH :6 +STR_01B2_7TH :7 +STR_01B3_8TH :8 +STR_01B4_9TH :9 +STR_01B5_10TH :10 +STR_01B6_11TH :11 +STR_01B7_12TH :12 +STR_01B8_13TH :13 +STR_01B9_14TH :14 +STR_01BA_15TH :15 +STR_01BB_16TH :16 +STR_01BC_17TH :17 +STR_01BD_18TH :18 +STR_01BE_19TH :19 +STR_01BF_20TH :20 +STR_01C0_21ST :21 +STR_01C1_22ND :22 +STR_01C2_23RD :23 +STR_01C3_24TH :24 +STR_01C4_25TH :25 +STR_01C5_26TH :26 +STR_01C6_27TH :27 +STR_01C7_28TH :28 +STR_01C8_29TH :29 +STR_01C9_30TH :30 +STR_01CA_31ST :31 +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Maakt kaart groter/kleiner +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Kies uitleg/demonstratie + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Accepteert: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Accepteert: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Accepteert: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz jukebox +STR_01D3_SOUND_MUSIC :Geluid/muziek +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Toon geluid/muziek scherm +STR_01D5_ALL :{TINYFONT}Alle +STR_01D6_OLD_STYLE :{TINYFONT}Oude stijl +STR_01D7_NEW_STYLE :{TINYFONT}Nieuwe stijl +STR_01D8_EZY_STREET :{TINYFONT}Ezy street +STR_01D9_CUSTOM_1 :{TINYFONT}Aangepast 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Aangepast 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Muziekvolume +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Geluidsvolume +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Vorige nummer in selectie +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Volgende nummer in selectie +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Stop muziek +STR_01E1_START_PLAYING_MUSIC :{BLACK}Start muziek +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Gebruik de schuifbalken om het volume aan te passen +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Nummer{SETX 88}Titel +STR_01E9_SHUFFLE :{TINYFONT}Shuffle +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programma +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Muziekprogrammakeuze +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Nummer index +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programma - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Leeg +STR_01F1_SAVE :{TINYFONT}{BLACK}Sla op +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Huidig muziekprogramma +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Selecteer 'alle nummers' programma +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Selecteer 'oude stijl muziek' programma +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Selecteer 'nieuwe stijl muziek' programma +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Selecteer 'aangepast 1' programma +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selecteer 'aangepast 2' programma +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Leeg huidig programma (alleen Aangepast 1 en Aangepast 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Sla muziekinstellingen op +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klik op het nummer om aan programma toe te voegen (alleen Aangepast 1 en Aangepast 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Programmashuffle aan/uit +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Toon nummerselectiescherm +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klik op de dienst om de stad/industrie te centreren +STR_01FE_DIFFICULTY :{BLACK}Moeilijkheidsgraad ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT ::Laatste (nieuws)bericht +STR_0201_MESSAGE_SETTINGS :Berichteninstellingen +STR_MESSAGE_HISTORY_MENU :Berichtengeschiedenis +STR_0202_SEND_MESSAGE :Stuur bericht +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Toon laatste (nieuws)bericht, toon berichteninstellingen +STR_0204_MESSAGE_OPTIONS :{WHITE}Berichtenopties +STR_0205_MESSAGE_TYPES :{BLACK}Berichttypen:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Eerste voertuig bij eigen station +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Eerste voertuig bij concurrerend station +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Ongelukken/rampen +STR_0209_COMPANY_INFORMATION :{YELLOW}Bedrijfsinformatie +STR_020A_ECONOMY_CHANGES :{YELLOW}Veranderingen in de economie +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Advies/informatie over voertuigen van de speler +STR_020C_NEW_VEHICLES :{YELLOW}Nieuwe voertuigen +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Verandering geaccepteerde goederen +STR_020E_SUBSIDIES :{YELLOW}Subsidies +STR_020F_GENERAL_INFORMATION :{YELLOW}Algemene informatie +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...te ver van vorige bestemming +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Beste bedrijven die 2050 bereikten{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Zakenman +STR_0214_ENTREPRENEUR :Entrepreneur +STR_0215_INDUSTRIALIST :Industrialist +STR_0216_CAPITALIST :Kapitalist +STR_0217_MAGNATE :Magnaat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon van de Eeuw +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} heeft de '{STRING}' status bereikt! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} van {STRING} heeft de '{STRING}' status bereikt! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Maak scenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Scenario editor +STR_0223_LAND_GENERATION :{WHITE}Landgeneratie +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Willekeurig land +STR_0227_RESET_LAND :{BLACK}Verwijder land +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Vergroot het stuk land om te verhogen/verlagen +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Verklein het stuk land om te verhogen/verlagen +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Genereer willekeurig land +STR_022B_RESET_LANDSCAPE :{BLACK}Verwijder landschap +STR_022C_RESET_LANDSCAPE :{WHITE}Verwijder landschap +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Weet u zeker dat u het land wilt verwijderen? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Landschapproductie +STR_022F_TOWN_GENERATION :{BLACK}Stadproductie +STR_0230_INDUSTRY_GENERATION :{BLACK}Industrieproductie +STR_0231_ROAD_CONSTRUCTION :{BLACK}Wegenbouw +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Begroeiïng en andere objecten +STR_0233_TOWN_GENERATION :{WHITE}Stadproductie +STR_0234_NEW_TOWN :{BLACK}Nieuwe stad +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Bouw nieuwe stad +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Kan hier geen nieuwe stad bouwen... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...te dicht bij de rand van de kaart +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...te dicht bij een andere stad +STR_0239_SITE_UNSUITABLE :{WHITE}...lokatie ongeschikt +STR_023A_TOO_MANY_TOWNS :{WHITE}...te veel steden +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Vergroot stad +STR_023C_EXPAND :{BLACK}Vergroot +STR_023D_RANDOM_TOWN :{BLACK}Willekeurige stad +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Bouw stad op willekeurige locatie +STR_023F_INDUSTRY_GENERATION :{WHITE}Industrieproductie +STR_0240_COAL_MINE :{BLACK}Kolenmijn +STR_0241_POWER_STATION :{BLACK}Energiecentrale +STR_0242_SAWMILL :{BLACK}Houtzagerij +STR_0243_FOREST :{BLACK}Bos +STR_0244_OIL_REFINERY :{BLACK}Olieraffinaderij +STR_0245_OIL_RIG :{BLACK}Olieplatform +STR_0246_FACTORY :{BLACK}Fabriek +STR_0247_STEEL_MILL :{BLACK}Hoogoven +STR_0248_FARM :{BLACK}Boerderij +STR_0249_IRON_ORE_MINE :{BLACK}IJzermijn +STR_024A_OIL_WELLS :{BLACK}Oliebron +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Papierfabriek +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Voedselverwerkingsfabriek +STR_024E_PRINTING_WORKS :{BLACK}Drukkerij +STR_024F_GOLD_MINE :{BLACK}Goudmijn +STR_0250_LUMBER_MILL :{BLACK}Houtkapperij +STR_0251_FRUIT_PLANTATION :{BLACK}Fruitplantage +STR_0252_RUBBER_PLANTATION :{BLACK}Rubberplantage +STR_0253_WATER_SUPPLY :{BLACK}Waterbron +STR_0254_WATER_TOWER :{BLACK}Watertoren +STR_0255_DIAMOND_MINE :{BLACK}Diamantmijn +STR_0256_COPPER_ORE_MINE :{BLACK}Kopermijn +STR_0257_COTTON_CANDY_FOREST :{BLACK}Suikerspinbos +STR_0258_CANDY_FACTORY :{BLACK}Snoepfabriek +STR_0259_BATTERY_FARM :{BLACK}Batterijplantage +STR_025A_COLA_WELLS :{BLACK}Colabronnen +STR_025B_TOY_SHOP :{BLACK}Speelgoedwinkel +STR_025C_TOY_FACTORY :{BLACK}Speelgoedfabriek +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plasticfonteinen +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Frisdrankfabriek +STR_025F_BUBBLE_GENERATOR :{BLACK}Bellenblazer +STR_0260_TOFFEE_QUARRY :{BLACK}Toffeegroeve +STR_0261_SUGAR_MINE :{BLACK}Suikermijn +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Plaats kolenmijn +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Plaats energiecentrale +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Plaats houtzagerij +STR_0265_PLANT_FOREST :{BLACK}Plant bos +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Plaats olieraffinaderij +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Plaats olieplatform (alleen bij randen van de kaart) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Plaats fabriek +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Plaats hoogoven +STR_026A_CONSTRUCT_FARM :{BLACK}Plaats boerderij +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Plaats ijzermijn +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Plaats oliebron +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Plaats bank (alleen in steden met een bevolking van meer dan 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Plaats papierfabriek +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Plaats voedselverwerkingsfabriek +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Plaats drukkerij +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Plaats goudmijn +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Plaats bank (alleen in steden) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Plaats houtkapperij (kapt regenwoud en produceert hout) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plant fruitplantage +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plant rubberplantage +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Plaats waterbron +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Plaats watertoren (alleen in steden) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Plaats diamantmijn +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Plaats kopermijn +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plant suikerspinbos +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Plaats snoepfabriek +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Plaats batterijplantage +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Plaats colabronnen +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Plaats speelgoedwinkel +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Plaats speelgoedfabriek +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Plaats plasticfonteinen +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Plaats frisdrankfabriek +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Plaats bellenblazer +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Plaats toffeegroeve +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Plaats suikermijn +STR_0285_CAN_T_BUILD_HERE :{WHITE}Kan {STRING} hier niet bouwen... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...plaats eerst stad +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...slechts één per stad toegestaan +STR_0288_PLANT_TREES :{BLACK}Plant bomen +STR_0289_PLACE_SIGN :{BLACK}Plaats bord +STR_028A_RANDOM_TREES :{BLACK}Willekeurige bomen +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Verspreid bomen over de kaart +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Plaats steenachtige gebieden op de kaart +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Plaats vuurtoren +STR_028E_PLACE_TRANSMITTER :{BLACK}Plaats radiomast +STR_028F_DEFINE_DESERT_AREA :{BLACK}Geef woestijngebied aan +STR_0290_DELETE :{BLACK}Verwijder +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Verwijder deze hele stad +STR_0292_SAVE_SCENARIO :Scenario opslaan +STR_0293_LOAD_SCENARIO :Scenario openen +STR_0294_QUIT_EDITOR :Sluit editor +STR_0295 : +STR_0296_QUIT :Afsluiten +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Sla scenario op, open scenario, scenarioeditor verlaten, OpenTTD afsluiten +STR_0298_LOAD_SCENARIO :{WHITE}Scenario openen +STR_0299_SAVE_SCENARIO :{WHITE}Scenario opslaan +STR_029A_PLAY_SCENARIO :{BLACK}Scenario spelen +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Weet je zeker dat je dit scenario wilt sluiten? +STR_029C_QUIT_EDITOR :{WHITE}Sluit editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan alleen in steden met bevolking van meer dan 1200 gebouwd worden +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Verplaats begindatum 1 jaar achteruit +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Verplaats begindatum 1 jaar vooruit +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...uiteinden van brug moeten beiden op land zijn +STR_02A1_SMALL :{BLACK}Klein +STR_02A2_MEDIUM :{BLACK}Middel +STR_02A3_LARGE :{BLACK}Groot +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Kies stadsgrootte +STR_02A5_TOWN_SIZE :{YELLOW}Stadsgrootte: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Laat laatste (nieuws)bericht zien +STR_02B8_SUMMARY :{BLACK}Kort +STR_02B9_FULL :{BLACK}Volledig +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Stedenlijst +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Voertuignamen +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Standaard +STR_02BF_CUSTOM :Aangepast +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Sla aangepaste namen op +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Keuze van voertuignamen +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Sla aangepaste voertuignamen op + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Spelopties +STR_02C4_GAME_OPTIONS :Spelopties +STR_02C5_DIFFICULTY_SETTINGS :Moeilijkheidsgraad +STR_02C6_DIFFICULTY_SETTINGS :Moeilijkheidsgraad +STR_02C7_CONFIG_PATCHES :Kies patches +STR_02C8_CONFIG_PATCHES :Kies patches +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Geef stadsnamen weer +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Geef stadsnamen weer +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Geef stationsnamen weer +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Geef stationsnamen weer +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Geef borden weer +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Geef borden weer +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Geef Checkpoints weer +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Geef Checkpoints weer +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Alle animatie +STR_02D0_FULL_ANIMATION :{SETX 12}Alle animatie +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Alle details +STR_02D2_FULL_DETAIL :{SETX 12}Alle details +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Transparante gebouwen +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Transparante gebouwen +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Info over blok land +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :ScreenShot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Grote ScreenShot (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Over OpenTTD +############ range ends here + +STR_02DA_ON :{BLACK}Aan +STR_02DB_OFF :{BLACK}Uit +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Toon subsidies +STR_02DD_SUBSIDIES :Subsidies +STR_02DE_MAP_OF_WORLD :Kaart +STR_02DF_TOWN_DIRECTORY :Stedenlijst +STR_02E0_CURRENCY_UNITS :{BLACK}Valuta +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Kies valuta +STR_02E3_DISTANCE_UNITS :{BLACK}Meetstelsel +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Kies meetstelsel +STR_02E6_ROAD_VEHICLES :{BLACK}Voertuigen +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Kies aan welke kant de voertuigen moeten rijden +STR_02E9_DRIVE_ON_LEFT :Links rijden +STR_02EA_DRIVE_ON_RIGHT :Rechts rijden +STR_02EB_TOWN_NAMES :{BLACK}Plaatsnamen +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Kies type plaatsnamen + +STR_02F4_AUTOSAVE :{BLACK}Autosave +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Kies interval tussen autosaves +STR_02F7_OFF :Uit +STR_02F8_EVERY_3_MONTHS :Iedere 3 maanden +STR_02F9_EVERY_6_MONTHS :Iedere 6 maanden +STR_02FA_EVERY_12_MONTHS :Iedere 12 maanden +STR_02FB_START_A_NEW_GAME :{BLACK}Start een nieuw spel +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Laad een opgeslagen spel +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Bekijk voorbeelden +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Maak een eigen spelwereld/scenario +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Kies een éénspelerspel +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Kies een tweespelerspel +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Bekijk opties +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Bekijk moeilijkheidsgraad +STR_0303_START_A_NEW_GAME_USING :{BLACK}Start een nieuw spel, gebaseerd op een scenario +STR_0304_QUIT :{BLACK}Afsluiten +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Verlaat OpenTTD +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Bekijk voorbeeld +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan alleen in steden gebouwd worden +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Kies gematigd klimaat +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Kies subarctisch klimaat +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Kies subtropisch klimaat +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Kies 'speelgoedland' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Betaal plaatsing van nieuwe industrie + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Betaal nieuwe industrie +STR_INDUSTRY_DIR :Industrielijst +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Betaal nieuwe industrie +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan alleen in steden gebouwd worden +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}...kan alleen in het regenwoud gebouwd worden +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kan alleen in woestijngebieden gebouwd worden +STR_0319_PAUSED :{YELLOW}* * GAPAUZEERD * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot succesvol opgeslagen als '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot mislukt! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Koop land voor toekomstig gebruik +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Voertuigen +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Spoorwegen +STR_032C_3_AIR_SERVICE :{BLACK}3: Vliegtuigen +STR_032D_4_SHIP_SERVICE :{BLACK}4: Schepen +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Spoorwegen (uitgebreid) +STR_032F_AUTOSAVE :{RED}AUTOSAVE +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Kies 'Ezy Street style music' programma + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Engels +STR_TOWNNAME_FRENCH :Frans +STR_TOWNNAME_GERMAN :Duits +STR_TOWNNAME_AMERICAN :Amerikaans +STR_TOWNNAME_LATIN_AMERICAN :Latijns-Amerikaans +STR_TOWNNAME_SILLY :Zot +STR_TOWNNAME_SWEDISH :Zweeds +STR_TOWNNAME_DUTCH :Nederlands +STR_TOWNNAME_FINNISH :Fins +STR_TOWNNAME_POLISH :Pools +STR_TOWNNAME_SLOVAKISH :Slowaaks +STR_TOWNNAME_HUNGARIAN :Hongaars +STR_TOWNNAME_AUSTRIAN :Oostenrijks +############ end of townname region + +STR_CURR_POUNDS :Ponden ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollars ($) +STR_CURR_FF :Franken (FF) +STR_CURR_DM :Duitse marken (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseta's (Pt) +STR_CURR_FT :Hongaarse Forint (Ft) +STR_CURR_ZL :Poolse Zloty (zl) +STR_CURR_ATS :Australische Shilling (ATS) +STR_CURR_BEF :Belgische Franken (BEF) +STR_CURR_DKK :Deense Kronen (DKK) +STR_CURR_FIM :Finse Markka (FIM) +STR_CURR_GRD :Griekse Drachma (GRD) +STR_CURR_CHF :Zwitserse Franken (CHF) +STR_CURR_NLG :Nederlandse Gulden (NLG) +STR_CURR_ITL :Italiaanse Lieren (ITL) +STR_CURR_SEK :Zweedse Kronen (SEK) +STR_CURR_RUR :Russische Rubel (rur) +STR_CURR_CZK :Tsjechse Koruna (CZK) +STR_CURR_ISK :IJslandse Kronen (ISK) +STR_CURR_NOK :Noorweegse Kronen (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Taal +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Selecteer de interfacetaal + +STR_OPTIONS_RES :{BLACK}Schermresolutie +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Selecteer de schermresolutie + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Screenshot formaat +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Selecteer het formaat van de screenshot + +STR_AUTOSAVE_1_MONTH :Elke maand +STR_AUTOSAVE_FAILED :{WHITE}Autosave is gefaald + +STR_MONTH_JAN :Januari +STR_MONTH_FEB :Februari +STR_MONTH_MAR :Maart +STR_MONTH_APR :April +STR_MONTH_MAY :Mei +STR_MONTH_JUN :Juni +STR_MONTH_JUL :Juli +STR_MONTH_AUG :Augustus +STR_MONTH_SEP :September +STR_MONTH_OCT :Oktober +STR_MONTH_NOV :November +STR_MONTH_DEC :December + +STR_HEADING_FOR_STATION :{LTBLUE}Op weg naar {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Op weg naar {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Geen orders +STR_NO_ORDERS_VEL :{LTBLUE}Geen orders, {VELOCITY} + +STR_PASSENGERS :passagiers +STR_BAGS :zakken +STR_TONS :ton +STR_LITERS :liter +STR_ITEMS :stuks +STR_CRATES :kratten +STR_RES_OTHER :anders +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Kan orderlijst niet delen... +STR_CANT_COPY_ORDER_LIST :{WHITE}Kan orderlijst niet kopieren... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Einde gedeelde orders - - + +STR_TRAIN_IS_LOST :{WHITE}Trein {COMMA16} is verdwaald. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Winst van train {COMMA16} was vorig jaar{CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Kies Patches +STR_CONFIG_PATCHES_TIP :{BLACK}Kies welke patches je wilt gebruiken +STR_CONFIG_PATCHES_CAPTION :{WHITE}Kies patches + +STR_CONFIG_PATCHES_OFF :Uit +STR_CONFIG_PATCHES_ON :Aan +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Geef snelheid in statusbalk weer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Bouwen op hellingen toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Verwijderen van meer stedelijke wegen, bruggen, tunnels, enz. toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Zeer lange treinen toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Realistische acceleratie van treinen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Stations samenvoegen als ze naast elkaar worden gebouwd: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Verlaat station wanneer één type lading geheel geladen is, met 'volledig laden': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflatie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Geen automatische treinreparatie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Lading alleen bezorgen aan een station als er vraag naar is: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Bouwen van zeer lange bruggen toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}'Ga naar depot' order toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Plaatsen van grondstofproducerende industrie toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Meerdere vergelijkbare industrieën per stad toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Industrieën van hetzelfde type dicht bij elkaar bouwen toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Altijd lange datum in statusbalk weergeven: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Seinen aan rijzijde plaatsen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Financieel overzicht aan het eind van het jaar weergeven: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch-compatibel nonstop-gebruik: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Rijvorming bij wegvoertuigen (met bijwerkingen): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Verschuif scherm als muis aan de rand is: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Omkopen van de gemeente toestaan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Nieuwe methode om het depot te vinden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Vrij gevormde stations: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Nieuw algorithme voor routeplanning van treinen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Bouwen in gepauzeerde toestand: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Altijd kleine vliegvelden toestaan: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Een trein is verdwaald als er geen voortgang is binnen: {ORANGE}{STRING} dagen +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Waarschuw als het inkomen van een trein negatief is: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES :{LTBLUE}Voertuigen verlopen nooit: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Automatisch voertuig vernieuwen wanneer het oud wordt +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Duur van foutmeldingen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Sneeuwhoogte: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maximale stationsomvang: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Helikopters automatisch repareren op helipads: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maximaal aantal treinen per speler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maximaal aantal wegvoertuigen per speler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maximaal aantal vliegtuigen per speler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maximaal aantal schepen per speler: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Treinen voor de computer uitschakelen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Wegvoertuigen voor de computer uitschakelen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Vliegtuigen voor de computer uitschakelen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Schepen voor de computer uitschakelen: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Standaard reparatie interval bij treinen: {ORANGE}{STRING} dagen +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Standaard reparatie interval bij wegvoertuigen: {ORANGE}{STRING} dagen +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Standaard reparatie interval bij vliegtuigen: {ORANGE}{STRING} dagen +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Standaard reparatie interval bij schepen: {ORANGE}{STRING} dagen + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Kleurenfoto's komen in: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Beginjaar: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Vloeiende economie inschakelen (meer, kleinere veranderingen) + +STR_CONFIG_PATCHES_GUI :{BLACK}Interface +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Constructie +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Voertuigen +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stations +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Economie + +STR_CONFIG_PATCHES_DISABLED :uitgeschakeld +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Verander waarde + + +STR_CHEATS :{WHITE}Cheats +STR_CHEATS_TIP :{BLACK}Keuzevakjes geven aan of je deze cheat al ooit gebruikt hebt. +STR_CHEATS_WARNING :{BLACK}Waarschuwing! Je staat op het punt je concurrenten te verraden. Denk eraan dat zo'n schande eeuwig onthouden wordt. +STR_CHEAT_MONEY :{LTBLUE}Verhoog geld met {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Spelend als speler: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magische bulldozer (industrieën en andere onverplaatsbare objecten verwijderen): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunnels mogen elkaar kruisen: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Naam +STR_TOWNDIR_POPULATION :{BLACK}Bevolking +STR_TOWNDIR_SORT_TIP :{BLACK}Kies sorteervolgorde + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Op weg naar {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Op weg naar {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Ga via {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Checkpoint {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Checkpoint {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Checkpoint + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Verander checkpointnaam + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Kan checkpointnaam niet veranderen... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Converteer rail naar checkpoint +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Kan hier geen checkpoint bouwen... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Kan hier geen checkpoint weghalen... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Bouw spoor met de Autorail-methode + +STR_NO_TOWN_IN_SCENARIO :{WHITE}...er is geen stad in dit scenario + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Weet je zeker dat je een willekeurig landschap wil maken? +STR_MANY_RANDOM_TOWNS :{BLACK}Veel willekeurige steden +STR_RANDOM_TOWNS_TIP :{BLACK}Bedek de kaart met willekeurig geplaatste steden +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Veel willekeurige industrieën +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Bedek de kaart met willekeurig geplaatste industrieën +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Kan geen industrieën genereren + +STR_LANDSCAPING_TOOLBAR :{WHITE}Terreinvorming +STR_LEVEL_LAND_TOOLTIP :{BLACK}Landhoogte gelijk maken + + +STR_TREES_RANDOM_TYPE :{BLACK}Bomen van willekeurig type +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Plant Bomen van willekeurig type + +STR_CANT_BUILD_CANALS :{WHITE}Kan hier geen kanaal bouwen... +STR_BUILD_CANALS_TIP :{BLACK}Bouw kanaal +STR_LANDINFO_CANAL :Kanaal + +STR_CANT_BUILD_LOCKS :{WHITE}Kan hier geen sluis bouwen... +STR_BUILD_LOCKS_TIP :{BLACK}Bouw sluis +STR_LANDINFO_LOCK :Sluis + +STR_LANDINFO_COORDS :{BLACK}Coördinaten: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Kan deel van station niet weghalen... +STR_CANT_CONVERT_RAIL :{WHITE}Kan railtype hier niet veranderen... +STR_CONVERT_RAIL_TIP :{BLACK}Verander railtype + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Sleep locomotief hierheen om de hele trein te verkopen + +STR_DRAG_DROP :{BLACK}Slepen +STR_STATION_DRAG_DROP :{BLACK}Bouw een station door te slepen + +STR_FAST_FORWARD :{BLACK}Verhoog de spelsnelheid +STR_MESSAGE_HISTORY :{WHITE}Berichtgeschiedenis +STR_MESSAGE_HISTORY_TIP :{BLACK}Een lijst met recente nieuwsberichten +STR_MESSAGES_DISABLE_ALL :{BLACK}Alles uitschakelen +STR_MESSAGES_ENABLE_ALL :{BLACK}Alles inschakelen + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Graaf kolenmijn +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plant bos +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Plaats olieplatform +STR_CONSTRUCT_FARM_TIP :{BLACK}Sticht boerderij +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Graaf kopermijn +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Boor voor olie +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Graaf goudmijn +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Graaf diamantmijn +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Graaf ijzermijn +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Sticht boomgaard +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Sticht rubberboerderij +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Sticht waterbron +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plant suikerspinbos +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Sticht batterijplantage +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Boor voor cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Sticht plasticfonteinen +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Plaats bellenblazer +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Sticht toffeegroeve +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Graaf suikermijn + +STR_INDUSTRYDIR_NAME :{BLACK}Naam +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Productie +STR_INDUSTRYDIR_TYPE :{BLACK}Type +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrielijst +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...te dicht bij een andere industrie + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Bouw trein om voor een ander ladingntype +STR_RAIL_REFIT :{WHITE}{STRING} (Omgebouwd} +STR_RAIL_REFIT_VEHICLE :{BLACK}Bouw trein om +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Kies type lading om te transporteren +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Bouw trein om voor geselecteerde ladingtype +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Kan trein niet ombouwen... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}Netwerkinterface werkt nog niet! + +STR_NETWORK_MULTIPLAYER :{WHITE}Multiplayer + +STR_NETWORK_FIND_SERVER :{BLACK}Server zoeken +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Zoeken naar een netwerkserver +STR_NETWORK_DIRECT_CONNECT :{BLACK}Directe verbinding +STR_NETWORK_ENTER_IP :{BLACK}IP adres van de server invoeren +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Verbind naar een bekend IP +STR_NETWORK_START_SERVER :{BLACK}Start server +STR_NETWORK_START_SERVER_TIP :{BLACK}Start eigen server + +STR_NETWORK_PLAYER_NAME :{BLACK}Spelernaam: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}Dit is de naam waarmee andere spelers je herkennen + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Selecteer verbindingstype: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Kies tussen een internetspel of een LAN spel +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Naam +STR_NETWORK_GAME_NAME_TIP :{BLACK}Naam van het spel +STR_NETWORK_PLAYERS :{BLACK}## +STR_NETWORK_PLAYERS_TIP :{BLACK}Spelers momenteel in dit spel / Maximum aantal spelers +STR_NETWORK_MAP_SIZE :{BLACK}Grootte +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Grootte van de kaart +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Taal, serverversie, etc. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Klik op een spel uit de lijst om deze te selecteren + +STR_NETWORK_JOIN_GAME :{BLACK}Meespelen + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Start nieuw spel + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Spelnaam: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}De spelnaam wordt weergegeven aan andere spelers in het multiplayer spelselectie menu +STR_NETWORK_PASSWORD :{BLACK}Wachtwoord: +STR_NETWORK_PASSWORD_TIP :{BLACK}Bescherm je spel met een wachtwoord als je niet wil dat andere mensen meespelen +STR_NETWORK_SELECT_MAP :{BLACK}Selecteer een kaart: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}Op welke kaart wil je spelen? +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Aantal spelers: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Kies een maximum aantal spelers. Niet alle plaatsen hoeven gevuld te zijn. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 spelers +STR_NETWORK_3_PLAYERS :{BLACK}3 spelers +STR_NETWORK_4_PLAYERS :{BLACK}4 spelers +STR_NETWORK_5_PLAYERS :{BLACK}5 spelers +STR_NETWORK_6_PLAYERS :{BLACK}6 spelers +STR_NETWORK_7_PLAYERS :{BLACK}7 spelers +STR_NETWORK_8_PLAYERS :{BLACK}8 spelers +STR_NETWORK_START_GAME :{BLACK}Start spel + + +STR_NETWORK_GAME_LOBBY :{WHITE}Multiplayer lobby + +STR_NETWORK_SEND :{BLACK}Verstuur +STR_NETWORK_SEND_TIP :{BLACK}Verstuur een bericht aan de andere spelers +STR_NETWORK_COMPANY_NAME :{BLACK}Bedrijfsnaam: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Verander de naam van je bedrijf. Druk op enter om de naam in te voeren +STR_NETWORK_SPECTATE_GAME :{BLACK}Bekijk spel +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Bekijk het spel als een toeschouwer +STR_NETWORK_NEW_COMPANY :{BLACK}Nieuw bedrijf +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Open een nieuw bedrijf +STR_NETWORK_READY :{BLACK}Klaar + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Kosten: {CURRENCY} +STR_0801_COST :{RED}Kosten: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Inkomsten: {CURRENCY} +STR_0803_INCOME :{GREEN}Inkomsten: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Verwachte kosten: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Verwachte kosten: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Verwachte inkomsten: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Verwachte inkomsten: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Kan het land hier niet verhogen... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Kan het land hier niet verlagen... +STR_080A_ROCKS :Rotsen +STR_080B_ROUGH_LAND :Ruw land +STR_080C_BARE_LAND :Onbegroeid land +STR_080D_GRASS :Gras +STR_080E_FIELDS :Akkers +STR_080F_SNOW_COVERED_LAND :Sneeuw +STR_0810_DESERT :Woestijn + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land heeft helling in verkeerde richting +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Onmogelijke spoorcombinatie +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Graafwerkzaamheden zouden tunnen beschadigen +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Reeds op zeeniveau +STR_1004_TOO_HIGH :{WHITE}Te hoog +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Geen bruikbaar spoor +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Train in depot +STR_1007_ALREADY_BUILT :{WHITE}...reeds gebouwd +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Bestaand spoor moet eerst weggehaald worden +STR_1009_TOO_MANY_DEPOTS :{WHITE}Te veel depots +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Spoorwegconstructie +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Monorailconstructie +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}MagLevconstructie +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Kies spoorbrug +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Kan hier geen treindepot bouwen... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Kan hier geen station bouwen... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Kan hier geen seinen plaatsen... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Kan hier geen spoor leggen... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Kan hier geen spoor weghalen... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Kan hier geen seinen weghalen... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Richting van treindepot +STR_1015_RAILROAD_CONSTRUCTION :Spoorwegconstructie +STR_1016_MONORAIL_CONSTRUCTION :Monorailconstructie +STR_1017_MAGLEV_CONSTRUCTION :MagLevconstructie +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Plaats spoor +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Bouw treindepot (om treinen te bouwen en te onderhouden) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Bouw station +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Plaats seinen +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Bouw spoorbrug +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Graaf spoortunnel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Kies tussen bouwen en weghalen voor spoor en seinen +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Brugkeuze - klik op de gewenste brug om die te bouwen +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Kies richting van treindepot +STR_1021_RAILROAD_TRACK :Spoor +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Spoor met seinen +STR_1023_RAILROAD_TRAIN_DEPOT :Treindepot +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...gebied is van ander bedrijf +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Spoor met normale seinen +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Spoor met voorseinen +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Spoor met uitgangseinen +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Spoor met combinatieseinen + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land heeft helling in verkeerde richting voor weg +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Moet weg eerst weghalen +STR_1802_ROAD_CONSTRUCTION :{WHITE}Wegenbouw +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Kies brug +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Kan hier geen weg bouwen... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Kan hier geen weg weghalen... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Richting van vrachtwagendepot +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan hier geen vrachtwagendepot bouwen... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Kan hier geen bushalte bouwen... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kan hier geen laadstation bouwen... +STR_180A_ROAD_CONSTRUCTION : +STR_180B_BUILD_ROAD_SECTION :{BLACK}Bouw weg +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Bouw wegvoertuigdepot (om voertuigen te bouwen en te repareren) +STR_180D_BUILD_BUS_STATION :{BLACK}Bouw bushalte +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Bouw vrachtwagen laadhal +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Bouw wegvoertuig +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Bouw wegtunnel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Schakel tussen bouwen en verwijderen voor wegbouw +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Brugselectie - klik op geselecteerde brug om deze te bouwen +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Selecteer richting van wegvoertuigdepot +STR_1814_ROAD : +STR_1815_ROAD_WITH_STREETLIGHTS : +STR_1816_TREE_LINED_ROAD : +STR_1817_ROAD_VEHICLE_DEPOT : +STR_1818_ROAD_RAIL_LEVEL_CROSSING : + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Steden +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Gebouw moet eerst gesloopt worden +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Bevolking: {ORANGE}{COMMA32}{BLACK} Huizen: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN : +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Kan stad niet hernoemen... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} gemeenteraad weigert dit toe te staan +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Plaatsnamen - klik op naam om het hoofdbeeld te centreren op de stad +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centreer de hoofdbeeld op de lokatie van de stad +STR_200C_CHANGE_TOWN_NAME :{BLACK}Hernoem stad +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagiers vorige maand: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Post vorige maand: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK : +STR_2010_OFFICE_BLOCK : +STR_2011_SMALL_BLOCK_OF_FLATS : +STR_2012_CHURCH :Kerk +STR_2013_LARGE_OFFICE_BLOCK : +STR_2014_TOWN_HOUSES : +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Standbeeld +STR_2017_FOUNTAIN :Fontein +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kantorenblok +STR_201A_SHOPS_AND_OFFICES :Winkels en kantoren +STR_201B_MODERN_OFFICE_BUILDING : +STR_201C_WAREHOUSE :Warenhuis +STR_201D_OFFICE_BLOCK : +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Oude huizen +STR_2020_LOCAL_AUTHORITY :{BLACK}Gemeente: +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Geef informatie over de gemeente weer +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} gemeente +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Reputatie van transportbedrijven: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subsidies +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Beschikbare subsidies:- +STR_2027_FROM_TO :{ORANGE}{STRING} van {STRING} naar {STRING} +STR_2028_BY :{YELLOW} (voor {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Geen +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Bestaande subsidies:- +STR_202C_FROM_TO :{ORANGE}{STRING} van {STATION} naar {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, tot {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Subsidieaanbod is verlopen:{}{}{STRING} van {STRING} naar {STRING} wordt nu niet meer gesubsidieerd. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subsidie teruggetrokken:{}{}{STRING}route van {STATION} naar {STATION} is nu niet meer gesubsidieerd. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Subsidie aangeboden:{}{}Eerste {STRING}route van {STRING} naar {STRING} krijgt een jaar lang subsidie van de gemeente! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subsidie uitgereikt aan {STRING}!{}{}{STRING}route van {STATION} naar {STATION} krijgt 50% extra voor het volgende jaar! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subsidie uitgereikt aan {STRING}!{}{}{STRING}route van {STATION} naar {STATION} krijgt dubbele omzet voor het volgende jaar! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subsidie uitgereikt aan {STRING}!{}{}{STRING}route van {STATION} naar {STATION} krijgt driedubbele omzet voor het volgende jaar! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subsidie uitgereikt aan {STRING}!{}{}{STRING}route van {STATION} naar {STATION} krijgt vierdubbele omzet voor het volgende jaar! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} gemeenteraad weigert het bouwen van nog een vliegveld in deze stad. +STR_2036_COTTAGES : +STR_2037_HOUSES :Huizen +STR_2038_FLATS :Flats +STR_2039_TALL_OFFICE_BLOCK : +STR_203A_SHOPS_AND_OFFICES : +STR_203B_SHOPS_AND_OFFICES : +STR_203C_THEATER :Theater +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Kantoren +STR_203F_HOUSES :Huizen +STR_2040_CINEMA :Bioscoop +STR_2041_SHOPPING_MALL :Winkelcentrum +STR_2042_DO_IT :{BLACK}Doe het +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Lijst met dingen die mogelijk zijn in deze stad - klik op een item voor meer details +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Voer de geselecteerde actie uit in de bovenstaande lijst +STR_2045_ACTIONS_AVAILABLE :{BLACK}Mogelijkheiden: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Kleine reclamecampagne +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Middelgrote reclamecampagne +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Grote reclamecampagne +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Betaal wegreparatie +STR_204A_BUILD_STATUE_OF_COMPANY :Bouw standbeeld van directeur +STR_204B_FUND_NEW_BUILDINGS :Betaal nieuwe gebouwen +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Koop exclusieve transportrechten +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Koop de gemeenteraad om +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Begin een kleine reclamecampagne, om meer passagiers en goederen naar je transportdiensten te trekken.{} Kosten: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Begin een middelgrote advertentiecampagne, om meer passagiers en goederen naar je transportdiensten te trekken.{} Kosten: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Begin een grote advertentiecampagne, om meer passagiers en goederen naar je transportdiensten te trekken.{} Kosten: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Betaal een vernieuwing van het wegdek. Veroorzaakt merkbare verstoring van het wegverkeer tot 6 maanden.{} Kosten: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Bouw een standbeeld ter ere van jouw bedrijf.{} Kosten: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Betaal de bouw van nieuwe commerciele gebouwen in de stad.{} Kosten: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Koop 1 jaar exclusieve transportrechten in deze stad. De gemeenteraad staat passagiers en goederen toe alleen jouw stations te gebruiken.{} Kosten: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Bribe the local authority to increase your rating, at the risk of a severe penalty if caught.{} Cost: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Kan dit niet doen... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Verkeerschaos in {TOWN}!{}{}Wegreparatie betaald door {STRING} zorgt voor 6 maanden van ergernis bij weggebruikers! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (in aanbouw) +STR_2059_IGLOO :Iglo +STR_205A_TEPEES :Tepees +STR_205B_TEAPOT_HOUSE :Theepothuis +STR_205C_PIGGY_BANK :Varkensbank + +##id 0x2800 +STR_LANDSCAPING :Terreinvorming +STR_2800_PLANT_TREES :Plant bomen +STR_2801_PLACE_SIGN :Plaats bord +STR_2802_TREES :{WHITE}Bomen +STR_2803_TREE_ALREADY_HERE :{WHITE}....er staat hier al een boom +STR_2804_SITE_UNSUITABLE :{WHITE}...plek niet geschikt +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Kan hier geen boom planten... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...teveel borden +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Kan hier geen bord plaatsen +STR_280A_SIGN :Bord +STR_280B_EDIT_SIGN_TEXT :{WHITE}Wijzig tekst van bord +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Kan de naam van het bord niet wijzigen +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Kies een boom om te planten +STR_280E_TREES :Bomen +STR_280F_RAINFOREST :Tropisch bos +STR_2810_CACTUS_PLANTS :Cactus planten + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Station selectie +STR_3001_AIRPORT_SELECTION :{WHITE}Vliegveld selectie +STR_3002_ORIENTATION :{BLACK}Richting +STR_3003_NUMBER_OF_TRACKS :{BLACK}Aantal sporen +STR_3004_PLATFORM_LENGTH :{BLACK}Platformlengte +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Te dicht bij een ander station +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Voegt meer dan één bestaand (laad)station samen +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Teveel (laad)stations in de buurt van deze stad +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Teveel (laad)stations +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Te dicht bij een andere (laad)station +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Verwijder eerst treinstation +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Te dicht bij een ander vliegveld +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Verwijder eerst vliegveld + +STR_3030_RENAME_STATION_LOADING :Hernoem station/laadgebied +STR_3031_CAN_T_RENAME_STATION :{WHITE}Kan station niet hernoemen... +STR_3032_RATINGS :{BLACK}Ratings +STR_3033_ACCEPTS :{BLACK}Accepts +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Local rating of transport service: + +############ range for rating starts +STR_3035_APPALLING :Teleurstellend +STR_3036_VERY_POOR :Erg slecht +STR_3037_POOR :Slecht +STR_3038_MEDIOCRE :Matig +STR_3039_GOOD :Goed +STR_303A_VERY_GOOD :Erg goed +STR_303B_EXCELLENT :Geweldig +STR_303C_OUTSTANDING :Uitstekend +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} no longer accepts {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} no longer accepts {STRING} or {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} now accepts {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} now accepts {STRING} and {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Richting van bushalte +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Richting van vrachtwagen laadgebied +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Te dicht bij een andere bushalte +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Te dicht bij een ander vrachtwagen laadgebied +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Verwijder eerst bushalte +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Verwijder eerst vrachtwagen laadgebied +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stations +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Geen - +STR_304B_SITE_UNSUITABLE :{WHITE}...plaats ongeschikt +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Te dicht bij een andere dok +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Verwijder eerst dock +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Selecteer stationrichting +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Selecteer aantal platforms voor station +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Selecteer lengte van station +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Selecteer richting van bushalte +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Selecteer richting van vrachtwagen laadgebied +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centreer hoofdbeeld op lokatie van station +STR_3054_SHOW_STATION_RATINGS :{BLACK}Show station ratings +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Hernoem station +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Laat lijst van gevraagde goederen zien +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Station namen - klik op naam om het hoofdbeeld te centreren op het station +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Selecteer grootte en type van vliegveld +STR_3059_SMALL :{BLACK}Klein +STR_305A_LARGE :{BLACK}Stedelijk +STR_305AA_LARGE :{BLACK}Hoofdstedelijk vliegveld +STR_305AB_LARGE :{BLACK}Internationaal vliegveld +STR_305B_SIZE :{BLACK}Grootte +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION : +STR_305F_AIRCRAFT_HANGAR : +STR_3060_AIRPORT :Vliegveld +STR_3061_TRUCK_LOADING_AREA : +STR_3062_BUS_STATION :Bushalte +STR_3063_SHIP_DOCK : +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Highlight coverage area of proposed site +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Don't highlight coverage area of proposed site +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Coverage area highlight +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Monorail stationselectie +STR_3068_DOCK :{WHITE}Dok +STR_3069_BUOY :Boei +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boei in de weg +STR_306B_HELIPORT :{BLACK}Helipoort +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...station te verspreid + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Ship Depot Orientation +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...must be built on water +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Can't build ship depot here... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Select ship depot orientation +STR_3804_WATER :Water +STR_3805_COAST_OR_RIVERBANK :Kust of rivierbed +STR_3806_SHIP_DEPOT :Schipdepot +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Can't build on water + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Save Game +STR_4001_LOAD_GAME :{WHITE}Load Game +STR_4002_SAVE :{BLACK}Opslaan +STR_4003_DELETE :{BLACK}Verwijderen +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes vrij +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Kan niet lezen van schijf +STR_4007_GAME_SAVE_FAILED :{WHITE}Game Save Failed +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Kan bestand niet verwijderen +STR_4009_GAME_LOAD_FAILED :{WHITE}Game Load Failed +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}List of drives, directories and saved-game files +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Currently selected name for saved-game +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Delete the currently selected saved-game +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Save the current game, using the selected name +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Select New Game Type +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Select scenario (green), pre-set game (blue), or random new game +STR_4010_GENERATE_RANDOM_NEW_GAME :Genereer willekeurig nieuw spel + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} in de weg +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kolenmijn +STR_4803_POWER_STATION :Energiecentrale +STR_4804_SAWMILL :Houtzagerij +STR_4805_FOREST :Bos +STR_4806_OIL_REFINERY :Olieraffinaderij +STR_4807_OIL_RIG :Olieplatform +STR_4808_FACTORY :Fabriek +STR_4809_PRINTING_WORKS :Drukkerij +STR_480A_STEEL_MILL :Hoogoven +STR_480B_FARM :Boerderij +STR_480C_COPPER_ORE_MINE :Kopermijn +STR_480D_OIL_WELLS :Oliebron +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Voedselfabriek +STR_4810_PAPER_MILL :Papierfabriek +STR_4811_GOLD_MINE :Goudmijn +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamandmijn +STR_4814_IRON_ORE_MINE :IJzermijn +STR_4815_FRUIT_PLANTATION :Boomgaard +STR_4816_RUBBER_PLANTATION :Rubberboerderij +STR_4817_WATER_SUPPLY :Waterbron +STR_4818_WATER_TOWER :Watertoren +STR_4819_FACTORY :Fabriek +STR_481A_FARM :Boerderij +STR_481B_LUMBER_MILL :Houtkapperij +STR_481C_COTTON_CANDY_FOREST :Suikerspinbos +STR_481D_CANDY_FACTORY :Snoepfabriek +STR_481E_BATTERY_FARM :Batterijplantage +STR_481F_COLA_WELLS :Colabronnen +STR_4820_TOY_SHOP :Speelgoedwinkel +STR_4821_TOY_FACTORY :Speelgoedfabriek +STR_4822_PLASTIC_FOUNTAINS :Plasticfonteinen +STR_4823_FIZZY_DRINK_FACTORY :Frisdrankfabriek +STR_4824_BUBBLE_GENERATOR :Bellenblazer +STR_4825_TOFFEE_QUARRY :Toffeegroeve +STR_4826_SUGAR_MINE :Suikermijn + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Requires: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Requires: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Requires: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Productie vorige maand: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% getransporteerd) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Center the main view on industry location +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}New {STRING} under construction near {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}New {STRING} being planted near {TOWN}! +STR_482F_COST :{BLACK}Kosten: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Can't construct this industry type here... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...forest can only be planted above snow-line +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} announces imminent closure! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Supply problems cause {TOWN} {STRING} to announce imminent closure! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Lack of nearby trees causes {TOWN} {STRING} to announce imminent closure! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} vergroot hun productie! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}New coal seam found at {TOWN} {STRING}!{}Production is expected to double! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}New oil reserves found at {TOWN} {STRING}!{}Production is expected to double! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Improved farming methods at {TOWN} {STRING} are expected to double production! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} productie verlaagd met 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insect infestation causes havoc at {TOWN} {STRING}!{}Production down by 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...can only be positioned near edges of map +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} production at {TOWN} {STRING} goes up by {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} production at {TOWN} {STRING} goes down by {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Trein in tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Road vehicle in tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Another tunnel in the way +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Unable to excavate land for other end of tunnel +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Must demolish tunnel first +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Must demolish bridge first +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Cannot start and end on same position +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Level land or water required under bridge +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start and end must be in line +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Site unsuitable for tunnel entrance +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Suspension, Steel +STR_500F_GIRDER_STEEL :Girder, Steel +STR_5010_CANTILEVER_STEEL :Cantilever, Steel +STR_5011_SUSPENSION_CONCRETE :Suspension, Concrete +STR_5012_WOODEN :Wooden +STR_5013_CONCRETE :Concrete +STR_5014_TUBULAR_STEEL :Tubular, Steel +STR_BRIDGE_TUBULAR_SILICON :Tubular, Silicon +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Can't build bridge here... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... +STR_5017_RAILROAD_TUNNEL :Railroad tunnel +STR_5018_ROAD_TUNNEL :Road tunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Steel suspension rail bridge +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Steel girder rail bridge +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Steel cantilever rail bridge +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Reinforced concrete suspension rail bridge +STR_501F_WOODEN_RAIL_BRIDGE :Wooden rail bridge +STR_5020_CONCRETE_RAIL_BRIDGE :Concrete rail bridge +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Steel suspension road bridge +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Steel girder road bridge +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Steel cantilever road bridge +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Reinforced concrete suspension road bridge +STR_5025_WOODEN_ROAD_BRIDGE :Wooden road bridge +STR_5026_CONCRETE_ROAD_BRIDGE :Concrete road bridge +STR_5027_TUBULAR_RAIL_BRIDGE :Tubular rail bridge +STR_5028_TUBULAR_ROAD_BRIDGE :Tubular road bridge +STR_5029_STEEL :Steel + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Object in the way +STR_5801_TRANSMITTER :Transmitter +STR_5802_LIGHTHOUSE :Lighthouse +STR_5803_COMPANY_HEADQUARTERS :Company Headquarters +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...company headquarters in the way +STR_5805_COMPANY_OWNED_LAND :Company-owned land +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Can't purchase this land area... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...you already own it! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Unnamed{SKIP} +STR_SV_TRAIN_NAME :Train {COMMA16} +STR_SV_ROADVEH_NAME :Wegvoertuig {COMMA16} +STR_SV_SHIP_NAME :Schip {COMMA16} +STR_SV_AIRCRAFT_NAME :Vliegtuig {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Noord +STR_SV_STNAME_SOUTH :{STRING} Zuid +STR_SV_STNAME_EAST :{STRING} Oost +STR_SV_STNAME_WEST :{STRING} West +STR_SV_STNAME_CENTRAL :{STRING} Centraal +STR_SV_STNAME_TRANSFER :{STRING} Transfer +STR_SV_STNAME_HALT :{STRING} Halt +STR_SV_STNAME_VALLEY :{STRING} Vallei +STR_SV_STNAME_HEIGHTS :{STRING} Heights +STR_SV_STNAME_WOODS :{STRING} Bossen +STR_SV_STNAME_LAKESIDE :{STRING} Lakeside +STR_SV_STNAME_EXCHANGE :{STRING} Exchange +STR_SV_STNAME_AIRPORT :{STRING} Vliegveld +STR_SV_STNAME_OILFIELD :{STRING} Oilfield +STR_SV_STNAME_MINES :{STRING} Mijnen +STR_SV_STNAME_DOCKS :{STRING} Docks +STR_SV_STNAME_BUOY_1 :{STRING} Boei 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boei 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boei 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boei 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boei 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boei 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boei 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boei 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boei 9 +STR_SV_STNAME_ANNEXE :{STRING} Annexe +STR_SV_STNAME_SIDINGS :{STRING} Sidings +STR_SV_STNAME_BRANCH :{STRING} Branch +STR_SV_STNAME_UPPER :Upper {STRING} +STR_SV_STNAME_LOWER :Lower {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Forest + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Moeilijksheidsgraad + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Gemakkelijk +STR_6802_MEDIUM :{BLACK}Gemiddeld +STR_6803_HARD :{BLACK}Moeilijk +STR_6804_CUSTOM :{BLACK}Aangepast +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maximaal aantal tegenstanders: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Starttijd van tegenstanders: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Aantal steden: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Aantal industrieën: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maximale lening: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Startrente: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Brandstofkosten: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}Bouwsnelheid van tegenstanders: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligentie van tegenstanders: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Vehicle breakdowns: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Subsidy multiplier: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Bouwkosten: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Terreinsoort: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Quantity of sea/lakes: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Economie: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Train reversing: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Rampen: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Laag +STR_6817_NORMAL :Normaal +STR_6818_HIGH :Hoog +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Erg langzaam +STR_681C_SLOW :Langzaam +STR_681D_MEDIUM :Gemiddeld +STR_681E_FAST :Snel +STR_681F_VERY_FAST :Erg snel +STR_VERY_LOW :Erg laag +STR_6820_LOW :Laag +STR_6821_MEDIUM :Gemiddeld +STR_6822_HIGH :Hoog +STR_6823_NONE :Geen +STR_6824_REDUCED :Verminderd +STR_6825_NORMAL :Normaal +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Erg plat +STR_682B_FLAT :Plat +STR_682C_HILLY :Heuvelachtig +STR_682D_MOUNTAINOUS :Bergachtig +STR_682E_STEADY :Stabiel +STR_682F_FLUCTUATING :Schommelend +STR_6830_IMMEDIATE :Meteen +STR_6831_3_MONTHS_AFTER_PLAYER :3 maanden na speler +STR_6832_6_MONTHS_AFTER_PLAYER :6 maanden na speler +STR_6833_9_MONTHS_AFTER_PLAYER :9 maanden na speler +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Aan het eind van het spoor, en in stations +STR_6835_AT_END_OF_LINE_ONLY :Aan het eind van het spoor +STR_6836_OFF :Uit +STR_6837_ON :Aan +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Show hi-score chart + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 :(Speler 1) +STR_7003_PLAYER_2 :(Speler 2) +STR_7004_NEW_FACE :{BLACK}Nieuw gezicht +STR_7005_COLOR_SCHEME :{BLACK}Kleurenschema +STR_7006_COLOR_SCHEME :{GOLD}Kleurenschema: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nieuw kleurenschema +STR_7008_COMPANY_NAME :{BLACK}Bedrijfsnaam +STR_7009_PRESIDENT_NAME :{BLACK}Naam van directeur +STR_700A_COMPANY_NAME :Bedrijfsnaam +STR_700B_PRESIDENT_S_NAME :Naam van directeur +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Kan bedrijfsnaam niet veranderen... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Can't change president's name... +STR_700E_FINANCES :{WHITE}{STRING} Finances{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Uitgaven/inkomsten +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Bouwkosten +STR_7012_NEW_VEHICLES :{GOLD}Nieuwe voertuigen +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Trein brandstofkosten +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Wegvoertuig brandstofkosten +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Vliegtuig brandstofkosten +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Schip brandstofkosten +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Eigendomsonderhoud +STR_7018_TRAIN_INCOME :{GOLD}Treininkomsten +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Wegvoertuiginkomsten +STR_701A_AIRCRAFT_INCOME :{GOLD}Vliegtuiginkomsten +STR_701B_SHIP_INCOME :{GOLD}Schipinkomsten +STR_701C_LOAN_INTEREST :{GOLD}Rente van lening +STR_701D_OTHER :{GOLD}Overig +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Totaal: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Inkomstengrafiek +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Operating Profit Graph +STR_7026_BANK_BALANCE :{WHITE}Bank Balance +STR_7027_LOAN :{WHITE}Lening +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Leen {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Betaal {SKIP}{SKIP}{SKIP}{CURRENCY} terug +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maximaal toegestane leninggrootte is {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Kan geen geld meer lenen... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...geen lening om terug te betalen +STR_702E_REQUIRED :{WHITE}...{CURRENCY} benodigd +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Kan geen lening terugbetalen +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Kies nieuw gezicht voor directeur +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Change the company vehicle livery +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Change the president's name +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Change the company name +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Klik op geselecteerde nieuwe kleurenschema +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Vergroot lening +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Betaal deel van lening terug +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Directeur) +STR_7038_INAUGURATED :{GOLD}Inaugurated: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Voertuigen: +STR_703A_TRAIN :{WHITE}{COMMA16} trein +STR_703B_TRAINS :{WHITE}{COMMA16} treinen +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} wegvoertuig +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} wegvoertuigen +STR_703E_AIRCRAFT :{WHITE}{COMMA16} vliegtuig +STR_703F_AIRCRAFT :{WHITE}{COMMA16} vliegtuigen +STR_7040_SHIP :{WHITE}{COMMA16} schip +STR_7041_SHIPS :{WHITE}{COMMA16} schepen +STR_7042_NONE :{WHITE}Geen +STR_7043_FACE_SELECTION :{WHITE}Gezichtsselectie +STR_7044_MALE :{BLACK}Mannelijk +STR_7045_FEMALE :{BLACK}Vrouwelijk +STR_7046_NEW_FACE :{BLACK}Nieuw gezicht +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Annuleer nieuwe gezichtsselectie +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Accepteer nieuwe gezichtsselectie +STR_7049_SELECT_MALE_FACES :{BLACK}Selecteer mannelijke gezichten +STR_704A_SELECT_FEMALE_FACES :{BLACK}Selecteer vrouwelijke gezichten +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Genereer willekeurig nieuw gezicht +STR_704C_KEY :{BLACK}Legenda +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Laat grafieklegenda zien +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Legenda voor bedrijfsgrafieken +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Klik hier om dit bedrijf weer te geven of te verbergen op de grafiek +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Eenheden van goederen afgeleverd +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Company performance ratings (maximum rating=1000) +STR_7052_COMPANY_VALUES :{WHITE}Bedrijfswaarde +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Company League Table +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transportbedrijf in de problemen! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} wordt verkocht of failliet verklaard tenzij finanicele situatie snel verbetert! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Directeur) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Transportbedrijf overgenomen! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} is verkocht aan {STRING} voor {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}We zoeken voor een transportbedrijf dat ons bedrijf over kan nemen.{}{}Wil je {STRING} kopen voor {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Failliet! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} has been closed down by creditors and all assets sold off! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nieuw transportbedrijf opgestart! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} begint met bouwen in de buurt van {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Kan bedrijf niet kopen... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Cargo Payment Rates +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Days in transit +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Payment for delivering 10 units (or 10,000 litres) of cargo a distance of 20 squares +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Toggle graph for cargo type on/off +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Engineer +STR_7067_TRAFFIC_MANAGER :Traffic Manager +STR_7068_TRANSPORT_COORDINATOR :Transport Coordinator +STR_7069_ROUTE_SUPERVISOR :Route Supervisor +STR_706A_DIRECTOR :Director +STR_706B_CHIEF_EXECUTIVE :Chief Executive +STR_706C_CHAIRMAN :Chairman +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Build HQ +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Build company headquarters / view company headquarters +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Can't build company headquarters... +STR_7072_VIEW_HQ :{BLACK}View HQ +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}World Recession!{}{}Financial experts fear worst as economy slumps! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Recession Over!{}{}Upturn in trade gives confidence to industries as economy strengthens! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Toggle large/small window size +STR_7076_COMPANY_VALUE :{GOLD}Company value: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Buy 25% share in company +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Sell 25% share in company +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Buy 25% share in this company +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Sell 25% share in this company +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Can't buy 25% share in this company... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Can't sell 25% share in this company... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% owned by {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% owned by {STRING}{} {COMMA16}% owned by {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} has been taken over by {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Steam) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Steam) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Steam) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Steam) +STR_800A_SH_8P_STEAM :SH '8P' (Steam) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Electric) +STR_8018_SH_40_ELECTRIC :SH '40' (Electric) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Electric) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Electric) +STR_801B_PASSENGER_CAR :Passenger Car +STR_801C_MAIL_VAN :Mail Van +STR_801D_COAL_CAR :Coal Car +STR_801E_OIL_TANKER :Oil Tanker +STR_801F_LIVESTOCK_VAN :Livestock Van +STR_8020_GOODS_VAN :Goods Van +STR_8021_GRAIN_HOPPER :Grain Hopper +STR_8022_WOOD_TRUCK :Wood Truck +STR_8023_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8024_STEEL_TRUCK :Steel Truck +STR_8025_ARMORED_VAN :Armored Van +STR_8026_FOOD_VAN :Food Van +STR_8027_PAPER_TRUCK :Paper Truck +STR_8028_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8029_WATER_TANKER :Water Tanker +STR_802A_FRUIT_TRUCK :Fruit Truck +STR_802B_RUBBER_TRUCK :Rubber Truck +STR_802C_SUGAR_TRUCK :Sugar Truck +STR_802D_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_802E_TOFFEE_HOPPER :Toffee Hopper +STR_802F_BUBBLE_VAN :Bubble Van +STR_8030_COLA_TANKER :Cola Tanker +STR_8031_CANDY_VAN :Candy Van +STR_8032_TOY_VAN :Toy Van +STR_8033_BATTERY_TRUCK :Battery Truck +STR_8034_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8035_PLASTIC_TRUCK :Plastic Truck +STR_8036_X2001_ELECTRIC :'X2001' (Electric) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Electric) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Passenger Car +STR_803A_MAIL_VAN :Mail Van +STR_803B_COAL_CAR :Coal Car +STR_803C_OIL_TANKER :Oil Tanker +STR_803D_LIVESTOCK_VAN :Livestock Van +STR_803E_GOODS_VAN :Goods Van +STR_803F_GRAIN_HOPPER :Grain Hopper +STR_8040_WOOD_TRUCK :Wood Truck +STR_8041_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8042_STEEL_TRUCK :Steel Truck +STR_8043_ARMORED_VAN :Armored Van +STR_8044_FOOD_VAN :Food Van +STR_8045_PAPER_TRUCK :Paper Truck +STR_8046_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8047_WATER_TANKER :Water Tanker +STR_8048_FRUIT_TRUCK :Fruit Truck +STR_8049_RUBBER_TRUCK :Rubber Truck +STR_804A_SUGAR_TRUCK :Sugar Truck +STR_804B_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_804C_TOFFEE_HOPPER :Toffee Hopper +STR_804D_BUBBLE_VAN :Bubble Van +STR_804E_COLA_TANKER :Cola Tanker +STR_804F_CANDY_VAN :Candy Van +STR_8050_TOY_VAN :Toy Van +STR_8051_BATTERY_TRUCK :Battery Truck +STR_8052_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8053_PLASTIC_TRUCK :Plastic Truck +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Electric) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Electric) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Electric) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Electric) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Passenger Car +STR_805A_MAIL_VAN :Mail Van +STR_805B_COAL_CAR :Coal Car +STR_805C_OIL_TANKER :Oil Tanker +STR_805D_LIVESTOCK_VAN :Livestock Van +STR_805E_GOODS_VAN :Goods Van +STR_805F_GRAIN_HOPPER :Grain Hopper +STR_8060_WOOD_TRUCK :Wood Truck +STR_8061_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8062_STEEL_TRUCK :Steel Truck +STR_8063_ARMORED_VAN :Armored Van +STR_8064_FOOD_VAN :Food Van +STR_8065_PAPER_TRUCK :Paper Truck +STR_8066_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8067_WATER_TANKER :Water Tanker +STR_8068_FRUIT_TRUCK :Fruit Truck +STR_8069_RUBBER_TRUCK :Rubber Truck +STR_806A_SUGAR_TRUCK :Sugar Truck +STR_806B_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_806C_TOFFEE_HOPPER :Toffee Hopper +STR_806D_BUBBLE_VAN :Bubble Van +STR_806E_COLA_TANKER :Cola Tanker +STR_806F_CANDY_VAN :Candy Van +STR_8070_TOY_VAN :Toy Van +STR_8071_BATTERY_TRUCK :Battery Truck +STR_8072_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8073_PLASTIC_TRUCK :Plastic Truck +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Coal Truck +STR_807C_UHL_COAL_TRUCK :Uhl Coal Truck +STR_807D_DW_COAL_TRUCK :DW Coal Truck +STR_807E_MPS_MAIL_TRUCK :MPS Mail Truck +STR_807F_REYNARD_MAIL_TRUCK :Reynard Mail Truck +STR_8080_PERRY_MAIL_TRUCK :Perry Mail Truck +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Mail Truck +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Mail Truck +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Mail Truck +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Oil Tanker +STR_8085_FOSTER_OIL_TANKER :Foster Oil Tanker +STR_8086_PERRY_OIL_TANKER :Perry Oil Tanker +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Livestock Van +STR_8088_UHL_LIVESTOCK_VAN :Uhl Livestock Van +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Livestock Van +STR_808A_BALOGH_GOODS_TRUCK :Balogh Goods Truck +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Goods Truck +STR_808C_GOSS_GOODS_TRUCK :Goss Goods Truck +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Grain Truck +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Grain Truck +STR_808F_GOSS_GRAIN_TRUCK :Goss Grain Truck +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Wood Truck +STR_8091_FOSTER_WOOD_TRUCK :Foster Wood Truck +STR_8092_MORELAND_WOOD_TRUCK :Moreland Wood Truck +STR_8093_MPS_IRON_ORE_TRUCK :MPS Iron Ore Truck +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Iron Ore Truck +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Iron Ore Truck +STR_8096_BALOGH_STEEL_TRUCK :Balogh Steel Truck +STR_8097_UHL_STEEL_TRUCK :Uhl Steel Truck +STR_8098_KELLING_STEEL_TRUCK :Kelling Steel Truck +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Armored Truck +STR_809A_UHL_ARMORED_TRUCK :Uhl Armored Truck +STR_809B_FOSTER_ARMORED_TRUCK :Foster Armored Truck +STR_809C_FOSTER_FOOD_VAN :Foster Food Van +STR_809D_PERRY_FOOD_VAN :Perry Food Van +STR_809E_CHIPPY_FOOD_VAN :Chippy Food Van +STR_809F_UHL_PAPER_TRUCK :Uhl Paper Truck +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Paper Truck +STR_80A1_MPS_PAPER_TRUCK :MPS Paper Truck +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Copper Ore Truck +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Copper Ore Truck +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Copper Ore Truck +STR_80A5_UHL_WATER_TANKER :Uhl Water Tanker +STR_80A6_BALOGH_WATER_TANKER :Balogh Water Tanker +STR_80A7_MPS_WATER_TANKER :MPS Water Tanker +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Fruit Truck +STR_80A9_UHL_FRUIT_TRUCK :Uhl Fruit Truck +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Fruit Truck +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Rubber Truck +STR_80AC_UHL_RUBBER_TRUCK :Uhl Rubber Truck +STR_80AD_RMT_RUBBER_TRUCK :RMT Rubber Truck +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Sugar Truck +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Sugar Truck +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Sugar Truck +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Cola Truck +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Cola Truck +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Cola Truck +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Cotton Candy Truck +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Cotton Candy Truck +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Cotton Candy Truck +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Toffee Truck +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Toffee Truck +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Toffee Truck +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Toy Van +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Toy Van +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Toy Van +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Candy Truck +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Candy Truck +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Candy Truck +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Battery Truck +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Battery Truck +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Battery Truck +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Fizzy Drink Truck +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Fizzy Drink Truck +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Fizzy Drink Truck +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastic Truck +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastic Truck +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastic Truck +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Bubble Truck +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Bubble Truck +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Bubble Truck +STR_80CC_MPS_OIL_TANKER :MPS Oil Tanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Oil Tanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Passenger Ferry +STR_80CF_FFP_PASSENGER_FERRY :FFP Passenger Ferry +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Hovercraft +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passenger Ferry +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passenger Ferry +STR_80D3_YATE_CARGO_SHIP :Yate Cargo ship +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Cargo ship +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Cargo ship +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Cargo ship +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helicopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helicopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helicopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE :{WHITE}Bericht van voertuigenfabrikant +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}We hebben zojuist een nieuwe {STRING} ontworpen - ben je geinteresseerd in een jaar lang exclusief gebruik van dit voertuig, zodat we kunnen zien of het goed werkt voordat we het wereldwijd beschikbaar maken? +STR_8102_RAILROAD_LOCOMOTIVE :spoorweg locomotief +STR_8103_ROAD_VEHICLE :wegvoertuig +STR_8104_AIRCRAFT :vliegtuig +STR_8105_SHIP :schip +STR_8106_MONORAIL_LOCOMOTIVE :monorail locomotief +STR_8107_MAGLEV_LOCOMOTIVE :maglev locomotief + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Treindepot +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First train arrives at {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Details) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Trein in de weg +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Ga naar {STATION} +STR_8807_GO_TO_UNLOAD :Ga naar {STATION} (Uitladen) +STR_8808_GO_TO_LOAD :Ga naar {STATION} (Inladen) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Ga non-stop naar {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Ga non-stop naar {STATION} (Uitladen) +STR_880C_GO_NON_STOP_TO_LOAD :Ga non-stop naar {STATION} (Inladen) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Ga naar {TOWN} treindepot +STR_SERVICE_AT_TRAIN_DEPOT :Reparatie in {TOWN} treindepot +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Ga non-stop naar {TOWN} treindepot +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Non-stop reparatie in {TOWN} treindepot + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Heading for {TOWN} Train Depot +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Train Depot, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Leeg +STR_8813_FROM :{LTBLUE}{CARGO} van {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Trein {COMMA16} wacht in depot +STR_8815_NEW_VEHICLES :{BLACK}Nieuwe voertuigen +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Kosten: {GOLD}{CURRENCY}{BLACK} Gewicht: {GOLD}{COMMA16}t{}{BLACK}Snelheid: {GOLD}{VELOCITY}{BLACK} Kracht: {GOLD}{COMMA16}pk{}{BLACK}Brandstofkosten: {GOLD}{CURRENCY}/jr{}{BLACK}Capaciteit: {GOLD}{STRING}{}{BLACK}Ontworpen: {GOLD}{NUMU16}{BLACK} Leeftijd: {GOLD}{COMMA16} jaren{}{BLACK}Max. betrouwbaarheid: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informatie +STR_8819_TRAIN_TOO_LONG :{WHITE}Trein te lang +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Treinen kunnen alleen aangepast worden wanneer ze gestopt zijn binnen een depot +STR_881B_TRAINS :{WHITE}{STRING} - Treinen +STR_881C_NEW_RAIL_VEHICLES :{WHITE}New Rail Vehicles +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}New Monorail Vehicles +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}New Maglev Vehicles +STR_881F_BUILD_VEHICLE :{BLACK}Bouw voertuig +STR_8820_RENAME :{BLACK}Hernoemen +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Kosten: {GOLD}{CURRENCY}{}{BLACK}Gewicht: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Capaciteit: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Overslaan +STR_8824_DELETE :{BLACK}Verwijderen +STR_8825_NON_STOP :{BLACK}Non-stop +STR_8826_GO_TO :{BLACK}Ga naar +STR_8827_FULL_LOAD :{BLACK}Volledig laden +STR_8828_UNLOAD :{BLACK}Uitladen +STR_8829_ORDERS :{WHITE}{STRING} (Orders) +STR_882A_END_OF_ORDERS :{SETX 10}- - Einde van orders - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Reparatie +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Can't build railroad vehicle... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebouwd: {LTBLUE}{NUMU16}{BLACK} Waarde: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Waarde: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}In- en uitladen +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Kan trein niet naar depot sturen... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Geen ruimte meer voor orders +STR_8832_TOO_MANY_ORDERS :{WHITE}Teveel orders +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Kan nieuwe order niet invoegen... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Kan deze order niet verwijderen... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Kan deze order niet aanpassen... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Bouw eerst een treindepot +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Kan voertuig niet verplaatsen... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Can't sell railroad vehicle... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Unable to find route to local depot +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Kan trein niet starten of stoppen... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Reparatieinterval: {LTBLUE}{COMMA16}dagen{BLACK} Laatste reparatie: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Treinen - klik op een trein voor informatie +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Build new trains (requires train depot) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trains - click on train for info., drag vehicle to add/remove from train +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Build new train vehicle +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Drag train vehicle to here to sell it +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Center main view on train depot location +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Train vehicle selection list - click on vehicle for information +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Build the highlighted train vehicle +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Rename train vehicle type +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Current train action - click here to stop/start train +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Show train's orders +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Center main view on train's location +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Stuur trein naar depot +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Forceer trein verder te rijden zonder te wachten op een groen signaal +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Keer trein om +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Show train details +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Increase servicing interval +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Decrease servicing interval +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Show details of cargo carried +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Show details of train vehicles +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Show capacities of each vehicle +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Show total capacity of train, split by cargo type +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Orders list - click on order to highlight it +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Skip the current order, and start the next +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Delete the highlighted order +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order non-stop +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Insert a new order before the highlighted order, or add to end of list +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to wait for a full load +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to unload +STR_SERVICE_HINT :{BLACK}Skip this order unless a service is needed +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}New {STRING} now available! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Prijs: {CURRENCY} Gewicht: {COMMA16}t{}Snelheid: {VELOCITY} Kracht: {COMMA16}pk{}Brandstofprijs: {CURRENCY}/jr{}Capaciteit: {STRING} +STR_885C_BROKEN_DOWN :{RED}Kapot +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Leeftijd: {LTBLUE}{STRING}{BLACK} Brandstofkosten: {LTBLUE}{CURRENCY}/jr +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Gewicht: {LTBLUE}{COMMA16}t {BLACK}Kracht: {LTBLUE}{COMMA32}pk{BLACK} Max. snelheid: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Winst dit jaar: {LTBLUE}{CURRENCY} (vorig jaar: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Betrouwbaarheid: {LTBLUE}{COMMA8}% {BLACK}Pechgevallen sinds laatste reparatie: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Gestopt +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... +STR_8863_CRASHED :{RED}Gecrashed! + +STR_8865_NAME_TRAIN :{WHITE}Name train +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Can't name train... +STR_8867_NAME_TRAIN :{BLACK}Name train +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Train Crash!{}{COMMA16} die in fireball after collision +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Can't reverse direction of train... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Rename train vehicle type +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Can't rename train vehicle type... + +STR_TRAIN_STOPPING :{RED}Stopping +STR_TRAIN_STOPPING_VEL :{RED}Stopping, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Wegvoertuig in de weg +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Wegvoertuigen +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} wegvoertuigendepot +STR_9004_NEW_VEHICLES :{BLACK}Nieuwe voertuigen +STR_9005_INFORMATION :{BLACK}Informatie +STR_9006_NEW_ROAD_VEHICLES :{WHITE}New Road Vehicles +STR_9007_BUILD_VEHICLE :{BLACK}Build Vehicle +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Prijs: {GOLD}{CURRENCY}{BLACK} Snelheid: {GOLD}{VELOCITY}{}{BLACK}Brandstofkosten: {GOLD}{CURRENCY}/jr{}{BLACK}Capaciteit: {GOLD}{STRING}{}{BLACK}Ontworpen: {GOLD}{NUMU16}{BLACK} Leeftijd: {GOLD}{COMMA16} jaar{}{BLACK}Max. betrouwbaarheid: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Can't build road vehicle... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Must build road vehicle depot first +STR_900B_ORDERS :{WHITE}{STRING} (Orders) +STR_900C_DETAILS :{WHITE}{STRING} (Details) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Leeftijd: {LTBLUE}{STRING}{BLACK} Brandstofkosten: {LTBLUE}{CURRENCY}/jr +STR_900E_MAX_SPEED :{BLACK}Max. snelheid: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Winst dit jaar: {LTBLUE}{CURRENCY} (vorig jaar: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Betrouwbaarheid: {LTBLUE}{COMMA8}% {BLACK}Pechgevallen sinds laatste reparaties: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebouwd: {LTBLUE}{NUMU16}{BLACK} Waarde: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Capaciteit: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...moet gestopt zijn binnen een wegvoertuig depot +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Kan dit wegvoertuig niet verkopen... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Kan wegvoertuig niet starten of stoppen... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Wegvoertuig {COMMA16} wacht in depot +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Heading for {TOWN} Road Depot +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Road Depot, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kan voertuig niet naar depot sturen... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan geen lokaal depot vinden +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Wegvoertuigen - klik op een voertuig voor informatie +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Bouw nieuwe wegvoertuigen (heeft wegvoertuigdepot nodig) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Huidige actie van voertuig - klik hier om voertuig te starten of te stoppen +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Laat orders van voertuig zien +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Center main view on vehicle's location +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Stuur voertuig naar depot +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Force vehicle to turn around +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Laat details van wegvoertuig zien +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Voertuigen - klik op voertuig voor informatie +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Bouw nieuw wegvoertuig +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Sleep een wegvoertuig hier om het te verkopen +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Center main view on road vehicle depot location +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Road vehicle selection list - click on vehicle for information +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Bouw het geselecteerde wegvoertuig +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Nieuw wegvoertuig nu beschikbaar! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Prijs: {CURRENCY}{}Snelheid: {VELOCITY}{}Brandstofkosten: {CURRENCY}/jr{}Capaciteit: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Hernoem wegvoertuig +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Kan wegvoertuig niet hernoemen... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Name road vehicle +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Inwoners feesten...{}Eerste bus arriveert in {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Inwoners feesten...{}Eerste vrachtwagen arriveert in {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Wegvoertuig gebostst!{}Bestuurder sterft in vuurbal na botsing met trein +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Wegvoertuig gebostst!{}{COMMA16} sterven in vuurbal na botsing met trein +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Kan voertuig niet omdraaien... +STR_9034_RENAME :{BLACK}Hernoem +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Hernoem wegvoertuigtype +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Hernoem wegvoertuigtype +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Kan wegvoertuigtype niet hernoemen... +STR_9038_GO_TO_ROADVEH_DEPOT :Ga naar {TOWN} wegvoertuigdepot +STR_SERVICE_AT_ROADVEH_DEPOT :Reparatie in {TOWN} wegvoertuigdepot + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION : +STR_9801_DOCK_CONSTRUCTION :{WHITE}Dokbouw +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Kan hier geen dok bouwen... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Schipdepot +STR_9804_NEW_SHIPS :{BLACK}Nieuwe schepen +STR_9805_SHIPS :{WHITE}{STRING} - Schepen +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Kan geen schip bouwen... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Bouw eerst een schipdepot +STR_9808_NEW_SHIPS :{WHITE}Nieuwe schepen +STR_9809_BUILD_SHIP :{BLACK}Bouw schip +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Prijs: {GOLD}{CURRENCY}{BLACK} Snelheid: {GOLD}{VELOCITY}{}{BLACK}Capaciteit: {GOLD}{STRING} {STRING}{}{BLACK}Running Cost: {GOLD}{CURRENCY}/jr{}{BLACK}Ontworpen: {GOLD}{NUMU16}{BLACK} Leeftijd: {GOLD}{COMMA16} jaar{}{BLACK}Max. betrouwbaarheid: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Schip moet gestopt zijn binnen een depot +STR_980C_CAN_T_SELL_SHIP :{WHITE}Kan schip niet verkopen... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Kan schip niet kopen... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Schip in de weg +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Orders) +STR_9811_DETAILS :{WHITE}{STRING} (Details) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Leeftijd: {LTBLUE}{STRING}{BLACK} Brandstofkosten: {LTBLUE}{CURRENCY}/jr +STR_9813_MAX_SPEED :{BLACK}Max. snelheid: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Winst dit jaar: {LTBLUE}{CURRENCY} (vorig jaar: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Betrouwbaarheid: {LTBLUE}{COMMA8}% {BLACK}Pechgevallen sinds laatste reparatie: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebouwd: {LTBLUE}{NUMU16}{BLACK} Waarde: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Capaciteit: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Kan schip niet starten of stoppen... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Kan schip niet naar depot sturen... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan lokaal depot niet vinden +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Heading for {TOWN} Ship Depot +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Ship Depot, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Schip {COMMA16} wacht in depot +STR_981D_BUILD_SHIP_DOCK :{BLACK}Bouw dok +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Bouw schipdepot (om schepen te bouwen en te repareren) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Schepen - klik op schip voor informatie +STR_9820_BUILD_NEW_SHIP :{BLACK}Bouw nieuw schip +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Sleep schip hierheen om het te verkopen +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centreer hoofdbeeld op de lokatie van het schipdepot +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Schepen - klik op een schip voor informatie +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Bouw nieuwe schepen (heeft schipdepot nodig) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Schepenlijst - klik op een schip voor informatie +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Bouw het geselecteerde schip +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Actie van dit schip - klik hier om het te starten of te stoppen +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Laat orders van schip zien +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centreer hoofdbeeld op de lokatie van dit schip +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Stuur schip naar depot +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Laat details van schip zien +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nieuw schip nu beschikbaar! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Prijs: {CURRENCY} Max. snelheid: {VELOCITY}{}Capaciteit: {STRING}{}Brandstofkosten: {CURRENCY}/jr +STR_982F_NAME_SHIP :{BLACK}Hernoem schip + +STR_9831_NAME_SHIP :{WHITE}Hernoem schip +STR_9832_CAN_T_NAME_SHIP :{WHITE}Kan schip niet hernoemen... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Inwoners feesten...{}Eerste schip arriveert in {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Plaats boei, kan gebruikt worden voor extra tussenstops +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Kan boei hier niet plaatsen... +STR_9836_RENAME :{BLACK}Hernoem +STR_9837_RENAME_SHIP_TYPE :{BLACK}Hernoem schiptype +STR_9838_RENAME_SHIP_TYPE :{WHITE}Hernoem schiptype +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Kan schiptype niet hernoemen... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Bouw schip om om andere goederen te vervoeren +STR_983B_REFIT :{WHITE}{STRING} (Ombouwen) +STR_983C_REFIT_SHIP :{BLACK}Schip ombouwen +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Selecteer type goederen dat dit schip moet vervoeren +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED :{BLACK}Bouw schip om om geselecteerde goederen te vervoeren +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selecteer goederentype om te vervoeren:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nieuwe capaciteit: {GOLD}{STRING}{}{BLACK}Ombouwkosten: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Kan schip niet ombouwen... +STR_9842_REFITTABLE :(ombouwbaar) +STR_GO_TO_SHIP_DEPOT :Ga naar {TOWN} schipdepot +SERVICE_AT_SHIP_DEPOT :Reparatie in {TOWN} schipdepot + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Vliegveldbouw +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Kan vliegveld hier niet bouwen... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Vliegtuighangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nieuw vliegtuig +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}New Aircraft +STR_A006_BUILD_AIRCRAFT :{BLACK}Build Aircraft +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Speed: {GOLD}{VELOCITY}{}{BLACK}Capacity: {GOLD}{COMMA16} passengers, {COMMA16} bags of mail{}{BLACK}Running Cost: {GOLD}{CURRENCY}/yr{}{BLACK}Designed: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} years{}{BLACK}Max. Reliability: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Can't build aircraft... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Vliegtuig +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Orders) +STR_A00C_DETAILS :{WHITE}{STRING} (Details) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Leeftijd: {LTBLUE}{STRING}{BLACK} Brandstofkosten: {LTBLUE}{CURRENCY}/jr +STR_A00E_MAX_SPEED :{BLACK}Max. snelheid: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Winst dit jaar: {LTBLUE}{CURRENCY} (vorig jaar: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Betrouwbaarheid: {LTBLUE}{COMMA8}% {BLACK}Pechgevallen sinds laatste reparatie: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bouwdatum: {LTBLUE}{NUMU16}{BLACK} Waarde: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Can't send aircraft to hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Heading for {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Heading for {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Aircraft {COMMA16} is waiting in the aircraft hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Aircraft in the way +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Can't stop/start aircraft... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Aircraft is in flight +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Must build airport first +STR_A019_CAPACITY :{BLACK}Capaciteit: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Capaciteit: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Vliegtuig moet gestopt zijn in een hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Kan vliegtuig niet verkopen... +STR_A01D_AIRPORT_CONSTRUCTION :Vliegveldbouw +STR_A01E_BUILD_AIRPORT :{BLACK}Bouw vliegveld +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Vliegtuig - klik op vliegtuig voor informatie +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Bouw nieuw vliegtuig (heeft vliegveld met hangar nodig) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Vliegtuig - klik op vliegtuig voor informatie +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Bouw nieuw vliegtuig +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Sleep vliegtuig hierheen om het te verkopen +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centreer hoofdbeeld op hangarlokatie +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Vliegtuiglijst - klik op een vliegtuig voor informatie +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Bouw het geselecteerde vliegtuig +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Actie van huidig vliegtuig - klik hier om het vliegtuig te stoppen of te starten +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Laat vliegtuigorders zien +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centreer hoofdbeeld op de vliegtuiglokatie +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Stuur vliegtuig naar hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Laat vliegtuigdetails zien +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nieuw vliegtuig nu beschikbaar! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Prijs: {CURRENCY} Max. snelheid: {VELOCITY}{}Capaciteit: {COMMA16} passagiers, {COMMA16} zakken post{}Brandstofkosten: {CURRENCY}/jr + +STR_A030_NAME_AIRCRAFT :{WHITE}Hernoem vliegtuig +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kan vliegtuig niet hernoemen... +STR_A032_NAME_AIRCRAFT :{BLACK}Hernoem vliegtuig +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Inwoners feesten...{}Eerste vliegtuig arriveert in {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Vliegtuig neergestort!{}{COMMA16} sterven in een vuurbal bij {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Doelen: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Hernoem +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Hernoem vliegtuigtype +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Hernoem vliegtuigtype +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Kan vliegtuigtype niet hernoemen... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Bouw vliegtuig om om andere goederen te vervoeren +STR_A03C_REFIT :{WHITE}{STRING} (Omgebouwd) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Vliegtuig ombouwen +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Selecteer goederentype om te vervoeren door het vliegtuig +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Bouw vliegtuig om om het geselecteerde goederentype te vervoeren +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selecteer goederentype om te vervoeren:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nieuwe capaciteit: {GOLD}{STRING}{}{BLACK}Ombouwkosten: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Kan vliegtuig niet ombouwen... +STR_A043_REFITTABLE :(ombouwbaar) +STR_GO_TO_AIRPORT_HANGAR :Ga naar {STATION} hanger +SERVICE_AT_AIRPORT_HANGAR :Reperatie bij {STATION} hanger + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin ongeluk bij {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Voertuig vernietigd in botsing met 'UFO' +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Olieraffinaderij geëxplodeerd bij {TOWN} +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS :{BLACK}{BIGFONT}Een frabriek is onder verdachte omstandigheden vernietigd in de buurt van {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' land in de buurt van {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Een instorting bij een kolenmijn laat een ravage achter bij {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Je poging tot omkopen is +STR_BRIBE_FAILED_2 :{WHITE}ondekt door regionale onderzoekers diff --git a/lang/english.txt b/lang/english.txt new file mode 100644 --- /dev/null +++ b/lang/english.txt @@ -0,0 +1,2455 @@ +##name English +##ownname English + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Off edge of map +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Too close to edge of map +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Not enough cash - requires {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Flat land required +STR_0008_WAITING :{BLACK}Waiting: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (en-route from +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accepts: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accepts: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passengers +STR_0010_COAL :Coal +STR_0011_MAIL :Mail +STR_0012_OIL :Oil +STR_0013_LIVESTOCK :Livestock +STR_0014_GOODS :Goods +STR_0015_GRAIN :Grain +STR_0016_WOOD :Wood +STR_0017_IRON_ORE :Iron Ore +STR_0018_STEEL :Steel +STR_0019_VALUABLES :Valuables +STR_001A_COPPER_ORE :Copper Ore +STR_001B_MAIZE :Maize +STR_001C_FRUIT :Fruit +STR_001D_DIAMONDS :Diamonds +STR_001E_FOOD :Food +STR_001F_PAPER :Paper +STR_0020_GOLD :Gold +STR_0021_WATER :Water +STR_0022_WHEAT :Wheat +STR_0023_RUBBER :Rubber +STR_0024_SUGAR :Sugar +STR_0025_TOYS :Toys +STR_0026_CANDY :Candy +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Cotton Candy +STR_0029_BUBBLES :Bubbles +STR_002A_TOFFEE :Toffee +STR_002B_BATTERIES :Batteries +STR_002C_PLASTIC :Plastic +STR_002D_FIZZY_DRINKS :Fizzy Drinks +STR_002E : +STR_002F_PASSENGER :Passenger +STR_0030_COAL :Coal +STR_0031_MAIL :Mail +STR_0032_OIL :Oil +STR_0033_LIVESTOCK :Livestock +STR_0034_GOODS :Goods +STR_0035_GRAIN :Grain +STR_0036_WOOD :Wood +STR_0037_IRON_ORE :Iron Ore +STR_0038_STEEL :Steel +STR_0039_VALUABLES :Valuables +STR_003A_COPPER_ORE :Copper Ore +STR_003B_MAIZE :Maize +STR_003C_FRUIT :Fruit +STR_003D_DIAMOND :Diamond +STR_003E_FOOD :Food +STR_003F_PAPER :Paper +STR_0040_GOLD :Gold +STR_0041_WATER :Water +STR_0042_WHEAT :Wheat +STR_0043_RUBBER :Rubber +STR_0044_SUGAR :Sugar +STR_0045_TOY :Toy +STR_0046_CANDY :Candy +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Cotton Candy +STR_0049_BUBBLE :Bubble +STR_004A_TOFFEE :Toffee +STR_004B_BATTERY :Battery +STR_004C_PLASTIC :Plastic +STR_004D_FIZZY_DRINK :Fizzy Drink +STR_004E : +STR_004F_PASSENGER :{COMMA16} passenger +STR_0050_TON_OF_COAL :{COMMA16} ton of coal +STR_0051_BAG_OF_MAIL :{COMMA16} bag of mail +STR_0052_OF_OIL :{VOLUME} of oil +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} item of livestock +STR_0054_CRATE_OF_GOODS :{COMMA16} crate of goods +STR_0055_TON_OF_GRAIN :{COMMA16} ton of grain +STR_0056_TON_OF_WOOD :{COMMA16} ton of wood +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton of iron ore +STR_0058_TON_OF_STEEL :{COMMA16} ton of steel +STR_0059_BAG_OF_VALUABLES :{COMMA16} bag of valuables +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton of copper ore +STR_005B_TON_OF_MAIZE :{COMMA16} ton of maize +STR_005C_TON_OF_FRUIT :{COMMA16} ton of fruit +STR_005D_BAG_OF_DIAMONDS :{COMMA16} bag of diamonds +STR_005E_TON_OF_FOOD :{COMMA16} ton of food +STR_005F_TON_OF_PAPER :{COMMA16} ton of paper +STR_0060_BAG_OF_GOLD :{COMMA16} bag of gold +STR_0061_OF_WATER :{VOLUME} of water +STR_0062_TON_OF_WHEAT :{COMMA16} ton of wheat +STR_0063_OF_RUBBER :{VOLUME} of rubber +STR_0064_TON_OF_SUGAR :{COMMA16} ton of sugar +STR_0065_TOY :{COMMA16} toy +STR_0066_BAG_OF_CANDY :{COMMA16} bag of candy +STR_0067_OF_COLA :{VOLUME} of cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton of cotton candy +STR_0069_BUBBLE :{COMMA16} bubble +STR_006A_TON_OF_TOFFEE :{COMMA16} ton of toffee +STR_006B_BATTERY :{COMMA16} battery +STR_006C_OF_PLASTIC :{VOLUME} of plastic +STR_006D_FIZZY_DRINK :{COMMA16} fizzy drink +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passengers +STR_0070_TONS_OF_COAL :{COMMA16} tons of coal +STR_0071_BAGS_OF_MAIL :{COMMA16} bags of mail +STR_0072_OF_OIL :{VOLUME} of oil +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} items of livestock +STR_0074_CRATES_OF_GOODS :{COMMA16} crates of goods +STR_0075_TONS_OF_GRAIN :{COMMA16} tons of grain +STR_0076_TONS_OF_WOOD :{COMMA16} tons of wood +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tons of iron ore +STR_0078_TONS_OF_STEEL :{COMMA16} tons of steel +STR_0079_BAGS_OF_VALUABLES :{COMMA16} bags of valuables +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tons of copper ore +STR_007B_TONS_OF_MAIZE :{COMMA16} tons of maize +STR_007C_TONS_OF_FRUIT :{COMMA16} tons of fruit +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} bags of diamonds +STR_007E_TONS_OF_FOOD :{COMMA16} tons of food +STR_007F_TONS_OF_PAPER :{COMMA16} tons of paper +STR_0080_BAGS_OF_GOLD :{COMMA16} bags of gold +STR_0081_OF_WATER :{VOLUME} of water +STR_0082_TONS_OF_WHEAT :{COMMA16} tons of wheat +STR_0083_OF_RUBBER :{VOLUME} of rubber +STR_0084_TONS_OF_SUGAR :{COMMA16} tons of sugar +STR_0085_TOYS :{COMMA16} toys +STR_0086_BAGS_OF_CANDY :{COMMA16} bags of candy +STR_0087_OF_COLA :{VOLUME} of cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tons of cotton candy +STR_0089_BUBBLES :{COMMA16} bubbles +STR_008A_TONS_OF_TOFFEE :{COMMA16} tons of toffee +STR_008B_BATTERIES :{COMMA16} batteries +STR_008C_OF_PLASTIC :{VOLUME} of plastic +STR_008D_FIZZY_DRINKS :{COMMA16} fizzy drinks +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Map - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Game Options +STR_00B2_MESSAGE :{YELLOW}Message +STR_00B3_MESSAGE_FROM :{YELLOW}Message from {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Can't do this.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Can't clear this area.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, All rights reserved +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Original design by Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Graphics by Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Quit +STR_00C8_YES :{BLACK}Yes +STR_00C9_NO :{BLACK}No +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Are you sure you want to abandon this game and return to {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nothing +STR_00D1_DARK_BLUE :Dark Blue +STR_00D2_PALE_GREEN :Pale Green +STR_00D3_PINK :Pink +STR_00D4_YELLOW :Yellow +STR_00D5_RED :Red +STR_00D6_LIGHT_BLUE :Light Blue +STR_00D7_GREEN :Green +STR_00D8_DARK_GREEN :Dark Green +STR_00D9_BLUE :Blue +STR_00DA_CREAM :Cream +STR_00DB_MAUVE :Mauve +STR_00DC_PURPLE :Purple +STR_00DD_ORANGE :Orange +STR_00DE_BROWN :Brown +STR_00DF_GREY :Grey +STR_00E0_WHITE :White +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Too many vehicles in game +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Location +STR_00E5_CONTOURS :Contours +STR_00E6_VEHICLES :Vehicles +STR_00E7_INDUSTRIES :Industries +STR_00E8_ROUTES :Routes +STR_00E9_VEGETATION :Vegetation +STR_00EA_OWNERS :Owners +STR_00EB_ROADS :{BLACK}{TINYFONT}Roads +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Railroads +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stations/Airports/Docks +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Buildings/Industries +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vehicles +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Trains +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Road Vehicles +STR_00F7_SHIPS :{BLACK}{TINYFONT}Ships +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Aircraft +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transport Routes +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Coal Mine +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Power Station +STR_00FC_FOREST :{BLACK}{TINYFONT}Forest +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Sawmill +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Oil Refinery +STR_00FF_FARM :{BLACK}{TINYFONT}Farm +STR_0100_FACTORY :{BLACK}{TINYFONT}Factory +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Printing Works +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Oil Wells +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Iron Ore Mine +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Steel Mill +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Paper Mill +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Gold Mine +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Food Processing Plant +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamond Mine +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Copper Ore Mine +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Fruit Plantation +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Rubber Plantation +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Water Supply +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Water Tower +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Lumber Mill +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Cotton Candy Forest +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Candy Factory +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Battery Farm +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Cola Wells +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Toy Shop +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Toy Factory +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastic Fountains +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Fizzy Drink Factory +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Bubble Generator +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Toffee Quarry +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Sugar Mine +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Railroad Station +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Truck Loading Bay +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Bus Station +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Airport/Heliport +STR_011F_DOCK :{BLACK}{TINYFONT}Dock +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Rough Land +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Grass Land +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Bare Land +STR_0123_FIELDS :{BLACK}{TINYFONT}Fields +STR_0124_TREES :{BLACK}{TINYFONT}Trees +STR_0125_ROCKS :{BLACK}{TINYFONT}Rocks +STR_0126_WATER :{BLACK}{TINYFONT}Water +STR_0127_NO_OWNER :{BLACK}{TINYFONT}No Owner +STR_0128_TOWNS :{BLACK}{TINYFONT}Towns +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industries +STR_012A_DESERT :{BLACK}{TINYFONT}Desert +STR_012B_SNOW :{BLACK}{TINYFONT}Snow +STR_012C_MESSAGE :{WHITE}Message +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Cancel +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Rename +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Too many names defined +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Chosen name in use already + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (miles) +STR_013A_METRIC_KILOMETERS :Metric (kilometers) +STR_013B_OWNED_BY :{WHITE}...owned by {STRING} +STR_013C_CARGO :{BLACK}Cargo +STR_013D_INFORMATION :{BLACK}Information +STR_013E_CAPACITIES :{BLACK}Capacities +STR_013E_TOTAL_CARGO :{BLACK}Total Cargo +STR_013F_CAPACITY :{BLACK}Capacity: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Total cargo (capacity) of this train: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}New Game +STR_0141_LOAD_GAME :{BLACK}Load Game +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demonstration +STR_SINGLE_PLAYER :{BLACK}Single player +STR_MULTIPLAYER :{BLACK}Multiplayer + +STR_0148_GAME_OPTIONS :{BLACK}Game Options + +STR_0150_SOMEONE :someone{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Map of world +STR_0152_TOWN_DIRECTORY :Town directory +STR_0153_SUBSIDIES :Subsidies + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Operating profit graph +STR_0155_INCOME_GRAPH :Income graph +STR_0156_DELIVERED_CARGO_GRAPH :Delivered cargo graph +STR_0157_PERFORMANCE_HISTORY_GRAPH :Performance history graph +STR_0158_COMPANY_VALUE_GRAPH :Company value graph +STR_0159_CARGO_PAYMENT_RATES :Cargo payment rates +STR_015A_COMPANY_LEAGUE_TABLE :Company league table +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Save game +STR_015D_LOAD_GAME :Load game +STR_015E_QUIT_GAME :Quit game +STR_015F_QUIT :Quit +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Are you sure you want to quit this game ? +STR_0161_QUIT_GAME :{WHITE}Quit Game +STR_SORT_TIP :{BLACK}Select sorting order +STR_SORT_BY_NAME :{BLACK}Name +STR_SORT_BY_DATE :{BLACK}Date + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :May +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Oct +STR_016C_NOV :Nov +STR_016D_DEC :Dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pause game +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Save game, abandon game, quit +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Display list of company's stations +STR_0174_DISPLAY_MAP :{BLACK}Display map +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Display map, town directory +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Display town directory +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Display company finances information +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Display company general information +STR_0179_DISPLAY_GRAPHS :{BLACK}Display graphs +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Display company league table +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Display list of company's trains +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Display list of company's road vehicles +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Display list of company's ships +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Display list of company's aircraft +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Zoom the view in +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Zoom the view out +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Build railroad track +STR_0182_BUILD_ROADS :{BLACK}Build roads +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Build ship docks +STR_0184_BUILD_AIRPORTS :{BLACK}Build airports +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plant trees, place signs etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Land area information +STR_0187_OPTIONS :{BLACK}Options +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Can't change servicing interval... +STR_018B_CLOSE_WINDOW :{BLACK}Close window +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Window title - drag this to move window +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Demolish buildings etc. on a square of land +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Lower a corner of land +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Raise a corner of land +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scroll bar - scrolls list up/down +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Show land contours on map +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Show vehicles on map +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Show industries on map +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Show transport routes on map +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Show vegetation on map +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Show land owners on map +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Toggle town names on/off on map +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Profit this year: {CURRENCY} (last year: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} year ({COMMA16}) +STR_019A_YEARS :{COMMA16} years ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} years ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Road vehicle +STR_019D_AIRCRAFT :Aircraft +STR_019E_SHIP :Ship +STR_019F_TRAIN :Train +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} is getting old +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} is getting very old +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} is getting very old and urgently needs replacing +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Land Area Information +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Cost to clear: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Cost to clear: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Owner: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Local authority: {LTBLUE}{STRING} +STR_01A9_NONE :None +STR_01AA_NAME :{BLACK}Name +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1st +STR_01AD_2ND :2nd +STR_01AE_3RD :3rd +STR_01AF_4TH :4th +STR_01B0_5TH :5th +STR_01B1_6TH :6th +STR_01B2_7TH :7th +STR_01B3_8TH :8th +STR_01B4_9TH :9th +STR_01B5_10TH :10th +STR_01B6_11TH :11th +STR_01B7_12TH :12th +STR_01B8_13TH :13th +STR_01B9_14TH :14th +STR_01BA_15TH :15th +STR_01BB_16TH :16th +STR_01BC_17TH :17th +STR_01BD_18TH :18th +STR_01BE_19TH :19th +STR_01BF_20TH :20th +STR_01C0_21ST :21st +STR_01C1_22ND :22nd +STR_01C2_23RD :23rd +STR_01C3_24TH :24th +STR_01C4_25TH :25th +STR_01C5_26TH :26th +STR_01C6_27TH :27th +STR_01C7_28TH :28th +STR_01C8_29TH :29th +STR_01C9_30TH :30th +STR_01CA_31ST :31st +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Toggle large/small map size +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Select Tutorial/Demonstration + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Cargo accepted: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Cargo accepted: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Cargo accepted: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Sound/music +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Show sound/music window +STR_01D5_ALL :{TINYFONT}All +STR_01D6_OLD_STYLE :{TINYFONT}Old Style +STR_01D7_NEW_STYLE :{TINYFONT}New Style +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Custom 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Custom 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Music Volume +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Effects Volume +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Skip to previous track in selection +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Skip to next track in selection +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Stop playing music +STR_01E1_START_PLAYING_MUSIC :{BLACK}Start playing music +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Drag sliders to set music and sound effect volumes +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Track{SETX 88}Title +STR_01E9_SHUFFLE :{TINYFONT}Shuffle +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Music Program Selection +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Track Index +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Clear +STR_01F1_SAVE :{TINYFONT}{BLACK}Save +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Current program of music tracks +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Select 'all tracks' program +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Select 'old style music' program +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Select 'new style music' program +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Select 'Custom 1' (user-defined) program +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Select 'Custom 2' (user-defined) program +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Clear current program (Custom1 or Custom2 only) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Save music settings to disk +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Click on music track to add to current program (Custom1 or Custom2 only) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Toggle program shuffle on/off +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Show music track selection window +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on service to center view on industry/town +STR_01FE_DIFFICULTY :{BLACK}Difficulty ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Last message/news report +STR_0201_MESSAGE_SETTINGS :Message settings +STR_MESSAGE_HISTORY_MENU :Message History +STR_0202_SEND_MESSAGE :Send message +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Show last message/news report, show message options +STR_0204_MESSAGE_OPTIONS :{WHITE}Message Options +STR_0205_MESSAGE_TYPES :{BLACK}Message types:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrival of first vehicle at player's station +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrival of first vehicle at competitor's station +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Accidents / disasters +STR_0209_COMPANY_INFORMATION :{YELLOW}Company information +STR_020A_ECONOMY_CHANGES :{YELLOW}Economy changes +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Advice / information on player's vehicles +STR_020C_NEW_VEHICLES :{YELLOW}New vehicles +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Changes of cargo acceptance +STR_020E_SUBSIDIES :{YELLOW}Subsidies +STR_020F_GENERAL_INFORMATION :{YELLOW}General information +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...too far from previous destination +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Top companies who reached 2050{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Businessman +STR_0214_ENTREPRENEUR :Entrepreneur +STR_0215_INDUSTRIALIST :Industrialist +STR_0216_CAPITALIST :Capitalist +STR_0217_MAGNATE :Magnate +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon of the Century +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} achieves '{STRING}' status! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} of {STRING} achieves '{STRING}' status! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Create Scenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Scenario Editor +STR_0223_LAND_GENERATION :{WHITE}Land Generation +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Random Land +STR_0227_RESET_LAND :{BLACK}Reset Land +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Increase size of land area to lower/raise +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Decrease size of land area to lower/raise +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Generate random land +STR_022B_RESET_LANDSCAPE :{BLACK}Reset landscape +STR_022C_RESET_LANDSCAPE :{WHITE}Reset Landscape +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Are you sure you want to reset the landscape? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Landscape generation +STR_022F_TOWN_GENERATION :{BLACK}Town generation +STR_0230_INDUSTRY_GENERATION :{BLACK}Industry generation +STR_0231_ROAD_CONSTRUCTION :{BLACK}Road construction +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetation and other objects +STR_0233_TOWN_GENERATION :{WHITE}Town Generation +STR_0234_NEW_TOWN :{BLACK}New Town +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Construct new town +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Can't build town here... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...too close to edge of map +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...too close to another town +STR_0239_SITE_UNSUITABLE :{WHITE}...site unsuitable +STR_023A_TOO_MANY_TOWNS :{WHITE}...too many towns +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Increase size of town +STR_023C_EXPAND :{BLACK}Expand +STR_023D_RANDOM_TOWN :{BLACK}Random Town +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Build town in random location +STR_023F_INDUSTRY_GENERATION :{WHITE}Industry Generation +STR_0240_COAL_MINE :{BLACK}Coal Mine +STR_0241_POWER_STATION :{BLACK}Power Station +STR_0242_SAWMILL :{BLACK}Sawmill +STR_0243_FOREST :{BLACK}Forest +STR_0244_OIL_REFINERY :{BLACK}Oil Refinery +STR_0245_OIL_RIG :{BLACK}Oil Rig +STR_0246_FACTORY :{BLACK}Factory +STR_0247_STEEL_MILL :{BLACK}Steel Mill +STR_0248_FARM :{BLACK}Farm +STR_0249_IRON_ORE_MINE :{BLACK}Iron Ore Mine +STR_024A_OIL_WELLS :{BLACK}Oil Wells +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Paper Mill +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Food Processing Plant +STR_024E_PRINTING_WORKS :{BLACK}Printing Works +STR_024F_GOLD_MINE :{BLACK}Gold Mine +STR_0250_LUMBER_MILL :{BLACK}Lumber Mill +STR_0251_FRUIT_PLANTATION :{BLACK}Fruit Plantation +STR_0252_RUBBER_PLANTATION :{BLACK}Rubber Plantation +STR_0253_WATER_SUPPLY :{BLACK}Water Supply +STR_0254_WATER_TOWER :{BLACK}Water Tower +STR_0255_DIAMOND_MINE :{BLACK}Diamond Mine +STR_0256_COPPER_ORE_MINE :{BLACK}Copper Ore Mine +STR_0257_COTTON_CANDY_FOREST :{BLACK}Cotton Candy Forest +STR_0258_CANDY_FACTORY :{BLACK}Candy Factory +STR_0259_BATTERY_FARM :{BLACK}Battery Farm +STR_025A_COLA_WELLS :{BLACK}Cola Wells +STR_025B_TOY_SHOP :{BLACK}Toy Shop +STR_025C_TOY_FACTORY :{BLACK}Toy Factory +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastic Fountains +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Fizzy Drink Factory +STR_025F_BUBBLE_GENERATOR :{BLACK}Bubble Generator +STR_0260_TOFFEE_QUARRY :{BLACK}Toffee Quarry +STR_0261_SUGAR_MINE :{BLACK}Sugar Mine +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Construct Coal Mine +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Construct Power Station +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Construct Sawmill +STR_0265_PLANT_FOREST :{BLACK}Plant Forest +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Construct Oil Refinery +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Construct Oil Rig (Can only be built near the edges of the map) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Construct Factory +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Construct Steel Mill +STR_026A_CONSTRUCT_FARM :{BLACK}Construct Farm +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Construct Iron Ore Mine +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Construct Oil Wells +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construct Bank (Can only be built in towns with a population greater than 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Construct Paper Mill +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Construct Food Processing Plant +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Construct Printing Works +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Construct Gold Mine +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construct Bank (Can only be built in towns) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Construct Lumber Mill (to clear rainforest and produce Wood) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plant Fruit Plantation +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plant Rubber Plantation +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Construct Water Supply +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Construct Water Tower (Can only be built in towns) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Construct Diamond Mine +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Construct Copper Ore Mine +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plant Cotton Candy Forest +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Construct Candy Factory +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Construct Battery Farm +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Construct Cola Wells +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Construct Toy Shop +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Construct Toy Factory +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Construct Plastic Fountains +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Construct Fizzy Drink Factory +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Construct Bubble Generator +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Construct Toffee Quarry +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Construct Sugar Mine +STR_0285_CAN_T_BUILD_HERE :{WHITE}Can't build {STRING} here... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...must build town first +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...only one allowed per town +STR_0288_PLANT_TREES :{BLACK}Plant trees +STR_0289_PLACE_SIGN :{BLACK}Place sign +STR_028A_RANDOM_TREES :{BLACK}Random Trees +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Plant trees randomly over landscape +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Place rocky areas on landscape +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Place lighthouse +STR_028E_PLACE_TRANSMITTER :{BLACK}Place transmitter +STR_028F_DEFINE_DESERT_AREA :{BLACK}Define desert area +STR_0290_DELETE :{BLACK}Delete +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Delete this town completely +STR_0292_SAVE_SCENARIO :Save scenario +STR_0293_LOAD_SCENARIO :Load scenario +STR_0294_QUIT_EDITOR :Quit editor +STR_0295 : +STR_0296_QUIT :Quit +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Save scenario, load scenario, abandon scenario editor, quit +STR_0298_LOAD_SCENARIO :{WHITE}Load Scenario +STR_0299_SAVE_SCENARIO :{WHITE}Save Scenario +STR_029A_PLAY_SCENARIO :{BLACK}Play Scenario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Are you sure you want to quit this scenario ? +STR_029C_QUIT_EDITOR :{WHITE}Quit Editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...can only be built in towns with a population of at least 1200 +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Move the starting date backward 1 year +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Move the starting date forward 1 year +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...ends of bridge must both be on land +STR_02A1_SMALL :{BLACK}Small +STR_02A2_MEDIUM :{BLACK}Medium +STR_02A3_LARGE :{BLACK}Large +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Select town size +STR_02A5_TOWN_SIZE :{YELLOW}Town size: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Show last message or news report +STR_02B8_SUMMARY :{BLACK}Summary +STR_02B9_FULL :{BLACK}Full +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Town directory +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Vehicle design names +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Default +STR_02BF_CUSTOM :Custom +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Save custom names to disk +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Vehicle design names selection +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Save customized vehicle design names to disk + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Game options +STR_02C4_GAME_OPTIONS :Game options +STR_02C5_DIFFICULTY_SETTINGS :Difficulty settings +STR_02C6_DIFFICULTY_SETTINGS :Difficulty settings +STR_02C7_CONFIG_PATCHES :Configure patches +STR_02C8_CONFIG_PATCHES :Configure patches +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Town names displayed +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Town names displayed +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Station names displayed +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Station names displayed +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Signs displayed +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Signs displayed +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Checkpoints displayed +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Checkpoints displayed +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Full animation +STR_02D0_FULL_ANIMATION :{SETX 12}Full animation +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Full detail +STR_02D2_FULL_DETAIL :{SETX 12}Full detail +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Transparent buildings +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Transparent buildings +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Land area information +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Screenshot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Giant Screenshot (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :About 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}On +STR_02DB_OFF :{BLACK}Off +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Display subsidies +STR_02DD_SUBSIDIES :Subsidies +STR_02DE_MAP_OF_WORLD :Map of world +STR_02DF_TOWN_DIRECTORY :Town directory +STR_02E0_CURRENCY_UNITS :{BLACK}Currency units +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Currency units selection +STR_02E3_DISTANCE_UNITS :{BLACK}Distance units +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Distance units selection +STR_02E6_ROAD_VEHICLES :{BLACK}Road vehicles +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Select side of road for vehicles to drive on +STR_02E9_DRIVE_ON_LEFT :Drive on left +STR_02EA_DRIVE_ON_RIGHT :Drive on right +STR_02EB_TOWN_NAMES :{BLACK}Town names +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Select style of town names + +STR_02F4_AUTOSAVE :{BLACK}Autosave +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Select interval between automatic game saves +STR_02F7_OFF :Off +STR_02F8_EVERY_3_MONTHS :Every 3 months +STR_02F9_EVERY_6_MONTHS :Every 6 months +STR_02FA_EVERY_12_MONTHS :Every 12 months +STR_02FB_START_A_NEW_GAME :{BLACK}Start a new game +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Load a saved game from disk +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}View demonstrations/tutorials +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Create a customized game world/scenario +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Select single-player game +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Select two-player game +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Display game options +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Display difficulty options +STR_0303_START_A_NEW_GAME_USING :{BLACK}Start a new game, using a customized scenario +STR_0304_QUIT :{BLACK}Quit +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Leave 'OpenTTD', and quit +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}View demonstration/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...can only be built in towns +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Select 'temperate' landscape style +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Select 'sub-arctic' landscape style +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Select 'sub-tropical' landscape style +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Select 'toyland' landscape style +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Fund construction of new industry + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Fund new industry +STR_INDUSTRY_DIR :Industry Directory +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Fund new industry +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...can only be built in towns +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...can only be built in rainforest areas +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...can only be built in desert areas +STR_0319_PAUSED :{YELLOW}* * PAUSED * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot successfully saved to disk as '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot failed! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Purchase land for future use +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Road vehicle service +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Railroad service +STR_032C_3_AIR_SERVICE :{BLACK}3: Air service +STR_032D_4_SHIP_SERVICE :{BLACK}4: Ship service +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Railroad service (advanced) +STR_032F_AUTOSAVE :{RED}AUTOSAVE +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Select 'Ezy Street style music' program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :English +STR_TOWNNAME_FRENCH :French +STR_TOWNNAME_GERMAN :German +STR_TOWNNAME_AMERICAN :American +STR_TOWNNAME_LATIN_AMERICAN :Latin-American +STR_TOWNNAME_SILLY :Silly +STR_TOWNNAME_SWEDISH :Swedish +STR_TOWNNAME_DUTCH :Dutch +STR_TOWNNAME_FINNISH :Finnish +STR_TOWNNAME_POLISH :Polish +STR_TOWNNAME_SLOVAKISH :Slovakish +STR_TOWNNAME_HUNGARIAN :Hungarian +STR_TOWNNAME_AUSTRIAN :Austrian +############ end of townname region + +STR_CURR_POUNDS :Pounds ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollars ($) +STR_CURR_FF :Franc (FF) +STR_CURR_DM :Deutschmark (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseta (Pt) +STR_CURR_FT :Hungarian Forint (Ft) +STR_CURR_ZL :Polish Zloty (zl) +STR_CURR_ATS :Austrian Shilling (ATS) +STR_CURR_BEF :Belgian Franc (BEF) +STR_CURR_DKK :Danish Krone (DKK) +STR_CURR_FIM :Finnish Markka (FIM) +STR_CURR_GRD :Greek Drachma (GRD) +STR_CURR_CHF :Swiss Franc (CHF) +STR_CURR_NLG :Dutch Guilder (NLG) +STR_CURR_ITL :Italian Lira (ITL) +STR_CURR_SEK :Swedish Krona (SEK) +STR_CURR_RUR :Russian Rubel (rur) +STR_CURR_CZK :Czech Koruna (CZK) +STR_CURR_ISK :Icelandic Krona (ISK) +STR_CURR_NOK :Norwegian Krone (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Language +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Select the interface language to use + +STR_OPTIONS_RES :{BLACK}Screen resolution +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Select the screen resolution to use + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Screenshot format +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Select the screenshot format to use + +STR_AUTOSAVE_1_MONTH :Every month +STR_AUTOSAVE_FAILED :{WHITE}Autosave failed + +STR_MONTH_JAN :January +STR_MONTH_FEB :February +STR_MONTH_MAR :March +STR_MONTH_APR :April +STR_MONTH_MAY :May +STR_MONTH_JUN :June +STR_MONTH_JUL :July +STR_MONTH_AUG :August +STR_MONTH_SEP :September +STR_MONTH_OCT :October +STR_MONTH_NOV :November +STR_MONTH_DEC :December + +STR_HEADING_FOR_STATION :{LTBLUE}Heading for {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Heading for {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}No orders +STR_NO_ORDERS_VEL :{LTBLUE}No orders, {VELOCITY} + +STR_PASSENGERS :passengers +STR_BAGS :bags +STR_TONS :tons +STR_LITERS :liters +STR_ITEMS :items +STR_CRATES :crates +STR_RES_OTHER :other +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Can't share order list... +STR_CANT_COPY_ORDER_LIST :{WHITE}Can't copy order list... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - End of Shared Orders - - + +STR_TRAIN_IS_LOST :{WHITE}Train {COMMA16} is lost. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Train {COMMA16}'s profit last year was {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Configure Patches +STR_CONFIG_PATCHES_TIP :{BLACK}Configure the patches +STR_CONFIG_PATCHES_CAPTION :{WHITE}Configure Patches + +STR_CONFIG_PATCHES_OFF :Off +STR_CONFIG_PATCHES_ON :On +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Show vehicle speed in status bar: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Allow building on slopes and coasts: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Allow removal of more town-owned roads, bridges, tunnels, etc: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Enable building very long trains: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Enable realistic acceleration for trains: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Join train stations built next to each other: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Leave station when any cargo is full, if 'full load': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflation: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}No automatic train servicing: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Deliver cargo to a station only when there is a demand: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Allow building very long bridges: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Allow goto depot orders: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Allow constructing raw material producing industries: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Allow multiple similar industries per town: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Industries of the same type can be built close to each other: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Always show long date in the status bar: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Show signals on the drive side: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Show finances window at the end of the year: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch compatible nonstop handling: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Road vehicle queueing (with quantum effects): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Pan window when mouse is at the edge: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Allow bribing the local authority: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}New depot finding: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Nonuniform stations: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}New algorithm for train pathfinding: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Build while in pause mode: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Always allow small airports: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}A train is lost if no progress is made for: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Warn if a train's income is negative: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES :{LTBLUE}Vehicles never expire: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Autorenew vehicle when it gets old +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Duration of error message: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Snow line height: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Max station spread: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Service helicopters at helipads automatically: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Max trains per player: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Max road vehicles per player: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Max aircraft per player: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Max ships per player: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Disable trains for computer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Disable road vehicles for computer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Disable aircraft for computer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Disable ships for computer: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Default service interval for trains: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Default service interval for road vehicles: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Default service interval for aircraft: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Default service interval for ships: {ORANGE}{STRING} days + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Colored news appears in: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Starting date: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Enable smooth economy (more, smaller changes) + +STR_CONFIG_PATCHES_GUI :{BLACK}Interface +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Vehicles +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stations +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Economy + +STR_CONFIG_PATCHES_DISABLED :disabled +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Change setting value + + +STR_CHEATS :{WHITE}Cheats +STR_CHEATS_TIP :{BLACK}Checkboxes indicate if you have used this cheat before +STR_CHEATS_WARNING :{BLACK}Warning! You are about to betray your fellow competitors. Keep in mind that such a disgrace will be remembered for eternity. +STR_CHEAT_MONEY :{LTBLUE}Increase money by {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Playing as player: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magic bulldozer (remove industries, unmovables): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunnels may cross each other: {ORANGE}{STRING} + +STR_SORT_BY_POPULATION :{BLACK}Population + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Heading for {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Heading for {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Go via {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Checkpoint {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Checkpoint {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Checkpoint + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Edit checkpoint name + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Can't change checkpoint name... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Convert rail to checkpoint +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Can't build train checkpoint here... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Can't remove train checkpoint here... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Build railroad track using the Autorail mode + +STR_NO_TOWN_IN_SCENARIO :{WHITE}...there is no town in this scenario + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Are you sure you want to create a random landscape? +STR_MANY_RANDOM_TOWNS :{BLACK}Many random towns +STR_RANDOM_TOWNS_TIP :{BLACK}Cover the map with randomly placed towns +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Many random industries +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Cover the map with randomly placed industries +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Can't generate industries... + +STR_LANDSCAPING_TOOLBAR :{WHITE}Landscaping +STR_LEVEL_LAND_TOOLTIP :{BLACK}Level land + + +STR_TREES_RANDOM_TYPE :{BLACK}Trees of random type +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Place trees of random type + +STR_CANT_BUILD_CANALS :{WHITE}Can't build canals here... +STR_BUILD_CANALS_TIP :{BLACK}Build canals +STR_LANDINFO_CANAL :Canal + +STR_CANT_BUILD_LOCKS :{WHITE}Can't build locks here... +STR_BUILD_LOCKS_TIP :{BLACK}Build locks +STR_LANDINFO_LOCK :Lock + +STR_LANDINFO_COORDS :{BLACK}Coordinates: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Can't remove part of station... +STR_CANT_CONVERT_RAIL :{WHITE}Can't convert railtype here... +STR_CONVERT_RAIL_TIP :{BLACK}Convert/Upgrade the type of the rail + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Drag train engine here to sell the whole train + +STR_DRAG_DROP :{BLACK}Drag & Drop +STR_STATION_DRAG_DROP :{BLACK}Build a station with drag & drop + +STR_FAST_FORWARD :{BLACK}Fast forward the game +STR_MESSAGE_HISTORY :{WHITE}Message History +STR_MESSAGE_HISTORY_TIP :{BLACK}A list of the recent news messages +STR_MESSAGES_DISABLE_ALL :{BLACK}Disable all +STR_MESSAGES_ENABLE_ALL :{BLACK}Enable all + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Construct Coal Mine +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plant Forest +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Construct Oil Rig +STR_CONSTRUCT_FARM_TIP :{BLACK}Fund Farm +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Construct Copper Ore Mine +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Drill for Oil +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Construct Gold Mine +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Construct Diamond Mine +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Construct Iron Ore Mine +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Fund Fruit Plantation +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Fund Rubber Plantation +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Fund Water Supply +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plant Cotton Candy Forest +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Fund Battery Farm +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Drill for Cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Fund Plastic Fountains +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Construct Bubble Generator +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Fund Toffee Quarry +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Construct Sugar Mine + +STR_SORT_BY_PRODUCTION :{BLACK}Production +STR_SORT_BY_TYPE :{BLACK}Type +STR_SORT_BY_TRANSPORTED :{BLACK}Transported +STR_INDUSTRYDIR_CAPTION :{WHITE}Industries +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}){YELLOW} ({COMMA16}% transported) +STR_INDUSTRYDIR_ITEM_TWO :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}/{STRING}){YELLOW} ({COMMA16}%/{COMMA16}% transported) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...too close to another industry + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Refit train to carry a different cargo type +STR_RAIL_REFIT :{WHITE}{STRING} (Refit) +STR_RAIL_REFIT_VEHICLE :{BLACK}Refit train +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Select type of cargo for train to carry +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Refit train to carry highlighted cargo type +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Can't refit train... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}Network interface is not working yet! + +STR_NETWORK_MULTIPLAYER :{WHITE}Multiplayer + +STR_NETWORK_FIND_SERVER :{BLACK}Find server +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Search network for a server +STR_NETWORK_DIRECT_CONNECT :{BLACK}Direct connect +STR_NETWORK_ENTER_IP :{BLACK}Enter the IP address of the server +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Connect to a known IP +STR_NETWORK_START_SERVER :{BLACK}Start server +STR_NETWORK_START_SERVER_TIP :{BLACK}Start an own server + +STR_NETWORK_PLAYER_NAME :{BLACK}Player name: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}This is the name other players will identify you by + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Select connection type: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Chose between an internet game or a local area nework game +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Name +STR_NETWORK_GAME_NAME_TIP :{BLACK}Name of the game +STR_NETWORK_PLAYERS :{BLACK}#/# +STR_NETWORK_PLAYERS_TIP :{BLACK}Players currently in this game / Maximum number of players +STR_NETWORK_MAP_SIZE :{BLACK}Size +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Size of the map +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Language, server version, etc. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Click a game from the list to select it + +STR_NETWORK_JOIN_GAME :{BLACK}Join game + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Start new game + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Game name: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}The game name will be displayed to other players in the multiplayer game selection menu +STR_NETWORK_PASSWORD :{BLACK}Password: +STR_NETWORK_PASSWORD_TIP :{BLACK}Protect your game with a password if you don't want other people to join it +STR_NETWORK_SELECT_MAP :{BLACK}Select a map: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}Which map do you want to play? +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Number of players: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Chose a maximum number of players. Not all slots need to be filled. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 players +STR_NETWORK_3_PLAYERS :{BLACK}3 players +STR_NETWORK_4_PLAYERS :{BLACK}4 players +STR_NETWORK_5_PLAYERS :{BLACK}5 players +STR_NETWORK_6_PLAYERS :{BLACK}6 players +STR_NETWORK_7_PLAYERS :{BLACK}7 players +STR_NETWORK_8_PLAYERS :{BLACK}8 players +STR_NETWORK_START_GAME :{BLACK}Start Game + + +STR_NETWORK_GAME_LOBBY :{WHITE}Multiplayer game lobby + +STR_NETWORK_SEND :{BLACK}Send +STR_NETWORK_SEND_TIP :{BLACK}Send a message to the other players +STR_NETWORK_COMPANY_NAME :{BLACK}Company name: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Change the name of your company. Hit enter to apply changes +STR_NETWORK_SPECTATE_GAME :{BLACK}Spectate game +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Watch the game as a spectator +STR_NETWORK_NEW_COMPANY :{BLACK}New company +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Open a new company +STR_NETWORK_READY :{BLACK}Ready + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Cost: {CURRENCY} +STR_0801_COST :{RED}Cost: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Income: {CURRENCY} +STR_0803_INCOME :{GREEN}Income: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Estimated Cost: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Estimated Cost: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Estimated Income: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Estimated Income: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Can't raise land here... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Can't lower land here... +STR_080A_ROCKS :Rocks +STR_080B_ROUGH_LAND :Rough land +STR_080C_BARE_LAND :Bare land +STR_080D_GRASS :Grass +STR_080E_FIELDS :Fields +STR_080F_SNOW_COVERED_LAND :Snow-covered land +STR_0810_DESERT :Desert + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Impossible track combination +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Excavation would damage tunnel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Already at sea-level +STR_1004_TOO_HIGH :{WHITE}Too high +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}No suitable railroad track +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Train inside depot +STR_1007_ALREADY_BUILT :{WHITE}...already built +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Must remove railroad track first +STR_1009_TOO_MANY_DEPOTS :{WHITE}Too many depots +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Railroad Construction +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Monorail Construction +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}MagLev Construction +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Select Rail Bridge +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Can't build train depot here... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Can't build railroad station here... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Can't build signals here... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Can't build railroad track here... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Can't remove railroad track from here... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Can't remove signals from here... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Train Depot Orientation +STR_1015_RAILROAD_CONSTRUCTION :Railroad construction +STR_1016_MONORAIL_CONSTRUCTION :Monorail construction +STR_1017_MAGLEV_CONSTRUCTION :MagLev construction +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Build railroad track +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Build train depot (for building and servicing trains) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Build railroad station +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Build railroad signals +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Build railroad bridge +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Build railroad tunnel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Toggle build/remove for railroad track and signals +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Bridge selection - click on selected bridge to build it +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Select railroad depot orientation +STR_1021_RAILROAD_TRACK :Railroad track +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Railroad track with signals +STR_1023_RAILROAD_TRAIN_DEPOT :Railroad train depot +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...area is owned by another company +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Railroad track with normal signals +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Railroad track with pre-signals +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Railroad track with exit-signals +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Railroad track with combo-signals + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction for road +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Must remove road first +STR_1802_ROAD_CONSTRUCTION :{WHITE}Road Construction +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Select Road Bridge +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Can't build road here... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Can't remove road from here... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Road Depot Orientation +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Can't build road vehicle depot here... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Can't build bus station... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Can't build truck station... +STR_180A_ROAD_CONSTRUCTION :Road construction +STR_180B_BUILD_ROAD_SECTION :{BLACK}Build road section +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Build road vehicle depot (for building and servicing vehicles) +STR_180D_BUILD_BUS_STATION :{BLACK}Build bus station +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Build truck loading bay +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Build road bridge +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Build road tunnel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Toggle build/remove for road construction +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Bridge selection - click on selected bridge to build it +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Select road vehicle depot orientation +STR_1814_ROAD :Road +STR_1815_ROAD_WITH_STREETLIGHTS :Road with streetlights +STR_1816_TREE_LINED_ROAD :Tree-lined road +STR_1817_ROAD_VEHICLE_DEPOT :Road vehicle depot +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Road/rail level crossing + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Towns +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Building must be demolished first +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Population: {ORANGE}{COMMA32}{BLACK} Houses: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Rename Town +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Can't rename town... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} local authority refuses to allow this +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Town names - click on name to center main view on town +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Center the main view on town location +STR_200C_CHANGE_TOWN_NAME :{BLACK}Change town name +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passengers last month: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Mail last month: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Tall office block +STR_2010_OFFICE_BLOCK :Office block +STR_2011_SMALL_BLOCK_OF_FLATS :Small block of flats +STR_2012_CHURCH :Church +STR_2013_LARGE_OFFICE_BLOCK :Large office block +STR_2014_TOWN_HOUSES :Town houses +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Statue +STR_2017_FOUNTAIN :Fountain +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Office block +STR_201A_SHOPS_AND_OFFICES :Shops and offices +STR_201B_MODERN_OFFICE_BUILDING :Modern office building +STR_201C_WAREHOUSE :Warehouse +STR_201D_OFFICE_BLOCK :Office block +STR_201E_STADIUM :Stadium +STR_201F_OLD_HOUSES :Old houses +STR_2020_LOCAL_AUTHORITY :{BLACK}Local authority +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Show information on local authority +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} local authority +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Transport company ratings: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subsidies +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Subsidies on offer for services taking:- +STR_2027_FROM_TO :{ORANGE}{STRING} from {STRING} to {STRING} +STR_2028_BY :{YELLOW} (by {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}None +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Services already subsidised:- +STR_202C_FROM_TO :{ORANGE}{STRING} from {STATION} to {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, until {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Offer of subsidy expired:{}{}{STRING} from {STRING} to {STRING} will now not attract a subsidy. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subsidy withdrawn:{}{}{STRING} service from {STATION} to {STATION} is no longer subsidised. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Service subsidy offered:{}{}First {STRING} service from {STRING} to {STRING} will attract a year's subsidy from the local authority! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay 50% extra for the next year! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay double rates for the next year! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay triple rates for the next year! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay quadruple rates for the next year! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} local authority refuses to allow another airport to be built in this town +STR_2036_COTTAGES :Cottages +STR_2037_HOUSES :Houses +STR_2038_FLATS :Flats +STR_2039_TALL_OFFICE_BLOCK :Tall office block +STR_203A_SHOPS_AND_OFFICES :Shops and offices +STR_203B_SHOPS_AND_OFFICES :Shops and offices +STR_203C_THEATER :Theater +STR_203D_STADIUM :Stadium +STR_203E_OFFICES :Offices +STR_203F_HOUSES :Houses +STR_2040_CINEMA :Cinema +STR_2041_SHOPPING_MALL :Shopping mall +STR_2042_DO_IT :{BLACK}Do it +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}List of things to do at this town - click on item for more details +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Carry out the highlighted action in the list above +STR_2045_ACTIONS_AVAILABLE :{BLACK}Actions available: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Small advertising campaign +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Medium advertising campaign +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Large advertising campaign +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Fund local road reconstruction +STR_204A_BUILD_STATUE_OF_COMPANY :Build statue of company owner +STR_204B_FUND_NEW_BUILDINGS :Fund new buildings +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Buy exclusive transport rights +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Bribe the local authority +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Initiate a small local advertising campaign, to attract more passengers and cargo to your transport services.{} Cost: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Initiate a medium local advertising campaign, to attract more passengers and cargo to your transport services.{} Cost: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Initiate a large local advertising campaign, to attract more passengers and cargo to your transport services.{} Cost: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Fund the reconstruction of the urban road network. Causes considerable disruption to road traffic for up to 6 months.{} Cost: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Build a statue in honor of your company.{} Cost: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Fund the construction of new commercial buildings in the town.{} Cost: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Buy 1 year's exclusive transport rights in town. Town authority will only allow passengers and cargo to use your company's stations.{} Cost: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Bribe the local authority to increase your rating, at the risk of a severe penalty if caught.{} Cost: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Can't do this... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {STRING} brings 6 months of misery to motorists! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (under construction) +STR_2059_IGLOO :Igloo +STR_205A_TEPEES :Tepees +STR_205B_TEAPOT_HOUSE :Teapot-House +STR_205C_PIGGY_BANK :Piggy-Bank + +##id 0x2800 +STR_LANDSCAPING :Landscaping +STR_2800_PLANT_TREES :Plant trees +STR_2801_PLACE_SIGN :Place sign +STR_2802_TREES :{WHITE}Trees +STR_2803_TREE_ALREADY_HERE :{WHITE}...tree already here +STR_2804_SITE_UNSUITABLE :{WHITE}...site unsuitable +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Can't plant tree here... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...too many signs +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Can't place sign here... +STR_280A_SIGN :Sign +STR_280B_EDIT_SIGN_TEXT :{WHITE}Edit sign text +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Can't change sign name... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Select tree type to plant +STR_280E_TREES :Trees +STR_280F_RAINFOREST :Rainforest +STR_2810_CACTUS_PLANTS :Cactus Plants + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Rail Station Selection +STR_3001_AIRPORT_SELECTION :{WHITE}Airport Selection +STR_3002_ORIENTATION :{BLACK}Orientation +STR_3003_NUMBER_OF_TRACKS :{BLACK}Number of tracks +STR_3004_PLATFORM_LENGTH :{BLACK}Platform length +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Too close to another railroad station +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Adjoins more than one existing station/loading area +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Too many stations/loading areas in this town +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Too many stations/loading areas +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Too close to another station/loading area +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Must demolish railroad station first +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Too close to another airport +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Must demolish airport first + +STR_3030_RENAME_STATION_LOADING :Rename station/loading area +STR_3031_CAN_T_RENAME_STATION :{WHITE}Can't rename station... +STR_3032_RATINGS :{BLACK}Ratings +STR_3033_ACCEPTS :{BLACK}Accepts +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Local rating of transport service: + +############ range for rating starts +STR_3035_APPALLING :Appalling +STR_3036_VERY_POOR :Very Poor +STR_3037_POOR :Poor +STR_3038_MEDIOCRE :Mediocre +STR_3039_GOOD :Good +STR_303A_VERY_GOOD :Very Good +STR_303B_EXCELLENT :Excellent +STR_303C_OUTSTANDING :Outstanding +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} no longer accepts {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} no longer accepts {STRING} or {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} now accepts {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} now accepts {STRING} and {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Bus Station Orientation +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Truck Station Orient. +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Too close to another bus station +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Too close to another truck station +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Must demolish bus station first +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Must demolish truck station first +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stations +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- None - +STR_304B_SITE_UNSUITABLE :{WHITE}...site unsuitable +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Too close to another dock +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Must demolish dock first +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Select railroad station orientation +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Select number of platforms for railroad station +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Select length of railroad station +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Select bus station orientation +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Select truck loading bay orientation +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Center main view on station location +STR_3054_SHOW_STATION_RATINGS :{BLACK}Show station ratings +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Change name of station +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Show list of accepted cargo +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Station names - click on name to center main view on station +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Select size/type of airport +STR_3059_SMALL :{BLACK}Small +STR_305A_LARGE :{BLACK}City +STR_305AA_LARGE :{BLACK}Metropolitan airport +STR_305AB_LARGE :{BLACK}International airport +STR_305B_SIZE :{BLACK}Size +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Railroad station +STR_305F_AIRCRAFT_HANGAR :Aircraft hangar +STR_3060_AIRPORT :Airport +STR_3061_TRUCK_LOADING_AREA :Truck loading area +STR_3062_BUS_STATION :Bus station +STR_3063_SHIP_DOCK :Ship dock +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Highlight coverage area of proposed site +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Don't highlight coverage area of proposed site +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Coverage area highlight +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Monorail Station Select. +STR_3068_DOCK :{WHITE}Dock +STR_3069_BUOY :Buoy +STR_306A_BUOY_IN_THE_WAY :{WHITE}...buoy in the way +STR_306B_HELIPORT :{BLACK}Heliport +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...station too spread out + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Ship Depot Orientation +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...must be built on water +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Can't build ship depot here... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Select ship depot orientation +STR_3804_WATER :Water +STR_3805_COAST_OR_RIVERBANK :Coast or riverbank +STR_3806_SHIP_DEPOT :Ship depot +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Can't build on water + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Save Game +STR_4001_LOAD_GAME :{WHITE}Load Game +STR_4002_SAVE :{BLACK}Save +STR_4003_DELETE :{BLACK}Delete +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes free +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Unable to read drive +STR_4007_GAME_SAVE_FAILED :{WHITE}Game Save Failed +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Unable to delete file +STR_4009_GAME_LOAD_FAILED :{WHITE}Game Load Failed +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}List of drives, directories and saved-game files +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Currently selected name for saved-game +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Delete the currently selected saved-game +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Save the current game, using the selected name +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Select New Game Type +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Select scenario (green), pre-set game (blue), or random new game +STR_4010_GENERATE_RANDOM_NEW_GAME :Generate random new game + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} in the way +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Coal Mine +STR_4803_POWER_STATION :Power Station +STR_4804_SAWMILL :Sawmill +STR_4805_FOREST :Forest +STR_4806_OIL_REFINERY :Oil Refinery +STR_4807_OIL_RIG :Oil Rig +STR_4808_FACTORY :Factory +STR_4809_PRINTING_WORKS :Printing Works +STR_480A_STEEL_MILL :Steel Mill +STR_480B_FARM :Farm +STR_480C_COPPER_ORE_MINE :Copper Ore Mine +STR_480D_OIL_WELLS :Oil Wells +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Food Processing Plant +STR_4810_PAPER_MILL :Paper Mill +STR_4811_GOLD_MINE :Gold Mine +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamond Mine +STR_4814_IRON_ORE_MINE :Iron Ore Mine +STR_4815_FRUIT_PLANTATION :Fruit Plantation +STR_4816_RUBBER_PLANTATION :Rubber Plantation +STR_4817_WATER_SUPPLY :Water Supply +STR_4818_WATER_TOWER :Water Tower +STR_4819_FACTORY :Factory +STR_481A_FARM :Farm +STR_481B_LUMBER_MILL :Lumber Mill +STR_481C_COTTON_CANDY_FOREST :Cotton Candy Forest +STR_481D_CANDY_FACTORY :Candy Factory +STR_481E_BATTERY_FARM :Battery Farm +STR_481F_COLA_WELLS :Cola Wells +STR_4820_TOY_SHOP :Toy Shop +STR_4821_TOY_FACTORY :Toy Factory +STR_4822_PLASTIC_FOUNTAINS :Plastic Fountains +STR_4823_FIZZY_DRINK_FACTORY :Fizzy Drink Factory +STR_4824_BUBBLE_GENERATOR :Bubble Generator +STR_4825_TOFFEE_QUARRY :Toffee Quarry +STR_4826_SUGAR_MINE :Sugar Mine + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Requires: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Requires: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Requires: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Production last month: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transported) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Center the main view on industry location +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}New {STRING} under construction near {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}New {STRING} being planted near {TOWN}! +STR_482F_COST :{BLACK}Cost: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Can't construct this industry type here... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...forest can only be planted above snow-line +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} announces imminent closure! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Supply problems cause {TOWN} {STRING} to announce imminent closure! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Lack of nearby trees causes {TOWN} {STRING} to announce imminent closure! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} increases production! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}New coal seam found at {TOWN} {STRING}!{}Production is expected to double! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}New oil reserves found at {TOWN} {STRING}!{}Production is expected to double! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Improved farming methods at {TOWN} {STRING} are expected to double production! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} production down by 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insect infestation causes havoc at {TOWN} {STRING}!{}Production down by 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...can only be positioned near edges of map +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} production at {TOWN} {STRING} goes up by {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} production at {TOWN} {STRING} goes down by {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Train in tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Road vehicle in tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Another tunnel in the way +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Unable to excavate land for other end of tunnel +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Must demolish tunnel first +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Must demolish bridge first +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Cannot start and end on same position +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Level land or water required under bridge +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start and end must be in line +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Site unsuitable for tunnel entrance +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Suspension, Steel +STR_500F_GIRDER_STEEL :Girder, Steel +STR_5010_CANTILEVER_STEEL :Cantilever, Steel +STR_5011_SUSPENSION_CONCRETE :Suspension, Concrete +STR_5012_WOODEN :Wooden +STR_5013_CONCRETE :Concrete +STR_5014_TUBULAR_STEEL :Tubular, Steel +STR_BRIDGE_TUBULAR_SILICON :Tubular, Silicon +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Can't build bridge here... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... +STR_5017_RAILROAD_TUNNEL :Railroad tunnel +STR_5018_ROAD_TUNNEL :Road tunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Steel suspension rail bridge +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Steel girder rail bridge +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Steel cantilever rail bridge +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Reinforced concrete suspension rail bridge +STR_501F_WOODEN_RAIL_BRIDGE :Wooden rail bridge +STR_5020_CONCRETE_RAIL_BRIDGE :Concrete rail bridge +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Steel suspension road bridge +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Steel girder road bridge +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Steel cantilever road bridge +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Reinforced concrete suspension road bridge +STR_5025_WOODEN_ROAD_BRIDGE :Wooden road bridge +STR_5026_CONCRETE_ROAD_BRIDGE :Concrete road bridge +STR_5027_TUBULAR_RAIL_BRIDGE :Tubular rail bridge +STR_5028_TUBULAR_ROAD_BRIDGE :Tubular road bridge +STR_5029_STEEL :Steel + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Object in the way +STR_5801_TRANSMITTER :Transmitter +STR_5802_LIGHTHOUSE :Lighthouse +STR_5803_COMPANY_HEADQUARTERS :Company Headquarters +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...company headquarters in the way +STR_5805_COMPANY_OWNED_LAND :Company-owned land +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Can't purchase this land area... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...you already own it! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Unnamed{SKIP} +STR_SV_TRAIN_NAME :Train {COMMA16} +STR_SV_ROADVEH_NAME :Road Vehicle {COMMA16} +STR_SV_SHIP_NAME :Ship {COMMA16} +STR_SV_AIRCRAFT_NAME :Aircraft {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} North +STR_SV_STNAME_SOUTH :{STRING} South +STR_SV_STNAME_EAST :{STRING} East +STR_SV_STNAME_WEST :{STRING} West +STR_SV_STNAME_CENTRAL :{STRING} Central +STR_SV_STNAME_TRANSFER :{STRING} Transfer +STR_SV_STNAME_HALT :{STRING} Halt +STR_SV_STNAME_VALLEY :{STRING} Valley +STR_SV_STNAME_HEIGHTS :{STRING} Heights +STR_SV_STNAME_WOODS :{STRING} Woods +STR_SV_STNAME_LAKESIDE :{STRING} Lakeside +STR_SV_STNAME_EXCHANGE :{STRING} Exchange +STR_SV_STNAME_AIRPORT :{STRING} Airport +STR_SV_STNAME_OILFIELD :{STRING} Oilfield +STR_SV_STNAME_MINES :{STRING} Mines +STR_SV_STNAME_DOCKS :{STRING} Docks +STR_SV_STNAME_BUOY_1 :{STRING} Buoy 1 +STR_SV_STNAME_BUOY_2 :{STRING} Buoy 2 +STR_SV_STNAME_BUOY_3 :{STRING} Buoy 3 +STR_SV_STNAME_BUOY_4 :{STRING} Buoy 4 +STR_SV_STNAME_BUOY_5 :{STRING} Buoy 5 +STR_SV_STNAME_BUOY_6 :{STRING} Buoy 6 +STR_SV_STNAME_BUOY_7 :{STRING} Buoy 7 +STR_SV_STNAME_BUOY_8 :{STRING} Buoy 8 +STR_SV_STNAME_BUOY_9 :{STRING} Buoy 9 +STR_SV_STNAME_ANNEXE :{STRING} Annexe +STR_SV_STNAME_SIDINGS :{STRING} Sidings +STR_SV_STNAME_BRANCH :{STRING} Branch +STR_SV_STNAME_UPPER :Upper {STRING} +STR_SV_STNAME_LOWER :Lower {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Forest + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Difficulty Level +STR_OPTIONS_SAVE_CHANGES :{BLACK}Save + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Easy +STR_6802_MEDIUM :{BLACK}Medium +STR_6803_HARD :{BLACK}Hard +STR_6804_CUSTOM :{BLACK}Custom +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maximum no. competitors: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Competitor start time: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}No. of towns: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}No. of industries: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maximum initial loan: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Initial interest rate: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Vehicle running costs: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Construction speed of competitors: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligence of competitors: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Vehicle breakdowns: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Subsidy multiplier: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Cost of construction: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Terrain type: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Quantity of sea/lakes: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Economy: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Train reversing: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Disasters: {ORANGE}{STRING} +STR_16816_CITY_APPROVAL :{LTBLUE}City council's attitude towards area restructuring: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Low +STR_6817_NORMAL :Normal +STR_6818_HIGH :High +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Very Slow +STR_681C_SLOW :Slow +STR_681D_MEDIUM :Medium +STR_681E_FAST :Fast +STR_681F_VERY_FAST :Very Fast +STR_VERY_LOW :Very Low +STR_6820_LOW :Low +STR_6821_MEDIUM :Medium +STR_6822_HIGH :High +STR_6823_NONE :None +STR_6824_REDUCED :Reduced +STR_6825_NORMAL :Normal +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Very Flat +STR_682B_FLAT :Flat +STR_682C_HILLY :Hilly +STR_682D_MOUNTAINOUS :Mountainous +STR_682E_STEADY :Steady +STR_682F_FLUCTUATING :Fluctuating +STR_6830_IMMEDIATE :Immediate +STR_6831_3_MONTHS_AFTER_PLAYER :3 months after player +STR_6832_6_MONTHS_AFTER_PLAYER :6 months after player +STR_6833_9_MONTHS_AFTER_PLAYER :9 months after player +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :At end of line, and at stations +STR_6835_AT_END_OF_LINE_ONLY :At end of line only +STR_6836_OFF :Off +STR_6837_ON :On +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Show hi-score chart +STR_6839_PERMISSIVE :Permissive +STR_683A_TOLERANT :Tolerant +STR_683B_HOSTILE :Hostile + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Player 1) +STR_7003_PLAYER_2 : (Player 2) +STR_7004_NEW_FACE :{BLACK}New Face +STR_7005_COLOR_SCHEME :{BLACK}Color Scheme +STR_7006_COLOR_SCHEME :{GOLD}Color Scheme: +STR_7007_NEW_COLOR_SCHEME :{WHITE}New Color Scheme +STR_7008_COMPANY_NAME :{BLACK}Company Name +STR_7009_PRESIDENT_NAME :{BLACK}President Name +STR_700A_COMPANY_NAME :Company Name +STR_700B_PRESIDENT_S_NAME :President's Name +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Can't change company name... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Can't change president's name... +STR_700E_FINANCES :{WHITE}{STRING} Finances{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Expenditure/Income +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Construction +STR_7012_NEW_VEHICLES :{GOLD}New Vehicles +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Train Running Costs +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Road Veh. Running Costs +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Aircraft Running Costs +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Ship Running Costs +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Property Maintenance +STR_7018_TRAIN_INCOME :{GOLD}Train Income +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Road Vehicles Income +STR_701A_AIRCRAFT_INCOME :{GOLD}Aircraft Income +STR_701B_SHIP_INCOME :{GOLD}Ship Income +STR_701C_LOAN_INTEREST :{GOLD}Loan Interest +STR_701D_OTHER :{GOLD}Other +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Total: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Income Graph +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Operating Profit Graph +STR_7026_BANK_BALANCE :{WHITE}Bank Balance +STR_7027_LOAN :{WHITE}Loan +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Borrow {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Repay {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maximum permitted loan size is {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Can't borrow any more money... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...no loan to repay +STR_702E_REQUIRED :{WHITE}...{CURRENCY} required +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Can't repay loan... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Select new face for president +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Change the company vehicle livery +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Change the president's name +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Change the company name +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Click on selected new color scheme +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Increase size of loan +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Repay part of loan +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(President) +STR_7038_INAUGURATED :{GOLD}Inaugurated: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Vehicles: +STR_703A_TRAIN :{WHITE}{COMMA16} train +STR_703B_TRAINS :{WHITE}{COMMA16} trains +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} road vehicle +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} road vehicles +STR_703E_AIRCRAFT :{WHITE}{COMMA16} aircraft +STR_703F_AIRCRAFT :{WHITE}{COMMA16} aircraft +STR_7040_SHIP :{WHITE}{COMMA16} ship +STR_7041_SHIPS :{WHITE}{COMMA16} ships +STR_7042_NONE :{WHITE}None +STR_7043_FACE_SELECTION :{WHITE}Face Selection +STR_7044_MALE :{BLACK}Male +STR_7045_FEMALE :{BLACK}Female +STR_7046_NEW_FACE :{BLACK}New Face +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Cancel new face selection +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Accept new face selection +STR_7049_SELECT_MALE_FACES :{BLACK}Select male faces +STR_704A_SELECT_FEMALE_FACES :{BLACK}Select female faces +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Generate random new face +STR_704C_KEY :{BLACK}Key +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Show key to graphs +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Key to company graphs +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Click here to toggle company's entry on graph on/off +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Units of cargo delivered +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Company performance ratings (maximum rating=1000) +STR_7052_COMPANY_VALUES :{WHITE}Company values +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Company League Table +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transport company in trouble! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} will be sold off or declared bankrupt unless performance increases soon! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(President) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Transport company merger! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} has been sold to {STRING} for {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}We are looking for a transport company to take-over our company{}{}Do you want to purchase {STRING} for {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrupt! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} has been closed down by creditors and all assets sold off! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}New transport company launched! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} starts construction near {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Can't buy company... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Cargo Payment Rates +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Days in transit +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Payment for delivering 10 units (or 10,000 litres) of cargo a distance of 20 squares +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Toggle graph for cargo type on/off +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Engineer +STR_7067_TRAFFIC_MANAGER :Traffic Manager +STR_7068_TRANSPORT_COORDINATOR :Transport Coordinator +STR_7069_ROUTE_SUPERVISOR :Route Supervisor +STR_706A_DIRECTOR :Director +STR_706B_CHIEF_EXECUTIVE :Chief Executive +STR_706C_CHAIRMAN :Chairman +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Build HQ +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Build company headquarters / view company headquarters +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Can't build company headquarters... +STR_7072_VIEW_HQ :{BLACK}View HQ +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}World Recession!{}{}Financial experts fear worst as economy slumps! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Recession Over!{}{}Upturn in trade gives confidence to industries as economy strengthens! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Toggle large/small window size +STR_7076_COMPANY_VALUE :{GOLD}Company value: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Buy 25% share in company +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Sell 25% share in company +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Buy 25% share in this company +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Sell 25% share in this company +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Can't buy 25% share in this company... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Can't sell 25% share in this company... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% owned by {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% owned by {STRING}{} {COMMA16}% owned by {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} has been taken over by {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Steam) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Steam) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Steam) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Steam) +STR_800A_SH_8P_STEAM :SH '8P' (Steam) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Electric) +STR_8018_SH_40_ELECTRIC :SH '40' (Electric) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Electric) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Electric) +STR_801B_PASSENGER_CAR :Passenger Car +STR_801C_MAIL_VAN :Mail Van +STR_801D_COAL_CAR :Coal Car +STR_801E_OIL_TANKER :Oil Tanker +STR_801F_LIVESTOCK_VAN :Livestock Van +STR_8020_GOODS_VAN :Goods Van +STR_8021_GRAIN_HOPPER :Grain Hopper +STR_8022_WOOD_TRUCK :Wood Truck +STR_8023_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8024_STEEL_TRUCK :Steel Truck +STR_8025_ARMORED_VAN :Armored Van +STR_8026_FOOD_VAN :Food Van +STR_8027_PAPER_TRUCK :Paper Truck +STR_8028_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8029_WATER_TANKER :Water Tanker +STR_802A_FRUIT_TRUCK :Fruit Truck +STR_802B_RUBBER_TRUCK :Rubber Truck +STR_802C_SUGAR_TRUCK :Sugar Truck +STR_802D_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_802E_TOFFEE_HOPPER :Toffee Hopper +STR_802F_BUBBLE_VAN :Bubble Van +STR_8030_COLA_TANKER :Cola Tanker +STR_8031_CANDY_VAN :Candy Van +STR_8032_TOY_VAN :Toy Van +STR_8033_BATTERY_TRUCK :Battery Truck +STR_8034_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8035_PLASTIC_TRUCK :Plastic Truck +STR_8036_X2001_ELECTRIC :'X2001' (Electric) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Electric) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Passenger Car +STR_803A_MAIL_VAN :Mail Van +STR_803B_COAL_CAR :Coal Car +STR_803C_OIL_TANKER :Oil Tanker +STR_803D_LIVESTOCK_VAN :Livestock Van +STR_803E_GOODS_VAN :Goods Van +STR_803F_GRAIN_HOPPER :Grain Hopper +STR_8040_WOOD_TRUCK :Wood Truck +STR_8041_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8042_STEEL_TRUCK :Steel Truck +STR_8043_ARMORED_VAN :Armored Van +STR_8044_FOOD_VAN :Food Van +STR_8045_PAPER_TRUCK :Paper Truck +STR_8046_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8047_WATER_TANKER :Water Tanker +STR_8048_FRUIT_TRUCK :Fruit Truck +STR_8049_RUBBER_TRUCK :Rubber Truck +STR_804A_SUGAR_TRUCK :Sugar Truck +STR_804B_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_804C_TOFFEE_HOPPER :Toffee Hopper +STR_804D_BUBBLE_VAN :Bubble Van +STR_804E_COLA_TANKER :Cola Tanker +STR_804F_CANDY_VAN :Candy Van +STR_8050_TOY_VAN :Toy Van +STR_8051_BATTERY_TRUCK :Battery Truck +STR_8052_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8053_PLASTIC_TRUCK :Plastic Truck +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Electric) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Electric) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Electric) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Electric) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Passenger Car +STR_805A_MAIL_VAN :Mail Van +STR_805B_COAL_CAR :Coal Car +STR_805C_OIL_TANKER :Oil Tanker +STR_805D_LIVESTOCK_VAN :Livestock Van +STR_805E_GOODS_VAN :Goods Van +STR_805F_GRAIN_HOPPER :Grain Hopper +STR_8060_WOOD_TRUCK :Wood Truck +STR_8061_IRON_ORE_HOPPER :Iron Ore Hopper +STR_8062_STEEL_TRUCK :Steel Truck +STR_8063_ARMORED_VAN :Armored Van +STR_8064_FOOD_VAN :Food Van +STR_8065_PAPER_TRUCK :Paper Truck +STR_8066_COPPER_ORE_HOPPER :Copper Ore Hopper +STR_8067_WATER_TANKER :Water Tanker +STR_8068_FRUIT_TRUCK :Fruit Truck +STR_8069_RUBBER_TRUCK :Rubber Truck +STR_806A_SUGAR_TRUCK :Sugar Truck +STR_806B_COTTON_CANDY_HOPPER :Cotton Candy Hopper +STR_806C_TOFFEE_HOPPER :Toffee Hopper +STR_806D_BUBBLE_VAN :Bubble Van +STR_806E_COLA_TANKER :Cola Tanker +STR_806F_CANDY_VAN :Candy Van +STR_8070_TOY_VAN :Toy Van +STR_8071_BATTERY_TRUCK :Battery Truck +STR_8072_FIZZY_DRINK_TRUCK :Fizzy Drink Truck +STR_8073_PLASTIC_TRUCK :Plastic Truck +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Coal Truck +STR_807C_UHL_COAL_TRUCK :Uhl Coal Truck +STR_807D_DW_COAL_TRUCK :DW Coal Truck +STR_807E_MPS_MAIL_TRUCK :MPS Mail Truck +STR_807F_REYNARD_MAIL_TRUCK :Reynard Mail Truck +STR_8080_PERRY_MAIL_TRUCK :Perry Mail Truck +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Mail Truck +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Mail Truck +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Mail Truck +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Oil Tanker +STR_8085_FOSTER_OIL_TANKER :Foster Oil Tanker +STR_8086_PERRY_OIL_TANKER :Perry Oil Tanker +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Livestock Van +STR_8088_UHL_LIVESTOCK_VAN :Uhl Livestock Van +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Livestock Van +STR_808A_BALOGH_GOODS_TRUCK :Balogh Goods Truck +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Goods Truck +STR_808C_GOSS_GOODS_TRUCK :Goss Goods Truck +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Grain Truck +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Grain Truck +STR_808F_GOSS_GRAIN_TRUCK :Goss Grain Truck +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Wood Truck +STR_8091_FOSTER_WOOD_TRUCK :Foster Wood Truck +STR_8092_MORELAND_WOOD_TRUCK :Moreland Wood Truck +STR_8093_MPS_IRON_ORE_TRUCK :MPS Iron Ore Truck +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Iron Ore Truck +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Iron Ore Truck +STR_8096_BALOGH_STEEL_TRUCK :Balogh Steel Truck +STR_8097_UHL_STEEL_TRUCK :Uhl Steel Truck +STR_8098_KELLING_STEEL_TRUCK :Kelling Steel Truck +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Armored Truck +STR_809A_UHL_ARMORED_TRUCK :Uhl Armored Truck +STR_809B_FOSTER_ARMORED_TRUCK :Foster Armored Truck +STR_809C_FOSTER_FOOD_VAN :Foster Food Van +STR_809D_PERRY_FOOD_VAN :Perry Food Van +STR_809E_CHIPPY_FOOD_VAN :Chippy Food Van +STR_809F_UHL_PAPER_TRUCK :Uhl Paper Truck +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Paper Truck +STR_80A1_MPS_PAPER_TRUCK :MPS Paper Truck +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Copper Ore Truck +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Copper Ore Truck +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Copper Ore Truck +STR_80A5_UHL_WATER_TANKER :Uhl Water Tanker +STR_80A6_BALOGH_WATER_TANKER :Balogh Water Tanker +STR_80A7_MPS_WATER_TANKER :MPS Water Tanker +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Fruit Truck +STR_80A9_UHL_FRUIT_TRUCK :Uhl Fruit Truck +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Fruit Truck +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Rubber Truck +STR_80AC_UHL_RUBBER_TRUCK :Uhl Rubber Truck +STR_80AD_RMT_RUBBER_TRUCK :RMT Rubber Truck +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Sugar Truck +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Sugar Truck +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Sugar Truck +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Cola Truck +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Cola Truck +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Cola Truck +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Cotton Candy Truck +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Cotton Candy Truck +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Cotton Candy Truck +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Toffee Truck +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Toffee Truck +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Toffee Truck +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Toy Van +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Toy Van +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Toy Van +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Candy Truck +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Candy Truck +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Candy Truck +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Battery Truck +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Battery Truck +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Battery Truck +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Fizzy Drink Truck +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Fizzy Drink Truck +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Fizzy Drink Truck +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastic Truck +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastic Truck +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastic Truck +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Bubble Truck +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Bubble Truck +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Bubble Truck +STR_80CC_MPS_OIL_TANKER :MPS Oil Tanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Oil Tanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Passenger Ferry +STR_80CF_FFP_PASSENGER_FERRY :FFP Passenger Ferry +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Hovercraft +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passenger Ferry +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passenger Ferry +STR_80D3_YATE_CARGO_SHIP :Yate Cargo ship +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Cargo ship +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Cargo ship +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Cargo ship +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helicopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helicopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helicopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Message from vehicle manufacturer +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}We have just designed a new {STRING} - would you be interested in a year's exclusive use of this vehicle, so we can see how it performs before making it universally available ? +STR_8102_RAILROAD_LOCOMOTIVE :railroad locomotive +STR_8103_ROAD_VEHICLE :road vehicle +STR_8104_AIRCRAFT :aircraft +STR_8105_SHIP :ship +STR_8106_MONORAIL_LOCOMOTIVE :monorail locomotive +STR_8107_MAGLEV_LOCOMOTIVE :maglev locomotive + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Train Depot +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First train arrives at {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Details) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Train in the way +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Go to {STATION} +STR_8807_GO_TO_UNLOAD :Go to {STATION} (Unload) +STR_8808_GO_TO_LOAD :Go to {STATION} (Load) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Go non-stop to {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Go non-stop to {STATION} (Unload) +STR_880C_GO_NON_STOP_TO_LOAD :Go non-stop to {STATION} (Load) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Go to {TOWN} Train Depot +STR_SERVICE_AT_TRAIN_DEPOT :Service at {TOWN} Train Depot +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Go non-stop to {TOWN} Train Depot +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Service non-stop at {TOWN} Train Depot + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Heading for {TOWN} Train Depot +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Train Depot, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Empty +STR_8813_FROM :{LTBLUE}{CARGO} from {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Train {COMMA16} is waiting in depot +STR_8815_NEW_VEHICLES :{BLACK}New Vehicles +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Weight: {GOLD}{COMMA16}t{}{BLACK}Speed: {GOLD}{VELOCITY}{BLACK} Power: {GOLD}{COMMA16}hp{}{BLACK}Running Cost: {GOLD}{CURRENCY}/yr{}{BLACK}Capacity: {GOLD}{STRING}{}{BLACK}Designed: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} years{}{BLACK}Max. Reliability: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Information +STR_8819_TRAIN_TOO_LONG :{WHITE}Train too long +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Trains can only be altered when stopped inside a depot +STR_881B_TRAINS :{WHITE}{STRING} - Trains +STR_881C_NEW_RAIL_VEHICLES :{WHITE}New Rail Vehicles +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}New Monorail Vehicles +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}New Maglev Vehicles +STR_881F_BUILD_VEHICLE :{BLACK}Build Vehicle +STR_8820_RENAME :{BLACK}Rename +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Cost: {GOLD}{CURRENCY}{}{BLACK}Weight: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Capacity: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Skip +STR_8824_DELETE :{BLACK}Delete +STR_8825_NON_STOP :{BLACK}Non-Stop +STR_8826_GO_TO :{BLACK}Go To +STR_8827_FULL_LOAD :{BLACK}Full Load +STR_8828_UNLOAD :{BLACK}Unload +STR_8829_ORDERS :{WHITE}{STRING} (Orders) +STR_882A_END_OF_ORDERS :{SETX 10}- - End of Orders - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Service +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Can't build railroad vehicle... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Built: {LTBLUE}{NUMU16}{BLACK} Value: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Value: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Loading / Unloading +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Can't send train to depot... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}No more space for orders +STR_8832_TOO_MANY_ORDERS :{WHITE}Too many orders +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Can't insert new order... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Can't delete this order... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Can't modify this order... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Must build train depot first +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Can't move vehicle... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Can't sell railroad vehicle... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Unable to find route to local depot +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Can't stop/start train... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Servicing interval: {LTBLUE}{COMMA16}days{BLACK} Last service: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trains - click on train for information +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Build new trains (requires train depot) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trains - click on train for info., drag vehicle to add/remove from train +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Build new train vehicle +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Drag train vehicle to here to sell it +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Center main view on train depot location +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Train vehicle selection list - click on vehicle for information +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Build the highlighted train vehicle +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Rename train vehicle type +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Current train action - click here to stop/start train +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Show train's orders +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Center main view on train's location +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Send train to depot +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Force train to proceed without waiting for signal to clear +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Reverse direction of train +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Show train details +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Increase servicing interval +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Decrease servicing interval +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Show details of cargo carried +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Show details of train vehicles +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Show capacities of each vehicle +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Show total capacity of train, split by cargo type +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Orders list - click on order to highlight it +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Skip the current order, and start the next +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Delete the highlighted order +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order non-stop +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Insert a new order before the highlighted order, or add to end of list +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to wait for a full load +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to unload +STR_SERVICE_HINT :{BLACK}Skip this order unless a service is needed +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}New {STRING} now available! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cost: {CURRENCY} Weight: {COMMA16}t{}Speed: {VELOCITY} Power: {COMMA16}hp{}Running Cost: {CURRENCY}/yr{}Capacity: {STRING} +STR_885C_BROKEN_DOWN :{RED}Broken down +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Running Cost: {LTBLUE}{CURRENCY}/yr +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Weight: {LTBLUE}{COMMA16}t {BLACK}Power: {LTBLUE}{COMMA32}hp{BLACK} Max. speed: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY} (last year: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA8}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Stopped +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... +STR_8863_CRASHED :{RED}Crashed! + +STR_8865_NAME_TRAIN :{WHITE}Name train +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Can't name train... +STR_8867_NAME_TRAIN :{BLACK}Name train +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Train Crash!{}{COMMA16} die in fireball after collision +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Can't reverse direction of train... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Rename train vehicle type +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Can't rename train vehicle type... + +STR_TRAIN_STOPPING :{RED}Stopping +STR_TRAIN_STOPPING_VEL :{RED}Stopping, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Road vehicle in the way +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Road Vehicles +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Road Vehicle Depot +STR_9004_NEW_VEHICLES :{BLACK}New Vehicles +STR_9005_INFORMATION :{BLACK}Information +STR_9006_NEW_ROAD_VEHICLES :{WHITE}New Road Vehicles +STR_9007_BUILD_VEHICLE :{BLACK}Build Vehicle +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Speed: {GOLD}{VELOCITY}{}{BLACK}Running Cost: {GOLD}{CURRENCY}/yr{}{BLACK}Capacity: {GOLD}{STRING}{}{BLACK}Designed: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} years{}{BLACK}Max. Reliability: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Can't build road vehicle... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Must build road vehicle depot first +STR_900B_ORDERS :{WHITE}{STRING} (Orders) +STR_900C_DETAILS :{WHITE}{STRING} (Details) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Running Cost: {LTBLUE}{CURRENCY}/yr +STR_900E_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY} (last year: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA8}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Built: {LTBLUE}{NUMU16}{BLACK} Value: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Capacity: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...must be stopped inside a road vehicle depot +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Can't sell road vehicle... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Can't stop/start road vehicle... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Road Vehicle {COMMA16} is waiting in depot +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Heading for {TOWN} Road Depot +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Road Depot, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Can't send vehicle to depot... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Unable to find local depot +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Road vehicles - click on vehicle for information +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Build new road vehicles (requires road vehicle depot) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Current vehicle action - click here to stop/start vehicle +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Show vehicle's orders +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Center main view on vehicle's location +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Send vehicle to depot +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Force vehicle to turn around +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Show road vehicle details +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Vehicles - click on vehicle for information +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Build new road vehicle +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Drag road vehicle to here to sell it +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Center main view on road vehicle depot location +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Road vehicle selection list - click on vehicle for information +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Build the highlighted road vehicle +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}New road vehicle now available! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Cost: {CURRENCY}{}Speed: {VELOCITY}{}Running Cost: {CURRENCY}/yr{}Capacity: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Name road vehicle +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Can't name road vehicle... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Name road vehicle +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First bus arrives at {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First truck arrives at {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Road Vehicle Crash!{}Driver dies in fireball after collision with train +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Road Vehicle Crash!{}{COMMA16} die in fireball after collision with train +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Can't make vehicle turn around... +STR_9034_RENAME :{BLACK}Rename +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Rename road vehicle type +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Rename road vehicle type +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Can't rename road vehicle type... +STR_9038_GO_TO_ROADVEH_DEPOT :Go to {TOWN} Road Vehicle Depot +STR_SERVICE_AT_ROADVEH_DEPOT :Service at {TOWN} Road Vehicle Depot + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Dock construction +STR_9801_DOCK_CONSTRUCTION :{WHITE}Dock construction +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Can't build dock here... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Ship Depot +STR_9804_NEW_SHIPS :{BLACK}New Ships +STR_9805_SHIPS :{WHITE}{STRING} - Ships +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Can't build ships... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Must build ship depot first +STR_9808_NEW_SHIPS :{WHITE}New Ships +STR_9809_BUILD_SHIP :{BLACK}Build Ship +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Speed: {GOLD}{VELOCITY}{}{BLACK}Capacity: {GOLD}{STRING} {STRING}{}{BLACK}Running Cost: {GOLD}{CURRENCY}/yr{}{BLACK}Designed: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} years{}{BLACK}Max. Reliability: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Ship must be stopped in depot +STR_980C_CAN_T_SELL_SHIP :{WHITE}Can't sell ship... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Can't build ship... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Ship in the way +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Orders) +STR_9811_DETAILS :{WHITE}{STRING} (Details) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Running Cost: {LTBLUE}{CURRENCY}/yr +STR_9813_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY} (last year: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA8}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Built: {LTBLUE}{NUMU16}{BLACK} Value: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Capacity: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Can't stop/start ship... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Can't send ship to depot... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Unable to find local depot +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Heading for {TOWN} Ship Depot +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Heading for {TOWN} Ship Depot, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Ship {COMMA16} is waiting in depot +STR_981D_BUILD_SHIP_DOCK :{BLACK}Build ship dock +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Build ship depot (for building and servicing ships) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Ships - click on ship for information +STR_9820_BUILD_NEW_SHIP :{BLACK}Build new ship +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Drag ship to here to sell it +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Center main view on ship depot location +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Ships - click on ship for information +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Build new ships (requires ship depot) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Ship selection list - click on ship for information +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Build the highlighted ship +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Current ship action - click here to stop/start ship +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Show ship's orders +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Center main view on ship's location +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Send ship to depot +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Show ship details +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}New ship now available! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Cost: {CURRENCY} Max. Speed: {VELOCITY}{}Capacity: {STRING}{}Running Cost: {CURRENCY}/yr +STR_982F_NAME_SHIP :{BLACK}Name ship + +STR_9831_NAME_SHIP :{WHITE}Name ship +STR_9832_CAN_T_NAME_SHIP :{WHITE}Can't name ship... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First ship arrives at {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Position buoy, which can be used for additional way points +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Can't position buoy here... +STR_9836_RENAME :{BLACK}Rename +STR_9837_RENAME_SHIP_TYPE :{BLACK}Rename ship type +STR_9838_RENAME_SHIP_TYPE :{WHITE}Rename ship type +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Can't rename ship type... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Refit cargo ship to carry a different cargo type +STR_983B_REFIT :{WHITE}{STRING} (Refit) +STR_983C_REFIT_SHIP :{BLACK}Refit ship +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Select type of cargo for ship to carry +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Refit ship to carry highlighted cargo type +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Select cargo type to carry:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}New capacity: {GOLD}{STRING}{}{BLACK}Cost of refit: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Can't refit ship... +STR_9842_REFITTABLE :(refittable) +STR_GO_TO_SHIP_DEPOT :Go to {TOWN} Ship Depot +SERVICE_AT_SHIP_DEPOT :Service at {TOWN} Ship Depot + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Airport Construct. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Can't build airport here... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Aircraft Hangar +STR_A003_NEW_AIRCRAFT :{BLACK}New Aircraft +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}New Aircraft +STR_A006_BUILD_AIRCRAFT :{BLACK}Build Aircraft +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Speed: {GOLD}{VELOCITY}{}{BLACK}Capacity: {GOLD}{COMMA16} passengers, {COMMA16} bags of mail{}{BLACK}Running Cost: {GOLD}{CURRENCY}/yr{}{BLACK}Designed: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} years{}{BLACK}Max. Reliability: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Can't build aircraft... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Aircraft +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Orders) +STR_A00C_DETAILS :{WHITE}{STRING} (Details) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Running Cost: {LTBLUE}{CURRENCY}/yr +STR_A00E_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY} (last year: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA8}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Built: {LTBLUE}{NUMU16}{BLACK} Value: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Can't send aircraft to hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Heading for {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Heading for {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Aircraft {COMMA16} is waiting in the aircraft hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Aircraft in the way +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Can't stop/start aircraft... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Aircraft is in flight +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Must build airport first +STR_A019_CAPACITY :{BLACK}Capacity: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Capacity: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Aircraft must be stopped in hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Can't sell aircraft... +STR_A01D_AIRPORT_CONSTRUCTION :Airport construction +STR_A01E_BUILD_AIRPORT :{BLACK}Build airport +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aircraft - click on aircraft for information +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Build new aircraft (requires airport with hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aircraft - click on aircraft for information +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Build new aircraft +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Drag aircraft to here to sell it +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Center main view on hangar location +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Aircraft selection list - click on aircraft for information +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Build the highlighted aircraft +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Current aircraft action - click here to stop/start aircraft +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Show aircraft's orders +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Center main view on aircraft's location +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Send aircraft to hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Show aircraft details +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}New aircraft now available! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Cost: {CURRENCY} Max. Speed: {VELOCITY}{}Capacity: {COMMA16} passengers, {COMMA16} bags of mail{}Running Cost: {CURRENCY}/yr + +STR_A030_NAME_AIRCRAFT :{WHITE}Name aircraft +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Can't name aircraft... +STR_A032_NAME_AIRCRAFT :{BLACK}Name aircraft +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First aircraft arrives at {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Plane Crash!{}{COMMA16} die in fireball at {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinations: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Rename +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Rename aircraft type +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Rename aircraft type +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Can't rename aircraft type... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Refit aircraft to carry a different cargo type +STR_A03C_REFIT :{WHITE}{STRING} (Refit) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Refit aircraft +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Select type of cargo for aircraft to carry +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Refit aircraft to carry highlighted cargo type +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Select cargo type to carry:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}New capacity: {GOLD}{STRING}{}{BLACK}Cost of refit: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Can't refit aircraft... +STR_A043_REFITTABLE :(refittable) +STR_GO_TO_AIRPORT_HANGAR :Go to {STATION} Hangar +SERVICE_AT_AIRPORT_HANGAR :Service at {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin disaster at {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Road vehicle destroyed in 'UFO' collision! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Oil refinery explosion near {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Factory destroyed in suspicious circumstances near {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' lands near {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Coal mine subsidence leaves trail of destruction near {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Your attempted bribery has been +STR_BRIBE_FAILED_2 :{WHITE}discovered by a regional investigator diff --git a/lang/french.txt b/lang/french.txt new file mode 100644 --- /dev/null +++ b/lang/french.txt @@ -0,0 +1,2448 @@ +##name French +##ownname Français +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Hors limites +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Trop près du bord de la carte +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Fonds insuffisants - nécessite {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Nécessite un terrain plat +STR_0008_WAITING :{BLACK}En attente: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (en provenance de +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accepte: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accepte: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passagers +STR_0010_COAL :Charbon +STR_0011_MAIL :Courrier +STR_0012_OIL :Pétrole +STR_0013_LIVESTOCK :Bétail +STR_0014_GOODS :Marchandises +STR_0015_GRAIN :Grain +STR_0016_WOOD :Bois +STR_0017_IRON_ORE :Minerai de fer +STR_0018_STEEL :Acier +STR_0019_VALUABLES :Objets de valeur +STR_001A_COPPER_ORE :Minerai de cuivre +STR_001B_MAIZE :Maïs +STR_001C_FRUIT :Fruits +STR_001D_DIAMONDS :Diamants +STR_001E_FOOD :Nourriture +STR_001F_PAPER :Papier +STR_0020_GOLD :Or +STR_0021_WATER :Eau +STR_0022_WHEAT :Blé +STR_0023_RUBBER :Caoutchouc +STR_0024_SUGAR :Sucre +STR_0025_TOYS :Jouets +STR_0026_CANDY :Sucreries +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Barbe à Papa +STR_0029_BUBBLES :Bulles +STR_002A_TOFFEE :Caramel +STR_002B_BATTERIES :Batteries +STR_002C_PLASTIC :Plastique +STR_002D_FIZZY_DRINKS :Boissons Gazeuses +STR_002E : +STR_002F_PASSENGER :Passager +STR_0030_COAL :Charbon +STR_0031_MAIL :Courrier +STR_0032_OIL :Pétrole +STR_0033_LIVESTOCK :Bétail +STR_0034_GOODS :Marchandise +STR_0035_GRAIN :Grain +STR_0036_WOOD :Bois +STR_0037_IRON_ORE :Minerai de fer +STR_0038_STEEL :Acier +STR_0039_VALUABLES :Objets de valeur +STR_003A_COPPER_ORE :Minerai de cuivre +STR_003B_MAIZE :Maïs +STR_003C_FRUIT :Fruit +STR_003D_DIAMOND :Diamant +STR_003E_FOOD :Nourriture +STR_003F_PAPER :Papier +STR_0040_GOLD :Or +STR_0041_WATER :Eau +STR_0042_WHEAT :Blé +STR_0043_RUBBER :Caoutchouc +STR_0044_SUGAR :Sucre +STR_0045_TOY :Jouet +STR_0046_CANDY :Sucrerie +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Barbe à Papa +STR_0049_BUBBLE :Bulle +STR_004A_TOFFEE :Caramel +STR_004B_BATTERY :Batterie +STR_004C_PLASTIC :Plastique +STR_004D_FIZZY_DRINK :Boisson Gazeuse +STR_004E : +STR_004F_PASSENGER :{COMMA16} passager +STR_0050_TON_OF_COAL :{COMMA16} tonne de charbon +STR_0051_BAG_OF_MAIL :{COMMA16} sac de courrier +STR_0052_OF_OIL :{VOLUME} de pétrole +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} tête de bétail +STR_0054_CRATE_OF_GOODS :{COMMA16} caisse de marchandise +STR_0055_TON_OF_GRAIN :{COMMA16} tonne de grain +STR_0056_TON_OF_WOOD :{COMMA16} tonne de bois +STR_0057_TON_OF_IRON_ORE :{COMMA16} tonne de minerai de fer +STR_0058_TON_OF_STEEL :{COMMA16} tonne d'acier +STR_0059_BAG_OF_VALUABLES :{COMMA16} sac d'objets de valeur +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonne de minerai de cuivre +STR_005B_TON_OF_MAIZE :{COMMA16} tonne de maïs +STR_005C_TON_OF_FRUIT :{COMMA16} tonne de fruits +STR_005D_BAG_OF_DIAMONDS :{COMMA16} sac de diamants +STR_005E_TON_OF_FOOD :{COMMA16} tonne de nourriture +STR_005F_TON_OF_PAPER :{COMMA16} tonne de papier +STR_0060_BAG_OF_GOLD :{COMMA16} sac d'or +STR_0061_OF_WATER :{VOLUME} d'eau +STR_0062_TON_OF_WHEAT :{COMMA16} tonne de blé +STR_0063_OF_RUBBER :{VOLUME} de caoutchouc +STR_0064_TON_OF_SUGAR :{COMMA16} tonne de sucre +STR_0065_TOY :{COMMA16} jouet +STR_0066_BAG_OF_CANDY :{COMMA16} sac de jouet +STR_0067_OF_COLA :{VOLUME} de cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonne de barbe à papa +STR_0069_BUBBLE :{COMMA16} bulle +STR_006A_TON_OF_TOFFEE :{COMMA16} tonne de caramel +STR_006B_BATTERY :{COMMA16} batterie +STR_006C_OF_PLASTIC :{VOLUME} de plastique +STR_006D_FIZZY_DRINK :{COMMA16} boisson gazeuse +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passagers +STR_0070_TONS_OF_COAL :{COMMA16} tonnes de charbon +STR_0071_BAGS_OF_MAIL :{COMMA16} sacs de courrier +STR_0072_OF_OIL :{VOLUME} de pétrole +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} têtes de bétail +STR_0074_CRATES_OF_GOODS :{COMMA16} caisses de marchandise +STR_0075_TONS_OF_GRAIN :{COMMA16} tonnes de grain +STR_0076_TONS_OF_WOOD :{COMMA16} tonnes de bois +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonnes de minerai de fer +STR_0078_TONS_OF_STEEL :{COMMA16} tonnes d'acier +STR_0079_BAGS_OF_VALUABLES :{COMMA16} sacs d'objets de valeur +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonnes de minerai de cuivre +STR_007B_TONS_OF_MAIZE :{COMMA16} tonnes de maïs +STR_007C_TONS_OF_FRUIT :{COMMA16} tonnes de fruits +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} sacs de diamants +STR_007E_TONS_OF_FOOD :{COMMA16} tonnes de nourriture +STR_007F_TONS_OF_PAPER :{COMMA16} tonnes de papier +STR_0080_BAGS_OF_GOLD :{COMMA16} sacs d'or +STR_0081_OF_WATER :{VOLUME} d'eau +STR_0082_TONS_OF_WHEAT :{COMMA16} tonnes de blé +STR_0083_OF_RUBBER :{VOLUME} de caoutchouc +STR_0084_TONS_OF_SUGAR :{COMMA16} tonnes de sucre +STR_0085_TOYS :{COMMA16} jouets +STR_0086_BAGS_OF_CANDY :{COMMA16} sacs de sucreries +STR_0087_OF_COLA :{VOLUME} de cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonnes de barbe à papa +STR_0089_BUBBLES :{COMMA16} bulles +STR_008A_TONS_OF_TOFFEE :{COMMA16} tonnes de caramel +STR_008B_BATTERIES :{COMMA16} batteries +STR_008C_OF_PLASTIC :{VOLUME} de plastique +STR_008D_FIZZY_DRINKS :{COMMA16} boisson gazeuses +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Carte - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Options +STR_00B2_MESSAGE :{YELLOW}Message +STR_00B3_MESSAGE_FROM :{YELLOW}Message de {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Impossible d'exécuter.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Impossible de balayer.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Copyright originel {COPYRIGHT} 1995 Chris Sawyer, Tous droits réservés +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Design original par Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Graphismes par Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Quitter +STR_00C8_YES :{BLACK}Oui +STR_00C9_NO :{BLACK}Non +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Êtes vous sur de vouloir abandonner cette partie et retourner à {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Rien +STR_00D1_DARK_BLUE :Bleu foncé +STR_00D2_PALE_GREEN :Vert pâle +STR_00D3_PINK :Rose +STR_00D4_YELLOW :Jaune +STR_00D5_RED :Rouge +STR_00D6_LIGHT_BLUE :Bleu pâle +STR_00D7_GREEN :Vert +STR_00D8_DARK_GREEN :Vert foncé +STR_00D9_BLUE :Bleu +STR_00DA_CREAM :Beige +STR_00DB_MAUVE :Mauve +STR_00DC_PURPLE :Violet +STR_00DD_ORANGE :Orange +STR_00DE_BROWN :Brun +STR_00DF_GREY :Gris +STR_00E0_WHITE :Blanc +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Trop de vehicules en jeu +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Emplacement +STR_00E5_CONTOURS :Relief +STR_00E6_VEHICLES :Véhicules +STR_00E7_INDUSTRIES :Industries +STR_00E8_ROUTES :Routes +STR_00E9_VEGETATION :Végétation +STR_00EA_OWNERS :Propriétaires +STR_00EB_ROADS :{BLACK}{TINYFONT}Routes +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Voies ferrées +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Gares/Aéroports/Ports +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Édifices/Industries +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Véhicules +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Trains +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Vehicules routiers +STR_00F7_SHIPS :{BLACK}{TINYFONT}Navires +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Avions +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Routes de Transport +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Mine de Charbon +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Centrale Électrique +STR_00FC_FOREST :{BLACK}{TINYFONT}Forêt +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Scierie +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Raffinerie de pétrole +STR_00FF_FARM :{BLACK}{TINYFONT}Ferme +STR_0100_FACTORY :{BLACK}{TINYFONT}Usine +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Imprimerie +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Puits de pétrole +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Mine de fer +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Aciérie +STR_0105_BANK :{BLACK}{TINYFONT}Banque +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Usine de papier +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Mine d'Or +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Usine Agroalimentaire +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Mine de Diamant +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Mine de Cuivre +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Plantation de Fruits +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Plantation de Caoutchouc +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Source d'Eau +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Tour d'Eau +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Scierie +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Forêt de Barbe à Papa +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Usine de Sucreries +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Ferme de Batteries +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Puits de Cola +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Boutique de Jouets +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Usine de Jouets +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Fontaines de Plastique +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Usine de Boissons Gazeuses +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Générateur de Bulles +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Carrière de Caramel +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Mine de Sucre +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Gare Ferroviaire +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Zone de Chargement +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Arrêt d'Autobus +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Aéroport/Héliport +STR_011F_DOCK :{BLACK}{TINYFONT}Port +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Terre en friche +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Herbe +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Terre nue +STR_0123_FIELDS :{BLACK}{TINYFONT}Champs +STR_0124_TREES :{BLACK}{TINYFONT}Arbres +STR_0125_ROCKS :{BLACK}{TINYFONT}Roches +STR_0126_WATER :{BLACK}{TINYFONT}Eau +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Sans Propriétaire +STR_0128_TOWNS :{BLACK}{TINYFONT}Villes +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industries +STR_012A_DESERT :{BLACK}{TINYFONT}Désert +STR_012B_SNOW :{BLACK}{TINYFONT}Neige +STR_012C_MESSAGE :{WHITE}Message +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Annuler +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Renommer +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Trop de noms déjà définis +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Nom déjà utilisé + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Impérial (miles) +STR_013A_METRIC_KILOMETERS :Métrique (kilomètres) +STR_013B_OWNED_BY :{WHITE}...appartient à {STRING} +STR_013C_CARGO :{BLACK}Cargaison +STR_013D_INFORMATION :{BLACK}Information +STR_013E_CAPACITIES :{BLACK}Capacités +STR_013E_TOTAL_CARGO :{BLACK}Charge totale +STR_013F_CAPACITY :{BLACK}Capacité: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Capacité totale de ce train: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nouvelle Partie +STR_0141_LOAD_GAME :{BLACK}Charger une Partie +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutoriel / Démonstration +STR_SINGLE_PLAYER :{BLACK}Un joueur +STR_MULTIPLAYER :{BLACK}Multijoueurs + +STR_0148_GAME_OPTIONS :{BLACK}Options + +STR_0150_SOMEONE :quelqu'un{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Carte du monde +STR_0152_TOWN_DIRECTORY :Annuaire des Villes +STR_0153_SUBSIDIES :Subventions + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Profit d'opération +STR_0155_INCOME_GRAPH :Revenu +STR_0156_DELIVERED_CARGO_GRAPH :Cargaison livrée +STR_0157_PERFORMANCE_HISTORY_GRAPH :Historique de performance +STR_0158_COMPANY_VALUE_GRAPH :Valeur de la compagnie +STR_0159_CARGO_PAYMENT_RATES :Valeur des cargaisons +STR_015A_COMPANY_LEAGUE_TABLE :Classement des compagnies +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Sauvegarder la partie +STR_015D_LOAD_GAME :Charger une partie +STR_015E_QUIT_GAME :Abandonner la partie +STR_015F_QUIT :Quitter le jeu +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Êtes vous sur de vouloir abandonner cette partie? +STR_0161_QUIT_GAME :{WHITE}Abandonner + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Fév +STR_0164_MAR :Mar +STR_0165_APR :Avr +STR_0166_MAY :Mai +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aut +STR_016A_SEP :Sep +STR_016B_OCT :Oct +STR_016C_NOV :Nov +STR_016D_DEC :Déc +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Suspendre la partie +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Sauvegarder, abandonner, quitter +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Afficher la liste des stations de la compagnie +STR_0174_DISPLAY_MAP :{BLACK}Afficher la carte +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Afficher la carte, annuaire des villes +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Afficher l'annuaire des villes +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Afficher les informations financières +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Afficher les informations générales +STR_0179_DISPLAY_GRAPHS :{BLACK}Afficher les graphiques +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Afficher le tableau de classement des compagnies +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Afficher la liste des trains +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Afficher la liste des véhicules routiers +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Afficher la liste des navires +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Afficher la liste des aéronefs +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Zoom avant +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Zoom arrière +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Construction ferroviaire +STR_0182_BUILD_ROADS :{BLACK}Construction routière +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Construction navale +STR_0184_BUILD_AIRPORTS :{BLACK}Construction aérienne +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Semer des arbres, placer des panneaux etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Outil d'Inspection +STR_0187_OPTIONS :{BLACK}Options +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Impossible de modifier l'intervalle de service... +STR_018B_CLOSE_WINDOW :{BLACK}Fermer la fenêtre +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Titre de fenêtre - Glissez ceci pour déplacer la fenêtre +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Démolir les constructions sur un carré de terrain +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Abaisser le terrain +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Élever le terrain +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Barre de défilement - défile la liste en haut/en bas +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Afficher le relief sur la carte +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Afficher les véhicules sur la carte +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Afficher les industries sur la carte +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Afficher les routes de transport sur la carte +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Afficher la végétation sur la carte +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Afficher les propriétaires sur la carte +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Afficher le nom des villes sur la carte +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Profit cette année: {CURRENCY} (l'an dernier: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} an ({COMMA16}) +STR_019A_YEARS :{COMMA16} années ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} années ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Vehicule routier +STR_019D_AIRCRAFT :Aéronef +STR_019E_SHIP :Navire +STR_019F_TRAIN :Train +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} devient désuet +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} devient très désuet +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} devient très désuet et doit être remplacé d'urgence +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Information sur le Terrain +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Coût du balayage: {LTBLUE}N/D +STR_01A5_COST_TO_CLEAR :{BLACK}Coût du balayage: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/D +STR_01A7_OWNER :{BLACK}Propriétaire: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Municipalité: {LTBLUE}{STRING} +STR_01A9_NONE :Aucun +STR_01AA_NAME :{BLACK}Nom +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1er +STR_01AD_2ND :2 +STR_01AE_3RD :3 +STR_01AF_4TH :4 +STR_01B0_5TH :5 +STR_01B1_6TH :6 +STR_01B2_7TH :7 +STR_01B3_8TH :8 +STR_01B4_9TH :9 +STR_01B5_10TH :10 +STR_01B6_11TH :11 +STR_01B7_12TH :12 +STR_01B8_13TH :13 +STR_01B9_14TH :14 +STR_01BA_15TH :15 +STR_01BB_16TH :16 +STR_01BC_17TH :17 +STR_01BD_18TH :18 +STR_01BE_19TH :19 +STR_01BF_20TH :20 +STR_01C0_21ST :21 +STR_01C1_22ND :22 +STR_01C2_23RD :23 +STR_01C3_24TH :24 +STR_01C4_25TH :25 +STR_01C5_26TH :26 +STR_01C6_27TH :27 +STR_01C7_28TH :28 +STR_01C8_29TH :29 +STR_01C9_30TH :30 +STR_01CA_31ST :31 +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Basculer entre la grande et la petite carte +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Choisir Didacticiel/Démonstration + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Cargaison acceptée: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Cargaison acceptée: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Cargaison acceptée: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jukebox Jazz +STR_01D3_SOUND_MUSIC :Son/musique +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Options son et musique +STR_01D5_ALL :{TINYFONT}Tout +STR_01D6_OLD_STYLE :{TINYFONT}Ancien Style +STR_01D7_NEW_STYLE :{TINYFONT}Nouveau Style +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Personnalisé 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Personnalisé 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Volume Musique +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Volume Effets Sonores +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Sauter à la piste précédente dans la sélection +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Sauter à la piste suivante dans la sélection +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Arrêter la musique +STR_01E1_START_PLAYING_MUSIC :{BLACK}Démarrer la musique +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Glissez les curseurs pour changer le volume +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Piste{SETX 88}Titre +STR_01E9_SHUFFLE :{TINYFONT}Aléatoire +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programme +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Selection du Programme Musical +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Index de Piste +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programme - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Balayer +STR_01F1_SAVE :{TINYFONT}{BLACK}Sauvegarder +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Programme musical courrant +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Choisir le programme 'tout' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Choisir le programme 'ancien style musical' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Choisir le programme 'nouveau style musical' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Choisir le programme personnalisé 'Personnalisé 1' +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Choisir le programme personnalisé 'Personnalisé 2' +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Balayer le programme courrant (Personnalisé 1 ou Personnalisé 2 seulement) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Sauvegarder les préférences musicales +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Cliquez sur une piste pour l'ajouter au pragramme courrant (Custom1 ou Custom2 seulement) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Active/Désactive le mode aléatoire +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Afficher la fenêtre de sélection de pistes +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Cliquez sur le service pour centrer la vue sur l'industrie ou la ville +STR_01FE_DIFFICULTY :{BLACK}Difficulté ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Message précédent/Bulletin de nouvelles +STR_0201_MESSAGE_SETTINGS :Options de messagerie +STR_MESSAGE_HISTORY_MENU :Historique des Messages +STR_0202_SEND_MESSAGE :Envoyer message +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Afficher le dernier message ou bulletin d'information, afficher les options des messages +STR_0204_MESSAGE_OPTIONS :{WHITE}Options des messages +STR_0205_MESSAGE_TYPES :{BLACK}Types de message:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrivée du premier véhicule à une station du joueur +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrivée du premier véhicule à une station du compétiteur +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Accidents / désastres +STR_0209_COMPANY_INFORMATION :{YELLOW}Information corporative +STR_020A_ECONOMY_CHANGES :{YELLOW}Changements économiques +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Conseils / information sur les véhicules du joueur +STR_020C_NEW_VEHICLES :{YELLOW}Nouveaux véhicules +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Changements d'acceptance de cargaison +STR_020E_SUBSIDIES :{YELLOW}Subventions +STR_020F_GENERAL_INFORMATION :{YELLOW}Information génerale +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...trop loin de la destination précédente +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Meilleures compagnies qui ont atteint 2050{}({STRING} Niveau) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Homme d'affaires +STR_0214_ENTREPRENEUR :Entrepreneur +STR_0215_INDUSTRIALIST :Industriel +STR_0216_CAPITALIST :Capitaliste +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon du Siècle +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} atteint le statut de '{STRING}'! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} de {STRING} atteint le statut de '{STRING}'! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Créer Scénario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Éditeur de Scénario +STR_0223_LAND_GENERATION :{WHITE}Génération de terrain +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Générer un terrain +STR_0227_RESET_LAND :{BLACK}RAZ du terrain +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Augmenter la quantité de terre à modifier +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Diminuer la quantité de terre à modifier +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Générer une terre aléatoire +STR_022B_RESET_LANDSCAPE :{BLACK}Réinitialiser le terrain +STR_022C_RESET_LANDSCAPE :{WHITE}Réinitialiser le terrain +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Voulez-vous vraiment réinitialiser le terrain? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Créer le terrain +STR_022F_TOWN_GENERATION :{BLACK}Créer les villes +STR_0230_INDUSTRY_GENERATION :{BLACK}Créer les industries +STR_0231_ROAD_CONSTRUCTION :{BLACK}Construction routière +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Végétation et autres objets +STR_0233_TOWN_GENERATION :{WHITE}Créer les villes +STR_0234_NEW_TOWN :{BLACK}Nouvelle ville +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Construire une nouvelle ville +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Impossible de construire une ville ici... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...trop près du bord de la carte +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...trop près d'une autre ville +STR_0239_SITE_UNSUITABLE :{WHITE}...site non convenable +STR_023A_TOO_MANY_TOWNS :{WHITE}...trop de villes +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Augmenter la taille de la ville +STR_023C_EXPAND :{BLACK}Agrandir +STR_023D_RANDOM_TOWN :{BLACK}Générer une ville +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Construire une ville dans un emplacement aléatoire +STR_023F_INDUSTRY_GENERATION :{WHITE}Créer les industries +STR_0240_COAL_MINE :{BLACK}Mine de Charbon +STR_0241_POWER_STATION :{BLACK}Centrale Électrique +STR_0242_SAWMILL :{BLACK}Scierie +STR_0243_FOREST :{BLACK}Forêt +STR_0244_OIL_REFINERY :{BLACK}Raffinerie de pétrole +STR_0245_OIL_RIG :{BLACK}Plate-forme Pétrolière +STR_0246_FACTORY :{BLACK}Usine +STR_0247_STEEL_MILL :{BLACK}Aciérie +STR_0248_FARM :{BLACK}Ferme +STR_0249_IRON_ORE_MINE :{BLACK}Mine de fer +STR_024A_OIL_WELLS :{BLACK}Puits de pétrole +STR_024B_BANK :{BLACK}Banque +STR_024C_PAPER_MILL :{BLACK}Usine de papier +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Usine Agroalimentaire +STR_024E_PRINTING_WORKS :{BLACK}Imprimerie +STR_024F_GOLD_MINE :{BLACK}Mine d'Or +STR_0250_LUMBER_MILL :{BLACK}Scierie +STR_0251_FRUIT_PLANTATION :{BLACK}Plantation de Fruits +STR_0252_RUBBER_PLANTATION :{BLACK}Plantation de Caoutchouc +STR_0253_WATER_SUPPLY :{BLACK}Source d'Eau +STR_0254_WATER_TOWER :{BLACK}Tour d'Eau +STR_0255_DIAMOND_MINE :{BLACK}Mine de Diamant +STR_0256_COPPER_ORE_MINE :{BLACK}Mine de Cuivre +STR_0257_COTTON_CANDY_FOREST :{BLACK}Forêt de Barbe à Papa +STR_0258_CANDY_FACTORY :{BLACK}Usine de Sucreries +STR_0259_BATTERY_FARM :{BLACK}Ferme de Batteries +STR_025A_COLA_WELLS :{BLACK}Puits de Cola +STR_025B_TOY_SHOP :{BLACK}Boutique de Jouets +STR_025C_TOY_FACTORY :{BLACK}Usine de Jouets +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Fontaines de Plastique +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Usine de Boissons Gazeuses +STR_025F_BUBBLE_GENERATOR :{BLACK}Générateur de Bulles +STR_0260_TOFFEE_QUARRY :{BLACK}Carrière de Caramel +STR_0261_SUGAR_MINE :{BLACK}Mine de Sucre +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Construire Mine de Charbon +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Construire Centrale Électrique +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Construire Scierie +STR_0265_PLANT_FOREST :{BLACK}Semer une Forêt +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Construire Raffinerie de Pétrole +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Construire Plate-forme Pétrolière (Peut seulement être construit au bord de la carte) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Construire Usine +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Construire Aciérie +STR_026A_CONSTRUCT_FARM :{BLACK}Construire Ferme +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Construire Mine de Fer +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Construire Puits de Pétrole +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construire Banque (Peut seulement être construite dans les villes ayant plus de 1200 habitants) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Construire Usine de Papier +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Construire Usine Agroalimentaire +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Construire Imprimerie +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Construire Mine d'Or +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construire Banque (Peut seulement être construite en ville) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Scierie (pour la coupe de forêt tropicale et la production de Bois) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Semer une Plantation de Fruits +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Semer une Plantation de Caoutchouc +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Construire Source d'Eau +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Construire Tour d'Eau (Peut seulement être construite en ville) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Construire Mine de Diamant +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Construire Mine de Cuivre +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Semer une Forêt de Barbe à Papa +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Construire Usine de Sucreries +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Construire Ferme de Batteries +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Construire Puits de Cola +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Construire Boutique de Jouets +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Construire Usine de Jouets +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Construire Fontaines de Plastique +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Construire Usine de Boissons Gazeuses +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Construire Générateur de Bulles +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Construire Carrière de Caramel +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Construire Mine de Sucre +STR_0285_CAN_T_BUILD_HERE :{WHITE}Impossible de construire {STRING} ici... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...doit d'abord construire une ville +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...Droit à un par ville seulement +STR_0288_PLANT_TREES :{BLACK}Semer des arbres +STR_0289_PLACE_SIGN :{BLACK}Placer un panneau +STR_028A_RANDOM_TREES :{BLACK}Générer des arbres +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Semer des arbres sur l'ensemble du terrain de façon aléatoire +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Placer des endroits rocheux sur le terrain +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Placer un Phare +STR_028E_PLACE_TRANSMITTER :{BLACK}Placer un Transmetteur +STR_028F_DEFINE_DESERT_AREA :{BLACK}Définir un endroit désertique +STR_0290_DELETE :{BLACK}Supprimer +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Supprimer complètement cette ville +STR_0292_SAVE_SCENARIO :Sauvegarder scénario +STR_0293_LOAD_SCENARIO :Charger scénario +STR_0294_QUIT_EDITOR :Quitter éditeur +STR_0295 : +STR_0296_QUIT :Quitter +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Sauvegarder scénario, charger scénario, abandonner éditeur de scénario, quitter +STR_0298_LOAD_SCENARIO :{WHITE}Charger Scénario +STR_0299_SAVE_SCENARIO :{WHITE}Sauvegarder Scénario +STR_029A_PLAY_SCENARIO :{BLACK}Jouer Scénario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Voulez-vous vraiment quitter ce scénario ? +STR_029C_QUIT_EDITOR :{WHITE}Quitter Éditeur +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...peut seulement être construit dans des villes ayant une population d'au moins 1200 habitants +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Reculer la date de commencement d'une année +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Avancer la date de commencement d'une année +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...les deux extrémités du pont doivent êtres sur la terre ferme +STR_02A1_SMALL :{BLACK}Petite +STR_02A2_MEDIUM :{BLACK}Moyenne +STR_02A3_LARGE :{BLACK}Grande +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Sélectionnez la taille de la ville +STR_02A5_TOWN_SIZE :{YELLOW}Taille: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Afficher le dernier message ou bulletin de nouvelles +STR_02B8_SUMMARY :{BLACK}Sommaire +STR_02B9_FULL :{BLACK}Complet +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Annuaire des villes +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Noms de conception des Vehicule +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Par Défaut +STR_02BF_CUSTOM :Personnalisé +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Sauvegarder les noms personnalisés +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Sélection des noms de conception de véhicule +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Sauvegarder noms personnalisés de conception de véhicule + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Options du Jeu +STR_02C4_GAME_OPTIONS :Options du Jeu +STR_02C5_DIFFICULTY_SETTINGS :Niveau de Difficulté +STR_02C6_DIFFICULTY_SETTINGS :Niveau de Difficulté +STR_02C7_CONFIG_PATCHES :Configuration Avancée +STR_02C8_CONFIG_PATCHES :Configuration Avancée +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Afficher le nom des villes +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Afficher le nom des villes +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Afficher le nom des stations +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Afficher le nom des stations +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Afficher les panneaux +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Afficher les panneaux +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Afficher les points de contrôle +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Afficher les points de contrôle +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Animation complète +STR_02D0_FULL_ANIMATION :{SETX 12}Animation complète +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Détail Maximal +STR_02D2_FULL_DETAIL :{SETX 12}Détails maximums +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Édifices transparents +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Édifices transparents +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Outil d'Inspection +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :ScreenShot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :ScreenShot Géant(Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :À Propos de 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}Activé +STR_02DB_OFF :{BLACK}Désactivé +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Afficher les subventions +STR_02DD_SUBSIDIES :Subventions +STR_02DE_MAP_OF_WORLD :Carte du monde +STR_02DF_TOWN_DIRECTORY :Annuaire des villes +STR_02E0_CURRENCY_UNITS :{BLACK}Unité monétaire +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Sélection d'unité monétaire +STR_02E3_DISTANCE_UNITS :{BLACK}Système de mesure +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Sélection d'unité de distance +STR_02E6_ROAD_VEHICLES :{BLACK}Véhicules routiers +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Choisir le sens de conduite routière +STR_02E9_DRIVE_ON_LEFT :Conduire sur la gauche +STR_02EA_DRIVE_ON_RIGHT :Conduire sur la droite +STR_02EB_TOWN_NAMES :{BLACK}Nom des villes +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Sélectionnez le style des noms de ville + +STR_02F4_AUTOSAVE :{BLACK}Sauvegarde automatique +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Sélectionnez l'intervalle de temps entre les sauvegardes automatiques +STR_02F7_OFF :Désactivé +STR_02F8_EVERY_3_MONTHS :Tous les 3 mois +STR_02F9_EVERY_6_MONTHS :Tous les 6 mois +STR_02FA_EVERY_12_MONTHS :Tous les 12 mois +STR_02FB_START_A_NEW_GAME :{BLACK}Commencer une nouvelle partie +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Charger une partie du disque +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Visionner démonstrations/didacticiels +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Créer un monde/scénario de jeu personnalisé +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Selectionner mode joueur simple +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Selectionner mode deux joueurs +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Afficher les options du jeu +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Afficher les options de niveau de difficulté +STR_0303_START_A_NEW_GAME_USING :{BLACK}Débuter une nouvelle partie à partir d'un scénario +STR_0304_QUIT :{BLACK}Quitter +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Quitter OpenTTD +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Visionner démonstration/didacticiel +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...peut seulement être construit en ville +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Selectionner l'environnement 'Tempéré' +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Selectionner l'environnement 'Arctique' +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Selectionner l'environnement 'Tropical' +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Selectionner l'environnement 'Jouets' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Financer la construction de nouvelles industries + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Financer une nouvelle industrie +STR_INDUSTRY_DIR :Annuaire des industries +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Financer une nouvelle industrie +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...peut seulement être construit en ville +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...peut seulement être construit en forêt tropicale +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...peut seulement être construit dans les endroits désertiques +STR_0319_PAUSED :{YELLOW}* * SUSPENDU * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot enregistré avec succès sous '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot échoué! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Acheter le terrain pour une utilisation ultérieure +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Service de véhicule routier +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Service de voie ferrée +STR_032C_3_AIR_SERVICE :{BLACK}3: Service de l'air +STR_032D_4_SHIP_SERVICE :{BLACK}4: Service de navire +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Service de voie ferrée (avancé) +STR_032F_AUTOSAVE :{RED}ENREGISTREMENT AUTOMATIQUE +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Selectionner programme de musique 'Ezy Street' + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Anglais +STR_TOWNNAME_FRENCH :Français +STR_TOWNNAME_GERMAN :Allemand +STR_TOWNNAME_AMERICAN :Américan +STR_TOWNNAME_LATIN_AMERICAN :Latino-Americain +STR_TOWNNAME_SILLY :Drôles +STR_TOWNNAME_SWEDISH :Suédois +STR_TOWNNAME_DUTCH :Hollandais +STR_TOWNNAME_FINNISH :Finnish +STR_TOWNNAME_POLISH :Polonais +STR_TOWNNAME_SLOVAKISH :Slovaques +STR_TOWNNAME_HUNGARIAN :Hongrois +STR_TOWNNAME_AUSTRIAN :Autrichiens +############ end of townname region + +STR_CURR_POUNDS :Livres ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollars ($) +STR_CURR_FF :Francs (FF) +STR_CURR_DM :Marks Allemands (DM) +STR_CURR_YEN :Yens ({YENSIGN}) +STR_CURR_PT :Pesetas Espagnols (PT) +STR_CURR_FT :Florins Hongrois (FT) +STR_CURR_ZL :Zloty Polonais (ZL) +STR_CURR_ATS :Shilings Australiens (ATS) +STR_CURR_BEF :Francs Belges (BEF) +STR_CURR_DKK :Couronnes Danoise (DKK) +STR_CURR_FIM :Marks Finlandais (FIM) +STR_CURR_GRD :Drachmes Grec (GRD) +STR_CURR_CHF :Franc Suisse (CHF) +STR_CURR_NLG :Florins Hollandais (NLG) +STR_CURR_ITL :Lires Italiennes (ITL) +STR_CURR_SEK :Couronnes Suédoises (SEK) +STR_CURR_RUR :Roubles Russes (RUR) +STR_CURR_CZK :Couronnes Tchèques (CZK) +STR_CURR_ISK :Couronnes Islandaises (ISK) +STR_CURR_NOK :Cour. Norvégiennes (NOK) +STR_CURR_EUR :Euros (EUR) + +STR_OPTIONS_LANG :{BLACK}Langue +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Selectionner la langue d'interface à utiliser + +STR_OPTIONS_RES :{BLACK}Résolution +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Selectionner la résolution d'écran à utiliser + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Format de la copie d'écran +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Choisissez le format de la copie d'écran + +STR_AUTOSAVE_1_MONTH :Tous les mois +STR_AUTOSAVE_FAILED :{WHITE}Enregistrement automatique échoué + +STR_MONTH_JAN :Janvier +STR_MONTH_FEB :Février +STR_MONTH_MAR :Mars +STR_MONTH_APR :Avril +STR_MONTH_MAY :Mai +STR_MONTH_JUN :Juin +STR_MONTH_JUL :Juillet +STR_MONTH_AUG :Août +STR_MONTH_SEP :Septembre +STR_MONTH_OCT :Octobre +STR_MONTH_NOV :Novembre +STR_MONTH_DEC :Décembre + +STR_HEADING_FOR_STATION :{LTBLUE}En route pour {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}En route pour {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Aucun ordre +STR_NO_ORDERS_VEL :{LTBLUE}Aucun ordre, {VELOCITY} + +STR_PASSENGERS :passagers +STR_BAGS :sacs +STR_TONS :tonnes +STR_LITERS :litres +STR_ITEMS :items +STR_CRATES :caisses +STR_RES_OTHER :autre +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Impossible de partager les ordres... +STR_CANT_COPY_ORDER_LIST :{WHITE}Impossible de copier les ordres... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Fin des ordres partagés - - + +STR_TRAIN_IS_LOST :{WHITE}Train {COMMA16} est perdu. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Train {COMMA16} a eu un profit de {CURRENCY} l'an dernier + +STR_CONFIG_PATCHES :{BLACK}Options Avancées +STR_CONFIG_PATCHES_TIP :{BLACK}Configurer les options avancées +STR_CONFIG_PATCHES_CAPTION :{WHITE}Options Avancées + +STR_CONFIG_PATCHES_OFF :Désactivé +STR_CONFIG_PATCHES_ON :Activé +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Afficher vitesse du véhicule dans la barre d'état: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Construction côtière et sur plans inclinés: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Permettre la suppression de plus de routes, ponts, tunnels, etc possédés par une ville: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Permettre les trains plus longs: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Permettre les accélérations réalistes pour les trains: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Joindre les gares juxtaposées: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Pleine cargaison par un seul type, si 'chargement complet': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflation: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Désactiver l'entretien automatique des trains: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Livrer cargaison seulement lorsqu'il y a une demande: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Permettre la construction de ponts longs: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Permettre l'ordre d'aller au dépôt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Permettre la construction de ressources primaires: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Permettre plusieurs industries similaires par ville: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Permettre plusieurs industries similaires à proximité: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Afficher la date complète dans la barre d'état: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Signaux ferroviaires du côté du sens de conduite: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Afficher le bilan de finances en fin d'année: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}Compatibilité TTDPatch "nonstop handling": {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Road vehicle queueing (avec effets quantiques): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Défiler la vue horizontalement avec le pointeur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Permettre la corruption de la municipalité: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Nouvelle recherche de dépôt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Gares non uniformes: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Nouvel algorithme de recherche de route: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Construire pendant le mode pause: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Toujours permettre les petits aéroports: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Un train est perdu si aucun progrès n'est fait pendant: {ORANGE}{STRING} jours +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Alerte en cas de profit négatif pour un train: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES :{LTBLUE}Les véhicules n'expirent jamais: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Renouvellement automatique des vieux véhicules +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Temps d'affichage des messages d'erreur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Altitude d'enneigement: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Etendue maximum des stations: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Entretenir automatiquement les hélicoptères à l'heliport: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Nombre de trains max. par joueur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Nombre de véhicules routiers max. par joueur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Nombre d'avions max. par joueur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Nombre de navires max. par joueur: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Désactiver les trains pour l'ordinateur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Désactiver les véhicules routiers pour l'ordinateur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Désactiver les avions pour l'ordinateur: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Désactiver les navires pour l'ordinateur: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Maintenance des trains tous les: {ORANGE}{STRING} jours +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Maintenance des véhicules routiers tous les: {ORANGE}{STRING} jours +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Maintenance des aéronefs tous les: {ORANGE}{STRING} jours +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Maintenance des navires tous les: {ORANGE}{STRING} jours + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Les journeaux en couleurs apparaissent en: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Date de départ: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Permettre une économie stable (plus de petits changements) + +STR_CONFIG_PATCHES_GUI :{BLACK}Interface +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Véhicules +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stations +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Economie + +STR_CONFIG_PATCHES_DISABLED :désactivé +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Entrez une valeur + + +STR_CHEATS :{WHITE}Triches +STR_CHEATS_TIP :{BLACK}Les cases à cocher indiquent que vous avez déjà utilisé cette triche auparavant +STR_CHEATS_WARNING :{BLACK}Attention ! Vous êtes sur le point de trahir vos adversaires. Gardez en tête qu'une telle honte sera gardée en mémoire pour l'éternité. +STR_CHEAT_MONEY :{LTBLUE}Augmenter l'argent de {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Jouer en tant que joueur n°: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Bulldozer magique (enlèvement industries et objets fixes): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Les tunnels peuvent se croiser: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Nom +STR_TOWNDIR_POPULATION :{BLACK}Population +STR_TOWNDIR_SORT_TIP :{BLACK}Ordre de classement + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}En route pour {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}En route pour {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Passant par {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Point de contrôle {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Point de contrôle {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Point de contrôle + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Modifier nom du point de contrôle + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Impossible de modifier le nom du point de contrôle... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Convertir rail en point de contrôle +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Impossible de construire point de contrôle ici... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Impossible de retirer point de contrôle ici... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Construire les rails avec le mode AutoRail + +STR_NO_TOWN_IN_SCENARIO :{WHITE}...il n'y a pas de ville dans ce scenario + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Etes-vous sûr de vouloir créer un terrain aléatoire? +STR_MANY_RANDOM_TOWNS :{BLACK}Beaucoup de villes au hasard +STR_RANDOM_TOWNS_TIP :{BLACK}Couvrir la carte avec des villes placées aléatoirement +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Beaucoup d'industries au hasard +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Couvrir la carte avec des industries placées au hasard +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Ne peut pas générer les industries... + +STR_LANDSCAPING_TOOLBAR :{WHITE}Manipulation du paysage +STR_LEVEL_LAND_TOOLTIP :{BLACK}Niveler le terrain + + +STR_TREES_RANDOM_TYPE :{BLACK}Au hasard +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Planter des arbres de types choisis au hasard + +STR_CANT_BUILD_CANALS :{WHITE}Impossible de construire un canal ici... +STR_BUILD_CANALS_TIP :{BLACK}Construire des canaux +STR_LANDINFO_CANAL :Canal + +STR_CANT_BUILD_LOCKS :{WHITE}Impossible de construire un écluse ici... +STR_BUILD_LOCKS_TIP :{BLACK}Construire des écluses +STR_LANDINFO_LOCK :Ecluse + +STR_LANDINFO_COORDS :{BLACK}Coordonnées: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Impossible de supprimer une partie de la gare... +STR_CANT_CONVERT_RAIL :{WHITE}Impossible de convertir le type de rail... +STR_CONVERT_RAIL_TIP :{BLACK}Convertir/Améliorer le type de rail + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Glissez la locomotive ici pour vendre le train entier + +STR_DRAG_DROP :{BLACK}Glisser/déposer +STR_STATION_DRAG_DROP :{BLACK}Construire une gare avec le glisser/déposer + +STR_FAST_FORWARD :{BLACK}Avance rapide du jeu +STR_MESSAGE_HISTORY :{WHITE}Historique des Messages +STR_MESSAGE_HISTORY_TIP :{BLACK}Liste des messages récents +STR_MESSAGES_DISABLE_ALL :{BLACK}Tout déscactiver +STR_MESSAGES_ENABLE_ALL :{BLACK}Tout activer + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Construire une mine de charbon +STR_CONSTRUCT_FOREST_TIP :{BLACK}Planter une forêt +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Construire une plateforme pétrolière +STR_CONSTRUCT_FARM_TIP :{BLACK}Financer une ferme +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Construire une mine de cuivre +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Forer pour trouver du pétrole +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Construire une mine d'or +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Construire une mine de diamants +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Construire une mine de fer +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Financer une plantation de fruits +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Financer une plantation de caoutchouc +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Financer une station de pompage +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Planter une forêt de barbe à papa +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Financer une ferme de piles +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Forer pour trouver du cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Financer des fontaines à plastique +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Construire un générateur de bulles +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Construire une carrière de caramel +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Construire une mine de sucre + +STR_INDUSTRYDIR_NAME :{BLACK}Nom +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Production +STR_INDUSTRYDIR_TYPE :{BLACK}Type +STR_INDUSTRYDIR_CAPTION :{WHITE}Industries +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...trop proche d'une autre industrie + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Réamenager le train pour d'autres marchandises +STR_RAIL_REFIT :{WHITE}{STRING} (Réaménager) +STR_RAIL_REFIT_VEHICLE :{BLACK}Réaménager le train +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Choix du type de marchandises à transporter +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Réaménager le train pour les marchandises sélectionnées +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Impossible de réaménager le train... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}L'interface réseau ne fonctionne pas pour le moment! + +STR_NETWORK_MULTIPLAYER :{WHITE}Multijoueur + +STR_NETWORK_FIND_SERVER :{BLACK}Trouver un serveur +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Cherche sur le réseau un serveur +STR_NETWORK_DIRECT_CONNECT :{BLACK}Connection directe +STR_NETWORK_ENTER_IP :{BLACK}Entrez l'adresse IP du serveur +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Permet la connection directe à une IP connue +STR_NETWORK_START_SERVER :{BLACK}Démarrer le serveur +STR_NETWORK_START_SERVER_TIP :{BLACK}Démarre son propre serveur + +STR_NETWORK_PLAYER_NAME :{BLACK}Nom du joueur: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}Ceci est le nom avec lequel les autres joueurs pourront vous identifier + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Choisissez le type de connection: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Permet de choisir entre une partie sur sur internet ou sur un lan +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Nom +STR_NETWORK_GAME_NAME_TIP :{BLACK}Nom de la partie +STR_NETWORK_PLAYERS :{BLACK}#/# +STR_NETWORK_PLAYERS_TIP :{BLACK}Joueurs présents dans la partie / Nombre maximum de joueurs +STR_NETWORK_MAP_SIZE :{BLACK}Taille +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Taille de la carte +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Langage, version du serveur, etc. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Cliquez une partie de la liste pour la sélectionner + +STR_NETWORK_JOIN_GAME :{BLACK}Rejoindre la partie + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Commencer une nouvelle partie + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Nom de la partie: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}Le nom de la partie sera affiché aux autres joueurs dans le menu de sélection de partie multijoueur +STR_NETWORK_PASSWORD :{BLACK}Mot de passe: +STR_NETWORK_PASSWORD_TIP :{BLACK}Protéger votre partie avec un mot de passe si vous ne souhaitez pas que d'autres joueurs la rejoignent +STR_NETWORK_SELECT_MAP :{BLACK}Choisissez une carte: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}Sur quelle carte voulez-vous jouer? +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Nombre de joueurs: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Choisissez le nombre maximum de joueurs. Vous n'êtes pas obligé de remplir tous les emplacements. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 joueurs +STR_NETWORK_3_PLAYERS :{BLACK}3 joueurs +STR_NETWORK_4_PLAYERS :{BLACK}4 joueurs +STR_NETWORK_5_PLAYERS :{BLACK}5 joueurs +STR_NETWORK_6_PLAYERS :{BLACK}6 joueurs +STR_NETWORK_7_PLAYERS :{BLACK}7 joueurs +STR_NETWORK_8_PLAYERS :{BLACK}8 joueurs +STR_NETWORK_START_GAME :{BLACK}Démarrer la partie + + +STR_NETWORK_GAME_LOBBY :{WHITE}Chat d'avant jeu + +STR_NETWORK_SEND :{BLACK}Envoyer +STR_NETWORK_SEND_TIP :{BLACK}Envoie un message aux autres joueurs +STR_NETWORK_COMPANY_NAME :{BLACK}Nom de la compagnie: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Change le nom de votre compagnie. Appuyer sur Entrée pour valider les changements +STR_NETWORK_SPECTATE_GAME :{BLACK}Observer une partie +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Permet d'observer une partie en tant que spectateur +STR_NETWORK_NEW_COMPANY :{BLACK}Nouvelle compagnie +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Crée une nouvelle compagnie +STR_NETWORK_READY :{BLACK}Prêt + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Coût: {CURRENCY} +STR_0801_COST :{RED}Coût: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Revenu: {CURRENCY} +STR_0803_INCOME :{GREEN}Revenu: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Coût Estimé: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Coût Estimé: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Revenu Estimé: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Revenu Estimé: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Impossible d'élever le terrain ici... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Impossible d'abaisser le terrain ici... +STR_080A_ROCKS :Roches +STR_080B_ROUGH_LAND :Terre en friche +STR_080C_BARE_LAND :Terre nue +STR_080D_GRASS :Herbe +STR_080E_FIELDS :Champs +STR_080F_SNOW_COVERED_LAND :Terre enneigée +STR_0810_DESERT :Désert + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terrain en pente dans la mauvaise direction +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Combinaison de rail impossible +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}L'excavation endommagerait le tunnel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Déjà au niveau de la mer +STR_1004_TOO_HIGH :{WHITE}Trop élevé +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Aucun rail convenable +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Train à l'intérieur du dépôt +STR_1007_ALREADY_BUILT :{WHITE}...déjà construit +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Doit d'abord enlever les rails +STR_1009_TOO_MANY_DEPOTS :{WHITE}Trop de dépôts +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Construction de Rail +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Construction de Monorail +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Construction de MagLev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Choisir Pont Ferroviaire +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Impossible de construire un dépôt ferroviaire ici... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Impossible de construire la gare ici... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Impossible de construire des signaux ici... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Impossible de construire des rails ici... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Impossible de retirer les rails d'ici... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Impossible de retirer les signaux d'ici... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Orientation du Dépôt +STR_1015_RAILROAD_CONSTRUCTION :Construction de Rail +STR_1016_MONORAIL_CONSTRUCTION :Construction de Monorail +STR_1017_MAGLEV_CONSTRUCTION :Construction de MagLev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Construire des rails +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Construire un dépôt ferroviaire (pour construire et entretenir les trains) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Construire une gare +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Construire des signaux +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Construire un pont ferroviaire +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Construire un tunel ferroviaire +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Basculer construire/retirer pour rails et signaux +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Sélection de Pont - cliquez sur un pont pour le construire +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Sélectionnez l'orientation du dépôt +STR_1021_RAILROAD_TRACK :Rail +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Rail avec signaux +STR_1023_RAILROAD_TRAIN_DEPOT :Dépôt de trains +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...appartient à une autre compagnie +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Rail avec des signaux normaux +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Rail avec des pré-signaux +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Rail avec des signaux de sortie +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Rail avec des signaux combinés + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terrain en pente dans la mauvaise direction pour des routes +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Doit d'abord retirer la route +STR_1802_ROAD_CONSTRUCTION :{WHITE}Construction routière +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Choisir Pont Routier +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Impossible de construire la route ici... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Impossible de retirer la route ici... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientation du dépôt routier +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Impossible de construire un dépôt routier ici... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Impossible de construire un arrêt d'autobus... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Impossible de construire une station de camions... +STR_180A_ROAD_CONSTRUCTION :Construction routière +STR_180B_BUILD_ROAD_SECTION :{BLACK}Construire une section de route +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Construire un dépôt routier (pour construire et entretenir les véhicules routiers) +STR_180D_BUILD_BUS_STATION :{BLACK}Construire un arrêt d'autobus +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Construire une station de camions +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Construire un pont routier +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Construire un tunnel routier +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Basculer construire/détruire routes +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Choix de Pont - cliquez sur pont sélectionné pour le construire +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Choisir orientation du dépôt routier +STR_1814_ROAD :Route +STR_1815_ROAD_WITH_STREETLIGHTS :Route avec lampadaires +STR_1816_TREE_LINED_ROAD :Route avec lignée d'arbustres +STR_1817_ROAD_VEHICLE_DEPOT :Dépôt de véhicules routiers +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Route/rail Croisement à niveau + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Villes +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}L'édifice doit d'abord être démolit +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Population: {ORANGE}{COMMA32}{BLACK} Maisons: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Renommer Ville +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Impossible de renommer la ville... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}La municipalité de {TOWN} refuse cette opération +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Noms des villes - Cliquez sur un nom pour défiler à l'emplacement +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrer la vue sur la ville +STR_200C_CHANGE_TOWN_NAME :{BLACK}Renommer la ville +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagers du mois dernier: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Courrier du mois dernier: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Grand immeuble de bureaux +STR_2010_OFFICE_BLOCK :Immeuble de bureaux +STR_2011_SMALL_BLOCK_OF_FLATS :Petit immeuble résidentiel +STR_2012_CHURCH :Eglise +STR_2013_LARGE_OFFICE_BLOCK :Gros immeuble de bureau +STR_2014_TOWN_HOUSES :Bâtiments municipaux +STR_2015_HOTEL :Hôtel +STR_2016_STATUE :Statue +STR_2017_FOUNTAIN :Fontaine +STR_2018_PARK :Parc +STR_2019_OFFICE_BLOCK :Immeuble de bureaux +STR_201A_SHOPS_AND_OFFICES :Commerces et bureaux +STR_201B_MODERN_OFFICE_BUILDING :Immeuble moderne de bureaux +STR_201C_WAREHOUSE :Entrepôt +STR_201D_OFFICE_BLOCK :Immeuble de bureaux +STR_201E_STADIUM :Stade +STR_201F_OLD_HOUSES :Vieilles maisons +STR_2020_LOCAL_AUTHORITY :{BLACK}Municipalité +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Afficher des informations sur la municipalité +STR_2022_LOCAL_AUTHORITY :{WHITE}Municipalité de {TOWN} +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Réputation de la compagnie de transport: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subventions +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Offres de subvention pour le transport de:- +STR_2027_FROM_TO :{ORANGE}{STRING} de {STRING} à {STRING} +STR_2028_BY :{YELLOW} (avant {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Aucune +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Subventions déjà accordées:- +STR_202C_FROM_TO :{ORANGE}{STRING} de {STATION} à {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, jusqu'à {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Offre de subvention expirée:{}{}Le transport de {STRING} entre {STRING} et {STRING} n'est désormais plus subventionné. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Abandon de la subvention:{}{}Le transport de {STRING} entre {STATION} et {STATION} n'est plus subventionné. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Offre de subvention:{}{}Le premier service de {STRING} entre {STRING} et {STRING} sera subventionné pendant un an! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention accordée à {STRING}!{}{}Le transport de {STRING} entre {STATION} et {STATION} rapportera 50% de plus l'année prochaine! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention accordée à {STRING}!{}{}Le transport de {STRING} entre {STATION} et {STATION} rapportera double l'année prochaine! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention accordée à {STRING}!{}{}Le transport de {STRING} entre {STATION} et {STATION} rapportera triple l'année prochaine! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention accordée à {STRING}!{}{}Le transport de {STRING} entre {STATION} et {STATION} rapportera quadruple l'année prochaine! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}La municipalité de {TOWN} refuse la construction d'un autre aéroport dans la ville +STR_2036_COTTAGES :Petites maisons +STR_2037_HOUSES :Maisons +STR_2038_FLATS :Appartements +STR_2039_TALL_OFFICE_BLOCK :Grand immeuble de bureau +STR_203A_SHOPS_AND_OFFICES :Commerces et bureaux +STR_203B_SHOPS_AND_OFFICES :Commerces et bureaux +STR_203C_THEATER :Théâtre +STR_203D_STADIUM :Stade +STR_203E_OFFICES :Bureaux +STR_203F_HOUSES :Maisons +STR_2040_CINEMA :Cinéma +STR_2041_SHOPPING_MALL :Centre commercial +STR_2042_DO_IT :{BLACK}Lancer cette action +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Liste des actions à entreprendre dans cette ville - Cliquez sur une action pour obtenir des détails +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Lancer l'action sélectionnée ci-dessus +STR_2045_ACTIONS_AVAILABLE :{BLACK}Actions disponibles: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Petite campagne de publicité +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Moyenne campagne de publicitié +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Grande campagne de publicité +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Financer la reconstruction du réseau routier local +STR_204A_BUILD_STATUE_OF_COMPANY :Construire une statue à votre effigie +STR_204B_FUND_NEW_BUILDINGS :Financer de nouveaux bâtiments +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Acheter les droits de transports exclusifs +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Corrompre la municipalité +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Lancer une petite campagne de publicité, pour attirer plus de voyageurs et de marchandises sur vos lignes.{} Cost: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Lancer une campagne de publicité moyenne, pour attirer plus de voyageurs et de marchandises sur vos lignes.{} Cost: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Lancer une grande campagne de publicité, pour attirer plus de voyageurs et de marchandises sur vos lignes.{} Cost: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Financer la reconstruction du réseau routier local. Provoque de nombreux problèmes de traffic routier pendant 6 mois.{} Cost: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Construire une statue en l'honneur de votre compagnie.{} Cost: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Financer la construction de nouveaux immeubles commerciaux.{} Cost: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Acheter les droits de transports exclusifs dans cette ville pour 1 an. Seules vos ligness seront autorisées dans la ville.{} Cost: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Corrompre la municipalité pour améliorer votre réputation. Risque de pénalisation si le pot-de-vin est dévoilé.{} Coût: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Impossible... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Problèmes de traffic à {TOWN}!{}{}La reconstruction des routes financée par {STRING} provoque 6 mois de problèmes aux automobilistes! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (en contruction) +STR_2059_IGLOO :Iglou +STR_205A_TEPEES :Tipis +STR_205B_TEAPOT_HOUSE :Salon de thé +STR_205C_PIGGY_BANK :Tirelire + +##id 0x2800 +STR_LANDSCAPING :Modification du paysage +STR_2800_PLANT_TREES :Planter des arbres +STR_2801_PLACE_SIGN :Placer un panneau +STR_2802_TREES :{WHITE}Arbres +STR_2803_TREE_ALREADY_HERE :{WHITE}...il y a déjà des arbres +STR_2804_SITE_UNSUITABLE :{WHITE}...l'endroit ne convient pas +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Plantation impossible... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...trop de panneaux +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Place du panneau impossible... +STR_280A_SIGN :Panneau +STR_280B_EDIT_SIGN_TEXT :{WHITE}Editer le texte du panneau +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Impossible d'éditer le texte... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Choix du type d'arbre +STR_280E_TREES :Arbres +STR_280F_RAINFOREST :Forêt tropicale +STR_2810_CACTUS_PLANTS :Cactus + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Choix de la gare +STR_3001_AIRPORT_SELECTION :{WHITE}Choix de l'aéroport +STR_3002_ORIENTATION :{BLACK}Orientation +STR_3003_NUMBER_OF_TRACKS :{BLACK}Nombre de voies +STR_3004_PLATFORM_LENGTH :{BLACK}Longueur du quai +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Trop près d'une autre gare +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Ajouter une ou plusieurs gares +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Trop de gares dans cette ville +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Trop de gares +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Trop près d'une autre gare +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Vous devez d'abord détruire la gare +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Trop près d'un autre aéroport +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Vous devez d'abord détruire l'aéroport + +STR_3030_RENAME_STATION_LOADING :Renommer la gare +STR_3031_CAN_T_RENAME_STATION :{WHITE}Impossible de renommer la gare... +STR_3032_RATINGS :{BLACK}Réputation +STR_3033_ACCEPTS :{BLACK}Accepte +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Réputation du service de transport: + +############ range for rating starts +STR_3035_APPALLING :Epouvantable +STR_3036_VERY_POOR :Très pauvre +STR_3037_POOR :Pauvre +STR_3038_MEDIOCRE :Médiocre +STR_3039_GOOD :Bon +STR_303A_VERY_GOOD :Très bon +STR_303B_EXCELLENT :Excellent +STR_303C_OUTSTANDING :Exceptionnel +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} n'accepte plus: {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} n'accepte plus: {STRING} ou {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} accepte désormais: {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} accepte désormais: {STRING} et {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Arrêt de bus +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Station de camions +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Trop près d'un autre arrêt +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Trop près d'une autre gare +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Détruisez d'abord l'arrêt +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Détruisez d'abord la station +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stations +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Aucun - +STR_304B_SITE_UNSUITABLE :{WHITE}...l'endroit ne convient pas +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Trop près d'un autre port +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Détruisez d'abord le port +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Choix de l'orientation de la gare +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Choix du nombre de voies +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Choix de la longueur du quai +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Choix de l'orientation de la station +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Choix de l'orientation de l'aire de chargement +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centrer la vue sur la station +STR_3054_SHOW_STATION_RATINGS :{BLACK}Montrer la réputation de la station +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Renommer la station +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Afficher les marchandises acceptées +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Nom des stations - Cliquez sur un nom pour centrer la vue +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Choix du type & taille de l'aéroport +STR_3059_SMALL :{BLACK}Petit +STR_305A_LARGE :{BLACK}Grand +STR_305AA_LARGE :{BLACK}Aéroport métropolitain +STR_305AB_LARGE :{BLACK}Aéroport international +STR_305B_SIZE :{BLACK}Taille +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Gare +STR_305F_AIRCRAFT_HANGAR :Hangar d'aéronefs +STR_3060_AIRPORT :Aéroport +STR_3061_TRUCK_LOADING_AREA :Aire de chargement +STR_3062_BUS_STATION :Arrêt de bus +STR_3063_SHIP_DOCK :Port +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Afficher la zone couverte +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Ne pas afficher la zone couverte +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Affichage de la zone couverte +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Choix de la gare monorail +STR_3068_DOCK :{WHITE}Port +STR_3069_BUOY :Bouée +STR_306A_BUOY_IN_THE_WAY :{WHITE}...bouée présente +STR_306B_HELIPORT :{BLACK}Héliport +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...gare trop étendue + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orientation du dépot naval +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...doit être construit sur l'eau +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Impossible de construire le dépôt naval ici... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Choix de l'orientation du dépôt +STR_3804_WATER :Eau +STR_3805_COAST_OR_RIVERBANK :Côte de riverbank +STR_3806_SHIP_DEPOT :Dépôt naval +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Impossible de construire sur l'eau + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Sauvegarder la partie +STR_4001_LOAD_GAME :{WHITE}Charger une partie +STR_4002_SAVE :{BLACK}Sauvegarder +STR_4003_DELETE :{BLACK}Supprimer +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} Mo libres +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Impossible d'accéder au disque +STR_4007_GAME_SAVE_FAILED :{WHITE}La sauvegarde à échoué +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Impossible de supprimer le fichier +STR_4009_GAME_LOAD_FAILED :{WHITE}Le chargement à échoué +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Liste des disques, répertoires, et fichiers de sauvegarde +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Nom sélectionné pour la sauvegarde +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Supprime la sauvegarde sélectionnée +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Sauvegarde la partie avec le nom choisi +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Choix du type de partie +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Choisissez un scénario (vert), une partie préparée (bleu), ou une partie aléatoire +STR_4010_GENERATE_RANDOM_NEW_GAME :Générer une partie aléatoirement + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} présente +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Mine de charbon +STR_4803_POWER_STATION :Centrale électrique +STR_4804_SAWMILL :Scierie +STR_4805_FOREST :Forêt +STR_4806_OIL_REFINERY :Raffinerie +STR_4807_OIL_RIG :Plate-forme pétrolière +STR_4808_FACTORY :Usine +STR_4809_PRINTING_WORKS :Imprimerie +STR_480A_STEEL_MILL :Aciérie +STR_480B_FARM :Ferme +STR_480C_COPPER_ORE_MINE :Mine de cuivre +STR_480D_OIL_WELLS :Puits de pétrôle +STR_480E_BANK :Banque +STR_480F_FOOD_PROCESSING_PLANT :Usine alimentaire +STR_4810_PAPER_MILL :Usine à papier +STR_4811_GOLD_MINE :Mine d'or +STR_4812_BANK :Banque +STR_4813_DIAMOND_MINE :Mine de diamants +STR_4814_IRON_ORE_MINE :Mine de fer +STR_4815_FRUIT_PLANTATION :Plantation de fruits +STR_4816_RUBBER_PLANTATION :Plantation de caoutchouc +STR_4817_WATER_SUPPLY :Réservoir d'eau +STR_4818_WATER_TOWER :Château d'eau +STR_4819_FACTORY :Usine +STR_481A_FARM :Ferme +STR_481B_LUMBER_MILL :Scierie +STR_481C_COTTON_CANDY_FOREST :Forêt de Barbe à Papa +STR_481D_CANDY_FACTORY :Usine de Sucreries +STR_481E_BATTERY_FARM :Ferme de Batteries +STR_481F_COLA_WELLS :Puits de Cola +STR_4820_TOY_SHOP :Boutique de Jouets +STR_4821_TOY_FACTORY :Usine de Jouets +STR_4822_PLASTIC_FOUNTAINS :Fontaines de plastique +STR_4823_FIZZY_DRINK_FACTORY :Usine de Boissons Gazeuses +STR_4824_BUBBLE_GENERATOR :Générateur de Bulles +STR_4825_TOFFEE_QUARRY :Carrière de caramel +STR_4826_SUGAR_MINE :Mine de sucre + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Nécessite: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Nécessite: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Nécessite: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Production le mois dernier: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transporté) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrer la vue sur l'industrie +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Un(e) nouveau(elle) {STRING} en construction près de {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Un(e) nouveau(elle) {STRING} s'implante près de {TOWN}! +STR_482F_COST :{BLACK}Prix: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Impossible de construire cette industrie ici... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...les forêts ne peuvent pas être plantées sur de la neige +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} annonce une fermeture imminente! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Des problèmes d'approvisionnement forcent {TOWN} {STRING} à fermer bientôt! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Le manque d'arbres proches force {TOWN} {STRING} à fermer bientôt! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} augmente la production! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nouveau filon de charbon trouvé à {TOWN} {STRING}!{}La production devrait doubler! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nouvelle nappe de pétrôle trouvée à {TOWN} {STRING}!{}La production devrait doubler! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}De nouvelles méthodes d'élevage à {TOWN} {STRING} permettent de doubler la production! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} : production en baisse de 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Invasion d'insectes à {TOWN} {STRING}!{}Production en baisse de 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...positionnement uniquement sur les bords de la carte +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}La production de {STRING} à {TOWN} {STRING} augmente de {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}La production de {STRING} à {TOWN} {STRING} diminue de {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Train dans le tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Véhicule dans le tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Autre tunnel présent +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Impossible de creuser pour faire déboucher le tunnel +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Vous devez démolir le tunnel avant +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Vous devez démolir le pont avant +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Impossible de commencer et de terminer au même endroit +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Crevasse ou eau requise sous le pont +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Le début et la fin doivent être alignés +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Le site pour l'entrée du tunnel ne convient pas +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :A suspensions, Acier +STR_500F_GIRDER_STEEL :A poutres, Acier +STR_5010_CANTILEVER_STEEL :Porte-a-faux, Steel +STR_5011_SUSPENSION_CONCRETE :A suspensions, Béton +STR_5012_WOODEN :Bois +STR_5013_CONCRETE :Béton +STR_5014_TUBULAR_STEEL :Tubes, Acier +STR_BRIDGE_TUBULAR_SILICON :Tubes, Silicone +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Impossible de construire un pont ici... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Impossible de construire un tunnel ici... +STR_5017_RAILROAD_TUNNEL :Tunnel ferroviaire +STR_5018_ROAD_TUNNEL :Tunnel routier +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Pont ferroviaire suspendu en acier +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Pont ferroviaire à poutres en acier +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Pont ferroviaire en porte-a-faux en acier +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Pont ferroviaire suspendu renforcé en béton +STR_501F_WOODEN_RAIL_BRIDGE :Pont ferroviaire en bois +STR_5020_CONCRETE_RAIL_BRIDGE :Pont ferroviaire en béton +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Pont routier suspendu en acier +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Pont routier à poutres en acier +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Pont routier en porte-a-faux en acier +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Pont routier suspendu renforcé en béton +STR_5025_WOODEN_ROAD_BRIDGE :Pont routier en bois +STR_5026_CONCRETE_ROAD_BRIDGE :Pont routier en béton +STR_5027_TUBULAR_RAIL_BRIDGE :Pont ferroviaire à tubes +STR_5028_TUBULAR_ROAD_BRIDGE :Pont ferroviaire à tubes d'acier +STR_5029_STEEL :Acier + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Objet présent +STR_5801_TRANSMITTER :Transmetteur +STR_5802_LIGHTHOUSE :Phare +STR_5803_COMPANY_HEADQUARTERS :Siège de la compagnie +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...siège de la compagnie présent +STR_5805_COMPANY_OWNED_LAND :Terrain appartenant à une compagnie +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Impossible d'acheter ce terrain... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...il vous appartient déjà! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Non nommé{SKIP} +STR_SV_TRAIN_NAME :Train {COMMA16} +STR_SV_ROADVEH_NAME :Véhicule {COMMA16} +STR_SV_SHIP_NAME :Navire {COMMA16} +STR_SV_AIRCRAFT_NAME :Aéronef {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Nord +STR_SV_STNAME_SOUTH :{STRING} Sud +STR_SV_STNAME_EAST :{STRING} Est +STR_SV_STNAME_WEST :{STRING} Ouest +STR_SV_STNAME_CENTRAL :{STRING} Central +STR_SV_STNAME_TRANSFER :{STRING} Transfert +STR_SV_STNAME_HALT :{STRING} Halte +STR_SV_STNAME_VALLEY :{STRING} Vallée +STR_SV_STNAME_HEIGHTS :{STRING} Hauteurs +STR_SV_STNAME_WOODS :{STRING} Bois +STR_SV_STNAME_LAKESIDE :{STRING} Bords de lac +STR_SV_STNAME_EXCHANGE :{STRING} Echange +STR_SV_STNAME_AIRPORT :{STRING} Aéroport +STR_SV_STNAME_OILFIELD :{STRING} Gisement +STR_SV_STNAME_MINES :{STRING} Mines +STR_SV_STNAME_DOCKS :{STRING} Docks +STR_SV_STNAME_BUOY_1 :{STRING} Bouée 1 +STR_SV_STNAME_BUOY_2 :{STRING} Bouée 2 +STR_SV_STNAME_BUOY_3 :{STRING} Bouée 3 +STR_SV_STNAME_BUOY_4 :{STRING} Bouée 4 +STR_SV_STNAME_BUOY_5 :{STRING} Bouée 5 +STR_SV_STNAME_BUOY_6 :{STRING} Bouée 6 +STR_SV_STNAME_BUOY_7 :{STRING} Bouée 7 +STR_SV_STNAME_BUOY_8 :{STRING} Bouée 8 +STR_SV_STNAME_BUOY_9 :{STRING} Bouée 9 +STR_SV_STNAME_ANNEXE :{STRING} Annexe +STR_SV_STNAME_SIDINGS :{STRING} Voies de garage +STR_SV_STNAME_BRANCH :{STRING} Embranchement +STR_SV_STNAME_UPPER :Haut {STRING} +STR_SV_STNAME_LOWER :Bas {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Forêt + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Niveau de difficulté + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Facile +STR_6802_MEDIUM :{BLACK}Moyen +STR_6803_HARD :{BLACK}Difficile +STR_6804_CUSTOM :{BLACK}Personnalisé +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Nombre maximum d'opposants: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Démarrage des opposants: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Nombre de villes: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Nombre d'industries: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Prêt initial maximum: {ORANGE}{CURRENCY},000 +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Taux d'interêt initial: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Coûts d'entretien: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Vitesse de développement des opposants: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligence des opposants: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Pannes des véhicules: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Multiplicateur de subvention: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Coût des constructions: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Type de terrain: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Quantité de mer/lacs: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Economie: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Demi-tour des trains: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Désastres: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Bas +STR_6817_NORMAL :Normal +STR_6818_HIGH :Élevé +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Très Lent +STR_681C_SLOW :Lent +STR_681D_MEDIUM :Moyen +STR_681E_FAST :Rapide +STR_681F_VERY_FAST :Très Rapide +STR_VERY_LOW :Très bas +STR_6820_LOW :Bas +STR_6821_MEDIUM :Moyen +STR_6822_HIGH :Élevé +STR_6823_NONE :Aucune +STR_6824_REDUCED :Réduites +STR_6825_NORMAL :Normales +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Très plat +STR_682B_FLAT :Plat +STR_682C_HILLY :Collines +STR_682D_MOUNTAINOUS :Montagneux +STR_682E_STEADY :Stable +STR_682F_FLUCTUATING :Fluctuant +STR_6830_IMMEDIATE :Immédiat +STR_6831_3_MONTHS_AFTER_PLAYER :3 mois après le joueur +STR_6832_6_MONTHS_AFTER_PLAYER :6 mois après le joueur +STR_6833_9_MONTHS_AFTER_PLAYER :9 mois après le joueur +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :A la fin de la ligne et aux gares +STR_6835_AT_END_OF_LINE_ONLY :A la fin de la ligne seulement +STR_6836_OFF :Désactivé +STR_6837_ON :Activé +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Afficher le tableau des scores + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Joueur 1) +STR_7003_PLAYER_2 : (Joueur 2) +STR_7004_NEW_FACE :{BLACK}Nouveau visage +STR_7005_COLOR_SCHEME :{BLACK}Couleur +STR_7006_COLOR_SCHEME :{GOLD}Couleur: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nouvelle couleur +STR_7008_COMPANY_NAME :{BLACK}Nom de la société +STR_7009_PRESIDENT_NAME :{BLACK}Nom du P.D.G. +STR_700A_COMPANY_NAME :Nom de la société +STR_700B_PRESIDENT_S_NAME :Nom du P.D.G. +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Impossible de changer le nom de compagnie... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Impossible de changer le nom du P.D.G. ... +STR_700E_FINANCES :{WHITE}Finances: {STRING}{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Dépenses/Revenus +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Construction +STR_7012_NEW_VEHICLES :{GOLD}Nouveaux Véhicules +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Entretien des trains +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Entretien des véhicules +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Entretien des aéronefs +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Entretien des navires +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Entretien de la propriété +STR_7018_TRAIN_INCOME :{GOLD}Revenu ferroviaire +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Revenu routier +STR_701A_AIRCRAFT_INCOME :{GOLD}Revenu aérien +STR_701B_SHIP_INCOME :{GOLD}Revenu naval +STR_701C_LOAN_INTEREST :{GOLD}Intérêts du prêt +STR_701D_OTHER :{GOLD}Autres +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Total: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Graphique du Revenu +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graphique du profit d'opération +STR_7026_BANK_BALANCE :{WHITE}Equilibre bancaire +STR_7027_LOAN :{WHITE}Prêt +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Emprunter {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Rembourser {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...le prêt maximum est de {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Impossible d'emprunter plus... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...Prêt déjà remboursé +STR_702E_REQUIRED :{WHITE}...{CURRENCY} nécessaires +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Impossible de rembourser... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Choix d'un nouveau visage pour le P.D.G. +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Change la couleur des véhicules +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Change le nom du président directeur général +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Change le nom de la compagnie +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Cliquez pour choisir une couleur +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Augmenter le prêt +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Rembourser une partie du prêt +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(President) +STR_7038_INAUGURATED :{GOLD}Inauguré en: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Vehicules: +STR_703A_TRAIN :{WHITE}{COMMA16} train +STR_703B_TRAINS :{WHITE}{COMMA16} trains +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} véhicule +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} véhicules +STR_703E_AIRCRAFT :{WHITE}{COMMA16} aéronef +STR_703F_AIRCRAFT :{WHITE}{COMMA16} aéronefs +STR_7040_SHIP :{WHITE}{COMMA16} navires +STR_7041_SHIPS :{WHITE}{COMMA16} navires +STR_7042_NONE :{WHITE}Aucun +STR_7043_FACE_SELECTION :{WHITE}Sélection du visage +STR_7044_MALE :{BLACK}Homme +STR_7045_FEMALE :{BLACK}Femme +STR_7046_NEW_FACE :{BLACK}Nouveau visage +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Annuler le choix du nouveau visage +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Valider le nouveau visage +STR_7049_SELECT_MALE_FACES :{BLACK}Choisir un visage masculin +STR_704A_SELECT_FEMALE_FACES :{BLACK}Choisir un visage féminin +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Génère un visage au hasard +STR_704C_KEY :{BLACK}Légende +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Affiche la légende +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Légende du graphique des compagnies +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Cliquez ici pour activer/désactiver l'affichage de la compagnie +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Cargaison livrée +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Historique de performace (performance max=1000) +STR_7052_COMPANY_VALUES :{WHITE}Valeur de la compagnie +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Classement des compagnies +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}La compagnie de transport à des ennuis! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} va être en banqueroute si ses performances ne s'améliorent pas! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Président) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Fusion de compagnies de transport! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} à été vendue à {STRING} pour {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Nous sommes à la recherche d'un acheteur pour notre compagnie{}{}Voulez vous acheter {STRING} pour {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Banqueroute! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} à été fermée par ses créanciers et tout ses acrifs vendus! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nouvelle compagnie de transport crée! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} commence à construire près de {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Impossible d'acheter la compagnie... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Valeur des cargaisons +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Jours de transit +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Prix payé pour livrer 10 unités (ou 10000 litres) à 20 carrés de distance +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Afficher/cacher le type de marchandise +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingénieur +STR_7067_TRAFFIC_MANAGER :Gestionnaire de traffic +STR_7068_TRANSPORT_COORDINATOR :Coordinateur de trafic +STR_7069_ROUTE_SUPERVISOR :Superviseur de route +STR_706A_DIRECTOR :Directeur +STR_706B_CHIEF_EXECUTIVE :Directeur Général +STR_706C_CHAIRMAN :Vice-président +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Const. siège +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Contruire/voir le siège +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Impossible de construire le siège... +STR_7072_VIEW_HQ :{BLACK}Voir le siège +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Récession mondiale!{}{}Les experts financiers craignent le pire! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Fin de la récession!{}{}La reprise redonne confiance aux industries! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Bascule entre une grande/petite fenêtre +STR_7076_COMPANY_VALUE :{GOLD}Valeur de la compagnie: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Acheter 25% de la compagnie +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Vendre 25% de la compagnie +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Acheter 25% de la compagnie +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Vendre 25% de la compagnie +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Impossible d'acheter des parts... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Impossible de vendre des parts... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% détenus par {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% détenus par {STRING}{} {COMMA16}% détenus par {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} a été rachetée par {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Vapeur) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Vapeur) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Vapeur) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Vapeur) +STR_800A_SH_8P_STEAM :SH '8P' (Vapeur) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Electrique) +STR_8018_SH_40_ELECTRIC :SH '40' (Electrique) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Electrique) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Electrique) +STR_801B_PASSENGER_CAR :Wagon de voyageurs +STR_801C_MAIL_VAN :Wagon de courrier +STR_801D_COAL_CAR :Wagon de charbon +STR_801E_OIL_TANKER :Citerne de pétrôle +STR_801F_LIVESTOCK_VAN :Wagon à bétail +STR_8020_GOODS_VAN :Wagon de marchandises +STR_8021_GRAIN_HOPPER :Wagon à grain +STR_8022_WOOD_TRUCK :Wagon à bois +STR_8023_IRON_ORE_HOPPER :Wagon à fer +STR_8024_STEEL_TRUCK :Wagon à acier +STR_8025_ARMORED_VAN :Wagon blindé +STR_8026_FOOD_VAN :Wagon de nourriture +STR_8027_PAPER_TRUCK :Wagon à papier +STR_8028_COPPER_ORE_HOPPER :Wagon à cuivre +STR_8029_WATER_TANKER :Citerne d'eau +STR_802A_FRUIT_TRUCK :Wagon à fruits +STR_802B_RUBBER_TRUCK :Wagon à caoutchouc +STR_802C_SUGAR_TRUCK :Wagon à sucre +STR_802D_COTTON_CANDY_HOPPER :Wagon à barbe à papa +STR_802E_TOFFEE_HOPPER :Wagon à caramel +STR_802F_BUBBLE_VAN :Wagon à bulles +STR_8030_COLA_TANKER :Citerne de cola +STR_8031_CANDY_VAN :Wagon à sucreries +STR_8032_TOY_VAN :Wagon à jouets +STR_8033_BATTERY_TRUCK :Wagon à batteries +STR_8034_FIZZY_DRINK_TRUCK :Wagon à boisson gazeuses +STR_8035_PLASTIC_TRUCK :Wagon à plastique +STR_8036_X2001_ELECTRIC :'X2001' (Electrique) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Electrique) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Wagon de voyageurs +STR_803A_MAIL_VAN :Wagon de courrier +STR_803B_COAL_CAR :Wagon de charbon +STR_803C_OIL_TANKER :Citerne de pétrôle +STR_803D_LIVESTOCK_VAN :Wagon à bétail +STR_803E_GOODS_VAN :Wagon de marchandises +STR_803F_GRAIN_HOPPER :Wagon à grain +STR_8040_WOOD_TRUCK :Wagon à bois +STR_8041_IRON_ORE_HOPPER :Wagon à fer +STR_8042_STEEL_TRUCK :Wagon à acier +STR_8043_ARMORED_VAN :Wagon blindé +STR_8044_FOOD_VAN :Wagon de nourriture +STR_8045_PAPER_TRUCK :Wagon à papier +STR_8046_COPPER_ORE_HOPPER :Wagon à cuivre +STR_8047_WATER_TANKER :Citerne d'eau +STR_8048_FRUIT_TRUCK :Wagon à fruits +STR_8049_RUBBER_TRUCK :Wagon à caoutchouc +STR_804A_SUGAR_TRUCK :Wagon à sucre +STR_804B_COTTON_CANDY_HOPPER :Wagon à barbe à papa +STR_804C_TOFFEE_HOPPER :Wagon à caramel +STR_804D_BUBBLE_VAN :Wagon à bulles +STR_804E_COLA_TANKER :Citerne de cola +STR_804F_CANDY_VAN :Wagon à sucreries +STR_8050_TOY_VAN :Wagon à jouets +STR_8051_BATTERY_TRUCK :Wagon à batteries +STR_8052_FIZZY_DRINK_TRUCK :Wagon à boisson gazeuses +STR_8053_PLASTIC_TRUCK :Wagon à plastique +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Electrique) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Electrique) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Electrique) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Electrique) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Wagon de voyageurs +STR_805A_MAIL_VAN :Wagon de courrier +STR_805B_COAL_CAR :Wagon de charbon +STR_805C_OIL_TANKER :Citerne de pétrôle +STR_805D_LIVESTOCK_VAN :Wagon à bétail +STR_805E_GOODS_VAN :Wagon de marchandises +STR_805F_GRAIN_HOPPER :Wagon à grain +STR_8060_WOOD_TRUCK :Wagon à bois +STR_8061_IRON_ORE_HOPPER :Wagon à fer +STR_8062_STEEL_TRUCK :Wagon à acier +STR_8063_ARMORED_VAN :Wagon blindé +STR_8064_FOOD_VAN :Wagon de nourriture +STR_8065_PAPER_TRUCK :Wagon à papier +STR_8066_COPPER_ORE_HOPPER :Wagon à cuivre +STR_8067_WATER_TANKER :Citerne d'eau +STR_8068_FRUIT_TRUCK :Wagon à fruits +STR_8069_RUBBER_TRUCK :Wagon à caoutchouc +STR_806A_SUGAR_TRUCK :Wagon à sucre +STR_806B_COTTON_CANDY_HOPPER :Wagon à barbe à papa +STR_806C_TOFFEE_HOPPER :Wagon à caramel +STR_806D_BUBBLE_VAN :Wagon à bulles +STR_806E_COLA_TANKER :Citerne de cola +STR_806F_CANDY_VAN :Wagon à sucreries +STR_8070_TOY_VAN :Wagon à jouets +STR_8071_BATTERY_TRUCK :Wagon à batteries +STR_8072_FIZZY_DRINK_TRUCK :Wagon à boisson gazeuses +STR_8073_PLASTIC_TRUCK :Wagon à plastique +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Camion de charbon +STR_807C_UHL_COAL_TRUCK :Uhl Camion de charbon +STR_807D_DW_COAL_TRUCK :DW Camion de charbon +STR_807E_MPS_MAIL_TRUCK :MPS Camion de courrier +STR_807F_REYNARD_MAIL_TRUCK :Reynard Camion de courrier +STR_8080_PERRY_MAIL_TRUCK :Perry Camion de courrier +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Camion de courrier +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Camion de courrier +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Camion de courrier +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Citerne de pétrole +STR_8085_FOSTER_OIL_TANKER :Foster Citerne de pétrole +STR_8086_PERRY_OIL_TANKER :Perry Citerne de pétrole +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Camion à bétail +STR_8088_UHL_LIVESTOCK_VAN :Uhl Camion à bétail +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Camion à bétail +STR_808A_BALOGH_GOODS_TRUCK :Balogh Camion de marchandises +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Camion de marchandises +STR_808C_GOSS_GOODS_TRUCK :Goss Camion de marchandises +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Camion à grain +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Camion à grain +STR_808F_GOSS_GRAIN_TRUCK :Goss Camion à grain +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Camion de bois +STR_8091_FOSTER_WOOD_TRUCK :Foster Camion de bois +STR_8092_MORELAND_WOOD_TRUCK :Moreland Camion de bois +STR_8093_MPS_IRON_ORE_TRUCK :MPS Camion de fer +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Camion de fer +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Camion de fer +STR_8096_BALOGH_STEEL_TRUCK :Balogh Camion d'acier +STR_8097_UHL_STEEL_TRUCK :Uhl Camion d'acier +STR_8098_KELLING_STEEL_TRUCK :Kelling Camion d'acier +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Fourgon blindé +STR_809A_UHL_ARMORED_TRUCK :Uhl Fourgon blindé +STR_809B_FOSTER_ARMORED_TRUCK :Foster Fourgon blindé +STR_809C_FOSTER_FOOD_VAN :Foster Camion de nourriture +STR_809D_PERRY_FOOD_VAN :Perry Camion de nourriture +STR_809E_CHIPPY_FOOD_VAN :Chippy Camion de nourriture +STR_809F_UHL_PAPER_TRUCK :Uhl Camion de papier +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Camion de papier +STR_80A1_MPS_PAPER_TRUCK :MPS Camion de papier +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Camion de cuivre +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Camion de cuivre +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Camion de cuivre +STR_80A5_UHL_WATER_TANKER :Uhl Citerne d'eau +STR_80A6_BALOGH_WATER_TANKER :Balogh Citerne d'eau +STR_80A7_MPS_WATER_TANKER :MPS Citerne d'eau +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Camion de fruits +STR_80A9_UHL_FRUIT_TRUCK :Uhl Camion de fruits +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Camion de fruits +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Camion de caoutchouc +STR_80AC_UHL_RUBBER_TRUCK :Uhl Camion de caoutchouc +STR_80AD_RMT_RUBBER_TRUCK :RMT Camion de caoutchouc +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Camion de sucre +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Camion de sucre +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Camion de sucre +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Camion de Cola +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Camion de Cola +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Camion de Cola +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Camion de barbe à papa +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Camion de barbe à papa +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Camion de barbe à papa +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Camion de caramel +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Camion de caramel +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Camion de sucreries +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Camion de jouets +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Camion de jouets +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Camion de jouets +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Camion de sucreries +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Camion de sucreries +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Camion de sucreries +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Camion de batteries +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Camion de batteries +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Camion de batteries +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Camion de boissons gazeuses +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Camion de boissons gazeuses +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Camion de boissons gazeuses +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Camion de plastique +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Camion de plastique +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Camion de plastique +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Camion de bulles +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Camion de bulles +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Camion de bulles +STR_80CC_MPS_OIL_TANKER :MPS Citerne de pétrole +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Citerne de pétrole +STR_80CE_MPS_PASSENGER_FERRY :MPS Ferry de voyageurs +STR_80CF_FFP_PASSENGER_FERRY :FFP Ferry de voyageurs +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Aéroglisseur +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Ferry de voyageurs +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Ferry de voyageurs +STR_80D3_YATE_CARGO_SHIP :Yate Navire cargo +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Navire cargo +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Navire cargo +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Navire cargo +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Hélicoptère +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Hélicoptère +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Hélicoptère +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Communiqué du fabriquant d'engins +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Nous venons juste d'inventer: {STRING} - Voulez vous l'exclusivité de ce véhicule pendant un an, afin que nous puissions le tester avant sa mise sur le marché ? +STR_8102_RAILROAD_LOCOMOTIVE :locomotive +STR_8103_ROAD_VEHICLE :véhicule +STR_8104_AIRCRAFT :aéronef +STR_8105_SHIP :navire +STR_8106_MONORAIL_LOCOMOTIVE :locomotive monorail +STR_8107_MAGLEV_LOCOMOTIVE :locomotive magnétique + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Dépôt ferroviaire +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Les habitants célèbrent . . .{}Arrivée du premier train à {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Détails) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Train présent +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Aller à {STATION} +STR_8807_GO_TO_UNLOAD :Aller à {STATION} (Décharger) +STR_8808_GO_TO_LOAD :Aller à {STATION} (Charger) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Aller sans s'arrêter à {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Aller sans s'arrêter à {STATION} (Décharger) +STR_880C_GO_NON_STOP_TO_LOAD :Aller sans s'arrêter à {STATION} (Charger) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Go to {TOWN} Dépôt ferroviaire +STR_SERVICE_AT_TRAIN_DEPOT :Maintenance au dépôt de {TOWN} +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Aller sans s'arrêter au dépôt de {TOWN} +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Aller faire la maintenance sans s'arrêter au dépôt de {TOWN} + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Roule vers le dépôt de {TOWN} +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Roule vers le dépôt de {TOWN}, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Vide +STR_8813_FROM :{LTBLUE}{CARGO} de {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Le train {COMMA16} est en attente au dépôt +STR_8815_NEW_VEHICLES :{BLACK}Nouveaux véhicules +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Prix: {GOLD}{CURRENCY}{BLACK} Poids: {GOLD}{COMMA16}t{}{BLACK}Vitesse: {GOLD}{VELOCITY}{BLACK} Puissance: {GOLD}{COMMA16}ch{}{BLACK}Coût d'entretien: {GOLD}{CURRENCY}/an{}{BLACK}Capacité: {GOLD}{STRING}{}{BLACK}Conçu en: {GOLD}{NUMU16}{BLACK} Durée de vie: {GOLD}{COMMA16} ans{}{BLACK}Fiabilité max.: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Information +STR_8819_TRAIN_TOO_LONG :{WHITE}Train trop long +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Les trains peuvent être manipulés qu'une fois stoppés au dépôt +STR_881B_TRAINS :{WHITE}{STRING} - Trains +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nouveaux véhicules ferroviaires +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nouveaux véhicules monorail +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nouveaux véhicules magnétiques +STR_881F_BUILD_VEHICLE :{BLACK}Construire +STR_8820_RENAME :{BLACK}Renommer +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Prix: {GOLD}{CURRENCY}{}{BLACK}Poids: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Capacité: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Suivant +STR_8824_DELETE :{BLACK}Supprimer +STR_8825_NON_STOP :{BLACK}Sans-arrêt +STR_8826_GO_TO :{BLACK}Aller à +STR_8827_FULL_LOAD :{BLACK}Charger +STR_8828_UNLOAD :{BLACK}Décharger +STR_8829_ORDERS :{WHITE}{STRING} (Ordres) +STR_882A_END_OF_ORDERS :{SETX 10}- - Fin des ordres - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Maintenance +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Impossible de construire le véhicule ferroviaire... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construit en: {LTBLUE}{NUMU16}{BLACK} Valeur: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Valeur: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Chargement/déchargement +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Impossible d'envoyer le train au dépôt... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Plus de places pour les ordres +STR_8832_TOO_MANY_ORDERS :{WHITE}Trop d'ordres +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Impossible d'insérer un nouvel ordre... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Impossible de supprimer cet ordre... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Impossible de modifier cet ordre... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Vous devez d'abord construire un dépôt ferroviaire +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Impossible de déplacer le véhicule... +STR_8838_N_A :N/D{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Impossible de vendre le véhicule ferroviaire... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Impossible de trouver la route jusqu'au dépôt +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Impossible de démarrer/stopper le train... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Intervalle de maintenance: {LTBLUE}{COMMA16}jours{BLACK} Dernière maintenance: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trains - Cliquez sur un train pour obtenir des informations +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Contruire de nouveaux trains (nécessite un dépôt ferroviaire) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trains - Cliquez sur un train pour obtenir des informations, glissez le wagon pour l'ajouter/le supprimer du train +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Construire un nouveau train/wagon +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Glissez le véhicule ici pour le vendre +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrer la vue sur le dépôt +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Selection du véhicule - Cliquez pour obtenir des informations +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Construire le véhicule sélectionné +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Renommer le type du véhicule +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Action courante du train. Cliquez pour le démarrer/l'arrêter +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Montrer les ordres du train +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrer la vue sur le train +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Envoyer le train au dépôt +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Forcer le train à continuer sans tenir compte des feux +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Faire faire demi-tour au train +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Afficher les détails +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Augmenter l'intervalle de maintenance +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Diminuer l'intervalle de maintenance +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Afficher des informations les marchandises +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Afficher des informations sur les wagons +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Montrer les capacités de chaque wagon +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Montre la capacité totale du train, séparé par type de marchandise +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Liste des ordres - Cliquez sur un ordre pour le sélectionner +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Saute l'ordre courant, et enchaîne sur le suivant +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Supprime l'ordre sélectionné +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Transformer l'ordre sélectionné en Sans-Arrêt +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Insérer un nouvel ordre +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Forcer le véhicule à attendre un chargement complet pour l'ordre sélectionné +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Forcer le véhicule à attendre un déchargement complet pour l'ordre sélectionné +STR_SERVICE_HINT :{BLACK}Sauter cet ordre tant qu'aucune maintenance n'est requise +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nouveau(elle) {STRING} disponible! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Prix: {CURRENCY} Poids: {COMMA16}t{}Vitesse: {VELOCITY} Puissance: {COMMA16}ch{}Coût d'entretien: {CURRENCY}/an{}Capacité: {STRING} +STR_885C_BROKEN_DOWN :{RED}En panne +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Coût d'entretien: {LTBLUE}{CURRENCY}/an +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Poids: {LTBLUE}{COMMA16}t {BLACK}Puissance: {LTBLUE}{COMMA32}ch{BLACK} Vitesse max.: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit cette année: {LTBLUE}{CURRENCY} (année précédente: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilité: {LTBLUE}{COMMA8}% {BLACK}Pannes depuis la dernière maintenance: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Stoppé +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Impossible de forcer le train à avancer sous le danger... +STR_8863_CRASHED :{RED}Crashé! + +STR_8865_NAME_TRAIN :{WHITE}Renommer le train +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Impossible de renommer le train... +STR_8867_NAME_TRAIN :{BLACK}Renommer le train +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Accident ferroviaire!{}{COMMA16} mort(s) brulé(s) vif(s) dans la collision +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Impossible de faire faire demi-tour... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Renommer le type de train +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Impossible de renommer le type de train... + +STR_TRAIN_STOPPING :{RED}Ralentit +STR_TRAIN_STOPPING_VEL :{RED}Ralentit, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Véhicule Routier présent +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Véhicules routiers +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}Dépôt routier de {TOWN} +STR_9004_NEW_VEHICLES :{BLACK}Nouveaux Véhicules +STR_9005_INFORMATION :{BLACK}Information +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nouveaux véhicules +STR_9007_BUILD_VEHICLE :{BLACK}Construire +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Prix: {GOLD}{CURRENCY}{BLACK} Vitesse: {GOLD}{VELOCITY}{}{BLACK}Coût d'entretien: {GOLD}{CURRENCY}/an{}{BLACK}Capacité: {GOLD}{STRING}{}{BLACK}Conçu en: {GOLD}{NUMU16}{BLACK} Durée de vie: {GOLD}{COMMA16} ans{}{BLACK}Fiabilité max.: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Impossible de construire le véhicule... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Vous devez d'abord construire un dépôt routier +STR_900B_ORDERS :{WHITE}{STRING} (Ordres) +STR_900C_DETAILS :{WHITE}{STRING} (Details) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING}{BLACK} Coût d'entretien: {LTBLUE}{CURRENCY}/an +STR_900E_MAX_SPEED :{BLACK}Vitesse max.: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit de cette année: {LTBLUE}{CURRENCY} (année dernière: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilité: {LTBLUE}{COMMA8}% {BLACK}Pannes depuis le dernier entretien: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construit en: {LTBLUE}{NUMU16}{BLACK} Valeur: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Capacité: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...doit être à l'arrêt dans un dépôt routier +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Impossible de vendre le véhicule... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Impossible de démarrer/stopper le véhicule... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Le véhicule {COMMA16} attend au dépôt +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Roule vers le dépôt de {TOWN} +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Roule vers le dépôt de {TOWN}, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Impossible d'envoyer le véhicule au dépôt... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Impossible de trouver le dépôt +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Véhicules - Cliquez sur un véhicule pour obtenir des informations +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Construire de nouveaux véhicules (nécessite un dépôt routier) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Comportement courant du véhicule - cliquez pour le démarrer/l'arrêter +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Affiche les ordres +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centre la vue sur le véhicule +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Envoie le véhicule au dépôt +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Force le véhicule à faire demi-tour +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Affiche les détails +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Véhicules - cliquez pour obtenir des informations +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Construire un nouveau véhicule +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Glissez un véhicule ici pour le vendre +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centre la vue sur le dépôt +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Choix du véhicule - cliquez sur un véhicule pour obtenir des informations +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Construire le véhicule sélectionné +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Nouveau véhicule disponible! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Prix: {CURRENCY}{}Vitesse: {VELOCITY}{}Coût d'entretien: {CURRENCY}/an{}Capacité: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Renommer le véhicule +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Impossible de renommer le véhicule... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Renommer le véhicule +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Les habitants célèbrent . . .{}Le premier bus arrive à {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Les habitants célèbrent . . .{}Le premier camion arrive à {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Accident routier!{}Un automobiliste meurt brulé vif après collision avec un train +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Accident routier!{}{COMMA16} meurent brulés vifs après une collision avec un train +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Impossible de faire faire demi-tour au véhicule... +STR_9034_RENAME :{BLACK}Renommer +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Renommer type de véhicule routier +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Renommer type de véhicule routier +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Impossible de renommer type de véhicule routier... +STR_9038_GO_TO_ROADVEH_DEPOT :Aller à {TOWN} Dépôt Routier +STR_SERVICE_AT_ROADVEH_DEPOT :Maintenance au dépôt de {TOWN} + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Construction Portuaire +STR_9801_DOCK_CONSTRUCTION :{WHITE}Construction Portuaire +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Impossible de construire port ici... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Dépôt Naval +STR_9804_NEW_SHIPS :{BLACK}Nouveaux navires +STR_9805_SHIPS :{WHITE}{STRING} - Navires +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Impossible de construire navire... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Doit d'abord construire un dépôt naval +STR_9808_NEW_SHIPS :{WHITE}Nouveaux navires +STR_9809_BUILD_SHIP :{BLACK}Construire navire +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Prix: {GOLD}{CURRENCY}{BLACK} Vitesse: {GOLD}{VELOCITY}{}{BLACK}Capacité: {GOLD}{STRING} {STRING}{}{BLACK}Coût d'entretien: {GOLD}{CURRENCY}/an{}{BLACK}Conçu en: {GOLD}{NUMU16}{BLACK} Durée de vie: {GOLD}{COMMA16} ans{}{BLACK}Fiabilité max.: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Navire doit être arrêté au dépôt +STR_980C_CAN_T_SELL_SHIP :{WHITE}Impossible de vendre navire... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Impossible de construire navire... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Navire présent +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Ordres) +STR_9811_DETAILS :{WHITE}{STRING} (Détails) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Âge: {LTBLUE}{STRING}{BLACK} Coût d'Opération: {LTBLUE}{CURRENCY}/an +STR_9813_MAX_SPEED :{BLACK}Vitesse max.: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit cette année: {LTBLUE}{CURRENCY} (l'an dernier: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilité: {LTBLUE}{COMMA8}% {BLACK}Pannes depuis le dernier entretien: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construit: {LTBLUE}{NUMU16}{BLACK} Valeur: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Capacité: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Impossible d'arrêter/démarrer le navire... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Impossible d'envoyer le navire au dépôt... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Impossible de trouver dépôt local +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}En route pour le dépôt naval de {TOWN} +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}En route pour {TOWN} Dépôt Naval, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Navire {COMMA16} est en attente au dépôt +STR_981D_BUILD_SHIP_DOCK :{BLACK}Construire un port +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Construire un dépôt naval (pour construire et entretenir les navires) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Navires - cliquez sur un navire pour informations +STR_9820_BUILD_NEW_SHIP :{BLACK}Construire nouveau navire +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Glissez navire jusqu'ici pour le vendre +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrer la vue sur emplacement du dépôt naval +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Navires - cliquez sur un navire pour informations +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Construire nouveaux navires (nécessite un dépôt naval) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Liste de sélection de navire - cliquez sur un navire pour informations +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Construire le navire surligné +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Action courante du navire - cliquez ici pour arrêter/démarrer le navire +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Afficher les ordres du navire +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrer la vue sur l'emplacement du navire +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Envoyer navire au dépôt +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Afficher détails du navire +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nouveau navire maintenant disponible! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Coût: {CURRENCY} Vitesse max.: {VELOCITY}{}Capacité: {STRING}{}Coût d'Opération: {CURRENCY}/an +STR_982F_NAME_SHIP :{BLACK}Nommer navire + +STR_9831_NAME_SHIP :{WHITE}Nommer navire +STR_9832_CAN_T_NAME_SHIP :{WHITE}Impossible de nommer le navire... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Les habitants célèbrent . . .{}Arrivée du premier navire à {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Placer une bouée, peut servir de guide aux navires +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Impossible de placer une bouée ici... +STR_9836_RENAME :{BLACK}Renommer +STR_9837_RENAME_SHIP_TYPE :{BLACK}Renommer type de navire +STR_9838_RENAME_SHIP_TYPE :{WHITE}Renommer type de navire +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Impossbile de renommer type de navire... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Réaménager navire pour transporter une cargaison différente +STR_983B_REFIT :{WHITE}{STRING} (Réaménager) +STR_983C_REFIT_SHIP :{BLACK}Réaménager navire +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Choisissez le type de cargaisons à transporter +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Réaménager le navire pour transporter la cargaison sélectionnée +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selectionnez cargaison à transporter:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nouvelle capacité: {GOLD}{STRING}{}{BLACK}Cost of refit: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Impossible de réaménager le navire... +STR_9842_REFITTABLE :(réaménageable) +STR_GO_TO_SHIP_DEPOT :Aller au dépôt de {TOWN} +SERVICE_AT_SHIP_DEPOT :Maintenance au dépôt de {TOWN} + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Construction d'Aéroport +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Impossible de construire un aéroport ici... +STR_A002_AIRCRAFT_HANGAR :{WHITE}Hangar à {STATION} +STR_A003_NEW_AIRCRAFT :{BLACK}Nouvel aéronef +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}Nouvel Aéronef +STR_A006_BUILD_AIRCRAFT :{BLACK}Construire aéronef +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Coût: {GOLD}{CURRENCY}{BLACK} Vitesse: {GOLD}{VELOCITY}{}{BLACK}Capacité: {GOLD}{COMMA16} passagers, {COMMA16} sacs de courrier{}{BLACK}Coût d'opération: {GOLD}{CURRENCY}/an{}{BLACK}Conception: {GOLD}{NUMU16}{BLACK} Durée de vie: {GOLD}{COMMA16} années{}{BLACK}Fiabilité max.: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Impossible de construire l'aéronef... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Aéronef +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Ordres) +STR_A00C_DETAILS :{WHITE}{STRING} (Détails) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Âge: {LTBLUE}{STRING}{BLACK} Coût d'opération: {LTBLUE}{CURRENCY}/an +STR_A00E_MAX_SPEED :{BLACK}Vitesse max.: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profits cette année: {LTBLUE}{CURRENCY} (l'an dernier: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilité: {LTBLUE}{COMMA8}% {BLACK}Cafouillages depuis le dernier service: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construit: {LTBLUE}{NUMU16}{BLACK} Valeur: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Impossible d'envoyer l'aéronef au hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}En route pour le hangar de {STATION} +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}En route pour le hangar de {STATION}, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Aéronef {COMMA16} est en attente dans le hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Aéronef présent +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Impossible d'arrêter/démarrer aéronef... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}L'aéronef est en vol +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Doit d'abord construire un aéroport +STR_A019_CAPACITY :{BLACK}Capacité: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Capacité: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Aéronef doit être arrêté dans le hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Impossible de vendre aéronef... +STR_A01D_AIRPORT_CONSTRUCTION :Construction d'aéroport +STR_A01E_BUILD_AIRPORT :{BLACK}Construire un aéroport +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aéronef - cliquez sur l'aéronef pour informations +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Construire un nouvel aéronef (nécessite un aéroport avec hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aéronef - cliquez sur l'aéronef pour informations +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Coustruire nouvel aéronef +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Glissez l'aéronef ici pour le vendre +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centrer la vue principale sur l'emplacement du hangar +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Liste de sélection d'aéronef - cliquez sur les aéronefs pour de plus amples informations +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Construire l'aéronef sélectionné +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Action courrante de l'aéronef - cliquez ici pour arrêter/démarrer l'aéronef +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Afficher les ordres de l'aéronef +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centrer la vue principale sur l'emplacement de l'aéronef +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Envoyer l'aéronef au hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Afficher détails de l'aéronef +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nouvel aéronef maintenant disponible! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Coût: {CURRENCY} Vitesse max.: {VELOCITY}{}Capacité: {COMMA16} passagers, {COMMA16} sacs de courrier{}Coût d'opération: {CURRENCY}/an + +STR_A030_NAME_AIRCRAFT :{WHITE}Nommer l'aéronef +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Impossible de nommer l'aéronef... +STR_A032_NAME_AIRCRAFT :{BLACK}Nommer l'aéronef +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Les habitants célèbrent . . .{}Arrivée du premier aéronef à {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Écrasement d'un aéronef!{}{COMMA16} meurent brulés vifs à {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinations: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Renommer +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Renommer type d'aéronef +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Renommer type d'aéronef +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Impossible de renommer type d'aéronef... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Réaménager aéronef pour transporter un différent type de cargaison +STR_A03C_REFIT :{WHITE}{STRING} (Refit) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Réaménager aéronef +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Choisir type de cargaison à transporter +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Réaménager aéronef pour transporter type de cargaison sélectionné +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selectionner type de cargaison à transporter:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nouvelle capacité: {GOLD}{STRING}{}{BLACK}Prix du réaménagement: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Impossible de réaménager l'aéronef... +STR_A043_REFITTABLE :(réaménageable) +STR_GO_TO_AIRPORT_HANGAR :Aller au hangar {STATION} +SERVICE_AT_AIRPORT_HANGAR :Maintenance au hangar {STATION} + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Désastre impliquant un Zeppelin à {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Véhicule routier détruit dans use collision avec un 'OVNI'! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Explosion d'une raffinerie de pétrole près de {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Usine détruite dans des circonstances suspectes près de {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}Un 'OVNI' attérit près de {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Affaissement d'une veine de charbon entraîne la desctruction de la mine de {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Votre tentative de corruption à été +STR_BRIBE_FAILED_2 :{WHITE}révélée à la presse par un journaliste régional. diff --git a/lang/galician.txt b/lang/galician.txt new file mode 100644 --- /dev/null +++ b/lang/galician.txt @@ -0,0 +1,2455 @@ +##name Galician +##ownname Galego + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Fora do borde do mapa +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Demasiado cerca do borde do mapa +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Diñeiro insuficiente - necesitas {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Necesitas terreo chan +STR_0008_WAITING :{BLACK}Esperando: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (en ruta dende +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Acepta: {WHITE} +STR_000D_ACCEPTS :{BLACK}Acepta: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Pasaxeiros +STR_0010_COAL :Carbón +STR_0011_MAIL :Correo +STR_0012_OIL :Petróleo +STR_0013_LIVESTOCK :Gando +STR_0014_GOODS :Mercadorías +STR_0015_GRAIN :Gran +STR_0016_WOOD :Madeira +STR_0017_IRON_ORE :Hematita +STR_0018_STEEL :Aceiro +STR_0019_VALUABLES :Valores +STR_001A_COPPER_ORE :Mineral de Cobre +STR_001B_MAIZE :Millo +STR_001C_FRUIT :Froita +STR_001D_DIAMONDS :Diamantes +STR_001E_FOOD :Comida +STR_001F_PAPER :Papel +STR_0020_GOLD :Ouro +STR_0021_WATER :Auga +STR_0022_WHEAT :Trigo +STR_0023_RUBBER :Caucho +STR_0024_SUGAR :Azucre +STR_0025_TOYS :Xoguetes +STR_0026_CANDY :Caramelo +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Algodón de Azucre +STR_0029_BUBBLES :Burbullas +STR_002A_TOFFEE :Toffee +STR_002B_BATTERIES :Baterías +STR_002C_PLASTIC :Plástico +STR_002D_FIZZY_DRINKS :Bebidas Gaseosas +STR_002E : +STR_002F_PASSENGER :Pasaxeiro +STR_0030_COAL :Carbón +STR_0031_MAIL :Correo +STR_0032_OIL :Petróleo +STR_0033_LIVESTOCK :Gando +STR_0034_GOODS :Mercadorías +STR_0035_GRAIN :Gran +STR_0036_WOOD :Madeira +STR_0037_IRON_ORE :Hematita +STR_0038_STEEL :Aceiro +STR_0039_VALUABLES :Valores +STR_003A_COPPER_ORE :Mineral de Cobre +STR_003B_MAIZE :Millo +STR_003C_FRUIT :Froita +STR_003D_DIAMOND :Diamante +STR_003E_FOOD :Comida +STR_003F_PAPER :Papel +STR_0040_GOLD :Ouro +STR_0041_WATER :Auga +STR_0042_WHEAT :Trigo +STR_0043_RUBBER :Caucho +STR_0044_SUGAR :Azucre +STR_0045_TOY :Xoguete +STR_0046_CANDY :Caramelo +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Algodón de Azucre +STR_0049_BUBBLE :Burbulla +STR_004A_TOFFEE :Toffee +STR_004B_BATTERY :Battería +STR_004C_PLASTIC :Plástico +STR_004D_FIZZY_DRINK :Bebida Gaseosa +STR_004E : +STR_004F_PASSENGER :{COMMA16} pasaxeiro +STR_0050_TON_OF_COAL :{COMMA16} ton. de carbón +STR_0051_BAG_OF_MAIL :{COMMA16} saco de correo +STR_0052_OF_OIL :{VOLUME} de petróleo +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} item de gando +STR_0054_CRATE_OF_GOODS :{COMMA16} caixón de mercadorías +STR_0055_TON_OF_GRAIN :{COMMA16} ton. de gran +STR_0056_TON_OF_WOOD :{COMMA16} ton. de madeira +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton. de hematita +STR_0058_TON_OF_STEEL :{COMMA16} ton. de aceiro +STR_0059_BAG_OF_VALUABLES :{COMMA16} saco de valores +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton. de mineral de cobre +STR_005B_TON_OF_MAIZE :{COMMA16} ton. de millo +STR_005C_TON_OF_FRUIT :{COMMA16} ton. de froita +STR_005D_BAG_OF_DIAMONDS :{COMMA16} saco de diamantes +STR_005E_TON_OF_FOOD :{COMMA16} ton. de comida +STR_005F_TON_OF_PAPER :{COMMA16} ton. de papel +STR_0060_BAG_OF_GOLD :{COMMA16} saco de ouro +STR_0061_OF_WATER :{VOLUME} de auga +STR_0062_TON_OF_WHEAT :{COMMA16} ton. de trigo +STR_0063_OF_RUBBER :{VOLUME} de caucho +STR_0064_TON_OF_SUGAR :{COMMA16} ton. de azucre +STR_0065_TOY :{COMMA16} xoguete +STR_0066_BAG_OF_CANDY :{COMMA16} saco de caramelo +STR_0067_OF_COLA :{VOLUME} de cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton. de algodón de azucre +STR_0069_BUBBLE :{COMMA16} burbulla +STR_006A_TON_OF_TOFFEE :{COMMA16} ton. de toffee +STR_006B_BATTERY :{COMMA16} batería +STR_006C_OF_PLASTIC :{VOLUME} de plástico +STR_006D_FIZZY_DRINK :{COMMA16} bebida gaseosa +STR_006E : +STR_006F_PASSENGERS :{COMMA16} pasaxeiros +STR_0070_TONS_OF_COAL :{COMMA16} tons. de carbón +STR_0071_BAGS_OF_MAIL :{COMMA16} sacos de correo +STR_0072_OF_OIL :{VOLUME} de petróleo +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} items de gando +STR_0074_CRATES_OF_GOODS :{COMMA16} caixóns de mercadorías +STR_0075_TONS_OF_GRAIN :{COMMA16} tons. de gran +STR_0076_TONS_OF_WOOD :{COMMA16} tons. de madeira +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tons. de hematita +STR_0078_TONS_OF_STEEL :{COMMA16} tons. de aceiro +STR_0079_BAGS_OF_VALUABLES :{COMMA16} sacos de valores +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tons. de mineral de cobre +STR_007B_TONS_OF_MAIZE :{COMMA16} tons. de millo +STR_007C_TONS_OF_FRUIT :{COMMA16} tons. de froita +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} sacos de diamantes +STR_007E_TONS_OF_FOOD :{COMMA16} tons. de comida +STR_007F_TONS_OF_PAPER :{COMMA16} tons. de papel +STR_0080_BAGS_OF_GOLD :{COMMA16} sacos de ouro +STR_0081_OF_WATER :{VOLUME} de auga +STR_0082_TONS_OF_WHEAT :{COMMA16} tons. de trigo +STR_0083_OF_RUBBER :{VOLUME} de caucho +STR_0084_TONS_OF_SUGAR :{COMMA16} tons. de azucre +STR_0085_TOYS :{COMMA16} xoguetes +STR_0086_BAGS_OF_CANDY :{COMMA16} sacos de caramelo +STR_0087_OF_COLA :{VOLUME} de cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tons. de algodón de azucre +STR_0089_BUBBLES :{COMMA16} burbullas +STR_008A_TONS_OF_TOFFEE :{COMMA16} tons. de toffee +STR_008B_BATTERIES :{COMMA16} baterías +STR_008C_OF_PLASTIC :{VOLUME} de plástico +STR_008D_FIZZY_DRINKS :{COMMA16} bebidas gaseosas +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Mapa - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Opcións da Partida +STR_00B2_MESSAGE :{YELLOW}Mensaxe +STR_00B3_MESSAGE_FROM :{YELLOW}Mensaxe de {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Non podes facer eso.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Non podes limpar esta área.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Copyright Orixinal {COPYRIGHT} 1995 Chris Sawyer, Tódolos dereitos reservados +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD versión {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Deseño orixinal de Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Gráficos de Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Saír +STR_00C8_YES :{BLACK}Si +STR_00C9_NO :{BLACK}Non +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}¿Estás seguro de querer saír e volver a {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nada +STR_00D1_DARK_BLUE :Azul Escuro +STR_00D2_PALE_GREEN :Verde Claro +STR_00D3_PINK :Rosa +STR_00D4_YELLOW :Amarelo +STR_00D5_RED :Vermello +STR_00D6_LIGHT_BLUE :Azul Claro +STR_00D7_GREEN :Verde +STR_00D8_DARK_GREEN :Verde Escuro +STR_00D9_BLUE :Azul +STR_00DA_CREAM :Crema +STR_00DB_MAUVE :Malva +STR_00DC_PURPLE :Morado +STR_00DD_ORANGE :Laranxa +STR_00DE_BROWN :Marrón +STR_00DF_GREY :Gris +STR_00E0_WHITE :Branco +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Hay demasiados vehículos na partida +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Situación +STR_00E5_CONTOURS :Contorno +STR_00E6_VEHICLES :Vehículos +STR_00E7_INDUSTRIES :Industrias +STR_00E8_ROUTES :Rutas +STR_00E9_VEGETATION :Vexetación +STR_00EA_OWNERS :Propietarios +STR_00EB_ROADS :{BLACK}{TINYFONT}Estradas +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Ferrocarrís +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Estacións/Aeroportos/Portos +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Edificios/Industrias +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vehículos +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Trens +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Vehículos de estrada +STR_00F7_SHIPS :{BLACK}{TINYFONT}Barcos +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Avións +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Rutas de transporte +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Mina de Carbón +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Estación Enerxética +STR_00FC_FOREST :{BLACK}{TINYFONT}Bosque +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Serradeiro +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Ref. de Petróleo +STR_00FF_FARM :{BLACK}{TINYFONT}Granxa +STR_0100_FACTORY :{BLACK}{TINYFONT}Factoría +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Imprenta +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Pozo Petrolífero +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Mina de Hematita +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Siderúrxica +STR_0105_BANK :{BLACK}{TINYFONT}Banco +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Fábrica de Papel +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Mina de Ouro +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Planta de Proc. de Comida +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Mina de Diamantes +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Mina de Mineral de Cobre +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Plantación de Froita +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Plant. de Árbores de Caucho +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Acuífero +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Torre de Auga +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Fábrica de Madeiros +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Bosque de Algodón de Azucre +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Fábrica de Caramelos +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Granxa de Baterías +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Fontes de Cola +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Xoguetería +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Fábrica de Xoguetes +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Fontes de Plástico +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Fábrica de Bebidas Gaseosas +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Xerador de Burbullas +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Canteira de Toffee +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Mina de Azucre +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Estación de Ferrocarril +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Bahía de Carga de Camións +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Estación de Autobús +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Aerporto/"Heliporto" +STR_011F_DOCK :{BLACK}{TINYFONT}Peirao +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Terra Quebrada +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Terra con Herba +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Terra Deserta +STR_0123_FIELDS :{BLACK}{TINYFONT}Campos +STR_0124_TREES :{BLACK}{TINYFONT}Árbores +STR_0125_ROCKS :{BLACK}{TINYFONT}Rochas +STR_0126_WATER :{BLACK}{TINYFONT}Auga +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Sen Propietario +STR_0128_TOWNS :{BLACK}{TINYFONT}Cidades +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrias +STR_012A_DESERT :{BLACK}{TINYFONT}Deserto +STR_012B_SNOW :{BLACK}{TINYFONT}Neve +STR_012C_MESSAGE :{WHITE}Mensaxe +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Cancelar +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Renomear +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Hay demasiados nomes definidos +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}O nome elixido xa está en uso + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (millas) +STR_013A_METRIC_KILOMETERS :Métrico (quilómetros) +STR_013B_OWNED_BY :{WHITE}...É propiedade de {STRING} +STR_013C_CARGO :{BLACK}Carga +STR_013D_INFORMATION :{BLACK}Información +STR_013E_CAPACITIES :{BLACK}Capacidades +STR_013E_TOTAL_CARGO :{BLACK}Carga Total +STR_013F_CAPACITY :{BLACK}Capacidade: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Carga total (capacidade) deste tren: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nova Partida +STR_0141_LOAD_GAME :{BLACK}Cargar Partida +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demostración +STR_SINGLE_PLAYER :{BLACK}Un Xogador +STR_MULTIPLAYER :{BLACK}Multixogador + +STR_0148_GAME_OPTIONS :{BLACK}Opcións da Partida + +STR_0150_SOMEONE :alguén{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Mapa do mundo +STR_0152_TOWN_DIRECTORY :Directorio de cidades +STR_0153_SUBSIDIES :Subsidios + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :G. Beneficios Operativos +STR_0155_INCOME_GRAPH :Gráfica de ingresos +STR_0156_DELIVERED_CARGO_GRAPH :Gráfica de carga entregada +STR_0157_PERFORMANCE_HISTORY_GRAPH :G. historial de Rendemento +STR_0158_COMPANY_VALUE_GRAPH :Gráfica do Valor da Compañía +STR_0159_CARGO_PAYMENT_RATES :Taxas de pago polas cargas +STR_015A_COMPANY_LEAGUE_TABLE :Táboa da Liga de compañías +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Grabar Partida +STR_015D_LOAD_GAME :Cargar Partida +STR_015E_QUIT_GAME :Saír ó menu principal +STR_015F_QUIT :Saír do programa +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}¿Está seguro de que desexa saír da partida? +STR_0161_QUIT_GAME :{WHITE}Saír ó menú principal + +############ range for months starts +STR_0162_JAN :Xan +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :Mai +STR_0167_JUN :Xuñ +STR_0168_JUL :Xul +STR_0169_AUG :Ago +STR_016A_SEP :Set +STR_016B_OCT :Out +STR_016C_NOV :Nov +STR_016D_DEC :Dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pausar Partida +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Grabar partida, abandonar partida, saír +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Amosa-la lista das estacións da compañía +STR_0174_DISPLAY_MAP :{BLACK}Amosa-lo mapa +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Amosa-lo mapa, directorio de cidades +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Amosa-lo directorio de cidades +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Amosa-la información das finanzas da compañía +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Amosa-la información xeral da compañía +STR_0179_DISPLAY_GRAPHS :{BLACK}Amosa-las gráficas +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Amosa-la táboa da liga de compañías +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Amosa-la lista dos trens da compañía +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Amosa-la lista dos vehículos de estrada da compañía +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Amosa-la lista dos barcos da compañía +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Amosa-la lista dos avións da compañía +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Achega-la vista +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Alonxa-la vista +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Construír elementos do ferrocarril +STR_0182_BUILD_ROADS :{BLACK}Construír elementos das estradas +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Construír elementos para barcos +STR_0184_BUILD_AIRPORTS :{BLACK}Construír aeroportos +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plantar árbores, situar sinais, etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Información dunha área de terreo +STR_0187_OPTIONS :{BLACK}Opcións +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Non se pode cambia-lo intervalo de servicio... +STR_018B_CLOSE_WINDOW :{BLACK}Pechar fiestra +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Título da fiestra - arrástrao para move-la fiestra +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Demoler edificios, etc. nun cadrado de terreo +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Baixar unha esquina de terreo +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Elevar unha esquina de terreo +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Barra de desprazamento - despraza a lista hacia arriba/abaixo +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Amosa-los contornos do terreo no mapa +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Amosa-los vehículos no mapa +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Amosa-las industrias no mapa +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Amosa-las rutas de transporte no mapa +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Amosa-la vexetación no mapa +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Amosa-los propietarios do terreo no mapa +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Amosar/agochar nomes das cidades no mapa +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Beneficio este ano: {CURRENCY} (ano pasado: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} ano ({COMMA16}) +STR_019A_YEARS :{COMMA16} anos ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} anos ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Vehículo de estrada +STR_019D_AIRCRAFT :Avión +STR_019E_SHIP :Barco +STR_019F_TRAIN :Tren +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} estase volvendo vello +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} estase volvendo moi vello +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} estase volvendo moi vello e debe ser substituído urxentemente +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Información dunha área de terreo +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Coste de limpar: {LTBLUE}N/D +STR_01A5_COST_TO_CLEAR :{BLACK}Coste de limpar: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/D +STR_01A7_OWNER :{BLACK}Propietario: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Autoridade local: {LTBLUE}{STRING} +STR_01A9_NONE :Ningún +STR_01AA_NAME :{BLACK}Nome +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1º +STR_01AD_2ND :2º +STR_01AE_3RD :3º +STR_01AF_4TH :4º +STR_01B0_5TH :5º +STR_01B1_6TH :6º +STR_01B2_7TH :7º +STR_01B3_8TH :8º +STR_01B4_9TH :9º +STR_01B5_10TH :10º +STR_01B6_11TH :11º +STR_01B7_12TH :12º +STR_01B8_13TH :13º +STR_01B9_14TH :14º +STR_01BA_15TH :15º +STR_01BB_16TH :16º +STR_01BC_17TH :17º +STR_01BD_18TH :18º +STR_01BE_19TH :19º +STR_01BF_20TH :20º +STR_01C0_21ST :21º +STR_01C1_22ND :22º +STR_01C2_23RD :23º +STR_01C3_24TH :24º +STR_01C4_25TH :25º +STR_01C5_26TH :26º +STR_01C6_27TH :27º +STR_01C7_28TH :28º +STR_01C8_29TH :29º +STR_01C9_30TH :30º +STR_01CA_31ST :31º +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Intercambiar tamaño do mapa grande/pequeno +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Seleccionar Tutorial/Demostración + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Carga aceptada: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Carga aceptada: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Carga aceptada: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Son/música +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Amosa-la fiestra de son/música +STR_01D5_ALL :{TINYFONT}Todo +STR_01D6_OLD_STYLE :{TINYFONT}Vello Estilo +STR_01D7_NEW_STYLE :{TINYFONT}Novo Estilo +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Personal 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Personal 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Volume da Música +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Volume dos Efectos de Son +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MÍN ' ' ' ' ' ' MÁX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Saltar á pista anterior da selección +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Saltar a pista seguinte da selección +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Para-la reproducción de música +STR_01E1_START_PLAYING_MUSIC :{BLACK}Comeza-la reproducción da música +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Arrastra os deslizadores para configura-los volumes da música e dos efectos de son +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Pista{SETX 88}Título +STR_01E9_SHUFFLE :{TINYFONT}Mezclar +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programa +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Selección do Programa de Música +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Índice de Pistas +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programa - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Limpar +STR_01F1_SAVE :{TINYFONT}{BLACK}Grabar +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Programa actual de pistas musicais +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Selecciona-lo programa 'Tódalas pistas' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Selecciona-lo programa 'Música vello estilo' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Selecciona-lo programa 'Música novo estilo' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Selecciona-lo programa 'Personal 1' +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Selecciona-lo programa 'Personal 2' +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Limpa-lo programa actual(Só Personalizado 1 e Personalizado 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Graba-la configuración de música no disco +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Pincha nunha pista de música para engadi-la ó programa actual(Sólo Personal 1 e Personal 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Activar/desactivar programa aleatorio +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostra-la pista musical na fiestra de selección +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Pincha no servicio para centra-la vista na industria/cidade +STR_01FE_DIFFICULTY :{BLACK}Dificultade ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Última mensaxe/noticia +STR_0201_MESSAGE_SETTINGS :Configuración das Mensaxes +STR_MESSAGE_HISTORY_MENU :Historial de Mensaxes +STR_0202_SEND_MESSAGE :Enviar Mensaxe +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Amosa-la última mensaxe/noticia, amosa-las opcións das mensaxes +STR_0204_MESSAGE_OPTIONS :{WHITE}Opcións das mensaxes +STR_0205_MESSAGE_TYPES :{BLACK}Tipos de mensaxes:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Chegada do 1º vehículo a estación do xogador +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Chegada do 1º vehículo a estación dun oponente +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Accidentes / desastres +STR_0209_COMPANY_INFORMATION :{YELLOW}Información da compañía +STR_020A_ECONOMY_CHANGES :{YELLOW}Cambios económicos +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Consellos/información sobre os teus vehículos +STR_020C_NEW_VEHICLES :{YELLOW}Novos vehículos +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Cambios na aceptación de carga +STR_020E_SUBSIDIES :{YELLOW}Subsidios +STR_020F_GENERAL_INFORMATION :{YELLOW}Información xeral +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...Demasiado lonxe do destino anterior +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Mellores compañías que chegaron ó 2050{}(Nivel {STRING}) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Home de negocios +STR_0214_ENTREPRENEUR :Empresario +STR_0215_INDUSTRIALIST :Industrial +STR_0216_CAPITALIST :Capitalista +STR_0217_MAGNATE :Magnate +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Magnate da Centuria +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :¡{BIGFONT}{STRING}{STRING} consegue o status de '{STRING}'! +STR_021C_OF_ACHIEVES_STATUS :¡{BIGFONT}{STRING}{STRING} de {STRING} consigue o status de '{STRING}'! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Crear Escenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Editor de Escenario +STR_0223_LAND_GENERATION :{WHITE}Xeración de Terreo +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Terreo Aleatorio +STR_0227_RESET_LAND :{BLACK}Reiniciar Terreo +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Aumenta-lo tamaño de terreo a baixar/subir +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Disminuí-lo tamaño de terreo a baixar/subir +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Xerar terreo aleatorio +STR_022B_RESET_LANDSCAPE :{BLACK}Reiniciar paisaxe +STR_022C_RESET_LANDSCAPE :{WHITE}Reiniciar paisaxe +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}¿Está seguro de querer reinicia-la paisaxe? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Xeración de paisaxe +STR_022F_TOWN_GENERATION :{BLACK}Xeración de cidades +STR_0230_INDUSTRY_GENERATION :{BLACK}Xeración de industrias +STR_0231_ROAD_CONSTRUCTION :{BLACK}Construcción de estradas +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vexetación e outros obxectos +STR_0233_TOWN_GENERATION :{WHITE}Xeración de Cidades +STR_0234_NEW_TOWN :{BLACK}Nova Cidade +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Construír nova cidade +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Non se pode construí-la cidade aí... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...demasiado cerca do borde do mapa +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...demasiado cerca doutra cidade +STR_0239_SITE_UNSUITABLE :{WHITE}...emprazamento inadecuado +STR_023A_TOO_MANY_TOWNS :{WHITE}...hai demasiadas cidades +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Incrementa-lo tamaño da cidade +STR_023C_EXPAND :{BLACK}Expandir +STR_023D_RANDOM_TOWN :{BLACK}Cidade aleatoria +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}COnstruír cidade en emprazamento aleatorio +STR_023F_INDUSTRY_GENERATION :{WHITE}Xeración de Industrias +STR_0240_COAL_MINE :{BLACK}Mina de Carbón +STR_0241_POWER_STATION :{BLACK}Estación Enerxética +STR_0242_SAWMILL :{BLACK}Serradeiro +STR_0243_FOREST :{BLACK}Bosque +STR_0244_OIL_REFINERY :{BLACK}Ref. de Petróleo +STR_0245_OIL_RIG :{BLACK}Torre Petrolífera +STR_0246_FACTORY :{BLACK}Factoría +STR_0247_STEEL_MILL :{BLACK}Siderúrxica +STR_0248_FARM :{BLACK}Granxa +STR_0249_IRON_ORE_MINE :{BLACK}Mina de Hematita +STR_024A_OIL_WELLS :{BLACK}Pozo Petrolífero +STR_024B_BANK :{BLACK}Banco +STR_024C_PAPER_MILL :{BLACK}Fábrica de Papel +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Planta de Proc. de Comida +STR_024E_PRINTING_WORKS :{BLACK}Imprenta +STR_024F_GOLD_MINE :{BLACK}Mina de Ouro +STR_0250_LUMBER_MILL :{BLACK}Fábrica de Madeiros +STR_0251_FRUIT_PLANTATION :{BLACK}Plantación de Froitas +STR_0252_RUBBER_PLANTATION :{BLACK}Plant. Árbores de Caucho +STR_0253_WATER_SUPPLY :{BLACK}Acuífero +STR_0254_WATER_TOWER :{BLACK}Torre de Auga +STR_0255_DIAMOND_MINE :{BLACK}Mina de Diamantes +STR_0256_COPPER_ORE_MINE :{BLACK}Mina de Mineral de Cobre +STR_0257_COTTON_CANDY_FOREST :{BLACK}Bosque de Algodón de Azucre +STR_0258_CANDY_FACTORY :{BLACK}Fábrica de Caramelos +STR_0259_BATTERY_FARM :{BLACK}Granxa de Baterías +STR_025A_COLA_WELLS :{BLACK}Fontes de Cola +STR_025B_TOY_SHOP :{BLACK}Tenda de Xoguetes +STR_025C_TOY_FACTORY :{BLACK}Fábrica de Xoguetes +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Fontes de Plástico +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Fábrica de Bebidas Gaseosas +STR_025F_BUBBLE_GENERATOR :{BLACK}Xerador de Burbullas +STR_0260_TOFFEE_QUARRY :{BLACK}Canteira de Toffee +STR_0261_SUGAR_MINE :{BLACK}Mina de Azucre +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Construír Mina de Carbón +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Construír Estación Enerxética +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Construír Serradeiro +STR_0265_PLANT_FOREST :{BLACK}Plantar Bosque +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Construír Ref. de Petróleo +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Construí Torre Petrolífera (Só se pode construír cerca dos bordes do mapa) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Construír Factoría +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Construír Siderúrxica +STR_026A_CONSTRUCT_FARM :{BLACK}Construír Granxa +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Construír Mina de Hematita +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Construír Pozo Petrolífero +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construct Banco (Só se pode construír en cidades con máis de 1200 hab.) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Construír Fábrica de Papel +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Construír Planta de Procesamiento de Comida +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Construír Imprenta +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Construír Mina de Ouro +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Construír Banco (Só se pode construír en cidades) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Construír Fábrica de Madeiros (para limpa-los bosques e producir madeiraa) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plantar Plantación de Froitas +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plantar Plant. de Árbores de Caucho +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Construír Acuífero +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Construír Torre de Auga (Só se pode construír en cidades) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Construír Mina de Diamantes +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Construír Mina de Mineral de Cobre +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plantar Bosque de Algodón de Azucre +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Construír Fábrica de Caramelos +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Construír Granxa de Baterías +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Construír Fontes de Cola +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Construír Xoguetería +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Construír Fábrica de Xoguetes +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Construír Fontes de Plástico +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Construír Fábrica de Bebidas Gaseosas +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Construír Xerador de Burbullas +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Construír Canteira de Toffee +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Construír Mina de Azucre +STR_0285_CAN_T_BUILD_HERE :{WHITE}Non se pode construír {STRING} aquí... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...debes construír unha cidade primeiro +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...soamente se permite un/unha por cidade +STR_0288_PLANT_TREES :{BLACK}Plantar árbores +STR_0289_PLACE_SIGN :{BLACK}Colocar sinal +STR_028A_RANDOM_TREES :{BLACK}Árbores aleatorias +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Plantar árbores aleatoriamente sobre a paisaxe +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Colocar áreas rocosas na paisaxe +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Colocar faro +STR_028E_PLACE_TRANSMITTER :{BLACK}Colocar transmisor +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definir área de deserto +STR_0290_DELETE :{BLACK}Borrar +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Borrar completamente esta cidade +STR_0292_SAVE_SCENARIO :Grabar Escenario +STR_0293_LOAD_SCENARIO :Cargar Escenario +STR_0294_QUIT_EDITOR :Saír do editor +STR_0295 : +STR_0296_QUIT :Saír +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Grabar escenario, cargar scenario, abandonar editor de escenarios, saír +STR_0298_LOAD_SCENARIO :{WHITE}Cargar Escenario +STR_0299_SAVE_SCENARIO :{WHITE}Grabar Escenario +STR_029A_PLAY_SCENARIO :{BLACK}Xogar Escenario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}¿Estás seguro de que desexas saír deste escenario? +STR_029C_QUIT_EDITOR :{WHITE}Saír do Editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...só se pode construír en cidades con polo menos 1200 hab. +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Move-lo ano de comezo un ano hacia atrás +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Move-lo ano de comezo un ano hacia adiante +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...os finais da ponte deben estar ambos en terra +STR_02A1_SMALL :{BLACK}Pequeno +STR_02A2_MEDIUM :{BLACK}Mediano +STR_02A3_LARGE :{BLACK}Grande +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Selecciona o tamaño da cidade: +STR_02A5_TOWN_SIZE :{YELLOW}Tamaño da cidade: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Amosa-la última mesaxe ou noticia +STR_02B8_SUMMARY :{BLACK}Sumario +STR_02B9_FULL :{BLACK}Completo +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Directorio de cidades +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Nomes dos deseños dos vehículos +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Defecto +STR_02BF_CUSTOM :Personalizado +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Graba-los nomes personalizados no disco +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Selección de nomes dos deseños dos vehículos +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Graba-los nomes dos deseños dos vehículos personalizados no disco + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Opcións da Partida +STR_02C4_GAME_OPTIONS :Opcións da Partida +STR_02C5_DIFFICULTY_SETTINGS :Configuración de Dificultade +STR_02C6_DIFFICULTY_SETTINGS :Configuración de Dificultade +STR_02C7_CONFIG_PATCHES :Configuración dos Parches +STR_02C8_CONFIG_PATCHES :Configurar parches +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Amosar nomes de cidades +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Amosar nomes de cidades +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Amosar nomes de estacións +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Amosae nomes de estacións +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Amosa-los sinais +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Amosa-los sinais +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Amosar puntos de control +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Amosar puntos de control +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Animacións completas +STR_02D0_FULL_ANIMATION :{SETX 12}Animación completa +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Detalle completo +STR_02D2_FULL_DETAIL :{SETX 12}Detalle completo +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Edificios transparentes +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Edificios transparentes +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Información de área de terreo +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Captura de Pantalla (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Capt.Pant. Xigante (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Acerca de 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}On +STR_02DB_OFF :{BLACK}Off +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Amosa-los subsidios +STR_02DD_SUBSIDIES :Subsidios +STR_02DE_MAP_OF_WORLD :Mapa do Mundo +STR_02DF_TOWN_DIRECTORY :Directorio de cidades +STR_02E0_CURRENCY_UNITS :{BLACK}Unidades monetarias +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Selección de unidades monetarias +STR_02E3_DISTANCE_UNITS :{BLACK}Unidades de medida +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Selección de unidades de medida +STR_02E6_ROAD_VEHICLES :{BLACK}Vehículos de estrada +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Selecciona o lado da estrada polo que rodarán os vehículos +STR_02E9_DRIVE_ON_LEFT :Conducir pola esquerda +STR_02EA_DRIVE_ON_RIGHT :Conducir pola dereita +STR_02EB_TOWN_NAMES :{BLACK}Nomes das cidades +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Selecciona o estilo dos nomes das cidades + +STR_02F4_AUTOSAVE :{BLACK}Autograbado +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Selecciona o intervalo entre autograbados +STR_02F7_OFF :Apagado +STR_02F8_EVERY_3_MONTHS :Cada 3 meses +STR_02F9_EVERY_6_MONTHS :Cada 6 meses +STR_02FA_EVERY_12_MONTHS :Cada 12 meses +STR_02FB_START_A_NEW_GAME :{BLACK}Comezar nova partida +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Cargar unha partida do disco +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Ver demostracións/tutoriais +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Crear un mundo/escenario personalizado +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Partida para un Xogador +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Partida para dous xogadores +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Amosa-las opcións do xogo +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Amosa-las opcións de dificultade +STR_0303_START_A_NEW_GAME_USING :{BLACK}Comezar unha nova partida, usando un escenario personalizado +STR_0304_QUIT :{BLACK}Saír +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Deixar 'OpenTTD', e saír +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Ver demostración/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...só se pode construír en cidades +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Selecciona-lo estilo da paisaxe 'Templado' +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Selecciona-lo estilo da paisaxe 'Subártico' +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Selecciona-lo estilo da paisaxe 'Subtropical' +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Selecciona-lo estilo da paisaxe 'Xoguetelandia' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Fundar unha nova industria + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Fundar unha nova industria +STR_INDUSTRY_DIR :Directorio de Industrias +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Fundar unha nova industria +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...só se pode construír en cidades +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...só se pode construír en zonas de selva tropical +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...só se pode construír en zonas desérticas +STR_0319_PAUSED :{YELLOW}* * EN PAUSA * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Captura de pantalla grabada con éxito no disco como '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}¡Captura de pantalla fallida! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Comprar terreo para futuro uso +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Servicio a vehículo de estrada +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Servicio a ferrocarril +STR_032C_3_AIR_SERVICE :{BLACK}3: Servicio a avión +STR_032D_4_SHIP_SERVICE :{BLACK}4: Servicio a barco +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Servicio a ferrocarril (avanzado) +STR_032F_AUTOSAVE :{RED}AUTOGUARDADO +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Selecciona-lo programa 'Música Estilo Ezy Street' + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Inglés +STR_TOWNNAME_FRENCH :Francés +STR_TOWNNAME_GERMAN :Alemán +STR_TOWNNAME_AMERICAN :Americano +STR_TOWNNAME_LATIN_AMERICAN :Latino-Americano +STR_TOWNNAME_SILLY :Estúpido +STR_TOWNNAME_SWEDISH :Sueco +STR_TOWNNAME_DUTCH :Holandés +STR_TOWNNAME_FINNISH :Finés +STR_TOWNNAME_POLISH :Polaco +STR_TOWNNAME_SLOVAKISH :Eslovaco +STR_TOWNNAME_HUNGARIAN :Húngaro +STR_TOWNNAME_AUSTRIAN :Austríaco +############ end of townname region + +STR_CURR_POUNDS :Libra ({POUNDSIGN}) +STR_CURR_DOLLARS :Dólar ($) +STR_CURR_FF :Franco (FF) +STR_CURR_DM :Marco alemán (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseta (Pt) +STR_CURR_FT :Forint Húngaro (Ft) +STR_CURR_ZL :Zloty Polaco (zl) +STR_CURR_ATS :Chelín Austríaco (ATS) +STR_CURR_BEF :Franco Belga (BEF) +STR_CURR_DKK :Corona Danesa (DKK) +STR_CURR_FIM :Marco Finés (FIM) +STR_CURR_GRD :Dracma Grego (GRD) +STR_CURR_CHF :Franco Suizo (CHF) +STR_CURR_NLG :Florín Holandés (NLG) +STR_CURR_ITL :Lira Italiana (ITL) +STR_CURR_SEK :Corona Sueca(SEK) +STR_CURR_RUR :Rublo Ruso (rur) +STR_CURR_CZK :Corona Checa (CZK) +STR_CURR_ISK :Corona Islandesa (ISK) +STR_CURR_NOK :Corona Noruguesa (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Idioma +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Selecciona o idioma para utilizar na interface + +STR_OPTIONS_RES :{BLACK}Resolución da pantalla +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Selecciona a resolución de pantalla a utilizar + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Formato capturas de pantalla +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Selecciona o formato a utilizar nas capturas de pantalla + +STR_AUTOSAVE_1_MONTH :Cada mes +STR_AUTOSAVE_FAILED :{WHITE}Autograbado fallido + +STR_MONTH_JAN :Xaneiro +STR_MONTH_FEB :Febreiro +STR_MONTH_MAR :Marzo +STR_MONTH_APR :Abril +STR_MONTH_MAY :Maio +STR_MONTH_JUN :Xuño +STR_MONTH_JUL :Xullo +STR_MONTH_AUG :Agosto +STR_MONTH_SEP :Setembro +STR_MONTH_OCT :Outubro +STR_MONTH_NOV :Novembro +STR_MONTH_DEC :Decembro + +STR_HEADING_FOR_STATION :{LTBLUE}Diríxese a {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Diríxese a {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Sen ordes +STR_NO_ORDERS_VEL :{LTBLUE}Sen ordes, {VELOCITY} + +STR_PASSENGERS :pasaxeiros +STR_BAGS :sacos +STR_TONS :tons +STR_LITERS :litros +STR_ITEMS :items +STR_CRATES :caixóns +STR_RES_OTHER :outro +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Non se pode comparti-la lista de ordes... +STR_CANT_COPY_ORDER_LIST :{WHITE}Non se pode copia-la lista de ordes... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Fin das ordes compartidas - - + +STR_TRAIN_IS_LOST :{WHITE}Perdiches o tren {COMMA16}. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}O beneficio para o tren {COMMA16} o ano pasado foi de {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Configuración dos Parches +STR_CONFIG_PATCHES_TIP :{BLACK}Configura-los parches +STR_CONFIG_PATCHES_CAPTION :{WHITE}Configuración dos Parches + +STR_CONFIG_PATCHES_OFF :Off +STR_CONFIG_PATCHES_ON :On +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Mostra-la velocidade do vehículo na barra de estado: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Permiti-la construción en rampas e costas: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Permiti-la eliminación de máis estradas, etc... das cidades: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Permiti-la construcción de trens moi largos: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Habilita-la aceleración realista nos trens: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Xunta-las estacións construídas xuntas: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Saír se calquera carga está chea,cando 'Carga chea': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflación: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Desactiva-lo servicio automático nos trens: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Descarga-la carga só cando haxa demanda: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Permiti-la construcción de pontes moi longas: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Permiti-las ordes de ir ó depósito: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Permiti-la construccion de industrias de materiales: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Permitir múltiples industrias similares en cada cidade: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Permiti-la construcción de industrias iguais cercanas: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Mostrar sempre a data longa na barra de estado: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Mostrar sinais no lado de conducción: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Mostra-la fiestra de finanzas ó final do ano: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}Manexo de nonstop compatible con TTDPatch: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Cola para vehículos de estrada (con efectos cuánticos): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Desplaza-la fiestra cando o ratón esté no borde: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Permiti-la chantaxe as autoridades locales: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Novo sistema para atopar depósito: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Estacións non uniformes: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Novo algoritmo para atopa-las rutas para os trens: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Permiti-la construcción en modo pausa: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Permitir sempre aeroportos pequenos: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Un tren está perdido se non progresa durante:: {ORANGE}{STRING} días +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Advertir se os ingresos dun tren son negativos: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES :{LTBLUE}Os vehículos nunca caducan: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Autorenova-los vehículos cando envellezan +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Duración das mensaxes de error: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Altura da liña de neve: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Máximo tamaño da estación: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Face-lo servicio os helicópteros no heliporto automáticam.: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Nº máximo de trens por xogador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Nº máximo de vehículos de estrada por xogador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Nº máximo de avións por xogador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Nº máximo de barcos por xogador: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Deshabilita-los trens para o ordenador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Deshabilita-los vehículos de estrada para o ordenador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Deshabilita-los avións para o ordenador: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Deshabilita-los barcos para o ordenador: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Intervalo de servicio para os trens: {ORANGE}{STRING} días +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Intervalo de servicio para os vehículos de estrada: {ORANGE}{STRING} días +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Intervalo de servicio para os avións: {ORANGE}{STRING} días +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Intervalo de servicio para os barcos: {ORANGE}{STRING} días + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Data de aparición das noticias en color: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Data de comezo: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Habilita-la economía "suave"(máis cambios, pero máis pequenos) + +STR_CONFIG_PATCHES_GUI :{BLACK}Interface +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construcción +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Vehículos +STR_CONFIG_PATCHES_STATIONS :{BLACK}Estacións +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Economía + +STR_CONFIG_PATCHES_DISABLED :deshabilitado +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Cambia-lo valor + + +STR_CHEATS :{WHITE}Trampas +STR_CHEATS_TIP :{BLACK}As caixas de confirmación indican se usaches esta trampa antes +STR_CHEATS_WARNING :{BLACK}¡Advertencia! Estás a piques de traizoa-los teus oponentes. Ten en conta que unha desgracia coma esta se lembrará eternamente. +STR_CHEAT_MONEY :{LTBLUE}Incrementa-lo diñeiro en {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Xogar coma xogador: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Escavadora máxica(Elimina industrias, non eliminables): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Os tuneis poden cruzarse entre eles: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Nome +STR_TOWNDIR_POPULATION :{BLACK}Poboación +STR_TOWNDIR_SORT_TIP :{BLACK}Selecciona o modo de ordenación + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Diríxese a {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Diríxese a {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Ir vía {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Punto de Control {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Punto de control {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Punto de control + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Edita-lo nome do punto de control + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Non se pode cambia-lo nome do punto de control... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Convertir raíl a punto de control +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Non se pode construír un punto de control de tren aí... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Non se pode eliminar-lo punto de control... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Construí-la vía de ferrocarril usando o modo Autoraíl + +STR_NO_TOWN_IN_SCENARIO :{WHITE}...non hai cidades neste escenario + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}¿Estás seguro de querer crear unha paizsaxe aleatoria? +STR_MANY_RANDOM_TOWNS :{BLACK}Varias cidades aleatorias +STR_RANDOM_TOWNS_TIP :{BLACK}Cubri-lo mapa con cidades colocadas aleatoriamente +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Varias industrias aleatorias +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Cubri-lo mapa con industrias colocadas aleatoriamente +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Non se poden xera-las industrias... + +STR_LANDSCAPING_TOOLBAR :{WHITE}Modifica-lo terreo +STR_LEVEL_LAND_TOOLTIP :{BLACK}Nivelar terreo + + +STR_TREES_RANDOM_TYPE :{BLACK}Árbores aleatorias +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Colocar árbores dun tipo aleatorio + +STR_CANT_BUILD_CANALS :{WHITE}Non se pode construí-los canais aí... +STR_BUILD_CANALS_TIP :{BLACK}Construír canais +STR_LANDINFO_CANAL :Canal + +STR_CANT_BUILD_LOCKS :{WHITE}Non se pode construí-lo peche aí... +STR_BUILD_LOCKS_TIP :{BLACK}Construír peches +STR_LANDINFO_LOCK :Peche + +STR_LANDINFO_COORDS :{BLACK}Coordenadas: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Non se pode eliminar parte da estación... +STR_CANT_CONVERT_RAIL :{WHITE}Non se pode converti-lo tipo de vía aí... +STR_CONVERT_RAIL_TIP :{BLACK}Convertir/actualizar tipo de vía + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Arrastra a máquina do tren aquí para vender todo o tren + +STR_DRAG_DROP :{BLACK}Arrastrar e Soltar +STR_STATION_DRAG_DROP :{BLACK}Construír estación arrastrando e soltando + +STR_FAST_FORWARD :{BLACK}Avance rápido da partida +STR_MESSAGE_HISTORY :{WHITE}Historial de Mensaxes +STR_MESSAGE_HISTORY_TIP :{BLACK}Unha lista das mensaxes e noticias recentes +STR_MESSAGES_DISABLE_ALL :{BLACK}Desactivar todo +STR_MESSAGES_ENABLE_ALL :{BLACK}Activar todo + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Construír Mina de Carbón +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plantar Bosque +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Construír Torre Petrolífera +STR_CONSTRUCT_FARM_TIP :{BLACK}Fundar granxa +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Construír Mina de Mineral de Cobre +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Perforar para buscar Petróleo +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Construír Mina de Ouro +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Construír Mina de Diamantes +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Construír Mina de Hematita +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Fundar Plantación de Froita +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Fundar Plant. de Árbores de Caucho +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Fundar Acuífero +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plantar Bosque de Algodón de Azucre +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Fundar Granxa de Baterías +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Perforar para buscar Cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Fundar Fontes de Plástico +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Construír Xerador de Burbullas +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Fundar Canteira de Toffee +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Construír Mina de Azucre + +STR_INDUSTRYDIR_NAME :{BLACK}Nome +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Producción +STR_INDUSTRYDIR_TYPE :{BLACK}Tipo +STR_INDUSTRYDIR_TRANSPORTED :{BLACK}Transportado +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrias +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}){YELLOW} ({COMMA16}% transportado) +STR_INDUSTRYDIR_ITEM_TWO :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}/{STRING}){YELLOW} ({COMMA16}%/{COMMA16}% transportado) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN}: {STRING} +STR_INDUSTRY_TOO_CLOSE :{WHITE}...demasiado cerca doutra industria + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Reaxusta-lo tren para un tipo de carga diferente +STR_RAIL_REFIT :{WHITE}{STRING} (Reauxstar) +STR_RAIL_REFIT_VEHICLE :{BLACK}Reaxustar tren +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Selecciona o tipo de carga que levará o tren +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Reaxusta-lo tren para o tipo de carga seleccionado +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}No se pode reaxusta-lo tren... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}¡A interface de rede todavía non funciona! + +STR_NETWORK_MULTIPLAYER :{WHITE}Multixogador + +STR_NETWORK_FIND_SERVER :{BLACK}Buscar servidor +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Buscar un servidor na rede +STR_NETWORK_DIRECT_CONNECT :{BLACK}Conexión directa +STR_NETWORK_ENTER_IP :{BLACK}Introduce a dirección IP do servidor +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Conectar cunha dirección IP coñecida +STR_NETWORK_START_SERVER :{BLACK}Iniciar servidor +STR_NETWORK_START_SERVER_TIP :{BLACK}Comezar un servidor propio + +STR_NETWORK_PLAYER_NAME :{BLACK}Nome do xogador: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}Este é o nome polo que te identificarán os outros xogadores + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Selecciona o tipo de conexión: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Escoller entre unha partida na Internet ou na rede de área local +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Nome +STR_NETWORK_GAME_NAME_TIP :{BLACK}Nome da partida +STR_NETWORK_PLAYERS :{BLACK}#/# +STR_NETWORK_PLAYERS_TIP :{BLACK}Xogadores na partida / Número máximo de xogadores +STR_NETWORK_MAP_SIZE :{BLACK}Tamaño +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Tamaño do mapa +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Idioma, versión do servidor, etc. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Pincha nunha partida da lista para seleccionala + +STR_NETWORK_JOIN_GAME :{BLACK}Unirse á partida + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Comezar nova partida + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Nome: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}O nome da partida mostraráse ó outros xogadores no menú de selección de partida multixogador +STR_NETWORK_PASSWORD :{BLACK}Contrasinal: +STR_NETWORK_PASSWORD_TIP :{BLACK}Protexe a túa partida cun contrasinal se non queres que outras persoas se unan +STR_NETWORK_SELECT_MAP :{BLACK}Selecciona un mapa: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}¿Que mapa queres xogar? +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Número de xogadores: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Selecciona o número máximo de xogadores. Non é necesario encher tódalas ranuras. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 xogadores +STR_NETWORK_3_PLAYERS :{BLACK}3 xogadores +STR_NETWORK_4_PLAYERS :{BLACK}4 xogadores +STR_NETWORK_5_PLAYERS :{BLACK}5 xogadores +STR_NETWORK_6_PLAYERS :{BLACK}6 xogadores +STR_NETWORK_7_PLAYERS :{BLACK}7 xogadores +STR_NETWORK_8_PLAYERS :{BLACK}8 xogadores +STR_NETWORK_START_GAME :{BLACK}Iniciar Partida + + +STR_NETWORK_GAME_LOBBY :{WHITE}Sala de espera de partida multixogador + +STR_NETWORK_SEND :{BLACK}Enviar +STR_NETWORK_SEND_TIP :{BLACK}Enviar unha mensaxe ós outros xogadores +STR_NETWORK_COMPANY_NAME :{BLACK}Nome da compañía: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Cambia o nome da túa compañía. Presino Enter para aplica-los cambios +STR_NETWORK_SPECTATE_GAME :{BLACK}Observar partida +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Observa-la partida coma espectador +STR_NETWORK_NEW_COMPANY :{BLACK}Nova compañía +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Abrir unha nova compañía +STR_NETWORK_READY :{BLACK}Preparado + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Coste: {CURRENCY} +STR_0801_COST :{RED}Coste: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Ingreso: {CURRENCY} +STR_0803_INCOME :{GREEN}Ingreso: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Coste Estimado: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Estimated Coste: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Ingreso Estimado: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Ingreso Estimado: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Non se pode subi-lo terreo aí... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Non se pode baixa-lo terreo aí... +STR_080A_ROCKS :Rochas +STR_080B_ROUGH_LAND :Terra Quebrada +STR_080C_BARE_LAND :Terra Deserta +STR_080D_GRASS :Herba +STR_080E_FIELDS :Campos +STR_080F_SNOW_COVERED_LAND :Terra cuberta de neve +STR_0810_DESERT :Deserto + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreo inclinado na direccion incorrecta +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Combinación de pistas imposible +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}A excavación danaría un tunel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Xa está a nivel do mar +STR_1004_TOO_HIGH :{WHITE}Demasiado alto +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Non hay vía de ferrocarril adecuada +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Hai un tren no depósito +STR_1007_ALREADY_BUILT :{WHITE}...xa está construído +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Debes elimina-la pistad e ferrocarril primeiro +STR_1009_TOO_MANY_DEPOTS :{WHITE}Hai demasiados depósitos +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Construcción de Ferrocarrís +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Construcción de Monorraíl +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Construcción de MagLev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Selecciona a Ponte do Ferrocarril +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Non se pode construír un depósito aí... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Non se pode construí-la estación de ferrorcarril aí... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Non se poden construí-los sinais aí... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Non se pode construí-la pista do ferrocarril aí... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Non se pode elimina-la pista de ferrocarril de aí... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Non se pode elimina-los sinais de aí... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Orient. do Dep. de Trens +STR_1015_RAILROAD_CONSTRUCTION :Construcción de Ferrocarrís +STR_1016_MONORAIL_CONSTRUCTION :Construcción de Monorraíl +STR_1017_MAGLEV_CONSTRUCTION :Construcción de MagLev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Construír vía de ferrocarril +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Construír depósito de trens (para construír e dar servicio os trens) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Construír estación de ferrocarril +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Construír sinais de ferrocaril +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Construír ponte de ferrocaril +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Construír túnel de ferocarril +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Intecambiar construír/eliminar para vías e sinais de ferrocarril +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Selección de pontes - picha na ponte seleccionada para construíla +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Selecciona-la orientación do depósito de ferrocarrís +STR_1021_RAILROAD_TRACK :Vía de ferrocarril +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Vía de ferrocarril con sinais +STR_1023_RAILROAD_TRAIN_DEPOT :Depósito para trens +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...a área é propiedade doutra compañía +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Vía de ferrocarril con sinais normais +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Vía de ferrocarril con pre-sinais +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :vía de ferrocarril con sinais de saída +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Via de ferrocarril con sinais combinados + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreo inclinado na direccion incorrecta para a estrada +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Debes elimina-la estrada primeiro +STR_1802_ROAD_CONSTRUCTION :{WHITE}Construcción de Estradas +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Selecciona a Ponte +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Non se pode construí-la estrada aí... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Non se pode elimina-la estrada aí... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orient. do Depósito +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Non se pode construí-lo depósito aí... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Non se pode construí-la estación de autobús... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Non se pode construí-la estacion de camións... +STR_180A_ROAD_CONSTRUCTION :Construcción de Estrada +STR_180B_BUILD_ROAD_SECTION :{BLACK}Construír unha sección de estrada +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Construír depósito de vehículos de estrada (para construír e dar servicio os vehículos de estrada) +STR_180D_BUILD_BUS_STATION :{BLACK}Construír estación de autobús +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Construír bahía de carga de camións +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Construír ponte de estrada +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Construír túnel de estrada +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Intecambiar construír/eliminar para construír estradas +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Selección de pontes - picha na ponte seleccionada para construíla +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Seleciona-la orientación do depósito de vehículos de estrada +STR_1814_ROAD :Estrada +STR_1815_ROAD_WITH_STREETLIGHTS :Estrada con iluminación +STR_1816_TREE_LINED_ROAD :Estrada con árbores +STR_1817_ROAD_VEHICLE_DEPOT :Depósito de vehículos de estrada +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Paso a nivel para estrada/ferrocarril + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Cidades +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Debes demole-lo edificio primeiro +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Poboación: {ORANGE}{COMMA32}{BLACK} Casas: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Renomear cidade +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Non se pode renomea-la cidade... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN}: a autoridade local négase a permitilo +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Nomes de cidades - pincha no nome para centra-la vista principal na cidade +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centra-la vista principal na situación da cidade +STR_200C_CHANGE_TOWN_NAME :{BLACK}Cambia-lo nome da cidade +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasaxeiros último mes: {ORANGE}{COMMA16}{BLACK} máx: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Correo último mes: {ORANGE}{COMMA16}{BLACK} máx: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Bloque alto de oficinas +STR_2010_OFFICE_BLOCK :Bloque de oficinas +STR_2011_SMALL_BLOCK_OF_FLATS :Bloque pequeno de apartamentos +STR_2012_CHURCH :Igrexa +STR_2013_LARGE_OFFICE_BLOCK :Bloque grande de oficinas +STR_2014_TOWN_HOUSES :Casas de cidade +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Estatua +STR_2017_FOUNTAIN :Fonte +STR_2018_PARK :Parque +STR_2019_OFFICE_BLOCK :Bloque de Oficinas +STR_201A_SHOPS_AND_OFFICES :Tendas e oficinas +STR_201B_MODERN_OFFICE_BUILDING :Edifcio moderno de oficinas +STR_201C_WAREHOUSE :Almacén +STR_201D_OFFICE_BLOCK :Bloque de oficinas +STR_201E_STADIUM :Estadio +STR_201F_OLD_HOUSES :Casas antigas +STR_2020_LOCAL_AUTHORITY :{BLACK}Aut. Local +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Mostra-la información sobre a autoridade local +STR_2022_LOCAL_AUTHORITY :{WHITE}Autoridade local de {TOWN} +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Puntuacións das compañías de transporte: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subsidios +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Sibsidios en oferta para sevicios que transporten: +STR_2027_FROM_TO :{ORANGE}{STRING} dende {STRING} ata {STRING} +STR_2028_BY :{YELLOW} (antes de {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Ningún +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Servicios que xa teñen subsidio: +STR_202C_FROM_TO :{ORANGE}{STRING} dende {STATION} ata {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, ata {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Oferta de subsidio esgotada:{}{}{STRING} dende {STRING} ata {STRING} non será subsidiada. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subsidio retirado:{}{}O servicio de transporte de {STRING} dende {STATION} ata {STATION} xa non ten subsidio. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}¡Oferta de subsidio:{}{}O primeiro servicio de transporte de {STRING} dende {STRING} ata {STRING} será subsidiado pola autoridade local! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}¡Subsidio concedido a {STRING}!{}{}Polo servicio de transporte de {STRING} dende {STATION} ata {STATION} pagarase un 50% máis durante o próximo ano! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}¡Subsidio concedido a {STRING}!{}{}Polo servicio de transporte de {STRING} dende {STATION} ata {STATION} pagarase o dobre durante o próximo ano! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}¡Subsidio concedido a {STRING}!{}{}Polo servicio de transporte de {STRING} dende {STATION} ata {STATION} pagarase o triple durante o próximo ano! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}¡Subsidio concedido a {STRING}!{}{}Polo servicio de transporte de {STRING} dende {STATION} ata {STATION} pagarase o cuádruple durante o próximo ano! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}A autoridade local de {TOWN} négase a permiti-la construcción doutro aeroporto +STR_2036_COTTAGES :Casiñas de campo +STR_2037_HOUSES :Casas +STR_2038_FLATS :Apartamentos +STR_2039_TALL_OFFICE_BLOCK :Bloque alto de oficinas +STR_203A_SHOPS_AND_OFFICES :Tendas e oficinas +STR_203B_SHOPS_AND_OFFICES :Tendas e oficinas +STR_203C_THEATER :Teatro +STR_203D_STADIUM :Estadio +STR_203E_OFFICES :Oficinas +STR_203F_HOUSES :Casas +STR_2040_CINEMA :Cine +STR_2041_SHOPPING_MALL :Centro comercial +STR_2042_DO_IT :{BLACK}Faino +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Lista de cousas para facer nesta cidade - pincha nun item para máis detalles +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Executa-la acción marcada na lista superior +STR_2045_ACTIONS_AVAILABLE :{BLACK}Accións dispoñibles: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Campaña publicitaria pequena +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Campaña publicitaria mediana +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Gan campaña publicitaria +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Subvenciona-la reconstrucción das estradas da cidade +STR_204A_BUILD_STATUE_OF_COMPANY :Construír unha estatua do propietario da compañía +STR_204B_FUND_NEW_BUILDINGS :Subvencionar novos edificios +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Compra-los dereitos de transporte exclusivos +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Soborna-la autoridade local +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciar unha campaña de publicidade pequena, para atraer máis pasaxeiros e mercadorías os teus servicios de transporte.{} Coste: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciar unha campaña de publicidade mediana, para atraer máis pasaxeiros e mercadorías os teus servicios de transporte.{} Coste: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Iniciar unha gran campaña de publicidade, para atraer máis pasaxeiros e mercadorías os teus servicios de transporte.{} Coste: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Subvenciona-la reconstrucción da rede de estradas urbanas. Provoca unha considerable interrupción no tráfico durante seis meses.{} Coste: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Construír unha estatua en honor a túa compañía.{} Coste: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Subvencina-la construcción de novos edificios comerciais na cidade.{} Coste: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Compra-los dereitos exclusivos de transporte na cidade durante 1 ano. A autoridade só permitirá que os pasaxeiros e as mercadorías usen as estacións da túa compañía.{} Coste: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Suborna-la autoridade local para mellora-la túa puntuación, co risco dunha gran penalización se o descobren.{} Cost: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Non podes facer isto... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}¡Caos no tráfico de {TOWN}!{}{}¡O programa de reconstrucción das estradas subvencionado por {STRING} trae 6 meses de miseria para os motoristas! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (en construcción) +STR_2059_IGLOO :Iglú +STR_205A_TEPEES :Tipis +STR_205B_TEAPOT_HOUSE :Casa Tetera +STR_205C_PIGGY_BANK :Banco Porquiño + +##id 0x2800 +STR_LANDSCAPING :Modifica-lo terreo +STR_2800_PLANT_TREES :Plantar árbores +STR_2801_PLACE_SIGN :Colocar sinal +STR_2802_TREES :{WHITE}Árbores +STR_2803_TREE_ALREADY_HERE :{WHITE}...Xa hai unha árbore aí +STR_2804_SITE_UNSUITABLE :{WHITE}...emprazamento inadecuado +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Non se pode plantar unha árbore aí... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...demasiados sinais +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Non se pode situa-lo sinal aí... +STR_280A_SIGN :Sinal +STR_280B_EDIT_SIGN_TEXT :{WHITE}Edita lo texto do sinal +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Non se pode cambia-lo nome do sinal... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Selecciona-lo tipo de árbore a plantar +STR_280E_TREES :Árbores +STR_280F_RAINFOREST :Selva tropical +STR_2810_CACTUS_PLANTS :Plantas cactus + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Config. da Estación +STR_3001_AIRPORT_SELECTION :{WHITE}Selección de aeroporto +STR_3002_ORIENTATION :{BLACK}Orientación +STR_3003_NUMBER_OF_TRACKS :{BLACK}Lonxitude da plataforma +STR_3004_PLATFORM_LENGTH :{BLACK}Número de vías +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Demasiado cerca doutra estación de ferrocarril +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Xunta máis dunha estación/área de carga existente +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Hay demasiadas estacións/áreas de carga nesta cidade +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Hay demasiadas estacións/áreas de carga +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Demasiado cerca doutra estación ou área de carga +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Debes demole-la estación de ferrocarril primeiro +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Demasiado cerca doutro aeroporto +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Debes demole-lo aeroporto primeiro + +STR_3030_RENAME_STATION_LOADING :Renomear estación/área de carga +STR_3031_CAN_T_RENAME_STATION :{WHITE}Non se pode renomea-la estación... +STR_3032_RATINGS :{BLACK}Puntuacións: +STR_3033_ACCEPTS :{BLACK}Acepta +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Puntuación local para o servicio de transporte: + +############ range for rating starts +STR_3035_APPALLING :Pésima +STR_3036_VERY_POOR :Moi Pobre +STR_3037_POOR :Pobre +STR_3038_MEDIOCRE :Mediocre +STR_3039_GOOD :Boa +STR_303A_VERY_GOOD :Moi Boa +STR_303B_EXCELLENT :Excelente +STR_303C_OUTSTANDING :Excepcional +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} xa non acepta {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} xa non acepta {STRING} ou {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} agora acepta {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} agora acepta {STRING} e {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Orientación da Estación +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Orientación da Estación +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Demasiado cerca doutra estación de autobús +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Demasiado cerca doutra estación de camións +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Debes demole-la estación de autobús primeiro +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Debes demole-la estación de camións primeiro +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Estacións +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Ningún - +STR_304B_SITE_UNSUITABLE :{WHITE}...emprazamento inadecuado +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Demasiado cerca doutro peirao +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Debes demole-lo peirao primeiro +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Selecciona-la orientación da estación de ferrocarril +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Selecciona-lo número de platafomas da estación de ferrocarrilrailroad station +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Selecciona-la lonxitude da estación de ferrocarril +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Selecciona-la orientación da estación de autobús +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Selecciona-la orientación da bahía de carga de camións +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centra-la vista principal na situación da estación +STR_3054_SHOW_STATION_RATINGS :{BLACK}Mostra-las puntuacións da estación +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Cambia-lo nome da estación +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Mostra-la lista da carga aceptada +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Nomes das estacións - pinga nun nome para centra-la vista principal na estación +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Selecciona o tamaño/tipo de aeroporto +STR_3059_SMALL :{BLACK}Pequeno +STR_305A_LARGE :{BLACK}Grande +STR_305AA_LARGE :{BLACK}Aeroporto Metropolitano +STR_305AB_LARGE :{BLACK}Aeroporto Internacional +STR_305B_SIZE :{BLACK}Tamaño +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Estación de ferrocarril +STR_305F_AIRCRAFT_HANGAR :Hangar de avións +STR_3060_AIRPORT :Aeroporto +STR_3061_TRUCK_LOADING_AREA :Área de carga de camións +STR_3062_BUS_STATION :Estación de autobús +STR_3063_SHIP_DOCK :Peirao para barco +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Resalta-la área de cobertura do sitio proposto +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Non resalta-la área de cobertura do sitio proposto +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Resaltar área de cobertura +STR_3067_MONORAIL_STATION_SELECT :{WHITE}selecciona-la Estación de Monoraíl +STR_3068_DOCK :{WHITE}Peirao +STR_3069_BUOY :Boia +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boia no camiño +STR_306B_HELIPORT :{BLACK}"Heliporto" +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...a estación ocupa demasiado + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orient. do Depósito de Barcos +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...debes construí-lo na auga +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Non se pode construí-lo depósito de barcos aí... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Selecciona-la orientación do depósito de barcos +STR_3804_WATER :Auga +STR_3805_COAST_OR_RIVERBANK :Costa ou beiramar +STR_3806_SHIP_DEPOT :Depósito de barcos +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Non se pode construír na auga + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Grabar Partida +STR_4001_LOAD_GAME :{WHITE}Cargar Partida +STR_4002_SAVE :{BLACK}Grabar +STR_4003_DELETE :{BLACK}Borrar +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes libres +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}No se pode lee-la unidade +STR_4007_GAME_SAVE_FAILED :{WHITE}Grabación da partida fallida +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Non se pode borra-lo arquivo +STR_4009_GAME_LOAD_FAILED :{WHITE}Carga da partida fallida +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Lista de unidades, directorios e arquivos de partida +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Nome seleccionado actualmente para o arquivo +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Borra-lo arquivo que está seleccionado +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Salva-la partida actual, usando o nome seleccionado +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Selecciona o tipo de partida a empezar +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Selecciona escenario(verde), partida pre-consigurada (azul), ou partida aleatoria +STR_4010_GENERATE_RANDOM_NEW_GAME :Xerar unha nova partida aleatoriamente + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} en camiño +STR_4801 :{WHITE}{TOWN}: {STRING} +STR_4802_COAL_MINE :Mina de Carbón +STR_4803_POWER_STATION :Estación Enerxética +STR_4804_SAWMILL :Serradeiro +STR_4805_FOREST :Bosque +STR_4806_OIL_REFINERY :Ref. de Petróleo +STR_4807_OIL_RIG :Torre Petrolífera +STR_4808_FACTORY :Factoría +STR_4809_PRINTING_WORKS :Imprenta +STR_480A_STEEL_MILL :Siderúrxica +STR_480B_FARM :Granxa +STR_480C_COPPER_ORE_MINE :Mina de Mineral de Cobre +STR_480D_OIL_WELLS :Pozo Petrolífero +STR_480E_BANK :Banco +STR_480F_FOOD_PROCESSING_PLANT :Planta de Proc. de Comida +STR_4810_PAPER_MILL :Fábrica de Papel +STR_4811_GOLD_MINE :Mina de Ouro +STR_4812_BANK :Banco +STR_4813_DIAMOND_MINE :Mina de Diamantes +STR_4814_IRON_ORE_MINE :Mina de Hematita +STR_4815_FRUIT_PLANTATION :Plantación de Froita +STR_4816_RUBBER_PLANTATION :Plant. de Árbores de Caucho +STR_4817_WATER_SUPPLY :Acuífero +STR_4818_WATER_TOWER :Torre de Auga +STR_4819_FACTORY :Factoría +STR_481A_FARM :Granxa +STR_481B_LUMBER_MILL :Frábrica de Madeiros +STR_481C_COTTON_CANDY_FOREST :Bosque de Algodón de Azucre +STR_481D_CANDY_FACTORY :Fábrica de Caramelos +STR_481E_BATTERY_FARM :Granxa de Baterías +STR_481F_COLA_WELLS :Fontes de Cola +STR_4820_TOY_SHOP :Xoguetería +STR_4821_TOY_FACTORY :Fábrica de Xoguetes +STR_4822_PLASTIC_FOUNTAINS :Fontes de Plástico +STR_4823_FIZZY_DRINK_FACTORY :Fábrica de Bebidas Gaseosas +STR_4824_BUBBLE_GENERATOR :Xerador de Burbullas +STR_4825_TOFFEE_QUARRY :Canteira de Toffee +STR_4826_SUGAR_MINE :Mina de Azucre + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Require: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Require: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Require: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Producción no último mes: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transportado) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centra-la vista principal na situación da industria +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}¡Nova {STRING} en construcción cerca de {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}¡Nova {STRING} cerca de {TOWN}! +STR_482F_COST :{BLACK}Coste: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Non se pode construír ese tipo de industria aí... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...o bosqur só se pode plantar sobre a liña de neve +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}¡{TOWN}: {STRING} anuncia o seu peche inminente! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}¡{TOWN}:Problemas de sumunistro levan a {STRING} anuncia-lo peche inminente! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}¡{TOWN}: A falta de árbores cercanas provoca que {STRING} anuncie o seu peche inminente! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}¡{TOWN}: {STRING} incrementa a producción! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}¡{TOWN}: Nova veta de carbón atopada na {STRING}!{}¡Agárdase que a producción dóbrese! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}¡{TOWN}: Novas reservas de petróleo atopadas na {STRING}!{}¡Agárdase que a producción dóbrese! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}¡{TOWN}: Agárdase que os novos métodos de cultivo doblen a producción na {STRING}! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}¡{TOWN}: A producción de {STRING} redúcese nun 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}¡{TOWN}: Unha infestación de insectos causa desastre na {STRING}!{}A producción redúcese nun 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...só se pode emprazar cerca dos bordes do mapa +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}A producción de {STRING} en {TOWN} {STRING} sube un {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}A producción de {STRING} en {TOWN} {STRING} baixa un {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Hai un tren no túnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}HAi un vehículo de estrada no túnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Hai outro túnel no camiño +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Non se pode excava-lo terreo no outro lado do túnel +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Debes demole-lo túnel primeiro +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Debes demole-la ponte primeiro +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Non pode empezar e rematar na mesma posición +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Necesítase terreo nivelado ou auga baixo a ponte +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}O inicio e o final deben estar aliñados +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Emprazamento inadecuado para a entrada do túnel +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Colgante, Aceiro +STR_500F_GIRDER_STEEL :Vigas, Aceiro +STR_5010_CANTILEVER_STEEL :Voladizo, Aceiro +STR_5011_SUSPENSION_CONCRETE :Colgante, Cemento +STR_5012_WOODEN :Madeira +STR_5013_CONCRETE :Cemento +STR_5014_TUBULAR_STEEL :Tubular, Aceiro +STR_BRIDGE_TUBULAR_SILICON :Tubular, Silicona +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}No se pode construí-la ponte aí... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Non se pode constrí-lo túnel aí... +STR_5017_RAILROAD_TUNNEL :Túnel de ferrocarril +STR_5018_ROAD_TUNNEL :Túnel de estrada +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Ponte colgante de aceiro para ferrocarrís +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Ponte de vigas de aceiro para ferrocarrís +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Ponte voladiza de aceiro para ferrocarrís +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Ponte colgante de cemento reforzado para ferrocarrís +STR_501F_WOODEN_RAIL_BRIDGE :Ponte de madeira para ferrocarrís +STR_5020_CONCRETE_RAIL_BRIDGE :Ponte de cemento para ferrocarrís +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Ponte colgante de aceiro para estradas +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Ponte de vigas de aceiro para estradas +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Ponte voladiza de aceiro para estradas +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Ponte colgante de cemento reforzado para estradas +STR_5025_WOODEN_ROAD_BRIDGE :Ponte de madeira para estradas +STR_5026_CONCRETE_ROAD_BRIDGE :Ponte de cemento para estradas +STR_5027_TUBULAR_RAIL_BRIDGE :Ponte tubular para ferrocarrís +STR_5028_TUBULAR_ROAD_BRIDGE :Ponte tubular para estradas +STR_5029_STEEL :Aceiro + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Hai un obxecto no camiño +STR_5801_TRANSMITTER :Transmisor +STR_5802_LIGHTHOUSE :Faro +STR_5803_COMPANY_HEADQUARTERS :Cuartel Xeral de Compañía +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...hai un cuartel xeral no camiño +STR_5805_COMPANY_OWNED_LAND :Terreo propiedade dunha compañía +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Non se pode compra-la área de terreo... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...¡xa é da túa propiedade! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Sen Nome{SKIP} +STR_SV_TRAIN_NAME :Tren {COMMA16} +STR_SV_ROADVEH_NAME :Vehículo de estrada {COMMA16} +STR_SV_SHIP_NAME :Barco {COMMA16} +STR_SV_AIRCRAFT_NAME :Avión {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Norte +STR_SV_STNAME_SOUTH :{STRING} Sur +STR_SV_STNAME_EAST :{STRING} Este +STR_SV_STNAME_WEST :{STRING} Oeste +STR_SV_STNAME_CENTRAL :{STRING} Central +STR_SV_STNAME_TRANSFER :{STRING} Transferencia +STR_SV_STNAME_HALT :{STRING} Alto +STR_SV_STNAME_VALLEY :{STRING} Val +STR_SV_STNAME_HEIGHTS :{STRING} Lombas +STR_SV_STNAME_WOODS :{STRING} Bosques +STR_SV_STNAME_LAKESIDE :{STRING} Ribeira de lago +STR_SV_STNAME_EXCHANGE :{STRING} Cambio +STR_SV_STNAME_AIRPORT :Aeroporto de {STRING} +STR_SV_STNAME_OILFIELD :{STRING} Campo de petróleo +STR_SV_STNAME_MINES :{STRING} Minas +STR_SV_STNAME_DOCKS :Peirao de {STRING} +STR_SV_STNAME_BUOY_1 :{STRING} Boia 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boia 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boia 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boia 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boia 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boia 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boia 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boia 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boia 9 +STR_SV_STNAME_ANNEXE :{STRING} Anexo +STR_SV_STNAME_SIDINGS :{STRING} Apartadeiro +STR_SV_STNAME_BRANCH :{STRING} Rama +STR_SV_STNAME_UPPER :Superior {STRING} +STR_SV_STNAME_LOWER :Inferior {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliporto +STR_SV_STNAME_FOREST :{STRING} Bosque + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Nivel de Dificultade +STR_OPTIONS_SAVE_CHANGES :{BLACK}Grabar + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Fácil +STR_6802_MEDIUM :{BLACK}Medio +STR_6803_HARD :{BLACK}Difícil +STR_6804_CUSTOM :{BLACK}Personal +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Nº máximo de oponentes: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Data de comezo dos oponentes: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Nº de cidades: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Nº de industrias: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Crédito máximo inicial: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Taxa de interés inicial: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Coste de mantemento dos vehículos: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Velocidade de construcción dos oponentes: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelixencia dos oponentes: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Averías nos vehículos: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Multiplicador de subsidio: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Costes de construcción: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Tipo de Terreo: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Cantidade de mares/lagos: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Economía: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Xiro do sentido do tren: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Desastres: {ORANGE}{STRING} +STR_16816_CITY_APPROVAL :{LTBLUE}Actitude do consello sobre a reestructuración de áreas: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Baixo +STR_6817_NORMAL :Normal +STR_6818_HIGH :Alto +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Moi Lento +STR_681C_SLOW :Lento +STR_681D_MEDIUM :Medio +STR_681E_FAST :Rápido +STR_681F_VERY_FAST :Moi Rápido +STR_VERY_LOW :Moi Baixo +STR_6820_LOW :Baixo +STR_6821_MEDIUM :Medio +STR_6822_HIGH :Alto +STR_6823_NONE :Ningún +STR_6824_REDUCED :Reducido +STR_6825_NORMAL :Normal +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Moi chan +STR_682B_FLAT :Chan +STR_682C_HILLY :Accidentado +STR_682D_MOUNTAINOUS :Montañoso +STR_682E_STEADY :Estable +STR_682F_FLUCTUATING :Variable +STR_6830_IMMEDIATE :Inmediato +STR_6831_3_MONTHS_AFTER_PLAYER :3 meses despois do xogador +STR_6832_6_MONTHS_AFTER_PLAYER :6 meses despois do xogador +STR_6833_9_MONTHS_AFTER_PLAYER :9 meses despois do xogador +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Ó final da liña, e nas estacións +STR_6835_AT_END_OF_LINE_ONLY :Só ó final da liña +STR_6836_OFF :Off +STR_6837_ON :On +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Mostra-la lista das mellores puntuacións +STR_6839_PERMISSIVE :Permisivo +STR_683A_TOLERANT :Tolerante +STR_683B_HOSTILE :Hostil + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Xogador 1) +STR_7003_PLAYER_2 : (Xogador 2) +STR_7004_NEW_FACE :{BLACK}Nova Cara +STR_7005_COLOR_SCHEME :{BLACK}Esquema de Cor +STR_7006_COLOR_SCHEME :{GOLD}Esquema de Cor: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Novo Esquema de Cor +STR_7008_COMPANY_NAME :{BLACK}Nome Compañía +STR_7009_PRESIDENT_NAME :{BLACK}Nome Presidente +STR_700A_COMPANY_NAME :Nome da Compañía +STR_700B_PRESIDENT_S_NAME :Nome Do Presidente +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Non se pode cambia-lo nome da compañía... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Non se pode cambia-lo nome do presidente... +STR_700E_FINANCES :{WHITE}{STRING} Finanzas{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Gastos/Ingresos +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Construccción +STR_7012_NEW_VEHICLES :{GOLD}Novos Vehículos +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Mantemento dos Trens +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Mantemento dos Vehículos +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Mantemendo dos Avións +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Mantemento dos Barcos +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Mantemento das Propiedades +STR_7018_TRAIN_INCOME :{GOLD}Ingresos dos Trens +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Ingresos dos Vehículos +STR_701A_AIRCRAFT_INCOME :{GOLD}Ingresos dos Avións +STR_701B_SHIP_INCOME :{GOLD}Ingresos dos Barcos +STR_701C_LOAN_INTEREST :{GOLD}Interese do Préstamo +STR_701D_OTHER :{GOLD}Outros +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Total: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Gráfico de Ingresos +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Gráfica de Beneficios Operativos +STR_7026_BANK_BALANCE :{WHITE}Balance do Banco +STR_7027_LOAN :{WHITE}Préstamo +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Solicitar {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Devolver {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...O tamaño máximo do préstamo permitido e de {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Non se pode solicitar máis diñeiro... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...non queda préstamo a pagar +STR_702E_REQUIRED :{WHITE}...necesitas {CURRENCY} +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Non se pode paga-lo préstamo... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Selecciona-la nova cara do presidente +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Cambia-la libra dos vehículos da compañía +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Cambia-lo nome do presidente +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Cambia-lo nome da compañía +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Pincha no novo esquema de cor +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Incrementa-lo préstamo +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Pagar parte do préstamo +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Presidente) +STR_7038_INAUGURATED :{GOLD}Inaugurado: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Vehículos: +STR_703A_TRAIN :{WHITE}{COMMA16} tren +STR_703B_TRAINS :{WHITE}{COMMA16} trens +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} vehículo de estrada +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} vehículos de estrada +STR_703E_AIRCRAFT :{WHITE}{COMMA16} avión +STR_703F_AIRCRAFT :{WHITE}{COMMA16} avións +STR_7040_SHIP :{WHITE}{COMMA16} barco +STR_7041_SHIPS :{WHITE}{COMMA16} barcos +STR_7042_NONE :{WHITE}Ningún +STR_7043_FACE_SELECTION :{WHITE}Selecció de cara +STR_7044_MALE :{BLACK}Home +STR_7045_FEMALE :{BLACK}Muller +STR_7046_NEW_FACE :{BLACK}Nova cara +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Cancela-la selección dunha nova cara +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Acepta-la selección da nova cara +STR_7049_SELECT_MALE_FACES :{BLACK}Seleccionar caras masculinas +STR_704A_SELECT_FEMALE_FACES :{BLACK}Seleccionar caras femininas +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Xerar unha nova cara aleatoriamente +STR_704C_KEY :{BLACK}Chave +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Mostra-la chave das gráficas +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Chave das gráficas da compañía +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Pincha aquí para amosar/ocultar a entrada da compañía na gráfica +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Unidades de carga transportadas +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Puntuación de rendemento da compañía (Máximo=1000) +STR_7052_COMPANY_VALUES :{WHITE}Valor da Compañía +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Tabla da Liga de Compañías +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}¡Compañía de transporte en problemas! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} vai ser vendida ou declarada en bancarrota se non mellora o seu rendemento pronto! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Presidente) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}¡Fusión de compañías de transporte! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} foi vendida a {STRING} por {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Buscamos unha compañía de transporte para adquiri-la nosa compañía{}{}¿Queres comprar {STRING} por {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}¡Bancarrota! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} foi cerrada polos acreedores e vendéronse tódalas posesións! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}¡Lanzada unha nova compañía de transporte! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} comeza a construcción cerca de {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Non se pode compra-la compañía... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Taxas de Pagamento por Carga +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Días en tránsito +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Pagamento por transportar 10 unidades (ou 1.000 litros) de carga unha distancia de 20 cadros +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Amosar/ocultar gráfica para o tipo de carga +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Enxeñeiro +STR_7067_TRAFFIC_MANAGER :Xestor de Tráfico +STR_7068_TRANSPORT_COORDINATOR :Coordinador de Transporte +STR_7069_ROUTE_SUPERVISOR :Supervisor de Ruta +STR_706A_DIRECTOR :Director +STR_706B_CHIEF_EXECUTIVE :Xefe Executivo +STR_706C_CHAIRMAN :Director +STR_706D_PRESIDENT :Presidente +STR_706E_TYCOON :Magnate +STR_706F_BUILD_HQ :{BLACK}Construír CX +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Construír/ver cuartel xeral da compañía +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Non se pode construí-lo cuartel xeral... +STR_7072_VIEW_HQ :{BLACK}Ve-lo CX +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}¡Recesión Mundial!{}{}¡Os expertos en finanzas témense o peor a medida que a economía afúndese! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}¡Fin da Recesión!{}{}¡A mellora no comercio inspira confianza nas industrias a media que a economía reforzase! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Intercambiar entre fiestra grande/pequena +STR_7076_COMPANY_VALUE :{GOLD}Valor da Compañía: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Comprar un 25% das accións da compañía +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Vender un 25% das accións da compañía +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Comprar un 25% das accións nesta compañía +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Vender un 25% das accións desta compañía +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Non se pode comprar un 25% das accións nesta compañía... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Non se pode vender un 25% das accións desta compañía... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% propiedade de {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% propiedade de {STRING}{} {COMMA16}% propiedade de {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} comprada por {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Vapor) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Vapor) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Vapor) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Vapor) +STR_800A_SH_8P_STEAM :SH '8P' (Vapor) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Eléctrica) +STR_8018_SH_40_ELECTRIC :SH '40' (Eléctrica) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Eléctrica) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Eléctrica) +STR_801B_PASSENGER_CAR :Coche de Pasaxeiros +STR_801C_MAIL_VAN :Furgón de Correo +STR_801D_COAL_CAR :Coche de Carbón +STR_801E_OIL_TANKER :Tanque de Petróleo +STR_801F_LIVESTOCK_VAN :Furgón de Gando +STR_8020_GOODS_VAN :Furgón de Mercadorías +STR_8021_GRAIN_HOPPER :Tolva de Gran +STR_8022_WOOD_TRUCK :Vagón de Madeira +STR_8023_IRON_ORE_HOPPER :Tolva de Hematita +STR_8024_STEEL_TRUCK :Vagón de Aceiro +STR_8025_ARMORED_VAN :Furgón Blindado +STR_8026_FOOD_VAN :Furgón de Comida +STR_8027_PAPER_TRUCK :Vagón de Papel +STR_8028_COPPER_ORE_HOPPER :Tolva de Mineral de Cobre +STR_8029_WATER_TANKER :Tanque de Auga +STR_802A_FRUIT_TRUCK :Vagón de Froitas +STR_802B_RUBBER_TRUCK :Vagón de Caucho +STR_802C_SUGAR_TRUCK :Vagón de Azucre +STR_802D_COTTON_CANDY_HOPPER :Tolva de Algodón de Azucre +STR_802E_TOFFEE_HOPPER :Tolva de Toffee +STR_802F_BUBBLE_VAN :Furgón de Burbullas +STR_8030_COLA_TANKER :Tanque de Cola +STR_8031_CANDY_VAN :Furgón de Caramelos +STR_8032_TOY_VAN :Furgón de Xoguetes +STR_8033_BATTERY_TRUCK :Vagón de Baterías +STR_8034_FIZZY_DRINK_TRUCK :Vagón de Bebidas Gaseosas +STR_8035_PLASTIC_TRUCK :Vagón de Plástico +STR_8036_X2001_ELECTRIC :'X2001' (Eléctrica) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Eléctrica) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Coche de Pasaxeiros +STR_803A_MAIL_VAN :Furgón de Correo +STR_803B_COAL_CAR :Coche de Carbón +STR_803C_OIL_TANKER :Tanque de Petróleo +STR_803D_LIVESTOCK_VAN :Furgón de Gando +STR_803E_GOODS_VAN :Furgón de Mercadorías +STR_803F_GRAIN_HOPPER :Tolva de Gran +STR_8040_WOOD_TRUCK :Vagón de Madeira +STR_8041_IRON_ORE_HOPPER :Tolva de Hematita +STR_8042_STEEL_TRUCK :Vagón de Aceiro +STR_8043_ARMORED_VAN :Furgón Blindado +STR_8044_FOOD_VAN :Furgón de Comida +STR_8045_PAPER_TRUCK :Vagón de Papel +STR_8046_COPPER_ORE_HOPPER :Tolva de Mineral de Cobre +STR_8047_WATER_TANKER :Tanque de Auga +STR_8048_FRUIT_TRUCK :Vagón de Froitas +STR_8049_RUBBER_TRUCK :Vagón de Caucho +STR_804A_SUGAR_TRUCK :Vagón de Azucre +STR_804B_COTTON_CANDY_HOPPER :Tolva de Algodón de Azucre +STR_804C_TOFFEE_HOPPER :Tolva de Toffee +STR_804D_BUBBLE_VAN :Furgón de Burbullas +STR_804E_COLA_TANKER :Tanque de Cola +STR_804F_CANDY_VAN :Furgón de Caramelos +STR_8050_TOY_VAN :Furgón de Xoguetes +STR_8051_BATTERY_TRUCK :Vagón de Baterías +STR_8052_FIZZY_DRINK_TRUCK :Vagón de Bebidas Gaseosas +STR_8053_PLASTIC_TRUCK :Vagón de Plástico +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Eléctrica) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Eléctrica) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Eléctrica) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Eléctrica) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Coche de Pasaxeiros +STR_805A_MAIL_VAN :Furgón de Correo +STR_805B_COAL_CAR :Coche de Carbón +STR_805C_OIL_TANKER :Tanque de Petróleo +STR_805D_LIVESTOCK_VAN :Furgón de Gando +STR_805E_GOODS_VAN :Furgón de Mercadorías +STR_805F_GRAIN_HOPPER :Tolva de Gran +STR_8060_WOOD_TRUCK :Vagón de Madeira +STR_8061_IRON_ORE_HOPPER :Tolva de Hematita +STR_8062_STEEL_TRUCK :Vagón de Aceiro +STR_8063_ARMORED_VAN :Furgón Blindado +STR_8064_FOOD_VAN :Furgón de Comida +STR_8065_PAPER_TRUCK :Vagón de Papel +STR_8066_COPPER_ORE_HOPPER :Tolva de Mineral de Cobre +STR_8067_WATER_TANKER :Tanque de Auga +STR_8068_FRUIT_TRUCK :Vagón de Froitas +STR_8069_RUBBER_TRUCK :Vagón de Caucho +STR_806A_SUGAR_TRUCK :Vagón de Azucre +STR_806B_COTTON_CANDY_HOPPER :Tolva de Algodón de Azucre +STR_806C_TOFFEE_HOPPER :Tolva de Toffee +STR_806D_BUBBLE_VAN :Furgón de Burbullas +STR_806E_COLA_TANKER :Tanque de Cola +STR_806F_CANDY_VAN :Furgón de Caramelos +STR_8070_TOY_VAN :Furgón de Xoguetes +STR_8071_BATTERY_TRUCK :Vagón de Baterías +STR_8072_FIZZY_DRINK_TRUCK :Vagón de Bebidas Gaseosas +STR_8073_PLASTIC_TRUCK :Vagón de Plástico +STR_8074_MPS_REGAL_BUS :Autobús Real MPS +STR_8075_HEREFORD_LEOPARD_BUS :Autobús Leopardo Hereford +STR_8076_FOSTER_BUS :Autobús Foster +STR_8077_FOSTER_MKII_SUPERBUS :Superautobús Foster MkII +STR_8078_PLODDYPHUT_MKI_BUS :Autobús Ploddyphut MkI +STR_8079_PLODDYPHUT_MKII_BUS :Autobús Ploddyphut MkII +STR_807A_PLODDYPHUT_MKIII_BUS :Autobús Ploddyphut MkIII +STR_807B_BALOGH_COAL_TRUCK :Camión de Carbón Balogh +STR_807C_UHL_COAL_TRUCK :Camión de Carbón Uhl +STR_807D_DW_COAL_TRUCK :Camión de Carbón DW +STR_807E_MPS_MAIL_TRUCK :Camión de Correo MPS +STR_807F_REYNARD_MAIL_TRUCK :Camión de Correo Reynard +STR_8080_PERRY_MAIL_TRUCK :Camión de Correo Perry +STR_8081_MIGHTYMOVER_MAIL_TRUCK :Camión de Correo MightyMover +STR_8082_POWERNAUGHT_MAIL_TRUCK :Camión de Correo Powernaught +STR_8083_WIZZOWOW_MAIL_TRUCK :Camión de Correo Wizzowow +STR_8084_WITCOMBE_OIL_TANKER :Tanque de Petróleo Witcombe +STR_8085_FOSTER_OIL_TANKER :Tanque de Petróleo Foster +STR_8086_PERRY_OIL_TANKER :Tanque de Petróleo Perry +STR_8087_TALBOTT_LIVESTOCK_VAN :Furgón de Gando Talbott +STR_8088_UHL_LIVESTOCK_VAN :Furgón de Gando Uhl +STR_8089_FOSTER_LIVESTOCK_VAN :Furgón de Gando Foster +STR_808A_BALOGH_GOODS_TRUCK :Camión de Mercadorías Balogh +STR_808B_CRAIGHEAD_GOODS_TRUCK :Camión de Mercadorías Craighead +STR_808C_GOSS_GOODS_TRUCK :Camión de Mercadorías Goss +STR_808D_HEREFORD_GRAIN_TRUCK :Camión de Gran Hereford +STR_808E_THOMAS_GRAIN_TRUCK :Camión de Gran Thomas +STR_808F_GOSS_GRAIN_TRUCK :Camión de Gran Goss +STR_8090_WITCOMBE_WOOD_TRUCK :Camión de Madeira Witcombe +STR_8091_FOSTER_WOOD_TRUCK :Camión de Madeira Foster +STR_8092_MORELAND_WOOD_TRUCK :Camión de Madeira Moreland +STR_8093_MPS_IRON_ORE_TRUCK :Camión de Hematita MPS +STR_8094_UHL_IRON_ORE_TRUCK :Camión de Hematita Uhl +STR_8095_CHIPPY_IRON_ORE_TRUCK :Camión de Hematita Chippy +STR_8096_BALOGH_STEEL_TRUCK :Camión de Aceiro Balogh +STR_8097_UHL_STEEL_TRUCK :Camión de Aceiro Uhl +STR_8098_KELLING_STEEL_TRUCK :Camión de Aceiro Kelling +STR_8099_BALOGH_ARMORED_TRUCK :Camión Blindado Balogh +STR_809A_UHL_ARMORED_TRUCK :Camión Blindado Uhl +STR_809B_FOSTER_ARMORED_TRUCK :Camión Blindado Foster +STR_809C_FOSTER_FOOD_VAN :Furgón de Comida Foster +STR_809D_PERRY_FOOD_VAN :Furgón de Comida Perry +STR_809E_CHIPPY_FOOD_VAN :Furgón de Comida Chippy +STR_809F_UHL_PAPER_TRUCK :Camión de Papel Uhl +STR_80A0_BALOGH_PAPER_TRUCK :Camión de Papel Balogh +STR_80A1_MPS_PAPER_TRUCK :Camión de Papel MPS +STR_80A2_MPS_COPPER_ORE_TRUCK :Camión de Mineral de Cobre MPS +STR_80A3_UHL_COPPER_ORE_TRUCK :Camión de Mineral de Cobre Uhl +STR_80A4_GOSS_COPPER_ORE_TRUCK :Camión de Mineral de Cobre Goss +STR_80A5_UHL_WATER_TANKER :Tanque de Auga Uhl +STR_80A6_BALOGH_WATER_TANKER :Tanque de Auga Balogh +STR_80A7_MPS_WATER_TANKER :Tanque de Auga MPS +STR_80A8_BALOGH_FRUIT_TRUCK :Camión de Froita Balogh +STR_80A9_UHL_FRUIT_TRUCK :Camión de Froita Uhl +STR_80AA_KELLING_FRUIT_TRUCK :Camión de Froita Kelling +STR_80AB_BALOGH_RUBBER_TRUCK :Camión de Caucho Balogh +STR_80AC_UHL_RUBBER_TRUCK :Camión de Caucho Uhl +STR_80AD_RMT_RUBBER_TRUCK :Camión de Caucho RMT +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :Camión de Azucre MightyMover +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Camión de Azucre Powernaught +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Camión de Azucre Wizzowow +STR_80B1_MIGHTYMOVER_COLA_TRUCK :Camión de Cola MightyMover +STR_80B2_POWERNAUGHT_COLA_TRUCK :Camión de Cola Powernaught +STR_80B3_WIZZOWOW_COLA_TRUCK :Camión de Cola Wizzowow +STR_80B4_MIGHTYMOVER_COTTON_CANDY :Cam. Alg. Azucre MightyMover +STR_80B5_POWERNAUGHT_COTTON_CANDY :Cam. de Algodón de Azucre Powernaught +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Camión de Algodón de Azucre Wizzowow +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :Camión de Tofee MightyMover +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Camión de Tofee Powernaught +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Camión de Tofee Wizzowow +STR_80BA_MIGHTYMOVER_TOY_VAN :Furgón de Xoguetes MightyMover +STR_80BB_POWERNAUGHT_TOY_VAN :Furgón de Xoguetes Powernaught +STR_80BC_WIZZOWOW_TOY_VAN :Furgón de Xoguetes Wizzowow +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :Camión de Caramelos MightyMover +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Camión de Caramelos Powernaught +STR_80BF_WIZZOWOW_CANDY_TRUCK :Camión de Caramelos Wizzowow +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :Camión de Baterías MightyMover +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Camión de Baterías Powernaught +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Camión de Baterías Wizzowow +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :Cam. de Bebidas Gaseosas MightyMover +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Cam. de Bebidas Gaseosas Powernaught +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Cam. de Bebidas Gaseosas Wizzowow +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :Camión de Plástico MightyMover +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Camión de Plástico Powernaught +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Camión de Plástico Wizzowow +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :Camión de Burbullas MightyMover +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Camión de Burbullas Powernaught +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Camión de Burbullas Wizzowow +STR_80CC_MPS_OIL_TANKER :Petroleiro MPS +STR_80CD_CS_INC_OIL_TANKER :Petroleíro CS-Inc. +STR_80CE_MPS_PASSENGER_FERRY :Barca de Pasaxeiros MPS +STR_80CF_FFP_PASSENGER_FERRY :Barca de Pasaxeiros FFP +STR_80D0_BAKEWELL_300_HOVERCRAFT :Aerodeslizador Bakewell 300 +STR_80D1_CHUGGER_CHUG_PASSENGER :Barca de Pasaxeiros Chugger-Chug +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Barca de Pasaxeiros Shivershake +STR_80D3_YATE_CARGO_SHIP :Barco de Mercadorías Yate +STR_80D4_BAKEWELL_CARGO_SHIP :Barco de Mercadorías Bakewell +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Barco de Mercadorías Mightymover +STR_80D6_POWERNAUT_CARGO_SHIP :Barco de Mercadorías Powernaut +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Helicóptero Tricario +STR_80FE_GURU_X2_HELICOPTER :Helicóptero Guru X2 +STR_80FF_POWERNAUT_HELICOPTER :Helicóptero Powernaut +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Mensaxe dun fabricante de vehículos +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Rematamo-lo deseño dun/dunha nov@ {STRING} - ¿Interésache probar este vehículo en exclusiva durante un ano, para comproba-lo seu rendemento antes de facelo dispoñible para todos? +STR_8102_RAILROAD_LOCOMOTIVE :locomotora de ferrocarril +STR_8103_ROAD_VEHICLE :vehículo de estrada +STR_8104_AIRCRAFT :avión +STR_8105_SHIP :barco +STR_8106_MONORAIL_LOCOMOTIVE :locomotora de monoraíl +STR_8107_MAGLEV_LOCOMOTIVE :locomotora de maglev + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}Depósito de Tren de {TOWN} +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Celebración cidadá . . .{}Chega o primeiro tren a {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Detalles) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Hai un tren no camiño +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Ir a {STATION} +STR_8807_GO_TO_UNLOAD :Ir a {STATION} (Unload) +STR_8808_GO_TO_LOAD :Ir a {STATION} (Carga) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Ir sen paradas a {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Ir sen paradas a {STATION} (Descarga) +STR_880C_GO_NON_STOP_TO_LOAD :Ir sen paradas a {STATION} (Carga) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Ir ó Depósito de Trens de {TOWN} +STR_SERVICE_AT_TRAIN_DEPOT :Face-lo servicio no Depósito de Trens de {TOWN} +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Ir sen paradas o Depósito de Trens de {TOWN} +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Face-lo servicio sen paradas no Depósito de Trens de {TOWN} + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}En camiño ó Depósito de Trens de {TOWN} +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}En camiño ó Depósito de Trens de {TOWN}, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Valeiro +STR_8813_FROM :{LTBLUE}{CARGO} de {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}O tren {COMMA16} está a esperar no depósito +STR_8815_NEW_VEHICLES :{BLACK}Novos Vehículos +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Coste: {GOLD}{CURRENCY}{BLACK} Peso: {GOLD}{COMMA16}t{}{BLACK}Velocidade: {GOLD}{VELOCITY}{BLACK} Potencia: {GOLD}{COMMA16}hp{}{BLACK}Coste mantemento: {GOLD}{CURRENCY}/ano{}{BLACK}Capacidade: {GOLD}{STRING}{}{BLACK}Deseñado: {GOLD}{NUMU16}{BLACK} Vida: {GOLD}{COMMA16} anos{}{BLACK}Fiabilidade Máx.: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Información +STR_8819_TRAIN_TOO_LONG :{WHITE}O tren é demasiado longo +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Os trens só se poden alterar cando estean parados nunha estación +STR_881B_TRAINS :{WHITE}{STRING} - Trens +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Novos Vehículos de Ferrocarril +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Novos Vehículos de Monorraíl +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Novos Vehículos de Maglev +STR_881F_BUILD_VEHICLE :{BLACK}Construír Vehículo +STR_8820_RENAME :{BLACK}Renomear +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Coste: {GOLD}{CURRENCY}{}{BLACK}Peso: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Capacidade: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Saltar +STR_8824_DELETE :{BLACK}Borrar +STR_8825_NON_STOP :{BLACK}Non Parar +STR_8826_GO_TO :{BLACK}Ir a +STR_8827_FULL_LOAD :{BLACK}Encher +STR_8828_UNLOAD :{BLACK}Descarga +STR_8829_ORDERS :{WHITE}{STRING} (Ordes) +STR_882A_END_OF_ORDERS :{SETX 10}- - Fin das Ordes - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Servicio +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}No se pode construí-lo vehículo de ferrocarril... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construído: {LTBLUE}{NUMU16}{BLACK} Valor: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Valor: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Cargando / Descargando +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}No se pode envía-lo tren o depósito... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Non haí espacio para máis ordes +STR_8832_TOO_MANY_ORDERS :{WHITE}Demasiadas ordes +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}No se pode inserta-la nova orde... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Non se pode borrar esta orde... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Non se pode modificar esta orde... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Debes construír un depósito de trens primeiro +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}No se pode move-lo vehículo... +STR_8838_N_A :N/D{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Non se pode vende-lo vehículo de ferrocarril... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}No se pode atopar unha ruta a un depósito local +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}No se pode para/arrinca-lo tren... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Intervalo de Servicio: {LTBLUE}{COMMA16}days{BLACK} Último Servicio: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trens - pincha nun tren para información +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Construír novos trens (é necesarió un depósito) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Trens - pincha nun tren para información, arrastra o vehículo para engadi/remove-lo do tren +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Construír novo vehículo de ferrocarril +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Arrastra un vehículo do tren aquí para vendelo +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centra-la vista principal na situación do depósito de trens +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Lista de selección de vehículos para trens - pincha nun vehículo para máis información +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Construílo vehículo de ferrocarril seleccionado +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Renomea-lo tipo de vehículo de ferrocarril +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Tarea actual do tren - pincha aquí para parar/arrincar o tren +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Mostra-las ordes do tren +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centra-al vista principal la situación do tren +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Enviar tren ó depósito +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Obliga-lo tren a continuar sen esperar a que o sinal o indique +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Invertí-lo sentido do tren +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Mostra-los detalles do tren +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Incrementa-lo intervalo dos servicios +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Disminuí-lo intervalo dos servicios +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Mostra-los detalles das mercadorías transportadas +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Mostra-los detalles dos vehículos do tren +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Mostra-la capacidade de cada vehículo +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Mostra-la capacidade total do tren, dividida por tipos de carga +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Lista de Ordes - Pincha nunha orde para seleccionala +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Salta-la orde actual, e comezar coa seguinte +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Borra-la orde seleccionada +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Facer que a orde seleccionada sexa de Non Parar +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Insertar unha nova orde despois da seleccionada, o insertar unha nova orde ó final da lista +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}A orde seleccionada forzará o vehículo a esperar ata que a carga estea completa +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}A orde seleccionada forzará o vehículo a descargar +STR_SERVICE_HINT :{BLACK}saltar esta orde a non ser que sexa necesario o servicio +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}¡Nov@ {STRING} dispoñible! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Coste: {CURRENCY} Peso: {COMMA16}t{}Velocidade: {VELOCITY} Potencia: {COMMA16}hp{}Coste de Mantemento: {CURRENCY}/ano{}Capacidade: {STRING} +STR_885C_BROKEN_DOWN :{RED}Roto +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Idade: {LTBLUE}{STRING}{BLACK} Coste de Mantemento: {LTBLUE}{CURRENCY}/ano +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Peso: {LTBLUE}{COMMA16}t {BLACK}Potencia: {LTBLUE}{COMMA32}cv{BLACK} Velocidade Máx.: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Beneficios este ano: {LTBLUE}{CURRENCY} (último ano: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidade: {LTBLUE}{COMMA8}% {BLACK}Roturas dende o último servicio: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Parado +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Non se pode face-lo tren pasar unha sinal de perigo... +STR_8863_CRASHED :{RED}¡Estrelado! + +STR_8865_NAME_TRAIN :{WHITE}Renomear tren +STR_8866_CAN_T_NAME_TRAIN :{WHITE}No se pode renomea-lo tren... +STR_8867_NAME_TRAIN :{BLACK}Renomear tren +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}¡Accidente Ferroviario!{}{COMMA16} mortos na explosión trala colisión +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}No se pode cambia-lo sentido do tren... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Renomea-lo tipo de vehículo de ferrocarril +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Non se pode renome-lo tipo de vehículo de ferrocarril... + +STR_TRAIN_STOPPING :{RED}Parando +STR_TRAIN_STOPPING_VEL :{RED}Parando, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Haí un vehículo de estrada no camiño +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Vehículos de Estrada +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}Depósito de Vehículos de Estrada de {TOWN} +STR_9004_NEW_VEHICLES :{BLACK}Novos Vehículos +STR_9005_INFORMATION :{BLACK}Información +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Novos Vehículos de Estrada +STR_9007_BUILD_VEHICLE :{BLACK}Constrír Vehículo +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Coste: {GOLD}{CURRENCY}{BLACK} Velocidade: {GOLD}{VELOCITY}{}{BLACK}Coste de Mantemento: {GOLD}{CURRENCY}/ano{}{BLACK}Capacidade: {GOLD}{STRING}{}{BLACK}Deseñado: {GOLD}{NUMU16}{BLACK} Vida: {GOLD}{COMMA16} anos{}{BLACK}Fiabilidade Máx.: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}No se pode construí-lo vehículo de estrada... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Debes construír un depósito de vehículos de estrada primeiro +STR_900B_ORDERS :{WHITE}{STRING} (Ordes) +STR_900C_DETAILS :{WHITE}{STRING} (Detalles) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Idade: {LTBLUE}{STRING}{BLACK} Coste de Mantemento: {LTBLUE}{CURRENCY}/ano +STR_900E_MAX_SPEED :{BLACK}Velocidade Máx.: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Beneficio este ano: {LTBLUE}{CURRENCY} (último ano: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidade: {LTBLUE}{COMMA8}% {BLACK}Roturas dende o último servicio: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construído: {LTBLUE}{NUMU16}{BLACK} Valor: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Capacidade: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...debe estar parado dentro dun depósito de vehículos de estrada +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Non se pode vende-lo vehículo de estrada... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}No se pode parar/arrincar o vehículo de estrada... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}O vehículo de estrada {COMMA16} está a esperar no depósito +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Diríxese o depósito de estrada de {TOWN} +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Diríxese o depósito de estrada de {TOWN}, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Non se pode envia-lo vehículo ó depósito de estrada... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}No se pode atopar unha ruta o depósito local +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Vehículos de estrada - pincha nun vehículo para máis información +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Construír novos vehículos de estrada (necesitas un depósito de vehículos de estrada) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Tarea actual do vehículo - pincha aquí para parar/arrincar o vehículo +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Mostra-las ordes do vehículo +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centra-la vista principal na situación do vehículo +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Envia-lo vehículo ó depósito +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Forza-lo vehículo a da-la volta +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Mostra-los detalles do vehículo de estrada +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Vehículos - pincha nun vehículo para máis información +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Construír vehículo de estrada +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Arrastra un vehículo de estrada aquí para vendelo +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centra-la vista principal na situación do depósito de vehículos de estrada +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Lista de selección de vehículos de estrada - pincha nun vehículo para máis información +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Construí-lo vehículo de estrada seleccionado +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}¡Novo vehículo de estrada dispoñible! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Coste: {CURRENCY}{}Velocidade: {VELOCITY}{}Coste de Mantemento: {CURRENCY}/ano{}Capacidade: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Renomear vehículo de estrada +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Non se pode renomea-lo vehículo de estrada... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Renomear vehículo de estrada +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Celebración cidadá . . .{}¡Chega o primeiro autobús a {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Celebración cidadá . . .{}¡Chega o primeiro camión a {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}¡Accidente de Tráfico!{}O conductor morre na explosión producida tra-la colisión cun tren +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}¡Accidente de Tráfico!{}{COMMA16} morren na explosión producida tra-la colisión cun tren +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}No se pode dacer que o vehículo de volta... +STR_9034_RENAME :{BLACK}Renomear +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Renomea-lo tipo de vehículo de estrada +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Renomea-lo tipo de vehículo de estrada +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Non se pode renomea-lo tipo de vehículo de estrada... +STR_9038_GO_TO_ROADVEH_DEPOT :Ir ó Depósito de Vehículos de Estrada de {TOWN} +STR_SERVICE_AT_ROADVEH_DEPOT :Servicio no Depósito de Vehículos de Estrada de {TOWN} + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Construcción de Peiraos +STR_9801_DOCK_CONSTRUCTION :{WHITE}Construcción de Peiraos +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Non se pode construí-lo peirao aí... +STR_9803_SHIP_DEPOT :{WHITE}Depósito de Barcos de {TOWN} +STR_9804_NEW_SHIPS :{BLACK}Novos Barcos +STR_9805_SHIPS :{WHITE}{STRING} - Barcos +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}No se pode construí-los barcos... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Debes construír un depósito de barcos primeiro +STR_9808_NEW_SHIPS :{WHITE}Novos Barcos +STR_9809_BUILD_SHIP :{BLACK}Construír Barco +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Coste: {GOLD}{CURRENCY}{BLACK} Velocidade: {GOLD}{VELOCITY}{}{BLACK}Capacidade: {GOLD}{STRING} {STRING}{}{BLACK}Coste de Mantemento: {GOLD}{CURRENCY}/ano{}{BLACK}Deseñado: {GOLD}{NUMU16}{BLACK} Vida: {GOLD}{COMMA16} anos{}{BLACK}Fiabilidade Máx.: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}O barco debe estar parado no depósito +STR_980C_CAN_T_SELL_SHIP :{WHITE}No se pode vende-lo barco... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Non se construí-lo barco... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Hay un barco no camiño +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Ordes) +STR_9811_DETAILS :{WHITE}{STRING} (Detalles) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Idade: {LTBLUE}{STRING}{BLACK} Coste de Mantemento: {LTBLUE}{CURRENCY}/ano +STR_9813_MAX_SPEED :{BLACK}Velodidade Máx.: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Beneficio este ano: {LTBLUE}{CURRENCY} (último ano: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidade: {LTBLUE}{COMMA8}% {BLACK}Roturas dende o último servicio: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construído: {LTBLUE}{NUMU16}{BLACK} Valor: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Capacidade: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Non se pode parar/arrincar o barco... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Non se pode envia-lo barco o depósito... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}No se pode atopar unha ruta ó depósito local +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Diríxese o Depósito de Barcos de {TOWN} +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Diríxese o Depósito de Barcos de {TOWN}, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}O barco {COMMA16} esta a esperar no depósito +STR_981D_BUILD_SHIP_DOCK :{BLACK}Construír peirao para barcos +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Construír depósito para barcos (para construír e dar servicio os barcos) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Barcos - pincha nun barco para máis información +STR_9820_BUILD_NEW_SHIP :{BLACK}Costruír noveo barco +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Arrastra o barco aquí para vendelo +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centra-la vista principal na situación do depósito de barcos +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Barcos - pincha no barco para máis información +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Construír novos barcos (necesitas un depósito de barcos) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Lista de selección de barcos - pincha nun barco para máis información +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Construí-lo barco seleccionado +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Tarea actual do barco - pincha aquí para parar/arrincar o barco +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Mostra-las ordes do barco +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centra-la vista principal na situación do barco +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Envia-lo barco o depósito +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Mostra-los detalles do barco +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}¡Novo barco dispoñible! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Coste: {CURRENCY} Velocidade Máx: {VELOCITY}{}Capacidade: {STRING}{}Coste de Mantemento: {CURRENCY}/ano +STR_982F_NAME_SHIP :{BLACK}Renomear barco + +STR_9831_NAME_SHIP :{WHITE}Renomear barco +STR_9832_CAN_T_NAME_SHIP :{WHITE}Non se pode renomea-lo barco +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Celebración cidadá . . .{}¡Chega o primeiro barco a {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Boia de posición, pódese utilizar para marcar puntos de ruta adicionais +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Non se pode coloca-la boia aquí... +STR_9836_RENAME :{BLACK}Renomear +STR_9837_RENAME_SHIP_TYPE :{BLACK}Renomear tipo de barco +STR_9838_RENAME_SHIP_TYPE :{WHITE}Renomear tipo de barco +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Non se pode renomear-lo tipo de barco... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Reaxusta-lo barco para levar un tipo diferente de mercadoría +STR_983B_REFIT :{WHITE}{STRING} (Reaxustar) +STR_983C_REFIT_SHIP :{BLACK}Reaxustar barco +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Selecciona o tipo de mercadoría que vai levar +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Reaxusta-lo barco para leva-lo tipo de mercacdoría seleccionada +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selecciona-lo tipo de carga a levar:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova Capacidade: {GOLD}{STRING}{}{BLACK}Coste do reaxuste: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Non se pode reaxusta-lo barco... +STR_9842_REFITTABLE :(reax.) +STR_GO_TO_SHIP_DEPOT :Ir ó Depósito de Barcos de {TOWN} +SERVICE_AT_SHIP_DEPOT :Face-lo servicio no Depósito de Barcos de {TOWN} + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Const. de Aeroportos +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nonse pode construí-lo aeroporto aí... +STR_A002_AIRCRAFT_HANGAR :{WHITE}Nagar de Avións de {STATION} +STR_A003_NEW_AIRCRAFT :{BLACK}Novo Avión +STR_A004_INFORMATION :{BLACK}Información +STR_A005_NEW_AIRCRAFT :{WHITE}Novo Avión +STR_A006_BUILD_AIRCRAFT :{BLACK}Construír Avión +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Coste: {GOLD}{CURRENCY}{BLACK} Velocidade: {GOLD}{VELOCITY}{}{BLACK}Capacidade: {GOLD}{COMMA16} pasaxeiros, {COMMA16} sacos de correo{}{BLACK}Coste de Mantemento: {GOLD}{CURRENCY}/ano{}{BLACK}Deseñado: {GOLD}{NUMU16}{BLACK} Vida: {GOLD}{COMMA16} anos{}{BLACK}Fiabilidade Máx.: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Non se pode construí-lo avíon... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Avión +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Ordes) +STR_A00C_DETAILS :{WHITE}{STRING} (Detalles) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Idade: {LTBLUE}{STRING}{BLACK} Coste de Mantemento: {LTBLUE}{CURRENCY}/ano +STR_A00E_MAX_SPEED :{BLACK}Velocidade Máx.: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Beneficio este ano: {LTBLUE}{CURRENCY} (último ano: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidade: {LTBLUE}{COMMA8}% {BLACK}Roturas dende o último serivicio: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Construído: {LTBLUE}{NUMU16}{BLACK} Valor: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Non se pode envia-lo avión ó hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Diríxese ó hangar de {STATION} +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Diríxese ó hangar de {STATION}, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}O avión {COMMA16} está a esperar no hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Avión en camiño +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Non se pode parar/arrincar o avión... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}O vaión esta voando +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Debes construír un aeroporto primeiro +STR_A019_CAPACITY :{BLACK}Capacidade: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Capacidade: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}O avión debe estar parado no hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Non se pode vende-lo avión... +STR_A01D_AIRPORT_CONSTRUCTION :Construcción de Aeroporto +STR_A01E_BUILD_AIRPORT :{BLACK}Construír aeroporto +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Avións - pincha no avión para máis información +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Construír novo avión (necesitas un aeroporto con hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Avións - pincha no avión para máis información +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Construír novo avión +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Arrastra o avión aquí para vendelo +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}centra-la vista principal na situación do hangar +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Lista de selección de avións - pincha nun avión para máis información +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Construí-lo avión seleccionado +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Tarea actual do avión - pincha aquí para parar/arrincar o avión +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Mostra-las ordes do avíon +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centra-la vista principal na situación do avión +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Envia-lo avión ó hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Mostra-los detalles do avión +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}¡Novo avión dispoñible! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Coste: {CURRENCY} Velocidade Máx.: {VELOCITY}{}Capacidade: {COMMA16} pasaxeiros, {COMMA16} sacos de correo{}Coste de Mantemento: {CURRENCY}/ano + +STR_A030_NAME_AIRCRAFT :{WHITE}Renomear avión +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Non se pode renomea-lo avión... +STR_A032_NAME_AIRCRAFT :{BLACK}Renomear avión +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Celebración cidadá . . .{}¡Chega o primeiro avión a {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Plane Crash!{}{COMMA16} die in fireball at {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinos: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Renomear +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Renomea-lo tipo de avión +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Renomea-lo tipo de avión +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Non se pode renomea-lo tipo de avión... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Reaxusta-lo avión para levar un tipo distinto de carga +STR_A03C_REFIT :{WHITE}{STRING} (Reaxustar) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Reaxustar avión +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Selecciona o tipo de carga que levará +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Reaxusta-lo avión para levar o tipo de carga seleccionada +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Selecciona o tipo de carga a levar:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova capacidade: {GOLD}{STRING}{}{BLACK}Cose do reaxuste: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Non se pode reaxusta-lo avión... +STR_A043_REFITTABLE :(reax.) +STR_GO_TO_AIRPORT_HANGAR :Ir ó hangar de {STATION} +SERVICE_AT_AIRPORT_HANGAR :Face-lo servicio no hangar de {STATION} + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}¡Desastre cun Zeppelin en {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}¡Vehículo de estrada destruído tras colisionar cun 'OVNI'! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}¡Explosión dunha refinería de petróleo cerca de {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}¡Factoría destruida en circunstancias sospeitosas cerca de {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}¡Aterrizaxe dun 'OVNI cerca de {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}¡Afundimento dunha Mina de Carbón deixa un rastro de destrucción cerca de {TOWN}! + +STR_BRIBE_FAILED :{WHITE}O tento de suborno foi +STR_BRIBE_FAILED_2 :{WHITE}descuberto por un investigador rexional. \ No newline at end of file diff --git a/lang/german.txt b/lang/german.txt new file mode 100644 --- /dev/null +++ b/lang/german.txt @@ -0,0 +1,2357 @@ +##name German +##ownname Deutsch + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Zu weit vom Kartenrand entfernt +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Zu nahe am Kartenrand +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Nicht genug Geld - {CURRENCY} benötigt! +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Ebenes Land erforderlich +STR_0008_WAITING :{BLACK}Wartend: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (unterwegs von +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Akzeptiert: {WHITE} +STR_000D_ACCEPTS :{BLACK}Akzeptiert: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passagiere +STR_0010_COAL :Kohle +STR_0011_MAIL :Post +STR_0012_OIL :Öl +STR_0013_LIVESTOCK :Vieh +STR_0014_GOODS :Waren +STR_0015_GRAIN :Getreide +STR_0016_WOOD :Holz +STR_0017_IRON_ORE :Eisenerz +STR_0018_STEEL :Stahl +STR_0019_VALUABLES :Wertsachen +STR_001A_COPPER_ORE :Kupfererz +STR_001B_MAIZE :Mais +STR_001C_FRUIT :Früchte +STR_001D_DIAMONDS :Diamanten +STR_001E_FOOD :Nahrungsmittel +STR_001F_PAPER :Papier +STR_0020_GOLD :Gold +STR_0021_WATER :Wasser +STR_0022_WHEAT :Weizen +STR_0023_RUBBER :Kautschuk +STR_0024_SUGAR :Zucker +STR_0025_TOYS :Spielwaren +STR_0026_CANDY :Bonbons +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Zuckerwatte +STR_0029_BUBBLES :Luftblasen +STR_002A_TOFFEE :Karamell +STR_002B_BATTERIES :Batterien +STR_002C_PLASTIC :Plastik +STR_002D_FIZZY_DRINKS :Limonaden +STR_002E : +STR_002F_PASSENGER :Passagier +STR_0030_COAL :Kohle +STR_0031_MAIL :Post +STR_0032_OIL :Öl +STR_0033_LIVESTOCK :Vieh +STR_0034_GOODS :Waren +STR_0035_GRAIN :Getreide +STR_0036_WOOD :Holz +STR_0037_IRON_ORE :Eisenerz +STR_0038_STEEL :Stahl +STR_0039_VALUABLES :Wertsachen +STR_003A_COPPER_ORE :Kupfererz +STR_003B_MAIZE :Mais +STR_003C_FRUIT :Früchte +STR_003D_DIAMOND :Diamanten +STR_003E_FOOD :Nahrungsmittel +STR_003F_PAPER :Papier +STR_0040_GOLD :Gold +STR_0041_WATER :Wasser +STR_0042_WHEAT :Weizen +STR_0043_RUBBER :Kautschuk +STR_0044_SUGAR :Zucker +STR_0045_TOY :Spielware +STR_0046_CANDY :Bonbon +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Zuckerwatte +STR_0049_BUBBLE :Luftblase +STR_004A_TOFFEE :Karamell +STR_004B_BATTERY :Batterie +STR_004C_PLASTIC :Plastik +STR_004D_FIZZY_DRINK :Limonade +STR_004E : +STR_004F_PASSENGER :{COMMA16} Passagier +STR_0050_TON_OF_COAL :{COMMA16} Tonne Kohle +STR_0051_BAG_OF_MAIL :{COMMA16} Postsack +STR_0052_OF_OIL :{VOLUME} Öl +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} Stück Vieh +STR_0054_CRATE_OF_GOODS :{COMMA16} Warenkisten +STR_0055_TON_OF_GRAIN :{COMMA16} Tonne Getreide +STR_0056_TON_OF_WOOD :{COMMA16} Tonne Holz +STR_0057_TON_OF_IRON_ORE :{COMMA16} Tonne Eisenerz +STR_0058_TON_OF_STEEL :{COMMA16} Tonne Stahl +STR_0059_BAG_OF_VALUABLES :{COMMA16} Sack mit Wertsachen +STR_005A_TON_OF_COPPER_ORE :{COMMA16} Tonne Kupfererz +STR_005B_TON_OF_MAIZE :{COMMA16} Tonne Mais +STR_005C_TON_OF_FRUIT :{COMMA16} Tonne Früchte +STR_005D_BAG_OF_DIAMONDS :{COMMA16} Sack mit Diamanten +STR_005E_TON_OF_FOOD :{COMMA16} Tonne Nahrungsmittel +STR_005F_TON_OF_PAPER :{COMMA16} Tonne Papier +STR_0060_BAG_OF_GOLD :{COMMA16} Sack mit Gold +STR_0061_OF_WATER :{VOLUME} Wasser +STR_0062_TON_OF_WHEAT :{COMMA16} Tonne Weizen +STR_0063_OF_RUBBER :{VOLUME} Kautschuk +STR_0064_TON_OF_SUGAR :{COMMA16} Tonne Zucker +STR_0065_TOY :{COMMA16} Spiel +STR_0066_BAG_OF_CANDY :{COMMA16} Sack mit Bonbons +STR_0067_OF_COLA :{VOLUME} Cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} Tonne Zuckerwatte +STR_0069_BUBBLE :{COMMA16} Luftblase +STR_006A_TON_OF_TOFFEE :{COMMA16} Tonne Karamell +STR_006B_BATTERY :{COMMA16} Batterie +STR_006C_OF_PLASTIC :{VOLUME} Plastik +STR_006D_FIZZY_DRINK :{COMMA16} Limonade +STR_006E : +STR_006F_PASSENGERS :{COMMA16} Passagiere +STR_0070_TONS_OF_COAL :{COMMA16} Tonnen Kohle +STR_0071_BAGS_OF_MAIL :{COMMA16} Postsäcke +STR_0072_OF_OIL :{VOLUME} Öl +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} Stück Vieh +STR_0074_CRATES_OF_GOODS :{COMMA16} Warenkisten +STR_0075_TONS_OF_GRAIN :{COMMA16} Tonnen Getreide +STR_0076_TONS_OF_WOOD :{COMMA16} Tonnen Holz +STR_0077_TONS_OF_IRON_ORE :{COMMA16} Tonnen Eisenerz +STR_0078_TONS_OF_STEEL :{COMMA16} Tonnen Stahl +STR_0079_BAGS_OF_VALUABLES :{COMMA16} Säcke mit Wertsachen +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} Tonnen Kupfererz +STR_007B_TONS_OF_MAIZE :{COMMA16} Tonnen Mais +STR_007C_TONS_OF_FRUIT :{COMMA16} Tonnen Früchte +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} Säcke mit Diamanten +STR_007E_TONS_OF_FOOD :{COMMA16} Tonnen Nahrungsmittel +STR_007F_TONS_OF_PAPER :{COMMA16} Tonnen Papier +STR_0080_BAGS_OF_GOLD :{COMMA16} Säcke mit Gold +STR_0081_OF_WATER :{VOLUME} Wasser +STR_0082_TONS_OF_WHEAT :{COMMA16} Tonnen Weizen +STR_0083_OF_RUBBER :{VOLUME} Kautschuk +STR_0084_TONS_OF_SUGAR :{COMMA16} Tonnen Zucker +STR_0085_TOYS :{COMMA16} Spielwaren +STR_0086_BAGS_OF_CANDY :{COMMA16} Tonnen Bonbons +STR_0087_OF_COLA :{VOLUME} Cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} Tonnen Zuckerwatte +STR_0089_BUBBLES :{COMMA16} Luftblasen +STR_008A_TONS_OF_TOFFEE :{COMMA16} Tonnen Karamell +STR_008B_BATTERIES :{COMMA16} Batterien +STR_008C_OF_PLASTIC :{VOLUME} Plastik +STR_008D_FIZZY_DRINKS :{COMMA16} Limonade +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Karte - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Spieleinstellungen +STR_00B2_MESSAGE :{YELLOW}Nachricht +STR_00B3_MESSAGE_FROM :{YELLOW}Nachricht von {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Kann dies nicht tun.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kann das Gebiet nicht räumen.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, Alle Rechte vorbehalten +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Original Design: Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Graphiken: Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 OpenTTD-Team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Verlassen +STR_00C8_YES :{BLACK}Ja +STR_00C9_NO :{BLACK}Nein +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Bist du sicher, dass du das Spiel abbrechen und zu {STRING} zurückkehren willst? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nichts +STR_00D1_DARK_BLUE :Dunkelblau +STR_00D2_PALE_GREEN :Hellgrün +STR_00D3_PINK :Rosa +STR_00D4_YELLOW :Gelb +STR_00D5_RED :Rot +STR_00D6_LIGHT_BLUE :Hellblau +STR_00D7_GREEN :Grün +STR_00D8_DARK_GREEN :Dunkelgrün +STR_00D9_BLUE :Blau +STR_00DA_CREAM :Beige +STR_00DB_MAUVE :Helllila +STR_00DC_PURPLE :Lila +STR_00DD_ORANGE :Orange +STR_00DE_BROWN :Braun +STR_00DF_GREY :Grau +STR_00E0_WHITE :Weiß +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Zu viele Fahrzeuge im Spiel +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Standort +STR_00E5_CONTOURS :Umrisse +STR_00E6_VEHICLES :Fahrzeuge +STR_00E7_INDUSTRIES :Industrie +STR_00E8_ROUTES :Strecken +STR_00E9_VEGETATION :Vegetation +STR_00EA_OWNERS :Eigentümer +STR_00EB_ROADS :{BLACK}{TINYFONT}Straßen +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Gleise +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Bahnhöfe/Flughäfen/Häfen +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Gebäude/Industrien +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Fahrzeuge +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Züge +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Fahrzeuge +STR_00F7_SHIPS :{BLACK}{TINYFONT}Schiffe +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Flugzeuge +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transportstrecken +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kohlebergwerk +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Kraftwerk +STR_00FC_FOREST :{BLACK}{TINYFONT}Wald +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Sägewerk +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Ölraffinerie +STR_00FF_FARM :{BLACK}{TINYFONT}Bauernhof +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabrik +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Druckerei +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Ölquellen +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Eisenerzmine +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Stahlfabrik +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papiermühle +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Goldmine +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Nahrungsmittelfabrik +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamantenmine +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kupfermine +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Fruchtplantage +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kautschukplantage +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Wasserquelle +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Wasserturm +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Holzmühle +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Zuckerwattewald +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Bonbonfabrik +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batterieplantage +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Colaquellen +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Spielwarengeschäft +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Spielwarenfabrik +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastikbrunnen +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Limonadefabrik +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Luftblasengenerator +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamellgrube +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Zuckerbergwerk +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Bahnhof +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Lkw-Ladestation +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Busbahnhof +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Flughafen / Heliport +STR_011F_DOCK :{BLACK}{TINYFONT}Hafen +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Unebenes Land +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Wiesen +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Kahles Land +STR_0123_FIELDS :{BLACK}{TINYFONT}Felder +STR_0124_TREES :{BLACK}{TINYFONT}Bäume +STR_0125_ROCKS :{BLACK}{TINYFONT}Felsen +STR_0126_WATER :{BLACK}{TINYFONT}Wasser +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Kein Eigentümer +STR_0128_TOWNS :{BLACK}{TINYFONT}Städte +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrien +STR_012A_DESERT :{BLACK}{TINYFONT}Wüste +STR_012B_SNOW :{BLACK}{TINYFONT}Schnee +STR_012C_MESSAGE :{WHITE}Mitteilung +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Abbrechen +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Umbenennen +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Zu viele Namen definiert +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Gewählter Name existiert bereits + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (Meilen) +STR_013A_METRIC_KILOMETERS :Metrisch (Kilometer) +STR_013B_OWNED_BY :{WHITE}...Eigentum von {STRING} +STR_013C_CARGO :{BLACK}Fracht +STR_013D_INFORMATION :{BLACK}Information +STR_013E_CAPACITIES :{BLACK}Kapazitäten +STR_013E_TOTAL_CARGO :{BLACK}Frachtübersicht +STR_013F_CAPACITY :{BLACK}Kapazität: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Frachtkapazität dieses Zuges: +STR_013F_TOTAL_CAPACITY :{LTBLUE}{CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Neues Spiel +STR_0141_LOAD_GAME :{BLACK}Spiel laden +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Einführung / Demonstration +STR_0143_1_PLAYER :{BLACK}1 Spieler +STR_0144_2_PLAYERS :{BLACK}2 Spieler + +STR_0148_GAME_OPTIONS :{BLACK}Spieleinstellungen + +STR_0150_SOMEONE :jemand{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Weltkarte +STR_0152_TOWN_DIRECTORY :Städteverzeichnis +STR_0153_SUBSIDIES :Subventionen + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Betriebsgewinn - Diagramm +STR_0155_INCOME_GRAPH :Einkommensdiagramm +STR_0156_DELIVERED_CARGO_GRAPH :Frachtlieferungs - Diagramm +STR_0157_PERFORMANCE_HISTORY_GRAPH :Leistungskurven - Diagramm +STR_0158_COMPANY_VALUE_GRAPH :Firmenwert - Diagramm +STR_0159_CARGO_PAYMENT_RATES :Frachtraten - Diagramm +STR_015A_COMPANY_LEAGUE_TABLE :Firmentabelle +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Spiel speichern +STR_015D_LOAD_GAME :Spiel laden +STR_015E_QUIT_GAME :Spiel beenden +STR_015F_QUIT :Beenden +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Bist du sicher, dass du das Spiel beenden willst? +STR_0161_QUIT_GAME :{WHITE}Spiel beenden + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mär +STR_0165_APR :Apr +STR_0166_MAY :Mai +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Okt +STR_016C_NOV :Nov +STR_016D_DEC :Dez +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Spiel anhalten +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Spiel speichern, Spiel laden, Spiel verlassen, Beenden +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Liste der Firmenbahnhöfe anzeigen +STR_0174_DISPLAY_MAP :{BLACK}Weltkarte anzeigen +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Weltkarte anzeigen, Städteverzeichnis +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Städteverzeichnis anzeigen +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Firmenfinanzen anzeigen +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Allgemeine Firmeninformationen anzeigen +STR_0179_DISPLAY_GRAPHS :{BLACK}Diagramm anzeigen +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Firmentabelle anzeigen +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Zugliste der Firmen +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Fahrzeugliste der Firmen +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Schiffsliste der Firmen +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Flugzeugliste der Firmen +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Heranzoomen (vergrößern) +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Wegzoomen (verkleinern) +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Gleise legen +STR_0182_BUILD_ROADS :{BLACK}Straßen bauen +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Hafen bauen +STR_0184_BUILD_AIRPORTS :{BLACK}Flughafen bauen +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Bäume pflanzen, Schilder aufstellen usw. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Gebiets-Information +STR_0187_OPTIONS :{BLACK}Einstellungen +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Das Wartungsintervall kann nicht geändert werden... +STR_018B_CLOSE_WINDOW :{BLACK}Fenster schließen +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Titelleiste verschieben um das Fenster zu bewegen +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Gebäude usw. auf einem Planquadrat abreißen +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Land absenken +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Land anheben +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scrollbalken - Liste auf- und abwärts blättern +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Höhenlinien auf der Karte anzeigen +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Fahrzeuge auf der Karte anzeigen +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Industrien auf der Karte anzeigen +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Transportwege auf der Karte anzeigen +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Vegetation auf der Karte anzeigen +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Landeigentümer auf der Karte anzeigen +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Stadtnamen anzeigen an/aus +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Profit laufendes Jahr: {CURRENCY} (vorheriges Jahr: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} Jahr ({COMMA16}) +STR_019A_YEARS :{COMMA16} Jahre ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} Jahre ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Fahrzeug +STR_019D_AIRCRAFT :Flugzeug +STR_019E_SHIP :Schiff +STR_019F_TRAIN :Zug +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} kommt in die Jahre +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} ist veraltet +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} ist völlig veraltet und sollte ersetzt werden +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Gebiets-Information +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Kosten für die Räumung: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Kosten für die Räumung: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Eigentümer: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Gehört zur Gemeinde: {LTBLUE}{STRING} +STR_01A9_NONE :Keine +STR_01AA_NAME :{BLACK}Name +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1. +STR_01AD_2ND :2. +STR_01AE_3RD :3. +STR_01AF_4TH :4. +STR_01B0_5TH :5. +STR_01B1_6TH :6. +STR_01B2_7TH :7. +STR_01B3_8TH :8. +STR_01B4_9TH :9. +STR_01B5_10TH :10. +STR_01B6_11TH :11. +STR_01B7_12TH :12. +STR_01B8_13TH :13. +STR_01B9_14TH :14. +STR_01BA_15TH :15. +STR_01BB_16TH :16. +STR_01BC_17TH :17. +STR_01BD_18TH :18. +STR_01BE_19TH :19. +STR_01BF_20TH :20. +STR_01C0_21ST :21. +STR_01C1_22ND :22. +STR_01C2_23RD :23. +STR_01C3_24TH :24. +STR_01C4_25TH :25. +STR_01C5_26TH :26. +STR_01C6_27TH :27. +STR_01C7_28TH :28. +STR_01C8_29TH :29. +STR_01C9_30TH :30. +STR_01CA_31ST :31. +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Zwischen kleiner/großer Karte umschalten +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Einführung / Demonstration wählen + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Akzeptierte Fracht: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Akzeptierte Fracht: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Akzeptierte Fracht: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Musikbox +STR_01D3_SOUND_MUSIC :Sound / Musik +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Zeige Sound- / Musikfenster +STR_01D5_ALL :{TINYFONT}Alle +STR_01D6_OLD_STYLE :{TINYFONT}Traditionell +STR_01D7_NEW_STYLE :{TINYFONT}Modern +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Individuell 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Individuell 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Musiklautstärke +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Soundlautstärke +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Springe zum vorherigen Titel +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Springe zum nächsten Titel +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Wiedergabe anhalten +STR_01E1_START_PLAYING_MUSIC :{BLACK}Wiedergabe starten +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Schieberegler für Musik- / Soundlautstärke +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Track{SETX 88}Titel +STR_01E9_SHUFFLE :{TINYFONT}Mischen +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programm +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Musik-Programmauswahl +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Track Inhalt +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programm - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Bereinigen +STR_01F1_SAVE :{TINYFONT}{BLACK}Speichern +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}laufendes Musikprogramm +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Programm 'Alle Titel' wählen +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Programm 'Traditionell' wählen +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Programm 'Modern' wählen +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Programm 'Individuell 1' (benutzerdefiniert) wählen +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Programm 'Individuell 2' (benutzerdefiniert) wählen +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Lösche laufendes Programm (nur für Individuell 2 und Individuell 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Sichere Musikeinstellungen +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klicke auf den Musiktitel, um ihn in das laufende Programm zu übernehmen (nur für Individuell 1 und Individuell 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Schalte Programmauswahl an/aus +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Zeige Musiktitelauswahl +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Anklicken, um die Ansicht auf die Industrie/Stadt zu zentrieren +STR_01FE_DIFFICULTY :{BLACK}Schwierigkeitsgrad ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Letzte Mitteilung / Nachricht +STR_0201_MESSAGE_SETTINGS :Nachrichtenoptionen +STR_MESSAGE_HISTORY_MENU :Vergangene Nachrichten +STR_0202_SEND_MESSAGE :Sende Mitteilung +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Zeige letzte Mitteilung / Nachricht, Nachrichtenoptionen anzeigen +STR_0204_MESSAGE_OPTIONS :{WHITE} Nachrichtenoptionen +STR_0205_MESSAGE_TYPES :{BLACK}Nachrichtenart:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankunft des ersten Fahrzeugs in der Station des Spielers +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankunft des ersten Fahrzeugs in der Station eines Gegners +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Unfälle / Katastrophen +STR_0209_COMPANY_INFORMATION :{YELLOW}Firmendaten +STR_020A_ECONOMY_CHANGES :{YELLOW}Änderungen der Wirtschaftslage +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Rat / Informationen zu Fahrzeugen des Spielers +STR_020C_NEW_VEHICLES :{YELLOW}Neue Fahrzeuge +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Änderungen akzeptierter Fracht +STR_020E_SUBSIDIES :{YELLOW}Subventionen +STR_020F_GENERAL_INFORMATION :{YELLOW}Allgemeine Nachrichten +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...zu weit vom vorherigen Bestimmungsort entfernt +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Die besten Firmen, die das Jahr 2050 erreichten{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Geschäftsmann +STR_0214_ENTREPRENEUR :Unternehmer +STR_0215_INDUSTRIALIST :Industrieller +STR_0216_CAPITALIST :Kapitalist +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon des Jahrhunderts +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} erreicht '{STRING}'-Status! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} zu {STRING} erreichender '{STRING}' Status! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Szenario erstellen +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Szenario bearbeiten +STR_0223_LAND_GENERATION :{WHITE}Land erstellen +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Zufälliges Land +STR_0227_RESET_LAND :{BLACK}Land wiederherstellen +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Landfläche vergrößern zum Anheben / Absenken +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Landfläche verkleinern zum Anheben / Absenken +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Erzeuge Land durch Zufall +STR_022B_RESET_LANDSCAPE :{BLACK}Landfläche wiederherstellen +STR_022C_RESET_LANDSCAPE :{WHITE}Landfläche wiederherstellen +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Bist du sicher, dass die Landschaft zurückgesetzt werden soll? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Landfläche erzeugen +STR_022F_TOWN_GENERATION :{BLACK}Stadt errichten +STR_0230_INDUSTRY_GENERATION :{BLACK}Industrie errichten +STR_0231_ROAD_CONSTRUCTION :{BLACK}Straße bauen +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetation und andere Objekte +STR_0233_TOWN_GENERATION :{WHITE}Stadt erzeugen +STR_0234_NEW_TOWN :{BLACK}Neue Stadt +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Neue Stadt errichten +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Kann hier keine Stadt errichten... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...zu dicht am Kartenrand +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...zu dicht an einer anderen Stadt +STR_0239_SITE_UNSUITABLE :{WHITE}...ungeeigneter Standort +STR_023A_TOO_MANY_TOWNS :{WHITE}...zu viele Städte +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Vergrößerere die Stadt +STR_023C_EXPAND :{BLACK}Ausdehnen +STR_023D_RANDOM_TOWN :{BLACK}Zufällige Stadt +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Stadt an zufälligem Platz errichten +STR_023F_INDUSTRY_GENERATION :{WHITE}Industrie errichten +STR_0240_COAL_MINE :{BLACK}Kohlebergwerk +STR_0241_POWER_STATION :{BLACK}Kraftwerk +STR_0242_SAWMILL :{BLACK}Sägewerk +STR_0243_FOREST :{BLACK}Wald +STR_0244_OIL_REFINERY :{BLACK}Ölraffinerie +STR_0245_OIL_RIG :{BLACK}Ölbohrinsel +STR_0246_FACTORY :{BLACK}Fabrik +STR_0247_STEEL_MILL :{BLACK}Stahlwerk +STR_0248_FARM :{BLACK}Bauernhof +STR_0249_IRON_ORE_MINE :{BLACK}Eisenerzmine +STR_024A_OIL_WELLS :{BLACK}Ölquellen +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Papiermühle +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Nahrungsmittelfabrik +STR_024E_PRINTING_WORKS :{BLACK}Druckerei +STR_024F_GOLD_MINE :{BLACK}Goldmine +STR_0250_LUMBER_MILL :{BLACK}Holzmühle +STR_0251_FRUIT_PLANTATION :{BLACK}Fruchtplantage +STR_0252_RUBBER_PLANTATION :{BLACK}Kautschukplantage +STR_0253_WATER_SUPPLY :{BLACK}Wasserquelle +STR_0254_WATER_TOWER :{BLACK}Wasserturm +STR_0255_DIAMOND_MINE :{BLACK}Diamantenmine +STR_0256_COPPER_ORE_MINE :{BLACK}Kupfermine +STR_0257_COTTON_CANDY_FOREST :{BLACK}Zuckerwattewald +STR_0258_CANDY_FACTORY :{BLACK}Bonbonfabrik +STR_0259_BATTERY_FARM :{BLACK}Batterieplantage +STR_025A_COLA_WELLS :{BLACK}Colaquellen +STR_025B_TOY_SHOP :{BLACK}Spielwarengeschäft +STR_025C_TOY_FACTORY :{BLACK}Spielwarenfabrik +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastikbrunnen +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Limonadefabrik +STR_025F_BUBBLE_GENERATOR :{BLACK}Luftblasengenerator +STR_0260_TOFFEE_QUARRY :{BLACK}Karamellgrube +STR_0261_SUGAR_MINE :{BLACK}Zuckerbergwerk +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Kohlebergwerk errichten +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Kraftwerk errichten +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Sägewerk errichten +STR_0265_PLANT_FOREST :{BLACK}Wald aufforsten +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Ölraffinerie errichten +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Ölbohrinsel errichten (Kann nur am Kartenrand erfolgen) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Fabrik errichten +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Stahlwerk errichten +STR_026A_CONSTRUCT_FARM :{BLACK}Bauernhof errichten +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Eisenerzmine errichten +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Ölquellen errichten +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bank errichten (Nur in Städten mit mehr als 1200 Einwohnern möglich) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Papiermühle errichten +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Nahrungsmittelfabrik errichten +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Druckerei errichten +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Goldmine errichten +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bank errichten (Kann nur in Städten errichtet werden) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Holzmühle errichten (Zur Säuberung des Regewaldes und Holzproduktion) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Fruchtplantage aufforsten +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Kautschukplantage aufforsten +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Wasserquelle errichten +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Wasserturm errichten (Kann nur in Städten errichtet werden) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Diamantenmine errichten +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Kupfermine errichten +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Zuckerwattewald aufforsten +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Bonbonfabrik errichten +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Batterieplantage errichten +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Colaquellen errichten +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Spielwarengeschäft errichten +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Spielwarenfabrik errichten +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Plastikbrunnen errichten +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Limonadefabrik errichten +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Luftblasengenerator errichten +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Karamellgrube errichten +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Zuckerbergwerk errichten +STR_0285_CAN_T_BUILD_HERE :{WHITE}Kann hier nicht {STRING} bauen... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...erst muss eine Stadt errichtet werden +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...pro Stadt nur einmal erlaubt +STR_0288_PLANT_TREES :{BLACK}Bäume pflanzen +STR_0289_PLACE_SIGN :{BLACK}Schild aufstellen +STR_028A_RANDOM_TREES :{BLACK}Zufällige Bäume +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Bäume zufällig über die Landschaft verteilen +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Felsige Gebiete in der Landschaft platzieren +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Leuchtturm erstellen +STR_028E_PLACE_TRANSMITTER :{BLACK}Sender erstellen +STR_028F_DEFINE_DESERT_AREA :{BLACK}Wüstengebiet definieren +STR_0290_DELETE :{BLACK}Löschen +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Diese Stadt vollständig löschen +STR_0292_SAVE_SCENARIO :Szenario speichern +STR_0293_LOAD_SCENARIO :Szenario laden +STR_0294_QUIT_EDITOR :Editor verlassen +STR_0295 : +STR_0296_QUIT :Beenden +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Szenario speichern, Szenario laden, Szenariobearbeitung beenden, Beenden +STR_0298_LOAD_SCENARIO :{WHITE}Szenario laden +STR_0299_SAVE_SCENARIO :{WHITE}Szenario speichern +STR_029A_PLAY_SCENARIO :{BLACK}Szenario spielen +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Bist du dir sicher, dass du das Szenario verlassen willst? +STR_029C_QUIT_EDITOR :{WHITE}Bearbeitung beenden +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kann nur in Städten mit mehr als 1200 Einwohnern gebaut werden +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Startdatum auf 1 Jahr früher setzen +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Startdatum auf 1 Jahr später setzen +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...Brücke muss an beiden Seiten auf dem Land enden +STR_02A1_SMALL :{BLACK}Klein +STR_02A2_MEDIUM :{BLACK}Mittel +STR_02A3_LARGE :{BLACK}Groß +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Stadtgröße bestimmen +STR_02A5_TOWN_SIZE :{YELLOW}Stadtgröße: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Letzte Nachricht oder Bericht anzeigen +STR_02B8_SUMMARY :{BLACK}Ticker +STR_02B9_FULL :{BLACK}Zeitung +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Städteverzeichnis +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Fahrzeugnamen +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Standard +STR_02BF_CUSTOM :Eigene +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Eigene Namen abspeichern +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Auswahl der Fahrzeugnamen +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Eigene Namen abspeichern + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Spieleinstellungen +STR_02C4_GAME_OPTIONS :Spieleinstellungen +STR_02C5_DIFFICULTY_SETTINGS :Schwierigkeitsgrad +STR_02C6_DIFFICULTY_SETTINGS :Schwierigkeitsgrad +STR_02C7_CONFIG_PATCHES :Einstellungen der Patches +STR_02C8_CONFIG_PATCHES :Einstellungen der Patches +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Städtenamen anzeigen +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Städtenamen anzeigen +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Stationsnamen anzeigen +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Stationsnamen anzeigen +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Schilder anzeigen +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Schilder anzeigen +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Wegpunkte anzeigen +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Wegpunkte anzeigen +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Vollständige Animation +STR_02D0_FULL_ANIMATION :{SETX 12}Vollständige Animation +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Vollständige Detailansicht +STR_02D2_FULL_DETAIL :{SETX 12}Vollständige Detailansicht +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Durchsichtige Gebäude +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Durchsichtige Gebäude +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Gebiets-Information +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Screenshot (Strg-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Riesiger Screenshot (Strg-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Über 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}an +STR_02DB_OFF :{BLACK}aus +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Subventionen anzeigen +STR_02DD_SUBSIDIES :Subventionen +STR_02DE_MAP_OF_WORLD :Weltkarte +STR_02DF_TOWN_DIRECTORY :Städteverzeichnis +STR_02E0_CURRENCY_UNITS :{BLACK}Währung +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Währung auswählen +STR_02E3_DISTANCE_UNITS :{BLACK}Entfernungsmessung +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Wähle Entfernungsmessung in +STR_02E6_ROAD_VEHICLES :{BLACK}Fahrzeuge +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Wähle auf welcher Straßenseite der Verkehr fließen soll +STR_02E9_DRIVE_ON_LEFT :Linksverkehr +STR_02EA_DRIVE_ON_RIGHT :Rechtsverkehr +STR_02EB_TOWN_NAMES :{BLACK}Städtenamen +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Wähle Städtenamen in + +STR_02F4_AUTOSAVE :{BLACK}Auto-Sicherung +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Abstand zwischen den automatischen Spielesicherungen wählen +STR_02F7_OFF :Aus +STR_02F8_EVERY_3_MONTHS :Alle 3 Monate +STR_02F9_EVERY_6_MONTHS :Alle 6 Monate +STR_02FA_EVERY_12_MONTHS :Alle 12 Monate +STR_02FB_START_A_NEW_GAME :{BLACK}Ein neues Spiel beginnen +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Einen Spielstand laden +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Übung / Einführung +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Eine eigene Spielwelt / Szenario kreieren +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Ein-Spieler-Modus wählen +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Zwei-Spieler-Modus wählen +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Spieleinstellungen anzeigen +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Schwierigkeitsgrad anzeigen +STR_0303_START_A_NEW_GAME_USING :{BLACK}Starte ein neues Spiel in einem eigenen Szenario +STR_0304_QUIT :{BLACK}Beenden +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}'OpenTTD' verlassen und beenden +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Übung / Einführung anzeigen +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kann nur in Städten gebaut werden +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}'gemässigte' Landschaft auswählen +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}'subarktische' Landschaft auswählen +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}'subtropische' Landschaft auswählen +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}'fantastische' Landschaft auswählen +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Errichtung und Finanzierung einer neuen Industrie + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Neue Industrie finanzieren +STR_INDUSTRY_DIR :Industrieverzeichnis +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Neue Industrie finanzieren +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kann nur in Städten errichtet werden +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...kann nur im Regenwaldgebiet errichtet werden +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kann nur im Wüstengebiet errichtet werden +STR_0319_PAUSED :{YELLOW}* * ANGEHALTEN * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot ist gespeichert als '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot misslungen ! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Land für künftige Nutzung kaufen +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Fahrzeugreparatur +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Zugreparatur +STR_032C_3_AIR_SERVICE :{BLACK}3: Flugzeugreparatur +STR_032D_4_SHIP_SERVICE :{BLACK}4: Schiffreparatur +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Zugreparatur (verbessert) +STR_032F_AUTOSAVE :{RED}Auto-Speicherung +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Wähle 'Ezy Street style music'-Programm + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Englisch +STR_TOWNNAME_FRENCH :Französisch +STR_TOWNNAME_GERMAN :Deutsch +STR_TOWNNAME_AMERICAN :Amerikanisch +STR_TOWNNAME_LATIN_AMERICAN :Lateinamerikanisch +STR_TOWNNAME_SILLY :Verrückt +STR_TOWNNAME_SWEDISH :Schwedisch +STR_TOWNNAME_DUTCH :Niederländisch +STR_TOWNNAME_FINNISH :Finnisch +STR_TOWNNAME_POLISH :Polnisch +STR_TOWNNAME_SLOVAKISH :Slovakisch +STR_TOWNNAME_HUNGARIAN :Ungarisch +STR_TOWNNAME_AUSTRIAN :Österreichisch +############ end of townname region + +STR_CURR_POUNDS :Pfund ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollar ($) +STR_CURR_FF :Frz. Franc (FF) +STR_CURR_DM :Deutsche Mark (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseten (Pt) +STR_CURR_FT :Ungarische Forint (Ft) +STR_CURR_ZL :Polnische Zloty (zl) +STR_CURR_ATS :Österreich. Schilling (ATS) +STR_CURR_BEF :Belgische Franc (BEF) +STR_CURR_DKK :Dänische Kronen (DKK) +STR_CURR_FIM :Finnmark (FIM) +STR_CURR_GRD :Griech. Drachmen (GRD) +STR_CURR_CHF :Schweizer Franken (CHF) +STR_CURR_NLG :Niederländ. Gulden (NLG) +STR_CURR_ITL :Italienische Lira (ITL) +STR_CURR_SEK :Swedische Kronen (SEK) +STR_CURR_RUR :Russische Rubel (rur) +STR_CURR_CZK :Tschechische Koruna (CZK) +STR_CURR_ISK :Isländische Krona (ISK) +STR_CURR_NOK :Norwegische Kronen (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Sprache +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Sprache für die Oberfläche aussuchen + +STR_OPTIONS_RES :{BLACK} Bildschirmgröße +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Bildschirmgrösse auswählen + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Screenshot-Format +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Wähle das zu benutzende Screenshot-Format aus + +STR_AUTOSAVE_1_MONTH :Jeden Monat +STR_AUTOSAVE_FAILED :{WHITE}Autosicherung fehlgeschlagen + +STR_MONTH_JAN :Januar +STR_MONTH_FEB :Februar +STR_MONTH_MAR :März +STR_MONTH_APR :April +STR_MONTH_MAY :Mai +STR_MONTH_JUN :Juni +STR_MONTH_JUL :Juli +STR_MONTH_AUG :August +STR_MONTH_SEP :September +STR_MONTH_OCT :Oktober +STR_MONTH_NOV :November +STR_MONTH_DEC :Dezember + +STR_HEADING_FOR_STATION :{LTBLUE}Unterwegs zu {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Unterwegs zu {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Keine Aufträge +STR_NO_ORDERS_VEL :{LTBLUE}Keine Aufträge, {VELOCITY} + +STR_PASSENGERS :Passagiere +STR_BAGS :Säcke +STR_TONS :Tonnen +STR_LITERS :Liter +STR_ITEMS :Stück +STR_CRATES :Kisten +STR_RES_OTHER :Andere +STR_NOTHING :nichts + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Der Fahrplan kann nicht gemeinsam benutzt werden... +STR_CANT_COPY_ORDER_LIST :{WHITE}Kann Fahrplan nicht kopieren... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Ende des gemeinsamen Fahrplans - - + +STR_TRAIN_IS_LOST :{WHITE}Zug {COMMA16} findet den Weg nicht. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Einkommen von Zug {COMMA16} war letztes Jahr {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Einstellungen der Patches +STR_CONFIG_PATCHES_TIP :{BLACK}Einstellungen der Patches +STR_CONFIG_PATCHES_CAPTION :{WHITE}Einstellungen der Patches + +STR_CONFIG_PATCHES_OFF :Aus +STR_CONFIG_PATCHES_ON :An +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Zeige Fahrzeuggeschwindigkeit in der Statusleiste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Erlaube das Bauen an Hängen und Küsten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Erlaube die Entfernung von Industrien, weiteren Straßen usw.: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Erlaube das Bauen von sehr langen Zügen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Realistische Zugbeschleunigung aktivieren: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Bahnhöfe vereinigen, die nebeneinander gebaut werden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Verlasse die Station, wenn eine Fracht vollgeladen ist: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Keine automatische Zugwartung: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Liefere Fracht nur, wenn die Station diese annimmt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Erlaube das Bauen von sehr langen Brücken: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Erlaube "Gehe zum Depot"-Aufträge im Fahrplan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Erlaube das Bauen von rohstoffproduzierenden Industrien: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Erlaube mehrere gleichartige Industrien pro Stadt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Gleiche Industrien können nahe beieinander gebaut werden: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Lange Datumsanzeige in der Statusleiste (links unten): {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Zeige Signale auf der selben Seite wie den Straßenverkehr: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Zeige Firmenfinanzen am Ende des Jahres: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch kompatibles "Nonstop"-Verhalten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Fahrzeugwarteschlange (mit Mengenwirkung): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Karte scrollen, wenn die Maus am Rand (links/rechts) anstößt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Bestechen der Stadtverwaltung erlauben: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Neues Wegfinden für Depots: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Ungleichmäßige Bahnhöfe: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Neuen Algorithmus für die Züge zur Wegfindung benutzen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Im pausiertem Spiel bauen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Kleine Flughäfen immer erlauben: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Ein Zug ist verloren, wenn kein Fortschritt seit: {ORANGE}{STRING} Tagen +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Warnung anzeigen, wenn ein Zug negative Einnahmen hat: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Fahrzeug automatisch erneuern, wenn es alt wird +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Dauer der Fehlermeldung: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Höhe der Schneegrenze: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maximale Bahnhofsausbreitung: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Hubschrauber auf Helipads automatisch warten: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maximale Anzahl der Züge pro Spieler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maximale Anzahl der Straßenfahrzeuge pro Spieler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maximale Anzahl der Flugzeuge pro Spieler: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maximale Anzahl der Schiffe pro Spieler: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Züge für den Computer abschalten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Straßenfahrzeuge für den Computer abschalten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Flugzeuge für den Computer abschalten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Schiffe für den Computer abschalten: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Vorgegebener Wartungsintervall für Züge: {ORANGE}{STRING} Tage +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Vorgegebener Wartungsintervall für Straßenfahrzeuge: {ORANGE}{STRING} Tage +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Vorgegebener Wartungsintervall für Flugzeuge: {ORANGE}{STRING} Tage +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Vorgegebener Wartungsintervall für Schiffe: {ORANGE}{STRING} Tage + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Farbige Nachrichten erscheinen ab: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Startdatum: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Feinere Wirtschaft aktivieren (mehrere, kleinere Veränderungen) + +STR_CONFIG_PATCHES_GUI :{BLACK}Oberfläche +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstruktion +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Fahrzeuge +STR_CONFIG_PATCHES_STATIONS :{BLACK}Bahnhöfe +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Wirtschaft + +STR_CONFIG_PATCHES_DISABLED :ausgeschaltet +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Einstellungswert ändern + + +STR_CHEATS :{WHITE}Cheats +STR_CHEATS_TIP :{BLACK}Kontrollfelder zeigen, ob du diesen Cheat schonmal benutzt hast. +STR_CHEATS_WARNING :{BLACK}Achtung! Du bist im Begriff, deine Mitspieler zu betrügen. Denke daran, dass dies niemals vergessen werden wird. +STR_CHEAT_MONEY :{LTBLUE}Kontostand um {CURRENCY64} erhöhen +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Folgenden Spieler steuern: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Mächtigeres Abrisswerkzeug: {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunnel dürfen sich kreuzen {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Name +STR_TOWNDIR_POPULATION :{BLACK}Einwohner +STR_TOWNDIR_SORT_TIP :{BLACK}Wahl der Sortierreihenfolge + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Fahre zu {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Fahre zu {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Fahre über {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Wegpunkt {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Wegpunkt {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Wegpunkt + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Wegpunktename ändern + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Kann Wegpunktname nicht ändern... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Ändere Schiene zu einem Wegpunkt +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Kann Wegpunkt hier nicht bauen... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Kann Wegpunkt hier nicht entfernen... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Bauen von Schienen unter Verwendung des Autorailmodus + +STR_TREES_RANDOM_TYPE :{BLACK}Zufällige Baumart +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Zufällige Baumart platzieren + +STR_CANT_BUILD_CANALS :{WHITE}Kann hier keinen Kanal bauen... +STR_BUILD_CANALS_TIP :{BLACK}Kanal bauen +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Kann hier keine Schleuse bauen... +STR_BUILD_LOCKS_TIP :{BLACK}Schleusen bauen +STR_LANDINFO_LOCK :Schleuse + +STR_LANDINFO_COORDS :{BLACK}Koordinaten: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Kann den Teil des Bahnhofs nicht entfernen... +STR_CANT_CONVERT_RAIL :{WHITE}Kann Gleistyp hier nicht verändern... +STR_CONVERT_RAIL_TIP :{BLACK}Konvertiere / Erweitere den Typ des Gleises + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Zugmaschine hierher ziehen, um den ganzen Zug zu verkaufen + +STR_DRAG_DROP :{BLACK}Drag & Drop +STR_STATION_DRAG_DROP :{BLACK}Bahnhof mittels 'Drag & Drop' bauen + +STR_FAST_FORWARD :{BLACK}Spiel vorspulen +STR_MESSAGE_HISTORY :{WHITE}Vorhergehende Nachrichten + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Kohlebergwerk errichten +STR_CONSTRUCT_FOREST_TIP :{BLACK}Wald aufforsten +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Ölbohrinsel errichten +STR_CONSTRUCT_FARM_TIP :{BLACK}Bauernhof errichten +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Kupfermine errichten +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Nach Öl bohren +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Goldmine errichten +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Diamantenmine errichten +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Eisenerzmine errichten +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Fruchtplantage aufforsten +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Kautschukplantage aufforsten +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Wasserquelle errichten +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Zuckerwattewald anbauen +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Batteriefarm anbauen +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Nach Cola bohren +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Platikbrunnen anbauen +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Luftblasengenerator errichten +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Karamellgrube anbauen +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Zuckermine errichten + +STR_INDUSTRYDIR_NAME :{BLACK}Name +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produktion +STR_INDUSTRYDIR_TYPE :{BLACK}Typ +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrien +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...zu nah an einer anderen Industrie + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Umrüstung des Zuges zur Beförderung anderer Frachten +STR_RAIL_REFIT :{WHITE}{STRING} (Umrüsten) +STR_RAIL_REFIT_VEHICLE :{BLACK}Zug umrüsten +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wähle die Frachten aus, die der Zug befördern soll +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Umrüstung des Zuges auf die ausgewählte Frachtart +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Kann den Zug nicht umrüsten... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Kosten: {CURRENCY} +STR_0801_COST :{RED}Kosten: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Einnahmen: {CURRENCY} +STR_0803_INCOME :{GREEN}Einnahmen: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Geschätzte Kosten: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Geschätzte Kosten: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Geschätzte Einnahmen: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Geschätzte Einnahmen: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Kann das Land nicht anheben... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Kann das Land nicht absenken... +STR_080A_ROCKS :Gebirge +STR_080B_ROUGH_LAND :Unebenes Land +STR_080C_BARE_LAND :Kahles Land +STR_080D_GRASS :Gras +STR_080E_FIELDS :Felder +STR_080F_SNOW_COVERED_LAND :Schneebedecktes Land +STR_0810_DESERT :Wüste + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Das Land neigt sich in die falsche Richtung +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Unmögliche Gleisverbindung +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Die Ausschachtung würde den Tunnel zerstören +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Ist bereits auf Meereshöhe +STR_1004_TOO_HIGH :{WHITE}Zu hoch +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Keine geeigneten Gleise +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Zug ist im Depot +STR_1007_ALREADY_BUILT :{WHITE}...ist bereits gebaut +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Gleise müssen erst entfernt werden +STR_1009_TOO_MANY_DEPOTS :{WHITE}Zu viele Depots +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Gleis- / Bahnhofsbau +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Monorailbau +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Magnetschwebebahnbau +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Eisenbahnbrücke auswählen +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Kann hier kein Zugdepot bauen... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Kann hier keinen Bahnhof bauen... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Kann hier kein Signal aufstellen... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Kann hier keine Gleise legen... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Gleise können nicht abgerissen werden... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Kann die Signale hier nicht entfernen... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Zugdepot-Ausrichtung +STR_1015_RAILROAD_CONSTRUCTION :Eisenbahnbau +STR_1016_MONORAIL_CONSTRUCTION :Monorailbau +STR_1017_MAGLEV_CONSTRUCTION :Magnetschwebebahnbau +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Gleise legen +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Zugdepot bauen (zum Bau und zur Wartung von Zügen) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Bahnhof bauen +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Signale errichten +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Bahnbrücken bauen +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Eisenbahntunnel bauen +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Umschalter für Bau/Abriss von Gleisen und Signalen +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Brückenauswahl - klicke auf die gewählte Brücke, um sie zu bauen +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Ausrichtung des Zugdepotes auswählen +STR_1021_RAILROAD_TRACK :Gleis +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Gleis mit Signal +STR_1023_RAILROAD_TRAIN_DEPOT :Zugdepot +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...Gelände gehört jemand anderem +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Gleis mit normalen Signalen +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Gleis mit Vorsignalen +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Gleis mit Ausfahrtsignalen +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Gleis mit kombinierten Vor-/Ausfahrtsignalen + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Das Land neigt sich in die falsche Richtung +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Straße muss erst entfernt werden +STR_1802_ROAD_CONSTRUCTION :{WHITE}Straßenbau +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Brücke wählen +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Kann hier keine Straße bauen... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Kann diese Straße nicht entfernen... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Fahrzeugdepot-Ausrichtung +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kann Fahrzeugdepot hier nicht bauen... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Kann Busbahnhof nicht bauen... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kann Lkw-Ladeplatz nicht bauen... +STR_180A_ROAD_CONSTRUCTION :Straßenbau +STR_180B_BUILD_ROAD_SECTION :{BLACK}Straße bauen +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Fahrzeugdepot bauen (zum Bau und zur Wartung von Fahrzeugen) +STR_180D_BUILD_BUS_STATION :{BLACK}Busbahnhof bauen +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Lkw-Ladeplatz bauen +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Straßenbrücke bauen +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Straßentunnel bauen +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Zwischen Bau/Abriss der Straße umschalten +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Brückenauswahl - klicke auf die ausgewählte Brücke, um sie zu bauen +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Ausrichtung des Fahrzeugdepots wählen +STR_1814_ROAD :Straße +STR_1815_ROAD_WITH_STREETLIGHTS :Straße mit Laternen +STR_1816_TREE_LINED_ROAD :Straße mit Bäumen +STR_1817_ROAD_VEHICLE_DEPOT :Fahrzeugdepot +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Bahnübergang + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Städte +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Gebäude muss erst abgerissen werden +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Bevölkerung: {ORANGE}{COMMA32}{BLACK} Häuser: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Stadt umbenennen +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Die Stadt kann nicht umbenannt werden... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} Die Stadtverwaltung erteilt keine Genehmigung +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Städtenamen - klicke auf den Namen, um die Stadt anzuzeigen +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Ansicht auf Stadt zentrieren +STR_200C_CHANGE_TOWN_NAME :{BLACK}Stadt umbenennen +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagiere letzten Monat: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Post letzten Monat: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Hohes Geschäftshaus +STR_2010_OFFICE_BLOCK :Geschäftshaus +STR_2011_SMALL_BLOCK_OF_FLATS :Kleines Wohnhaus +STR_2012_CHURCH :Kirche +STR_2013_LARGE_OFFICE_BLOCK :Großes Geschäftshaus +STR_2014_TOWN_HOUSES :Stadthaus +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Statue +STR_2017_FOUNTAIN :Springbrunnen +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Geschäftshaus +STR_201A_SHOPS_AND_OFFICES :Läden und Büros +STR_201B_MODERN_OFFICE_BUILDING :Modernes Geschäftshaus +STR_201C_WAREHOUSE :Kaufhaus +STR_201D_OFFICE_BLOCK :Geschäftshaus +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Alte Häuser +STR_2020_LOCAL_AUTHORITY :{BLACK}Stadtverwaltung +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Zeige Einzelheiten der Stadtverwaltung +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} Stadtverwaltung +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Bewertung der Transportfirma : +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subventionen +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Subventionsangebot für:- +STR_2027_FROM_TO :{ORANGE}{STRING} von {STRING} nach {STRING} +STR_2028_BY :{YELLOW} (bis {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Keine +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Bereits vergebene Subventionen:- +STR_202C_FROM_TO :{ORANGE}{STRING} von {STATION} nach {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, bis {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Subventionsangebot abgelaufen:{}{}{STRING} von {STRING} nach {STRING} wird nicht mehr subventioniert. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subventionsende: {}{}{STRING} Dienstleistung von {STATION} nach {STATION} wird nicht mehr subventioniert. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Subventionsangebot {}{}Erster {STRING}transport von {STRING} nach {STRING} wird ein Jahr von der Stadtverwaltung subventioniert! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention wird vergeben an {STRING}!{}{}{STRING}transport von {STATION} nach {STATION} bringt im nächsten Jahr einen 50% höheren Frachtpreis! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention wird vergeben an {STRING}!{}{}{STRING}transport von {STATION} nach {STATION} bringt im nächsten Jahr den doppelten Frachtpreis! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention wird vergeben an {STRING}!{}{}{STRING}transport von {STATION} nach {STATION} bringt im nächsten Jahr den dreifachen Frachtpreis! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention wird vergeben an {STRING}!{}{}{STRING}transport von {STATION} nach {STATION} bringt im nächsten Jahr den vierfachen Frachtpreis! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} Die Stadtverwaltung erlaubt keinen weiteren Bau eines Flughafens in der Stadt +STR_2036_COTTAGES :Landhaus +STR_2037_HOUSES :Haus +STR_2038_FLATS :Wohnhaus +STR_2039_TALL_OFFICE_BLOCK :Hohes Geschäftshaus +STR_203A_SHOPS_AND_OFFICES :Läden und Büros +STR_203B_SHOPS_AND_OFFICES :Läden und Büros +STR_203C_THEATER :Theater +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Büros +STR_203F_HOUSES :Häuser +STR_2040_CINEMA :Kino +STR_2041_SHOPPING_MALL :Einkaufszentrum +STR_2042_DO_IT :{BLACK}Tu es +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Liste der verfügbaren Handlungen in dieser Stadt - klicke hier für Einzelheiten +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Ausführung der markierten Handlung +STR_2045_ACTIONS_AVAILABLE :{BLACK}Verfügbare Handlungen: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Kleine Werbekampagne +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Mittlere Werbekampagne +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Große Werbekampagne +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Straßenreparaturen des Ortes finanzieren +STR_204A_BUILD_STATUE_OF_COMPANY :Statue des Transporteigentümers finanzieren +STR_204B_FUND_NEW_BUILDINGS :Neue Gebäude finanzieren +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Exklusive Transportrechte kaufen +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Die Stadtverwaltung bestechen +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Führen Sie im Ort eine kleine Werbekampagne durch, um mehr Passagier- und Frachtaufträge für das Unternehmen zu gewinnen.{} Kosten: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Führen Sie im Ort eine mittlere Werbekampagne durch, um mehr Passagier- und Frachtaufträge für das Unternehmen zu gewinnen.{} Kosten: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Führen Sie im Ort eine große Werbekampagne durch, um mehr Passagier- und Frachtaufträge für das Unternehmen zu gewinnen.{} Kosten: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Finanzieren Sie die örtlichen Straßenreparaturen. Der Straßenverkehr wird bis zu 6 Monate beeinträchtigt.{} Kosten: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Errichten Sie eine Statue in Ehre an den Transporteigentümer.{} Kosten: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Finanzieren Sie den Bau kommerzieller Gebäude im Ort.{} Kosten: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Kaufen Sie für 1 Jahre die exklusiven Transportrechte der Stadt. Die Stadtverwaltung erlaubt nur Passagier- und Frachttransporte für Ihr Unternehmen.{} Kosten: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Bestechen Sie die Stadtverwaltung, um Ihre Bewertung zu verbessern. Dabei riskieren Sie allerdings eine harte Strafe, falls Sie ertappt werden.{} Kosten: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Leider nicht möglich... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Verkehrschaos in {TOWN}!{}{}Straßensanierungsprogramm finanziert durch {STRING} werden 6 Monate lang Verzögerungen im Verkehr bewirken! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (in Bearbeitung) +STR_2059_IGLOO :Iglu +STR_205A_TEPEES :Zelt +STR_205B_TEAPOT_HOUSE :Teekannenhaus +STR_205C_PIGGY_BANK :Piggy-Bank + +##id 0x2800 +STR_2800_PLANT_TREES :Bäume pflanzen +STR_2801_PLACE_SIGN :Schild aufstellen +STR_2802_TREES :{WHITE}Bäume +STR_2803_TREE_ALREADY_HERE :{WHITE}...hier sind bereits Bäume +STR_2804_SITE_UNSUITABLE :{WHITE}...ungeeignetes Gelände +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Schild kann hier nicht aufgestellt werden... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...zu viele Schilder +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Schild kann hier nicht aufgestellt werden... +STR_280A_SIGN :Schild +STR_280B_EDIT_SIGN_TEXT :{WHITE}Schildtext ändern +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Kann Schildnamen nicht ändern... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Wähle die zu pflanzende Baumart +STR_280E_TREES :Bäume +STR_280F_RAINFOREST :Regenwald +STR_2810_CACTUS_PLANTS :Kakteen + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Bahnhof bauen +STR_3001_AIRPORT_SELECTION :{WHITE}Flughafen bauen +STR_3002_ORIENTATION :{BLACK}Ausrichtung +STR_3003_NUMBER_OF_TRACKS :{BLACK}Anzahl der Gleise +STR_3004_PLATFORM_LENGTH :{BLACK}Bahnsteiglänge +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Zu nah an einem anderen Bahnhof +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grenzt an mehr als eine vorhandene Station/Ladeplatz +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Zu viele Stationen/Ladeplätze im Stadtgebiet +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Zu viele Stationen/Ladeplätze im Umkreis +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Stationen/Ladeplätze liegen zu dicht beisammen +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Bahnhof muss erst abgerissen werden +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Zu dicht an einem anderen Flughafen +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Flughafen muss erst abgerissen werden + +STR_3030_RENAME_STATION_LOADING :Station/Ladeplatz umbenennen +STR_3031_CAN_T_RENAME_STATION :{WHITE}Kann die Station nicht umbenennen... +STR_3032_RATINGS :{BLACK}Einschätzung +STR_3033_ACCEPTS :{BLACK}Akzeptiert +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Örtliche Bewertung der Transportunternehmen: + +############ range for rating starts +STR_3035_APPALLING :Furchtbar +STR_3036_VERY_POOR :Sehr schlecht +STR_3037_POOR :Schlecht +STR_3038_MEDIOCRE :Mittelmäßig +STR_3039_GOOD :Gut +STR_303A_VERY_GOOD :Sehr gut +STR_303B_EXCELLENT :Ausgezeichnet +STR_303C_OUTSTANDING :Hervorragend +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} akzeptiert keine {STRING} mehr +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} akzeptiert keine {STRING} oder {STRING} mehr +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} akzeptiert jetzt {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} akzeptiert jetzt {STRING} und {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Ausrichtung des Busbahnhofes +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Ausrichtung des Lkw-Ladeplatzes +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Zu dicht an einem anderen Busbahnhof +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Zu dicht an einer anderen Lkw-Ladestation +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Der Busbahnhof muss erst abgerissen werden +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Der Lkw-Ladeplatz muss erst abgerissen werden +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Haltestellen +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Keine - +STR_304B_SITE_UNSUITABLE :{WHITE}...Gelände ungeeignet +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Zu dicht an einem anderen Hafen +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Hafen muss erst entfernt werden +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Bahnhofausrichtung auswählen +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Anzahl der Bahnsteige wählen +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Bahnsteiglänge wählen +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Busbahnhofsausrichtung wählen +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Ladeplatzausrichtung wählen +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Ansicht auf die Station zentrieren +STR_3054_SHOW_STATION_RATINGS :{BLACK}Stationsbewertung anzeigen +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Name der Station ändern +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Zeige Liste der akzeptierten Frachten +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Stationsnamen - Klicke auf den Namen, um die Station anzuzeigen +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Wähle die Größe/Art des Flughafens +STR_3059_SMALL :{BLACK}klein +STR_305A_LARGE :{BLACK}mittel +STR_305AA_LARGE :{BLACK}Großstädtischer Flughafen +STR_305AB_LARGE :{BLACK}Internationaler Flughafen +STR_305B_SIZE :{BLACK}Größe +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Bahnhof +STR_305F_AIRCRAFT_HANGAR :Flugzeughangar +STR_3060_AIRPORT :Flughafen +STR_3061_TRUCK_LOADING_AREA :Lkw-Ladeplatz +STR_3062_BUS_STATION :Busbahnhof +STR_3063_SHIP_DOCK :Schiffshafen +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Einzugsgebiet angezeigen +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Einzugsgebiet nicht angezeigen +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Zeige Einzugsgebiet +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Wähle Monorailbahnhof. +STR_3068_DOCK :{WHITE}Hafen +STR_3069_BUOY :Boje +STR_306A_BUOY_IN_THE_WAY :{WHITE}...Boje ist im Weg +STR_306B_HELIPORT :{BLACK}Heliport +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...Bahnhof ist zu groß + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Werft-Ausrichtung +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...muss auf Wasser gebaut werden +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Kann hier keine Werft bauen... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Werftausrichtung auswählen +STR_3804_WATER :Wasser +STR_3805_COAST_OR_RIVERBANK :Küste oder Flussufer +STR_3806_SHIP_DEPOT :Werft +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...kann nicht auf Wasser gebaut werden + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Spiel speichern +STR_4001_LOAD_GAME :{WHITE}Spiel laden +STR_4002_SAVE :{BLACK}Speichern +STR_4003_DELETE :{BLACK}Löschen +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} Megabytes frei +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Kann vom Laufwerk nicht lesen +STR_4007_GAME_SAVE_FAILED :{WHITE}Spielspeicherung fehlgeschlagen +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Datei kann nicht gelöscht werden +STR_4009_GAME_LOAD_FAILED :{WHITE}Laden des Spieles fehlgeschlagen +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Liste der Laufwerke, Verzeichnisse und gespeicherten Spiele +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Ausgewählter Spielname +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Lösche gewählten Spielstand +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Speichere das Spiel unter dem gewählten Namen +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Neues Spiel auswählen +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Wähle Szenario (grün), vorgegebens Spiel (blau), oder ein Spiel nach dem Zufallsprinzip +STR_4010_GENERATE_RANDOM_NEW_GAME :Spiel nach Zufallsprinzip erstellen + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} im Weg +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kohlebergwerk +STR_4803_POWER_STATION :Kraftwerk +STR_4804_SAWMILL :Sägewerk +STR_4805_FOREST :Wald +STR_4806_OIL_REFINERY :Ölraffinerie +STR_4807_OIL_RIG :Ölbohrinsel +STR_4808_FACTORY :Fabrik +STR_4809_PRINTING_WORKS :Druckerei +STR_480A_STEEL_MILL :Stahlwerk +STR_480B_FARM :Bauernhof +STR_480C_COPPER_ORE_MINE :Kupfermine +STR_480D_OIL_WELLS :Ölquellen +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Nahrungsmittelfabrik +STR_4810_PAPER_MILL :Papiermühle +STR_4811_GOLD_MINE :Goldmine +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamantenmine +STR_4814_IRON_ORE_MINE :Eisenerzmine +STR_4815_FRUIT_PLANTATION :Fruchtplantage +STR_4816_RUBBER_PLANTATION :Kautschukplantage +STR_4817_WATER_SUPPLY :Wasserquelle +STR_4818_WATER_TOWER :Wasserturm +STR_4819_FACTORY :Fabrik +STR_481A_FARM :Bauernhof +STR_481B_LUMBER_MILL :Holzmühle +STR_481C_COTTON_CANDY_FOREST :Zuckerwattewald +STR_481D_CANDY_FACTORY :Bonbonfabrik +STR_481E_BATTERY_FARM :Batterieplantage +STR_481F_COLA_WELLS :Colaquellen +STR_4820_TOY_SHOP :Spielwarengeschäft +STR_4821_TOY_FACTORY :Spielwarenfabrik +STR_4822_PLASTIC_FOUNTAINS :Plastikbrunnen +STR_4823_FIZZY_DRINK_FACTORY :Limonadefabrik +STR_4824_BUBBLE_GENERATOR :Luftblasengenerator +STR_4825_TOFFEE_QUARRY :Karamellgrube +STR_4826_SUGAR_MINE :Zuckermine + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Benötigt: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Benötigt: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Benötigt: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produktion im letzten Monat: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% befördert) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Zentriere die Ansicht auf das Industriegebiet +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Neue(s) {STRING} wird nahe {TOWN} gebaut! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Neue(r) {STRING} wird nahe {TOWN} aufgeforstet! +STR_482F_COST :{BLACK}Kosten: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Kann diese Industrie hier nicht bauen... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...Wald kann nur oberhalb der Schneegrenze gepflanzt werden +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} gibt bevorstehende Schließung bekannt! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Wegen fehlender Rohstoffe kündigt {TOWN} {STRING} die drohende Schließung an! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Wegen Holzmangel gibt {TOWN} {STRING} die bevorstehende Schließung bekannt! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} erhöht die Produktion ! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Neue Kohlevorkommen bei {TOWN} {STRING} gefunden!{}Förderung verdoppelt! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Neue Ölfunde bei {TOWN} {STRING}!{}Förderung wird vermutlich verdoppelt! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Neue Getreideanbaumethoden bei {TOWN} {STRING} werden Erträge verdoppeln! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} Produktion sinkt um 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insektenplage bei {TOWN} {STRING} verursacht Schaden!{}Produktion sinkt um 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...kann nur in der Nähe vom Kartenrand errichtet werden +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING}produktion bei {TOWN} {STRING} erhöht sich um {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING}produktion bei {TOWN} {STRING} verringert sich um {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Zug im Tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Fahrzeug im Tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Ein anderer Tunnel ist im Weg +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Kann das Land am anderen Ende des Tunnels nicht anheben +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Der Tunnel muss zuerst abgerissen werden +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Die Brücke muss erst abgerissen werden +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Anfang und Ende können nicht im selben Feld liegen +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Ebenes Land oder Wasser muss unter der Brücke sein +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Anfang und Ende müssen auf einer Ebene liegen +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Platz ist nicht für einen Tunnel geeignet +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Stahl-Hängebrücke +STR_500F_GIRDER_STEEL :Stahl-Trägerbrücke +STR_5010_CANTILEVER_STEEL :Selbsttragende Stahlbrücke +STR_5011_SUSPENSION_CONCRETE :Beton-Hängebrücke +STR_5012_WOODEN :Holzbrücke +STR_5013_CONCRETE :Betonbrücke +STR_5014_TUBULAR_STEEL :Rundstahlbrücke +STR_BRIDGE_TUBULAR_SILICON :Silizium-Rundbrücke +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Kann die Brücke hier nicht bauen... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kann den Tunnel hier nicht bauen... +STR_5017_RAILROAD_TUNNEL :Eisenbahntunnel +STR_5018_ROAD_TUNNEL :Straßentunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Stahl-Hängebrücke +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Stahl-Trägerbrücke +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Selbsttragende Stahlbrücke +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Stahlbetonbrücke +STR_501F_WOODEN_RAIL_BRIDGE :Holzbrücke +STR_5020_CONCRETE_RAIL_BRIDGE :Betonbrücke +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Stahl-Hängebrücke +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Stahl-Trägerbrücke +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Selbsttragende Stahlbrücke +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Stahlbetonbrücke +STR_5025_WOODEN_ROAD_BRIDGE :Holzbrücke +STR_5026_CONCRETE_ROAD_BRIDGE :Betonbrücke +STR_5027_TUBULAR_RAIL_BRIDGE :Rundstahlbrücke +STR_5028_TUBULAR_ROAD_BRIDGE :Rundstahlbrücke +STR_5029_STEEL :Stahl + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Gegenstand im Weg +STR_5801_TRANSMITTER :Sender +STR_5802_LIGHTHOUSE :Leuchtturm +STR_5803_COMPANY_HEADQUARTERS :Firmensitz +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...Firmensitz ist im Weg +STR_5805_COMPANY_OWNED_LAND :Firmeneigenes Gelände +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Das Land kann nicht erworben werden... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...Sie besitzen es bereits! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Unbenannt{SKIP} +STR_SV_TRAIN_NAME :Zug {COMMA16} +STR_SV_ROADVEH_NAME :Fahrzeug {COMMA16} +STR_SV_SHIP_NAME :Schiff {COMMA16} +STR_SV_AIRCRAFT_NAME :Flugzeug {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Nord +STR_SV_STNAME_SOUTH :{STRING} Süd +STR_SV_STNAME_EAST :{STRING} Ost +STR_SV_STNAME_WEST :{STRING} West +STR_SV_STNAME_CENTRAL :{STRING} Zentral +STR_SV_STNAME_TRANSFER :{STRING} Transfer +STR_SV_STNAME_HALT :{STRING} Halt +STR_SV_STNAME_VALLEY :{STRING} Tal +STR_SV_STNAME_HEIGHTS :{STRING} Höhe +STR_SV_STNAME_WOODS :{STRING} Wald +STR_SV_STNAME_LAKESIDE :{STRING} Seeblick +STR_SV_STNAME_EXCHANGE :{STRING} Zentral +STR_SV_STNAME_AIRPORT :{STRING} Flughafen +STR_SV_STNAME_OILFIELD :{STRING} Ölfeld +STR_SV_STNAME_MINES :{STRING} Mine +STR_SV_STNAME_DOCKS :{STRING} Hafen +STR_SV_STNAME_BUOY_1 :{STRING} Boje 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boje 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boje 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boje 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boje 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boje 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boje 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boje 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boje 9 +STR_SV_STNAME_ANNEXE :{STRING} Anbau +STR_SV_STNAME_SIDINGS :{STRING} Nebengleis +STR_SV_STNAME_BRANCH :{STRING} Zweig +STR_SV_STNAME_UPPER :Obere {STRING} +STR_SV_STNAME_LOWER :Untere {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Wald + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Schwierigkeitsgrad + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Leicht +STR_6802_MEDIUM :{BLACK}Normal +STR_6803_HARD :{BLACK}Schwer +STR_6804_CUSTOM :{BLACK}Individuell +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Max. Gegenspielerzahl: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Gegenspieler-Startzeit: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Städteanzahl: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Industriedichte: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Höhe des Anfangskredites: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Kreditzinsen: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Fahrzeug-Betriebskosten: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Baugeschwindigkeit der Gegenspieler: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligenz der Gegenspieler: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Fahrzeugpannen: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Subventionsmultiplikator: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Baukosten: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Landschaftsform: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Wasseranteil: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Wirtschaft: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Zug umkehren: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katastrophen: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Niedrig +STR_6817_NORMAL :Normal +STR_6818_HIGH :Hoch +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Sehr langsam +STR_681C_SLOW :Langsam +STR_681D_MEDIUM :Mittel +STR_681E_FAST :Schnell +STR_681F_VERY_FAST :Sehr schnell +STR_VERY_LOW :Sehr niedrig +STR_6820_LOW :Niedrig +STR_6821_MEDIUM :Mittel +STR_6822_HIGH :Hoch +STR_6823_NONE :Keine +STR_6824_REDUCED :Verringert +STR_6825_NORMAL :Normal +STR_6826_X1_5 :x1,5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Sehr flach +STR_682B_FLAT :Flach +STR_682C_HILLY :Hügelig +STR_682D_MOUNTAINOUS :Bergig +STR_682E_STEADY :Ruhig +STR_682F_FLUCTUATING :Schwankend +STR_6830_IMMEDIATE :Zusammen mit dem Spieler +STR_6831_3_MONTHS_AFTER_PLAYER :3 Monate nach dem Spieler +STR_6832_6_MONTHS_AFTER_PLAYER :6 Monate nach dem Spieler +STR_6833_9_MONTHS_AFTER_PLAYER :9 Monate nach dem Spieler +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Am Streckenende und bei Bahnhöfe +STR_6835_AT_END_OF_LINE_ONLY :Nur am Streckenende +STR_6836_OFF :Aus +STR_6837_ON :An +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Highscoretabelle zeigen + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Spieler 1) +STR_7003_PLAYER_2 : (Spieler 2) +STR_7004_NEW_FACE :{BLACK}Neues Gesicht +STR_7005_COLOR_SCHEME :{BLACK}Farbauswahl +STR_7006_COLOR_SCHEME :{GOLD}Farbauswahl: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Neue Farbauswahl +STR_7008_COMPANY_NAME :{BLACK}Firmenname +STR_7009_PRESIDENT_NAME :{BLACK}Managername +STR_700A_COMPANY_NAME :Firmenname +STR_700B_PRESIDENT_S_NAME :Name des Managers +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Firmenname kann nicht geändert werden... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Mannagername kann nicht geändert werden... +STR_700E_FINANCES :{WHITE}{STRING} Finanzen {BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Ausgaben / Einnahmen +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Baukosten +STR_7012_NEW_VEHICLES :{GOLD}Neue Fahrzeuge +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Betriebskosten Züge +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Betriebskosten Fahrzeug +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Betriebskosten Flugzeuge +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Betriebskosten Schiffe +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Betriebskosten Gebäude +STR_7018_TRAIN_INCOME :{GOLD}Einnahmen Züge +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Einnahmen Fahrzeug +STR_701A_AIRCRAFT_INCOME :{GOLD}Einnahmen Flugzeuge +STR_701B_SHIP_INCOME :{GOLD}Einnahmen Schiffe +STR_701C_LOAN_INTEREST :{GOLD}Kreditzinsen +STR_701D_OTHER :{GOLD}Sonstiges +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Gesamt: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Einkommensdiagramm +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Betriebsgewinn-Diagramm +STR_7026_BANK_BALANCE :{WHITE}Kontostand +STR_7027_LOAN :{WHITE}Kredit +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}{SKIP}{SKIP}{SKIP}{CURRENCY} leihen +STR_702A_REPAY :{BLACK}{SKIP}{SKIP}{SKIP}{CURRENCY} zurückzahlen +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...Maximaler Kredit ist {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Kann keinen weiteren Kredit aufnehmen ... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...kein Kredit zum zurückzahlen +STR_702E_REQUIRED :{WHITE}...{CURRENCY} benötigt +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Kredit kann nicht getilgt werden... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Neues Profil für Manager aussuchen +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Farbauswahl ändern für Firma +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Managername ändern +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Firmenname ändern +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Auf die ausgewählte neue Farbe klicken +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Kredites aufnehmen +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Kredites abzahlen +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Manager) +STR_7038_INAUGURATED :{GOLD}Gegründet: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Fahrzeuge: +STR_703A_TRAIN :{WHITE}{COMMA16} Zug +STR_703B_TRAINS :{WHITE}{COMMA16} Züge +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} Fahrzeug +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} Fahrzeuge +STR_703E_AIRCRAFT :{WHITE}{COMMA16} Flugzeug +STR_703F_AIRCRAFT :{WHITE}{COMMA16} Flugzeuge +STR_7040_SHIP :{WHITE}{COMMA16} Schiff +STR_7041_SHIPS :{WHITE}{COMMA16} Schiffe +STR_7042_NONE :{WHITE}Keine +STR_7043_FACE_SELECTION :{WHITE}Gesicht auswählen +STR_7044_MALE :{BLACK}Männlich +STR_7045_FEMALE :{BLACK}Weiblich +STR_7046_NEW_FACE :{BLACK}Neues Gesicht +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Gesichtswahl abbrechen +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Gesichtswahl übernehmen +STR_7049_SELECT_MALE_FACES :{BLACK}Wähle männliches Gesicht aus +STR_704A_SELECT_FEMALE_FACES :{BLACK}Wähle weibliches Gesicht aus +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Wähle zufälliges neues Gesicht +STR_704C_KEY :{BLACK}Schlüssel +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Aufschlüsselung für Diagramm +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Schlüssel für Firmen - Diagramm +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Hier klicken um Frachttyp ein-/auszuschalten +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Beförderte Frachteinheiten +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Bewertung der Firmenleistung (Höchstwert = 1000) +STR_7052_COMPANY_VALUES :{WHITE}Firmenwert-Diagramm +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Firmentabelle +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transportfirma in der Krise ! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} Falls die Firmenleitung sich nicht bessert, wird der Verkauf oder die Insolvenz eingeleitet! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Manager) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Transportfirmen fusionieren! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} ist verkauft worden an {STRING} für {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Wir suchen jemanden, der die Firma übernimmt.{}{}Nehmen Sie das Angebot an und kaufen {STRING} für {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Insolvenz !! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} ist von den Gläubigern geschlossen worden, alles Vermögen wurde veräussert ! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Neue Transportfirma gegründet ! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} startet bei {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Kann die Firma nicht kaufen... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Frachtbeförderungspreise +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Tage unterwegs +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Zahlung für 10 gelieferte Einheiten (oder 10.000 Liter) Fracht über eine Strecke von 20 Quadraten +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Diagrammschalter für Frachttyp ein/aus +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingenieur +STR_7067_TRAFFIC_MANAGER :Verkehrsmanager +STR_7068_TRANSPORT_COORDINATOR :Fuhrparkleiter +STR_7069_ROUTE_SUPERVISOR :Streckenmanager +STR_706A_DIRECTOR :Direktor +STR_706B_CHIEF_EXECUTIVE :Geschäftsführer +STR_706C_CHAIRMAN :Vorsitzender +STR_706D_PRESIDENT :Manager +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Firmensitz bauen +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Firmensitz bauen / anzeigen +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Kann keinen Firmensitz bauen ... +STR_7072_VIEW_HQ :{BLACK}Zeige Firmensitz +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Weltwirtschaftskrise!{}{}Finanzexperten befürchten schlimmsten Zusammenbruch der Wirtschaft! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Wirtschaftskrise beendet!{}{}Aufschwung des Handels gibt Vertrauen in die Industrie und stärkt die Wirtschaft! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Schalter für großes/kleines Fenster +STR_7076_COMPANY_VALUE :{GOLD}Firmenwert : {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Kaufe 25% Anteil an Firma +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Verkaufe 25% Anteil an Firma +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kaufe 25% Anteil an dieser Firma +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Verkaufe 25% Anteil an dieser Firma +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Kann 25% Anteil an dieser Firma nicht kaufen... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Kann 25% Anteil an dieser Firma nicht verkaufen... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% Eigentum von {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% Eigentum von {STRING}{} {COMMA16}% Eigentum von {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} wurde von {STRING} übernommen! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Dampf) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Dampf) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Dampf) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Dampf) +STR_800A_SH_8P_STEAM :SH '8P' (Dampf) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektrisch) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektrisch) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektrisch) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektrisch) +STR_801B_PASSENGER_CAR :Passagierwagen +STR_801C_MAIL_VAN :Postwagen +STR_801D_COAL_CAR :Kohlenwagen +STR_801E_OIL_TANKER :Öltanker +STR_801F_LIVESTOCK_VAN :Viehtransporter +STR_8020_GOODS_VAN :Güterwagen +STR_8021_GRAIN_HOPPER :Getreidetransporter +STR_8022_WOOD_TRUCK :Holzlastwagen +STR_8023_IRON_ORE_HOPPER :Eisenerzwagen +STR_8024_STEEL_TRUCK :Stahltransporter +STR_8025_ARMORED_VAN :Sicherheitstransporter +STR_8026_FOOD_VAN :Lebensmitteltransporter +STR_8027_PAPER_TRUCK :Papiertransporter +STR_8028_COPPER_ORE_HOPPER :Kupfererzwagen +STR_8029_WATER_TANKER :Wassertanker +STR_802A_FRUIT_TRUCK :Fruchttransporter +STR_802B_RUBBER_TRUCK :Kautschukwagen +STR_802C_SUGAR_TRUCK :Zuckerlaster +STR_802D_COTTON_CANDY_HOPPER :Zuckerwattewagen +STR_802E_TOFFEE_HOPPER :Karamellwagen +STR_802F_BUBBLE_VAN :Luftblasentransporter +STR_8030_COLA_TANKER :Colatanker +STR_8031_CANDY_VAN :Bonbontransporter +STR_8032_TOY_VAN :Spielwarentransporter +STR_8033_BATTERY_TRUCK :Batterielaster +STR_8034_FIZZY_DRINK_TRUCK :Limonadenspudeltransporter +STR_8035_PLASTIC_TRUCK :Plastiklaster +STR_8036_X2001_ELECTRIC :'X2001' (Elektrisch) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektrisch) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Passagierwagen +STR_803A_MAIL_VAN :Postwagen +STR_803B_COAL_CAR :Kohlewagen +STR_803C_OIL_TANKER :Öltanker +STR_803D_LIVESTOCK_VAN :Viehtransporter +STR_803E_GOODS_VAN :Warenwagen +STR_803F_GRAIN_HOPPER :Getreidewagen +STR_8040_WOOD_TRUCK :Holzwagen +STR_8041_IRON_ORE_HOPPER :Eisenerzwagen +STR_8042_STEEL_TRUCK :Stahltransporter +STR_8043_ARMORED_VAN :Sicherheitstransporter +STR_8044_FOOD_VAN :Lebensmitteltransporter +STR_8045_PAPER_TRUCK :Papiertransporter +STR_8046_COPPER_ORE_HOPPER :Kupfererzwagen +STR_8047_WATER_TANKER :Wassertanker +STR_8048_FRUIT_TRUCK :Fruchttransporter +STR_8049_RUBBER_TRUCK :Kautschuktransporter +STR_804A_SUGAR_TRUCK :Zuckertransporter +STR_804B_COTTON_CANDY_HOPPER :Zuckerwattewagen +STR_804C_TOFFEE_HOPPER :Karamelltransporter +STR_804D_BUBBLE_VAN :Luftblasentransporter +STR_804E_COLA_TANKER :Colatransporter +STR_804F_CANDY_VAN :Bonbontransporter +STR_8050_TOY_VAN :Spielwarentransporter +STR_8051_BATTERY_TRUCK :Batterietransporter +STR_8052_FIZZY_DRINK_TRUCK :Limonadetransporter +STR_8053_PLASTIC_TRUCK :Plastikwagen +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektrisch) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektrisch) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektrisch) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektrisch) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Passagierwagen +STR_805A_MAIL_VAN :Postwagen +STR_805B_COAL_CAR :Kohlewagen +STR_805C_OIL_TANKER :Öltanker +STR_805D_LIVESTOCK_VAN :Viehtransporter +STR_805E_GOODS_VAN :Warenwagen +STR_805F_GRAIN_HOPPER :Getreidetransporter +STR_8060_WOOD_TRUCK :Holzwagen +STR_8061_IRON_ORE_HOPPER :Eisenerzwagen +STR_8062_STEEL_TRUCK :Stahltransporter +STR_8063_ARMORED_VAN :Sicherheitstransporter +STR_8064_FOOD_VAN :Lebensmitteltransporter +STR_8065_PAPER_TRUCK :Papiertransporter +STR_8066_COPPER_ORE_HOPPER :Kupfererzwagen +STR_8067_WATER_TANKER :Wassertanker +STR_8068_FRUIT_TRUCK :Fruchttransporter +STR_8069_RUBBER_TRUCK :Kautschukwagen +STR_806A_SUGAR_TRUCK :Zuckertransporter +STR_806B_COTTON_CANDY_HOPPER :Zuckerwattewagen +STR_806C_TOFFEE_HOPPER :Karamelltransporter +STR_806D_BUBBLE_VAN :Luftblasentransporter +STR_806E_COLA_TANKER :Colatransporter +STR_806F_CANDY_VAN :Bonbontransporter +STR_8070_TOY_VAN :Spielwarentransporter +STR_8071_BATTERY_TRUCK :Batterielaster +STR_8072_FIZZY_DRINK_TRUCK :Limonadetransporter +STR_8073_PLASTIC_TRUCK :Plastikwagen +STR_8074_MPS_REGAL_BUS :MPS Regal Bus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus +STR_8076_FOSTER_BUS :Foster Bus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus +STR_807B_BALOGH_COAL_TRUCK :Balogh Kohlelaster +STR_807C_UHL_COAL_TRUCK :Uhl Kohlelaster +STR_807D_DW_COAL_TRUCK :DW Kohlelaster +STR_807E_MPS_MAIL_TRUCK :MPS Postwagen +STR_807F_REYNARD_MAIL_TRUCK :Reynard Postwagen +STR_8080_PERRY_MAIL_TRUCK :Perry Postwagen +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postwagen +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Postwagen +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Postwagen +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Öltanker +STR_8085_FOSTER_OIL_TANKER :Foster Öltanker +STR_8086_PERRY_OIL_TANKER :Perry Öltanker +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Viehtransporter +STR_8088_UHL_LIVESTOCK_VAN :Uhl Viehtransporter +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Viehtransporter +STR_808A_BALOGH_GOODS_TRUCK :Balogh Gütertransporter +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Gütertransporter +STR_808C_GOSS_GOODS_TRUCK :Goss Gütertransporter +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Getreidetransporter +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Getreidetransporter +STR_808F_GOSS_GRAIN_TRUCK :Goss Getreidetransporter +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Holzlaster +STR_8091_FOSTER_WOOD_TRUCK :Foster Holzlaster +STR_8092_MORELAND_WOOD_TRUCK :Moreland Holzlaster +STR_8093_MPS_IRON_ORE_TRUCK :MPS Eisenerzlaster +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Eisenerzlaster +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Eisenerzlaster +STR_8096_BALOGH_STEEL_TRUCK :Balogh Stahltransporter +STR_8097_UHL_STEEL_TRUCK :Uhl Stahltransporter +STR_8098_KELLING_STEEL_TRUCK :Kelling Stahltransporter +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Sicherheitstransporter +STR_809A_UHL_ARMORED_TRUCK :Uhl Sicherheitstransporter +STR_809B_FOSTER_ARMORED_TRUCK :Foster Sicherheitstransporter +STR_809C_FOSTER_FOOD_VAN :Foster Nahrungstransporter +STR_809D_PERRY_FOOD_VAN :Perry Nahrungstransporter +STR_809E_CHIPPY_FOOD_VAN :Chippy Nahrungstransporter +STR_809F_UHL_PAPER_TRUCK :Uhl Papierlaster +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Papierlaster +STR_80A1_MPS_PAPER_TRUCK :MPS Papierlaster +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Kupfererzlaster +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Kupfererzlaster +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Kupfererzlaster +STR_80A5_UHL_WATER_TANKER :Uhl Wasser Tankwagen +STR_80A6_BALOGH_WATER_TANKER :Balogh Wasser Tankwagen +STR_80A7_MPS_WATER_TANKER :MPS Wasser Tankwagen +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Früchtetransporter +STR_80A9_UHL_FRUIT_TRUCK :Uhl Früchtetransporter +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Früchtetransporter +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Kautschuklaster +STR_80AC_UHL_RUBBER_TRUCK :Uhl Kautschuklaster +STR_80AD_RMT_RUBBER_TRUCK :RMT Kautschuklaster +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Zuckertransporter +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Zuckertransporter +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Zuckertransporter +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Cola-Tankwagen +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Cola-Tankwagen +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Cola Tankwagen +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Zuckerwattelaster +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Zuckerwattelaster +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Zuckerwattelaster +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Karamelllaster +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Karamelllaster +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Karamelllaster +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Spielwarentransporter +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Spielwarentransporter +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Spielwarentransporter +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Bonbontransporter +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Bonbontransporter +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Bonbontransporter +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Batterielaster +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Batterielaster +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Batterielaster +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Limonadentanker +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Limonadentanker +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Limonadentanker +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastiktransporter +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastiktransporter +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastiktransporter +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Luftblasenlaster +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Luftblasenlaster +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Luftblasenlaster +STR_80CC_MPS_OIL_TANKER :MPS Öltanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Öltanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Passagierschiff +STR_80CF_FFP_PASSENGER_FERRY :FFP Passagierschiff +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Luftkissenboot +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passagierschiff +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passagierschiff +STR_80D3_YATE_CARGO_SHIP :Yate Frachter +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Frachter +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Frachter +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Frachter +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Hubschrauber +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Hubschrauber +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Hubschrauber +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Nachricht vom Fahrzeughersteller +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Wir haben gerade ein(e) neue(s) {STRING} erstellt - sind Sie daran interessiert, das Fahrzeug ein Jahr lang exklusiv zu testen, so dass wir die Funktionen testen können, bevor es allgemein zur Verfügung gestellt wird? +STR_8102_RAILROAD_LOCOMOTIVE :Lokomotive +STR_8103_ROAD_VEHICLE :Fahrzeug +STR_8104_AIRCRAFT :Flugzeug +STR_8105_SHIP :Schiff +STR_8106_MONORAIL_LOCOMOTIVE :Monorailbahn +STR_8107_MAGLEV_LOCOMOTIVE :Magnetschwebebahn + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Zugdepot +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Die Stadt feiert . . .{}Der erste Zug erreicht {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Details) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Zug ist im Weg +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Fahre nach {STATION} +STR_8807_GO_TO_UNLOAD :Fahre nach {STATION} (Entladen) +STR_8808_GO_TO_LOAD :Fahre nach {STATION} (Beladen) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Fahre ohne Halt nach {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Fahre ohne Halt nach {STATION} (Entladen) +STR_880C_GO_NON_STOP_TO_LOAD :Fahre ohne Halt nach {STATION} (Beladen) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Fahre zu {TOWN} Zugdepot +STR_SERVICE_AT_TRAIN_DEPOT :Wartung bei {TOWN} Zugdepot +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Fahre ohne Halt zu {TOWN} Zugdepot +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Wartung (ohne Halt) bei {TOWN} Zugdepot + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Unterwegs zu {TOWN} Zugdepot +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Unterwegs zu {TOWN} Zugdepot, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Leer +STR_8813_FROM :{LTBLUE}{CARGO} von {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Zug {COMMA16} wartet im Depot +STR_8815_NEW_VEHICLES :{BLACK}Neue Fahrzeuge +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Kosten: {GOLD}{CURRENCY}{BLACK} Gewicht: {GOLD}{COMMA16}t{}{BLACK}Geschwindigk.: {GOLD}{VELOCITY}{BLACK} Leistung: {GOLD}{COMMA16} PS {}{BLACK}Betriebskosten: {GOLD}{CURRENCY}/Jahr{}{BLACK}Kapazität: {GOLD}{STRING}{}{BLACK}Entwurf: {GOLD}{NUMU16}{BLACK} Lebensdauer: {GOLD}{COMMA16} Jahre{}{BLACK}Max. Zuverlässigkeit: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Information +STR_8819_TRAIN_TOO_LONG :{WHITE}Zug zu lang +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Züge können nur verändert werden, wenn sie im Depot halten +STR_881B_TRAINS :{WHITE}{STRING} - Züge +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Neues Schienenfahrzeug +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Neue Monorailzüge +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Neue Magnetzüge +STR_881F_BUILD_VEHICLE :{BLACK}Fahrzeug bauen +STR_8820_RENAME :{BLACK}Umbenennen +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Kosten: {GOLD}{CURRENCY}{}{BLACK}Gewicht: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapazität: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Übergehen +STR_8824_DELETE :{BLACK}Löschen +STR_8825_NON_STOP :{BLACK}ohne Halt +STR_8826_GO_TO :{BLACK}Nach +STR_8827_FULL_LOAD :{BLACK}Beladen +STR_8828_UNLOAD :{BLACK}Entladen +STR_8829_ORDERS :{WHITE}{STRING} (Aufträge) +STR_882A_END_OF_ORDERS :{SETX 10}- - Ende der Aufträge - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Wartung +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Kann Schienenfahrzeug nicht bauen... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebaut: {LTBLUE}{NUMU16}{BLACK} Wert: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Wert: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Laden / Entladen +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Kann den Zug nicht ins Depot schicken... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Kein Platz für weitere Aufträge +STR_8832_TOO_MANY_ORDERS :{WHITE}Zu viele Aufträge +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Kann keinen neuen Auftrag hinzufügen... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Kann den Auftrag nicht löschen... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Kann den Auftrag nicht bearbeiten... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Erst muss ein Zugdepot gebaut werden +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Kann das Fahrzeug nicht bewegen... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Kann Schienenfahrzeug nicht verkaufen... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Kann keinen weg zum Depot finden +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Kann den Zug nicht anhalten/starten ... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Wartungsintervall: {LTBLUE}{COMMA16}Tage {BLACK} Letzte Wartung: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Züge - für Einzelheiten auf den jeweiligen Zug klicken +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Neue Züge bauen (setzt Zugdepot voraus) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Züge - für Einzelheiten auf den Zug klicken; Waggon ziehen, um ihn an-/abzukoppeln +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Baue neues Schienenfahrzeug +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Schienenfahrzeug hierher ziehen, um es zu verkaufen +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Ansicht auf das Zugdepot zentrieren +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Zugfahrzeugliste - Einzelheiten durch Anklicken des Fahrzeuges +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Baue das angewählte Fahrzeug +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Umbenennen der Waggontypen +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Laufende Zugbewegung - Klicke hier, um den Zug anzuhalten / zu starten +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Anzeige der Zugaufträge +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Ansicht auf den Zug zentrieren +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Zug ins Depot schicken +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Zug zur Weiterfahrt zwingen, ohne das Signal zu beachten +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Zug umkehren +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Zeige Zug-Einzelheiten +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Wartungsintervall erhöhen +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Wartungsintervall verringern +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Zeige Einzelheiten zur geladenen Fracht +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Zeige Einzelheiten zu den Schienenfahrzeugen +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Zeige Kapazität jedes Fahrzeugs +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Frachtübersicht des Zuges anzeigen, aufgeteilt nach Frachttyp +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Auftragsliste - zum Markieren hier anklicken +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Übergehe den laufenden Auftrag, und starte den nächsten +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Lösche den markierten Auftrag +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Führe den markierten Auftrag ohne Halt durch +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Füge einen neuen Auftrag vor dem markierten Auftrag ein, oder setze ihn ans Ende der Liste +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Der markierte Auftrag wird nur nach voller Beladung ausgeführt +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Beim markierten Auftrag wird die volle Entladung veranlasst +STR_SERVICE_HINT :{BLACK}Überspringe diesen Auftrag, sofern keine Wartung benötigt wird +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Neue {STRING} ist jetzt verfügbar! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Kosten: {CURRENCY} Gewicht: {COMMA16}t{}Geschwindigk.: {VELOCITY} Leistung: {COMMA16} PS {}Betriebskosten: {CURRENCY}/Jahr{}Kapazität: {STRING} +STR_885C_BROKEN_DOWN :{RED}Panne +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Alter: {LTBLUE}{STRING}{BLACK} Betriebskosten: {LTBLUE}{CURRENCY}/Jahr +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Gewicht: {LTBLUE}{COMMA16}t {BLACK}Leistung: {LTBLUE}{COMMA32} PS {BLACK} Max. Geschwindigk.: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit lfd. Jahr: {LTBLUE}{CURRENCY} (letztes Jahr: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA8}% {BLACK}Ausfälle seit letzter Wartung: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Angehalten +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Der Zug kann das Signal nicht ohne Gefahr passieren... +STR_8863_CRASHED :{RED}Zusammenstoß! + +STR_8865_NAME_TRAIN :{WHITE}Name des Zuges +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Kann den Zug nicht benennen... +STR_8867_NAME_TRAIN :{BLACK}Name des Zuges +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Zugunglück!{}{COMMA16} sterben in einem Feuerball nach Zusammenstoß +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Die Zugbewegung kann nicht umgekehrt werden... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Zugtyp umbenennen +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Zugtyp kann nicht umbenannt werden... + +STR_TRAIN_STOPPING :{RED}Halte an +STR_TRAIN_STOPPING_VEL :{RED}Halte an, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Fahrzeug ist im Weg +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Fahrzeuge +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Fahrzeugdepot +STR_9004_NEW_VEHICLES :{BLACK}Neue Fahrzeuge +STR_9005_INFORMATION :{BLACK}Information +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Neue Fahrzeuge +STR_9007_BUILD_VEHICLE :{BLACK}Baue Fahrzeug +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Kosten: {GOLD}{CURRENCY}{BLACK} Geschwindigk.: {GOLD}{VELOCITY}{}{BLACK}Betriebskosten: {GOLD}{CURRENCY}/Jahr{}{BLACK} Kapazität: {GOLD}{STRING}{}{BLACK}Entwurf: {GOLD}{NUMU16}{BLACK} Lebensdauer: {GOLD}{COMMA16} Jahre{}{BLACK}Max. Zuverlässigkeit: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kann das Fahrzeug nicht bauen... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Erst muss ein Fahrzeugdepot gebaut werden +STR_900B_ORDERS :{WHITE}{STRING} (Aufträge) +STR_900C_DETAILS :{WHITE}{STRING} (Einzelheiten) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Alter: {LTBLUE}{STRING}{BLACK} Betriebskosten: {LTBLUE}{CURRENCY}/Jahr +STR_900E_MAX_SPEED :{BLACK}Max. Geschwindigk.: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit lfd. Jahr: {LTBLUE}{CURRENCY} (letztes Jahr: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA8}% {BLACK}Pannen seit letzter Wartung: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebaut: {LTBLUE}{NUMU16}{BLACK} Wert: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapazität: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...muss in einem Fahrzeugdepot angehalten werden +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Kann das Fahrzeug nicht verkaufen... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Kann das Fahrzeug nicht anhalten/starten... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Fahrzeug {COMMA16} wartet im Depot +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Unterwegs zu {TOWN} Fahrzeugdepot +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Unterwegs zu {TOWN} Fahrzeugdepot, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kann das Fahrzeug nicht zum Depot schicken... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kann kein Fahrzeugdepot finden +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Straßenfahrzeuge - für Einzelheiten auf das Fahrzeug klicken +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Baue neues Fahrzeug (setzt Fahrzeugdepot voraus) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Laufende Fahrzeugbewegung - Klicke hier, um das Fahrzeug anzuhalten / zu starten +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Zeige Aufträge für das Fahrzeug +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Ansicht auf das Fahrzeug zentrieren +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Schicke das Fahrzeug in das Depot +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Das Fahrzeug zur Umkehr zwingen +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Zeige Einzelheiten des Fahrzeuges +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Straßenfahrzeuge - für Einzelheiten auf das Fahrzeug klicken +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Baue neues Fahrzeug +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Ziehe Fahrzeug hierher, um es zu verkaufen +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Ansicht auf das Fahrzeugdepot zentrieren +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Fahrzeugauswahlliste - Klicke auf ein Fahrzeug für Einzelheiten +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Baue das ausgewählte Fahrzeug +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Neues Fahrzeug jetzt erhältlich ! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Kosten: {CURRENCY}{}Geschwindigk.: {VELOCITY}{}Betriebskosten: {CURRENCY}/Jahr{}Capacity: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Name des Fahrzeuges +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Kann das Fahrzeug nicht benennen... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Name des Fahrzeuges +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Die Stadt feiert . . .{}Der erste Bus erreicht {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Die Stadt feiert . . .{}Der erste Lkw erreicht {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Fahrzeug verunglückt!{}Fahrer stirbt in einem Feuerball nach Zusammenstoß mit einem Zug +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Fahrzeug verunglückt!{}{COMMA16} sterben nach Zusammenstoß mit einem Zug im Feuerball +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Das Fahrzeug kann nicht gewendet werden... +STR_9034_RENAME :{BLACK}Umbenennen +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Fahrzeug umbenennen +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Fahrzeug umbenennen +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Kann das Fahrzeug nicht umbenennen... +STR_9038_GO_TO_ROADVEH_DEPOT :Fahre zu {TOWN} Fahrzeugdepot +STR_SERVICE_AT_ROADVEH_DEPOT :Wartung bei {TOWN} Fahrzeugdepot + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Hafenanlage bauen +STR_9801_DOCK_CONSTRUCTION :{WHITE}Hafenanlage bauen +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Kann den Hafen hier nicht bauen... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Werft +STR_9804_NEW_SHIPS :{BLACK}Neue Schiffe +STR_9805_SHIPS :{WHITE}{STRING} - Schiffe +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Kann das Schiff nicht bauen... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Erst muss eine Werft gebaut werden +STR_9808_NEW_SHIPS :{WHITE}Neue Schiffe +STR_9809_BUILD_SHIP :{BLACK}Baue Schiff +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Kosten: {GOLD}{CURRENCY}{BLACK} Geschwindigk.: {GOLD}{VELOCITY}{}{BLACK}Kapazität: {GOLD}{STRING} {STRING}{}{BLACK}Betriebskosten: {GOLD}{CURRENCY}/Jahr{}{BLACK}Entworfen: {GOLD}{NUMU16}{BLACK} Lebensdauer: {GOLD}{COMMA16} Jahre{}{BLACK}Max. Zuverlässigkeit: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Schiff muss in der Werft angehalten werden +STR_980C_CAN_T_SELL_SHIP :{WHITE}Kann das Schiff nicht verkaufen... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Kann das Schiff nicht bauen... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Schiff ist im Weg +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Aufträge) +STR_9811_DETAILS :{WHITE}{STRING} (Einzelheiten) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Alter: {LTBLUE}{STRING}{BLACK} Betriebskosten: {LTBLUE}{CURRENCY}/Jahr +STR_9813_MAX_SPEED :{BLACK}Max. Geschwindigk.: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit lfd. Jahr: {LTBLUE}{CURRENCY} (letztes Jahr: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA8}% {BLACK}Pannen seit letzter Wartung: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebaut: {LTBLUE}{NUMU16}{BLACK} Wert: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapazität: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Kann das Schiff nicht anhalten/starten... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Kann das Schiff nicht in die Werft schicken... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kann keine Werft finden +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Unterwegs zu {TOWN} Werft +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Unterwegs zu {TOWN} Werft, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Schiff {COMMA16} wartet in der Werft +STR_981D_BUILD_SHIP_DOCK :{BLACK}Hafen bauen +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Werft bauen (für den Bau und die Wartung von Schiffen) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Schiffe - für Einzelheiten auf das Schiff klicken +STR_9820_BUILD_NEW_SHIP :{BLACK}Neues Schiff bauen +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Ziehe Schiff hierher, um es zu verkaufen +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Ansicht auf die Werft zentrieren +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Schiffe - für Einzelheiten auf das Schiff klicken +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Baue neues Schiff (setzt Werft voraus) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Schiffauswahliste - für Einzelheiten auf das Schiff klicken +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Baue das ausgewählte Schiff +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Laufende Schiffsbewegung - Klicke hier, um das Schiff anzuhalten / zu starten +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Aufträge des Schiffes +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Anzeige auf das Schiff zentrieren +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Schicke das Schiff zur Werft +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Zeige Schiffs Einzelheiten +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Neues Schiff ist erhältlich ! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Kosten: {CURRENCY} Max. Geschwindigk.: {VELOCITY}{}Kapazität: {STRING}{}Betriebskosten: {CURRENCY}/Jahr +STR_982F_NAME_SHIP :{BLACK}Schiffsname + +STR_9831_NAME_SHIP :{WHITE}Schiffsname +STR_9832_CAN_T_NAME_SHIP :{WHITE}Kann Schiffsnamen nicht vergeben... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Die Stadt feiert . . .{}Das erste Schiff erreicht {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Positionsboje, wird als Wegpunkt benötigt +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Kann die Boje hier nicht plazieren... +STR_9836_RENAME :{BLACK}Umbenennen +STR_9837_RENAME_SHIP_TYPE :{BLACK}Schiff umbenennen +STR_9838_RENAME_SHIP_TYPE :{WHITE}Schiff umbenennen +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Kann das Schiff nicht umbenennen... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Umrüstung des Schiffes zur Beförderung anderer Frachtarten +STR_983B_REFIT :{WHITE}{STRING} (Umrüsten) +STR_983C_REFIT_SHIP :{BLACK}Schiff umrüsten +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wähle die Frachtart aus, die das Schiff befördern soll +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Umrüstung des Schiffes auf die ausgewählte Frachtart +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Wähle Frachtart für die Beförderung:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Neue Kapazität: {GOLD}{STRING}{}{BLACK}Kosten der Umrüstung: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Kann das Schiff nicht umrüsten... +STR_9842_REFITTABLE :(umrüstbar) +STR_GO_TO_SHIP_DEPOT :Fahre zu {TOWN} Schiffswerft +SERVICE_AT_SHIP_DEPOT :Wartung bei {TOWN} Schiffswerft + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Flughafenbau +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Flughafen kann hier nicht gebaut werden... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Flugzeughangar +STR_A003_NEW_AIRCRAFT :{BLACK}Neues Flugzeug +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}Neues Flugzeug +STR_A006_BUILD_AIRCRAFT :{BLACK}Flugzeug bauen +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Kosten: {GOLD}{CURRENCY}{BLACK} Geschwindigk.: {GOLD}{VELOCITY}{}{BLACK}Kapazität: {GOLD}{COMMA16} Passagiere, {COMMA16} Postsäcke{}{BLACK}Betriebskosten: {GOLD}{CURRENCY}/Jahr{}{BLACK}Entworfen: {GOLD}{NUMU16}{BLACK} Lebensdauer: {GOLD}{COMMA16} Jahre{}{BLACK}Max. Zuverlässigkeit: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Kann das Flugzeug nicht bauen... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Flugzeug +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Aufträge) +STR_A00C_DETAILS :{WHITE}{STRING} (Einzelheiten) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Alter: {LTBLUE}{STRING}{BLACK} Betriebskosten: {LTBLUE}{CURRENCY}/Jahr +STR_A00E_MAX_SPEED :{BLACK}Max. Geschwindigk.: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit lfd. Jahr: {LTBLUE}{CURRENCY} (letztes Jahr: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Zuverlässigkeit: {LTBLUE}{COMMA8}% {BLACK}Pannen seit letzter Wartung: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Gebaut: {LTBLUE}{NUMU16}{BLACK} Wert: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Kann das Flugzeug nicht in den Hangar schicken... +STR_HEADING_FOR_HANGAR :{LTBLUE}Unterwegs zu {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Unterwegs zu {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Flugzeug {COMMA16} wartet im Flugzeug Hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Flugzeug ist auf dem Weg +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Kann das Flugzeug nicht anhalten/starten... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Das Flugzeug ist in der Luft +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Erst muss ein Flugzeug gebaut werden +STR_A019_CAPACITY :{BLACK}Kapazität: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapazität: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Flugzeug muss im Hangar angehalten werden +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Kann das Flugzeug nicht verkaufen... +STR_A01D_AIRPORT_CONSTRUCTION :Flugzeugbau +STR_A01E_BUILD_AIRPORT :{BLACK}Baue Flughafen +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Flugzeuge - für Einzelheiten auf das Flugzeug klicken +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Baue neues Flugzeug (setzt Flughafen mit Hangar voraus) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Flugzeuge - für Einzelheiten auf das Flugzeug klicken +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Baue neues Flugzeug +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Zum Verkauf des Flugzeuges hierher ziehen +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Ansicht auf den Hangar zentrieren +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Flugzeug-Auswahlliste - Klicke auf das Flugzeug für weitere Einzelheiten +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Baue das augewählte Flugzeug +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Laufende Flugzeugbewegung - Klicke hier, um das Flugzeug anzuhalten / zu starten +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Zeige Aufträge für das Flugzeug +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Ansicht auf das Flugzeug zentrieren +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Schicke das Flugzeug in den Hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Zeige Einzelheiten des Flugzeuges +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Neues Flugzeug ist jetzt verfügbar! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Kosten: {CURRENCY} Max. Geschwindigk.: {VELOCITY}{}Kapazität: {COMMA16} Passagiere, {COMMA16} Postsäcke{}Betriebskosten: {CURRENCY}/Jahr + +STR_A030_NAME_AIRCRAFT :{WHITE}Flugzeugname +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kann Flugzeugname nicht vergeben... +STR_A032_NAME_AIRCRAFT :{BLACK}Flugzeugname +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Die Stadt feiert . . .{}Erstes Flugzeug landet auf {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Flugzeugabsturz!{}{COMMA16} sterben in einem Feuerball auf {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Bestimmungsort: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Umbenennen +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Flugzeug umbenennen +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Flugzeug umbenennen +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Kann das Flugzeug nicht umbenennen... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Umrüstung des Flugzeuges zum Transport anderer Frachten +STR_A03C_REFIT :{WHITE}{STRING} (Umrüstung) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Flugzeug umrüsten +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wähle die Fracht die das Flugzeug transportieren soll +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Umrüstung des Flugzeuges auf die ausgewählte Frachtart +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Wähle Frachtart für Umrüstung aus:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Neue Kapazität: {GOLD}{STRING}{}{BLACK}Kosten der Umrüstung: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Kann das Flugzeug nicht umrüsten... +STR_A043_REFITTABLE :(umrüstbar) +STR_GO_TO_AIRPORT_HANGAR :Fliege zu {STATION} Hangar +SERVICE_AT_AIRPORT_HANGAR :Wartung bei {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin-Absturz bei {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Fahrzeug bei einem UFO-Zusammenstoß zerstört! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Explosion einer Ölraffinerie nahe {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabrik nahe {TOWN} durch mysteriöse Umstände zerstört! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' landet bei {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Stolleneinbruch hinterläßt einen Pfad der Zerstörung bei {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Ihr Bestechungsversuch wurde +STR_BRIBE_FAILED_2 :{WHITE}von einem regionalen Untersuchungsbeamten aufgedeckt. diff --git a/lang/hungarian.txt b/lang/hungarian.txt new file mode 100644 --- /dev/null +++ b/lang/hungarian.txt @@ -0,0 +1,2335 @@ +##name Hungarian +##ownname Magyar + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Kilóg a térképrõl +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Túl közel van a térkép széléhez +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Nincs elég pénzed - {CURRENCY} kellene +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Sima föld szükséges +STR_0008_WAITING :{BLACK}Várakozik: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (elvitelre +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Elfogad:{WHITE} +STR_000D_ACCEPTS :{BLACK}Elfogad:{GOLD} +STR_000E : +STR_000F_PASSENGERS :Utas +STR_0010_COAL :Szén +STR_0011_MAIL :Levél +STR_0012_OIL :Olaj +STR_0013_LIVESTOCK :Állat +STR_0014_GOODS :Áru +STR_0015_GRAIN :Búza +STR_0016_WOOD :Fa +STR_0017_IRON_ORE :Vasérc +STR_0018_STEEL :Acél +STR_0019_VALUABLES :Értéktárgyak +STR_001A_COPPER_ORE :Rézérc +STR_001B_MAIZE :Kukorica +STR_001C_FRUIT :Gyümölcs +STR_001D_DIAMONDS :Gyémánt +STR_001E_FOOD :Étel +STR_001F_PAPER :Papír +STR_0020_GOLD :Arany +STR_0021_WATER :Víz +STR_0022_WHEAT :Búza +STR_0023_RUBBER :Gumi +STR_0024_SUGAR :Cukor +STR_0025_TOYS :Játék +STR_0026_CANDY :Cukorka +STR_0027_COLA :Kóla +STR_0028_COTTON_CANDY :Vattacukor +STR_0029_BUBBLES :Buborék +STR_002A_TOFFEE :Tejkaramella +STR_002B_BATTERIES :Elem +STR_002C_PLASTIC :Mûanyag +STR_002D_FIZZY_DRINKS :Szénsavas ital +STR_002E : +STR_002F_PASSENGER :utas +STR_0030_COAL :szén +STR_0031_MAIL :levél +STR_0032_OIL :olaj +STR_0033_LIVESTOCK :állat +STR_0034_GOODS :áru +STR_0035_GRAIN :búza +STR_0036_WOOD :fa +STR_0037_IRON_ORE :vasérc +STR_0038_STEEL :acél +STR_0039_VALUABLES :értéktárgy +STR_003A_COPPER_ORE :rézérc +STR_003B_MAIZE :kukorica +STR_003C_FRUIT :gyümölcs +STR_003D_DIAMOND :gyémánt +STR_003E_FOOD :étel +STR_003F_PAPER :papír +STR_0040_GOLD :arany +STR_0041_WATER :víz +STR_0042_WHEAT :búza +STR_0043_RUBBER :gumi +STR_0044_SUGAR :cukor +STR_0045_TOY :játék +STR_0046_CANDY :cukorka +STR_0047_COLA :kóla +STR_0048_COTTON_CANDY :vattacukor +STR_0049_BUBBLE :buborék +STR_004A_TOFFEE :tejkaramella +STR_004B_BATTERY :elem +STR_004C_PLASTIC :mûanyag +STR_004D_FIZZY_DRINK :szénsavas ital +STR_004E : +STR_004F_PASSENGER :{COMMA16} utas +STR_0050_TON_OF_COAL :{COMMA16} tonna szén +STR_0051_BAG_OF_MAIL :{COMMA16} csomag levél +STR_0052_OF_OIL :{VOLUME} olaj +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} állat +STR_0054_CRATE_OF_GOODS :{COMMA16} láda áru +STR_0055_TON_OF_GRAIN :{COMMA16} tonna búza +STR_0056_TON_OF_WOOD :{COMMA16} tonna fa +STR_0057_TON_OF_IRON_ORE :{COMMA16} tonna vasérc +STR_0058_TON_OF_STEEL :{COMMA16} tonna acél +STR_0059_BAG_OF_VALUABLES :{COMMA16} csomag értéktárgy +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonna rézérc +STR_005B_TON_OF_MAIZE :{COMMA16} tonna kukorica +STR_005C_TON_OF_FRUIT :{COMMA16} tonna gyümölcs +STR_005D_BAG_OF_DIAMONDS :{COMMA16} zsák gyémánt +STR_005E_TON_OF_FOOD :{COMMA16} tonna étel +STR_005F_TON_OF_PAPER :{COMMA16} tonna papír +STR_0060_BAG_OF_GOLD :{COMMA16} zsák arany +STR_0061_OF_WATER :{VOLUME} víz +STR_0062_TON_OF_WHEAT :{COMMA16} tonna búza +STR_0063_OF_RUBBER :{VOLUME} gumi +STR_0064_TON_OF_SUGAR :{COMMA16} tonna cukor +STR_0065_TOY :{COMMA16} játék +STR_0066_BAG_OF_CANDY :{COMMA16} zsák cukorka +STR_0067_OF_COLA :{VOLUME} kóla +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonna vattacukor +STR_0069_BUBBLE :{COMMA16} buborék +STR_006A_TON_OF_TOFFEE :{COMMA16} tonna tejkaramella +STR_006B_BATTERY :{COMMA16} elem +STR_006C_OF_PLASTIC :{VOLUME} mûanyag +STR_006D_FIZZY_DRINK :{COMMA16} szénsavas ital +STR_006E : +STR_006F_PASSENGERS :{COMMA16} utas +STR_0070_TONS_OF_COAL :{COMMA16} tonna szén +STR_0071_BAGS_OF_MAIL :{COMMA16} csomag levél +STR_0072_OF_OIL :{VOLUME} olaj +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} állat +STR_0074_CRATES_OF_GOODS :{COMMA16} láda áru +STR_0075_TONS_OF_GRAIN :{COMMA16} tonna búza +STR_0076_TONS_OF_WOOD :{COMMA16} tonna fa +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonna vasérc +STR_0078_TONS_OF_STEEL :{COMMA16} tonna acél +STR_0079_BAGS_OF_VALUABLES :{COMMA16} csomag értéktárgy +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonna rézérc +STR_007B_TONS_OF_MAIZE :{COMMA16} tonna kukorica +STR_007C_TONS_OF_FRUIT :{COMMA16} tonna gyümölcs +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} zsák gyémánt +STR_007E_TONS_OF_FOOD :{COMMA16} tonna étel +STR_007F_TONS_OF_PAPER :{COMMA16} tonna papír +STR_0080_BAGS_OF_GOLD :{COMMA16} zsák arany +STR_0081_OF_WATER :{VOLUME} víz +STR_0082_TONS_OF_WHEAT :{COMMA16} tonna búza +STR_0083_OF_RUBBER :{VOLUME} gumi +STR_0084_TONS_OF_SUGAR :{COMMA16} tonna cukor +STR_0085_TOYS :{COMMA16} játék +STR_0086_BAGS_OF_CANDY :{COMMA16} zsák cukorka +STR_0087_OF_COLA :{VOLUME} kóla +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonna vattacukor +STR_0089_BUBBLES :{COMMA16} buborék +STR_008A_TONS_OF_TOFFEE :{COMMA16} tonna tejkaramella +STR_008B_BATTERIES :{COMMA16} elem +STR_008C_OF_PLASTIC :{VOLUME} mûanyag +STR_008D_FIZZY_DRINKS :{COMMA16} szénsavas ital +STR_008E : +STR_008F_PS :{TINYFONT}UT +STR_0090_CL :{TINYFONT}SZ +STR_0091_ML :{TINYFONT}LV +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}ÁL +STR_0094_GD :{TINYFONT}ÁR +STR_0095_GR :{TINYFONT}BZ +STR_0096_WD :{TINYFONT}FA +STR_0097_OR :{TINYFONT}VÉ +STR_0098_ST :{TINYFONT}AC +STR_0099_VL :{TINYFONT}ÉP +STR_009A_CO :{TINYFONT}RÉ +STR_009B_MZ :{TINYFONT}KU +STR_009C_FT :{TINYFONT}GÜ +STR_009D_DM :{TINYFONT}GM +STR_009E_FD :{TINYFONT}ÉT +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}AR +STR_00A1_WR :{TINYFONT}VZ +STR_00A2_WH :{TINYFONT}BZ +STR_00A3_RB :{TINYFONT}GM +STR_00A4_SG :{TINYFONT}CU +STR_00A5_TY :{TINYFONT}JT +STR_00A6_SW :{TINYFONT}CK +STR_00A7_CL :{TINYFONT}KL +STR_00A8_CF :{TINYFONT}VC +STR_00A9_BU :{TINYFONT}BB +STR_00AA_TF :{TINYFONT}TK +STR_00AB_BA :{TINYFONT}EL +STR_00AC_PL :{TINYFONT}MA +STR_00AD_FZ :{TINYFONT}SS +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Térkép - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Beállítások +STR_00B2_MESSAGE :{YELLOW}Üzenet +STR_00B3_MESSAGE_FROM :{YELLOW}{STRING} üzenete +STR_00B4_CAN_T_DO_THIS :{WHITE}Nem teheted ezt... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Nem tisztíthatod meg a területet... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Copyright {COPYRIGHT} 1995 Chris Sawyer, Minden jog fenntartva +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Eredeti tervek: Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafika : Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Kilépés +STR_00C8_YES :{BLACK}Igen +STR_00C9_NO :{BLACK}Nem +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Biztosan bezárod ezt a programot és kilépsz a {STRING}ba ? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :semmi +STR_00D1_DARK_BLUE :Sötétkék +STR_00D2_PALE_GREEN :Halványzöld +STR_00D3_PINK :Rózsaszín +STR_00D4_YELLOW :Sárga +STR_00D5_RED :Piros +STR_00D6_LIGHT_BLUE :Világoskék +STR_00D7_GREEN :Zöld +STR_00D8_DARK_GREEN :Sötétzöld +STR_00D9_BLUE :Kék +STR_00DA_CREAM :Krémszín +STR_00DB_MAUVE :Mályvaszín +STR_00DC_PURPLE :Lila +STR_00DD_ORANGE :Narancssárga +STR_00DE_BROWN :Barna +STR_00DF_GREY :Szürke +STR_00E0_WHITE :Fehér +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Túl sok jármû van a játékban +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Megnéz +STR_00E5_CONTOURS :Domborzat +STR_00E6_VEHICLES :Jármûvek +STR_00E7_INDUSTRIES :Gazdaság +STR_00E8_ROUTES :Utak +STR_00E9_VEGETATION :Növényzet +STR_00EA_OWNERS :Tulajdonosok +STR_00EB_ROADS :{BLACK}{TINYFONT}Út +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Vasút +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Állomás/Reptér/Kikötõ +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Épület/Gazdasági épület +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Jármû +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Vonat +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Közúti jármû +STR_00F7_SHIPS :{BLACK}{TINYFONT}Hajó +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Repülõgép +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Szállítási útvonal +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}szénbánya +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}erõmû +STR_00FC_FOREST :{BLACK}{TINYFONT}erdõ +STR_00FD_SAWMILL :{BLACK}{TINYFONT}fûrésztelep +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}olajfinomító +STR_00FF_FARM :{BLACK}{TINYFONT}farm +STR_0100_FACTORY :{BLACK}{TINYFONT}gyár +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}nyomda +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}olajkút +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}vasércbánya +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}acélöntõ +STR_0105_BANK :{BLACK}{TINYFONT}bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}papírgyár +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}aranybánya +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}konzervgyár +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}gyémántbánya +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}rézércbánya +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}gyümölcsültetvény +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}gumiültetvény +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}vízforrás +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}víztorony +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}favágó +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}vattacukor-erdõ +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}cukorkagyár +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}elemfarm +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}kólakút +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}játékbolt +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}játékgyár +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}mûanyagforrás +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}üdítõital-gyár +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}buborékgenerátor +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}tejkaramella fejtõ +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}cukorbánya +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Vasútállomás +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Teherautó-rakodóhely +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Buszmegálló +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Repülõtér/Helikopter-leszálló +STR_011F_DOCK :{BLACK}{TINYFONT}Kikötõ +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Göröngyös talaj +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Füves talaj +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Csupasz föld +STR_0123_FIELDS :{BLACK}{TINYFONT}Szántóföld +STR_0124_TREES :{BLACK}{TINYFONT}Fa +STR_0125_ROCKS :{BLACK}{TINYFONT}Kõ +STR_0126_WATER :{BLACK}{TINYFONT}Víz +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Nincs tulajdonos +STR_0128_TOWNS :{BLACK}{TINYFONT}Város +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Gazdasági épület +STR_012A_DESERT :{BLACK}{TINYFONT}Sivatag +STR_012B_SNOW :{BLACK}{TINYFONT}Hó +STR_012C_MESSAGE :{WHITE}Üzenet +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Mégsem +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Átnevez +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Túl sok név van megadva +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}A megadott név már használatban van + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Mérföld +STR_013A_METRIC_KILOMETERS :Kilométer +STR_013B_OWNED_BY :{WHITE}... {STRING} tulajdona +STR_013C_CARGO :{BLACK}Rakomány +STR_013D_INFORMATION :{BLACK}Információ +STR_013E_CAPACITIES :{BLACK}Kapacitás +STR_013F_CAPACITY :{BLACK}Kapacitás: {LTBLUE}{STRING} +STR_0140_NEW_GAME :{BLACK}Új játék +STR_0141_LOAD_GAME :{BLACK}Játék betöltése +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tanítás / Demo +STR_0143_1_PLAYER :{BLACK}1 játékos +STR_0144_2_PLAYERS :{BLACK}2 játékos + +STR_0148_GAME_OPTIONS :{BLACK}Beállítások + +STR_0150_SOMEONE :valaki{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Világtérkép +STR_0152_TOWN_DIRECTORY :Városlista +STR_0153_SUBSIDIES :Támogatások + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Mûködési nyereség grafikon +STR_0155_INCOME_GRAPH :Jövedelem grafikon +STR_0156_DELIVERED_CARGO_GRAPH :Elszállított rakomány grafikon +STR_0157_PERFORMANCE_HISTORY_GRAPH :Teljesítmény grafikon +STR_0158_COMPANY_VALUE_GRAPH :Vállalat értéke grafikon +STR_0159_CARGO_PAYMENT_RATES :Rakományok szállítási díja +STR_015A_COMPANY_LEAGUE_TABLE :A cégek helyezése +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Játék mentése +STR_015D_LOAD_GAME :Jaték betöltése +STR_015E_QUIT_GAME :Kilépés a játékból +STR_015F_QUIT :Kilépés +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Biztosan kilépsz ebbõl a játékból ? +STR_0161_QUIT_GAME :{WHITE}Kilépés a játékból + +############ range for months starts +STR_0162_JAN :jan +STR_0163_FEB :feb +STR_0164_MAR :már +STR_0165_APR :ápr +STR_0166_MAY :máj +STR_0167_JUN :jún +STR_0168_JUL :júl +STR_0169_AUG :aug +STR_016A_SEP :sze +STR_016B_OCT :okt +STR_016C_NOV :nov +STR_016D_DEC :dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Játék szüneteltetése +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Játék mentése, kilépés a játékból, kilépés +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Állomások listája +STR_0174_DISPLAY_MAP :{BLACK}Térkép +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Térkép, városlista +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Városlista +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Pénzügyi adatok +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Általános adatok +STR_0179_DISPLAY_GRAPHS :{BLACK}Grafikonok +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}A cégek helyezése +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Vonatok listája +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Közúti jármûvek listája +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Hajók listája +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Repülõgépek listája +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Közelítés +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Távolítás +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Vasúti sín lerakása +STR_0182_BUILD_ROADS :{BLACK}Út építése +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Kikötõ építése +STR_0184_BUILD_AIRPORTS :{BLACK}Repülõtér építése +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Faültetés, feliratok lerakása stb. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Terület-információ +STR_0187_OPTIONS :{BLACK}Beállítások +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Nem változtathatod meg a javítási idõközt... +STR_018B_CLOSE_WINDOW :{BLACK}Az ablak bezárása +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Az ablak címsora - húzd ezt a mozgatáshoz +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Tárgyak lerombolása egy mezõrõl +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Egy pont lesüllyesztése +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Egy pont megemelése +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Görgetõsáv - fel/le görgeti a listát +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Domborzat mutatása a térképen +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Jármûvek mutatása a térképen +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Gazdasági épületek mutatása a térképen +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Szállítási útvonalak mutatása a térképen +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Növényzet mutatása a térképen +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Tulajdonosok mutatása a térképen +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Városnevek ki/be +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Ezévi nyereség: {CURRENCY} (Tavalyi: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} év ({COMMA16}) +STR_019A_YEARS :{COMMA16} év ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} év ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :közúti jármû +STR_019D_AIRCRAFT :repülõgép +STR_019E_SHIP :hajó +STR_019F_TRAIN :vonat +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} kezd elöregedni +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} kezd nagyon elöregedni +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} nagyon öreg és sürgõsen ki kell cserélni +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Terület-információ +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}{LTBLUE}Nem lehet lerombolni +STR_01A5_COST_TO_CLEAR :{BLACK}A megtisztítás költsége: {LTBLUE}{CURRENCY} +STR_01A6_N_A :Nincs +STR_01A7_OWNER :{BLACK}Tulajdonos: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Helyi önkormányzat: {LTBLUE}{STRING} +STR_01A9_NONE :Nincs +STR_01AA_NAME :{BLACK}Név +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1. +STR_01AD_2ND :2. +STR_01AE_3RD :3. +STR_01AF_4TH :4. +STR_01B0_5TH :5. +STR_01B1_6TH :6. +STR_01B2_7TH :7. +STR_01B3_8TH :8. +STR_01B4_9TH :9. +STR_01B5_10TH :10. +STR_01B6_11TH :11. +STR_01B7_12TH :12. +STR_01B8_13TH :13. +STR_01B9_14TH :14. +STR_01BA_15TH :15. +STR_01BB_16TH :16. +STR_01BC_17TH :17. +STR_01BD_18TH :18. +STR_01BE_19TH :19. +STR_01BF_20TH :20. +STR_01C0_21ST :21. +STR_01C1_22ND :22. +STR_01C2_23RD :23. +STR_01C3_24TH :24. +STR_01C4_25TH :25. +STR_01C5_26TH :26. +STR_01C6_27TH :27. +STR_01C7_28TH :28. +STR_01C8_29TH :29. +STR_01C9_30TH :30. +STR_01CA_31ST :31. +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Váltás kis és nagy térkép között +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Válassz egy tanítást/demót + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Elfogad: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Elfogad: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Elfogad: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz zenegép +STR_01D3_SOUND_MUSIC :Hang/zene +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Hang/zene beállítás +STR_01D5_ALL :{TINYFONT}Mind +STR_01D6_OLD_STYLE :{TINYFONT}Régi stílus +STR_01D7_NEW_STYLE :{TINYFONT}Új stílus +STR_01D8_EZY_STREET :{TINYFONT}Szép az élet +STR_01D9_CUSTOM_1 :{TINYFONT}Saját 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Saját 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Zene hangereje +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Hangok hangereje +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Elõzõ szám +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION :{BLACK}Következõ szám +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Zene leállítása +STR_01E1_START_PLAYING_MUSIC :{BLACK}Zene elindítása +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}A csúszkákkal beállíthatod a zene és a hanghatások hangerejét +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Szám{SETX 88}Cím +STR_01E9_SHUFFLE :{TINYFONT}Kever +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Mûsor +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Zenei mûsor kiválasztása +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Számlista +STR_01EF_PROGRAM :{TINYFONT}{BLACK}"{STRING}" mûsora +STR_01F0_CLEAR :{TINYFONT}{BLACK}Törlés +STR_01F1_SAVE :{TINYFONT}{BLACK}Mentés +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Az aktuális mûsor számai +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}A 'minden szám' mûsor kiválasztása +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}A 'régi stílus' zenei mûsor kiválasztása +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Az 'új stílus' zenei program kiválasztása +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}A 'Saját 1' (felhasználói) zenei mûsor kiválasztása +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}A 'Saját 2' (felhasználói) zenei mûsor kiválasztása +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Az aktuális mûsor kiürítése (csak Saját 1 és Saját 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Zenei beállítások mentése a lemezre +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Egy számra kattintva hozzáadod azt a kiválasztott zenei mûsorhoz (csak Saját 1 és Saját 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}A mûsor megkeverése be/ki +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}A zenekiválasztó ablak megjelenítése +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Kattints egy sorra a város/gazdasági épület megnézéséhez +STR_01FE_DIFFICULTY :{BLACK}Nehézség ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Legutóbbi üzenet/újsághír +STR_0201_MESSAGE_SETTINGS :Üzenetek beállításai +STR_MESSAGE_HISTORY_MENU :Elõzõ üzenetek +STR_0202_SEND_MESSAGE :Üzenet küldése +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Legutóbbi üzenet/újsághír, üzenetek beállításai +STR_0204_MESSAGE_OPTIONS :{WHITE}Üzenetek beállításai +STR_0205_MESSAGE_TYPES :{BLACK}Üzenetfajták: +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Elsõ jármû megérkezése a játékos megállójába +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Elsõ jármû megérkezése az ellenfél megállójába +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Balesetek / természeti csapások +STR_0209_COMPANY_INFORMATION :{YELLOW}Céginformációk +STR_020A_ECONOMY_CHANGES :{YELLOW}Gazdasági változások +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Tanácsok / információk a játékos jármûveirõl +STR_020C_NEW_VEHICLES :{YELLOW}Új jármûvek +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Áruk elfogadásának változásai +STR_020E_SUBSIDIES :{YELLOW}Támogatások +STR_020F_GENERAL_INFORMATION :{YELLOW}Általános információk +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO :{WHITE}...túl távol van az elõzõ céltól +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}A legjobb cégek, akik elérték 2050-et{}({STRING} szinten) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Üzletember +STR_0214_ENTREPRENEUR :Vállalkozó +STR_0215_INDUSTRIALIST :Iparos +STR_0216_CAPITALIST :Tõkés +STR_0217_MAGNATE :Mágnás +STR_0218_MOGUL :Fejes +STR_0219_TYCOON_OF_THE_CENTURY :Az évszázad iparmágnása +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} '{STRING}' rangot ért el! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING}, a közismert {STRING} cég elnöke '{STRING}' rangot ért el! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Saját pálya készítése +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}pályaszerkesztõ +STR_0223_LAND_GENERATION :{WHITE}Táj szerkesztése +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Véletlenszerû táj +STR_0227_RESET_LAND :{BLACK}Táj törlése +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Az emelendõ/süllyesztendõ földterület növelése +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Az emelendõ/süllyesztendõ földterület csökkentése +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Véletlenszerû táj készítése +STR_022B_RESET_LANDSCAPE :{BLACK}A táj törlése +STR_022C_RESET_LANDSCAPE :{WHITE}Táj törlése +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Biztosan le akarod törölni az egész tájat? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Táj szerkesztése +STR_022F_TOWN_GENERATION :{BLACK}Városkészítés +STR_0230_INDUSTRY_GENERATION :{BLACK}Gazdasági épület készítése +STR_0231_ROAD_CONSTRUCTION :{BLACK}Útépítés +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Növényzet és egyéb tárgyak +STR_0233_TOWN_GENERATION :{WHITE}Városkészítés +STR_0234_NEW_TOWN :{BLACK}Új város +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Új város építése +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Nem építhetsz ide várost... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...túl közel van a térkép széléhez +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...túl közel van egy másik városhoz +STR_0239_SITE_UNSUITABLE :{WHITE}...nem alkalmas rá a hely +STR_023A_TOO_MANY_TOWNS :{WHITE}...túl sok a város +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}A város méretének növelése +STR_023C_EXPAND :{BLACK}Növel +STR_023D_RANDOM_TOWN :{BLACK}Véletlenszerû város +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Város építése véletlenszerû helyre +STR_023F_INDUSTRY_GENERATION :{WHITE}Gazdasági épület készítése +STR_0240_COAL_MINE :{BLACK}Szénbánya +STR_0241_POWER_STATION :{BLACK}Erõmû +STR_0242_SAWMILL :{BLACK}Fûrésztelep +STR_0243_FOREST :{BLACK}Erdõ +STR_0244_OIL_REFINERY :{BLACK}Olajfinomító +STR_0245_OIL_RIG :{BLACK}Olajfúró torony +STR_0246_FACTORY :{BLACK}Gyár +STR_0247_STEEL_MILL :{BLACK}Acélöntõ +STR_0248_FARM :{BLACK}Farm +STR_0249_IRON_ORE_MINE :{BLACK}Vasércbánya +STR_024A_OIL_WELLS :{BLACK}Olajkút +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Papírgyár +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Konzervgyár +STR_024E_PRINTING_WORKS :{BLACK}Nyomda +STR_024F_GOLD_MINE :{BLACK}Aranybánya +STR_0250_LUMBER_MILL :{BLACK}Favágó +STR_0251_FRUIT_PLANTATION :{BLACK}Gyümölcsültetvény +STR_0252_RUBBER_PLANTATION :{BLACK}Gumiültetvény +STR_0253_WATER_SUPPLY :{BLACK}Vízforrás +STR_0254_WATER_TOWER :{BLACK}Víztorony +STR_0255_DIAMOND_MINE :{BLACK}Gyémántbánya +STR_0256_COPPER_ORE_MINE :{BLACK}Rézércbánya +STR_0257_COTTON_CANDY_FOREST :{BLACK}Vattacukor-erdõ +STR_0258_CANDY_FACTORY :{BLACK}Cukorkagyár +STR_0259_BATTERY_FARM :{BLACK}Elemfarm +STR_025A_COLA_WELLS :{BLACK}Kólakút +STR_025B_TOY_SHOP :{BLACK}Játékbolt +STR_025C_TOY_FACTORY :{BLACK}Játékgyár +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Mûanyagforrás +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Üdítõital-gyár +STR_025F_BUBBLE_GENERATOR :{BLACK}Buborékgenerátor +STR_0260_TOFFEE_QUARRY :{BLACK}Tejkaramella-fejtõ +STR_0261_SUGAR_MINE :{BLACK}Cukorbánya +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Szénbánya építése +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Erõmû építése +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Fûrésztelep építése +STR_0265_PLANT_FOREST :{BLACK}Erdõ ültetése +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Olajfinomító építése +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Olajfúró torony építése (csak a térkép széléhez közel építhetõ) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Gyár építése +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Acélöntõ építése +STR_026A_CONSTRUCT_FARM :{BLACK}Farm építése +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Vasércbánya építése +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Olajkút építése +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bank építése (csak 1200-nál nagyobb lakosságú városokban építhetõ) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Papírgyár építése +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Konzervgyár építése +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Nyomda építése +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Aranybánya építése +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bank építése (csak városokba építhetõ) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Favágó építése (az esõerdõ kivágására és fa termelésére) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Gyümölcsültetvény ültetése +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Gumiültetvény ültetése +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Vízforrás építése +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Víztorony építése (csak városokban építhetõ) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Gyémántbánya építése +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Rézércbánya építése +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Vattacukor-erdõ ültetése +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Cukorkagyár építése +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Elemfarm építése +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Kólakút építése +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Játékbolt építése +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Játékgyár építése +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Mûanyagforrás építése +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Üdítõital-gyár építése +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Buborékgenerátor építése +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Tejkaramella-fejtõ építése +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Cukorbánya építése +STR_0285_CAN_T_BUILD_HERE :{WHITE}Nem építhetõ ide {STRING}... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...elõbb várost kell építened +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...városonként csak egy lehet +STR_0288_PLANT_TREES :{BLACK}Faültetés +STR_0289_PLACE_SIGN :{BLACK}Felirat lerakása +STR_028A_RANDOM_TREES :{BLACK}Véletlenszerû fák +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Véletlenszerûen fákat ültet a térképre +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Sziklás területek elhelyezése a térképen +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Világítótorony építése +STR_028E_PLACE_TRANSMITTER :{BLACK}Rádióadó építése +STR_028F_DEFINE_DESERT_AREA :{BLACK}Sivatagos terület kijelölése +STR_0290_DELETE :{BLACK}Töröl +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}A város teljes eltüntetése +STR_0292_SAVE_SCENARIO :Pálya mentése +STR_0293_LOAD_SCENARIO :Pálya betöltése +STR_0294_QUIT_EDITOR :Kilépés a szerkesztõbõl +STR_0295 : +STR_0296_QUIT :Kilépés +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Pálya betöltése, mentése, kilépés a szerkesztõbõl, kilépés +STR_0298_LOAD_SCENARIO :{WHITE}Pálya betöltése +STR_0299_SAVE_SCENARIO :{WHITE}Pálya mentése +STR_029A_PLAY_SCENARIO :{BLACK}Játék saját pályán +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Biztosan abba akarod hagyni a pálya szerkesztését ? +STR_029C_QUIT_EDITOR :{WHITE}Kilépés a szerkesztõbõl +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...csak 1200-nál nagyobb lakosságú városokba építhetõ +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}A kezdõdátum visszább állítása egy évvel +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}A kezdõdátum elõrébb állítása egy évvel +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...a híd mindkét végének szárazföldön kell lennie +STR_02A1_SMALL :{BLACK}Kicsi +STR_02A2_MEDIUM :{BLACK}Közepes +STR_02A3_LARGE :{BLACK}Nagy +STR_02A4_SELECT_TOWN_SIZE :{BLACK}A város méretének kiválasztása +STR_02A5_TOWN_SIZE :{YELLOW}A város mérete: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Utolsó üzenet vagy újsághír megmutatása +STR_02B8_SUMMARY :{BLACK}Kivonat +STR_02B9_FULL :{BLACK}Teljes +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Városlista +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Jármûvek márkanevei +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Alap +STR_02BF_CUSTOM :Saját +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Saját nevek mentése +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}A jármûvek márkanevének kiválasztása +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}A saját jármû-márkanevek elmentése lemezre + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Beállítások +STR_02C4_GAME_OPTIONS :Beállítások +STR_02C5_DIFFICULTY_SETTINGS :Nehézségi beállítások +STR_02C6_DIFFICULTY_SETTINGS :Nehézségi beállítások +STR_02C7_CONFIG_PATCHES :Foltok beállítása +STR_02C8_CONFIG_PATCHES :Foltok beállítása +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Városnevek mutatása +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Városnevek mutatása +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Állomásnevek mutatása +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Állomásnevek mutatása +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Feliratok mutatása +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Feliratok mutatása +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Ellenõrzõ pontok mutatása +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Ellenõrzõ pontok mutatása +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Teljes animáció +STR_02D0_FULL_ANIMATION :{SETX 12}Teljes animáció +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Minden részlet +STR_02D2_FULL_DETAIL :{SETX 12}Minden részlet +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Átlátszó épületek +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Átlátszó épületek +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Terület-információ +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Képmentés (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Óriás képmentés (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Az 'OpenTTD'-ról +############ range ends here + +STR_02DA_ON :{BLACK}Be +STR_02DB_OFF :{BLACK}Ki +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Állami támogatások +STR_02DD_SUBSIDIES :Támogatások +STR_02DE_MAP_OF_WORLD :Világtérkép +STR_02DF_TOWN_DIRECTORY :Városlista +STR_02E0_CURRENCY_UNITS :{BLACK}Pénznem +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}A használt pénznem kiválasztása +STR_02E3_DISTANCE_UNITS :{BLACK}Távolság mértékegysége +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}A távolságokhoz használt mértékegység kiválasztása +STR_02E6_ROAD_VEHICLES :{BLACK}Közúti jármûvek +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Válaszd ki,az út melyik oldalán haladjanak a közúti jármûvek +STR_02E9_DRIVE_ON_LEFT :Balra hajts +STR_02EA_DRIVE_ON_RIGHT :Jobbra hajts +STR_02EB_TOWN_NAMES :{BLACK}Városnevek +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}A városnevek stílusának kiválasztása + +STR_02F4_AUTOSAVE :{BLACK}Automatikus mentés +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Az automatikus mentések közötti idõtartam kiválasztása +STR_02F7_OFF :Nincs +STR_02F8_EVERY_3_MONTHS :3 havonta +STR_02F9_EVERY_6_MONTHS :6 havonta +STR_02FA_EVERY_12_MONTHS :12 havonta +STR_02FB_START_A_NEW_GAME :{BLACK}Új játék kezdése +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Egy mentett játék betöltése lemezrõl +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Demonstrációk/tanítások megnézése +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Testreszabott pálya készítése +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Egy játékos játék kiválasztása +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Két játékos játék kiválasztása +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}A játék beállításainak megmutatása +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}A nehézségi beállítások megmutatása +STR_0303_START_A_NEW_GAME_USING :{BLACK}Új játék kezdése saját pályán +STR_0304_QUIT :{BLACK}Kilépés +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Kilépés az OpenTTD-bõl +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Demonstráció/tanítás megnézése +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...csak városban építhetõ +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Mérsékelt táj kiválasztása +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Szubarktikus táj kiválasztása +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Szubtrópusi táj kiválasztása +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Játékvilág táj kiválasztása +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Gazdasági épület építése + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Új gazdasági épület építése +STR_INDUSTRY_DIR :Gazdasági épületek listája +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Új gazdasági épület +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...csak városban építhetõ +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}...csak esõerdõben építhetõ +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...csak sivatagban építhetõ +STR_0319_PAUSED :{YELLOW}* * SZÜNET * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}A képernyõ elmentve '{STRING}' néven +STR_031C_SCREENSHOT_FAILED :{WHITE}A képmentés nem sikerült! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Föld megvétele késõbbi használatra +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Közúti szállítás +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Vasúti szállítás +STR_032C_3_AIR_SERVICE :{BLACK}3: Légi szállítás +STR_032D_4_SHIP_SERVICE :{BLACK}4: Vízi szállítás +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Haladó vasúti szállítás +STR_032F_AUTOSAVE :{RED}AutoMentés +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}A 'szép az élet' zenei mûsor kiválasztása + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Angol +STR_TOWNNAME_FRENCH :Francia +STR_TOWNNAME_GERMAN :Német +STR_TOWNNAME_AMERICAN :Amerikai +STR_TOWNNAME_LATIN_AMERICAN :Latin-Amerikai +STR_TOWNNAME_SILLY :Komolytalan +STR_TOWNNAME_SWEDISH :Svéd +STR_TOWNNAME_DUTCH :Holland +STR_TOWNNAME_FINNISH :Finn +STR_TOWNNAME_POLISH :Lengyel +STR_TOWNNAME_SLOVAKISH :Szlovák +STR_TOWNNAME_HUNGARIAN :Magyar +STR_TOWNNAME_AUSTRIAN :Osztrák +############ end of townname region + +STR_CURR_POUNDS :Font ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollár ($) +STR_CURR_FF :Frank (FF) +STR_CURR_DM :Német Márka (DM) +STR_CURR_YEN :Ken ({YENSIGN}) +STR_CURR_PT :Pezeta (Pt) +STR_CURR_FT :Magyar Forint (Ft) +STR_CURR_ZL :Lengyel Zloty (zl) +STR_CURR_ATS :Osztrák Shilling (ATS) +STR_CURR_BEF :Belga Frank (BEF) +STR_CURR_DKK :Dán Korona (DKK) +STR_CURR_FIM :Finn Márka (FIM) +STR_CURR_GRD :Görög Drachma (GRD) +STR_CURR_CHF :Svájci Frank (CHF) +STR_CURR_NLG :Holland Guilder (NLG) +STR_CURR_ITL :Olasz Líra (ITL) +STR_CURR_SEK :Svéd Korona (SEK) +STR_CURR_RUR :Orosz Rubel (rur) +STR_CURR_CZK :Cseh Korona (CZK) +STR_CURR_ISK :Izlandi Korona (ISK) +STR_CURR_NOK :Norvég Korona (NOK) +STR_CURR_EUR :Euró (€) + +STR_OPTIONS_LANG :{BLACK}Nyelv +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Válassz nyelvet + +STR_OPTIONS_RES :{BLACK}A képernyõ felbontása +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Válaszd ki, milyen felbontást szeretnél a játékhoz + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Képmentés formátuma +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Válaszd ki milyen formátumú képmentést szeretnél + +STR_AUTOSAVE_1_MONTH :Minden hónapban +STR_AUTOSAVE_FAILED :{WHITE}Autómentés sikertelen + +STR_MONTH_JAN :január +STR_MONTH_FEB :február +STR_MONTH_MAR :március +STR_MONTH_APR :április +STR_MONTH_MAY :május +STR_MONTH_JUN :június +STR_MONTH_JUL :július +STR_MONTH_AUG :augusztus +STR_MONTH_SEP :szeptember +STR_MONTH_OCT :október +STR_MONTH_NOV :november +STR_MONTH_DEC :december + +STR_HEADING_FOR_STATION :{LTBLUE}{STATION} állomás felé +STR_HEADING_FOR_STATION_VEL :{LTBLUE}{STATION} állomás felé, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Nincs menetrend +STR_NO_ORDERS_VEL :{LTBLUE}Nincs menetrend, {VELOCITY} + +STR_LITERS :liter +STR_RES_OTHER :egyéb + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Nem lehet megosztani a menetrendet... +STR_CANT_COPY_ORDER_LIST :{WHITE}Nem lehet másolni a menetrendet... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Megosztott menetrend vége - - + +STR_TRAIN_IS_LOST :{WHITE}{COMMA16}. vonat eltévedt. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}{COMMA16}. vonat profitja az elmúlt évben: {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Foltok beállítása +STR_CONFIG_PATCHES_TIP :{BLACK}Foltok beállítása +STR_CONFIG_PATCHES_CAPTION :{WHITE}Foltok beállítása + +STR_CONFIG_PATCHES_OFF :Ki +STR_CONFIG_PATCHES_ON :Be +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Jármûvek sebességének kijelzése: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Lejtõre es partokra építés: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Engedélyezi az ipari létesítmények és utak rombolását, pl: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Óriásvonatok engedélyezése: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Vonatok valósághû gyorsulása: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Egymás mellé építhetõ vonatállomások: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Bármelyik rakomány telipakolása esetén induljon a jármû: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Nincs automatikus vonatjavítás: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Csak akkor szállítson árut az állomásra, ha ott van rá kereslet: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Nagyon hosszú hidak engedélyezése: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}'Menj a garázsba' engedélyezés a menetrendben: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Nyersanyagtermelõ ipari épületek építési lehetõsége: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Több hasonló ipari épület egy városon belül: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Több ugyanolyan gyár építhetõ közel egymáshoz: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Mindig teljes dátum a képernyõn: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Közlekedési lámpák a menetirány szerinti oldalon legyenek: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Pénzügyi összesítés minden év végén: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch kompatibilis nonstop kezelés: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Közúti jármûvek sorbanállása (quantum effektektus): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Ablakmozgatás, ha az egér a képernyõ szélén van: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Önkormányzatok lefizethetõsége: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Új garázskeresés: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Különbözõ vágánytípusok engedélyezése egy állomáson: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Új algoritmus a vonatok útkeresésére: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Építés szünet módban: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Mindig engedélyezze a kis repülõtereket: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}A vonat eltévedt, ha az úton töltött napok száma legalább : {ORANGE}{STRING} nap +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Figyelmeztetés, ha a vonat veszteséges: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Elöregedett jármûvek automatikus cseréje +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Hibaüzenetek megjelenítési ideje: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Hóhatár magassága: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Állomások legnagyobb kiterjedése: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Helikopterek automatikus javítása a helikopter-leszállókon: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maximum vonat játékosonként: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maximum közúti jármû játékosonként: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maximum repülõgép játékosonként: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maximum hajó játékosonként: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Vonatok tiltása a gépi ellenfeleknek: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Közúti jármûvek tiltása a gépi ellenfeleknek: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Repülõgépek tiltása a gépi ellenfeleknek: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Hajók tiltása a gépi ellenfeleknek: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Alapértelmezett szervízelés vonatoknak: {ORANGE}{STRING} naponta +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Alapértelmezett szervízelés közúti jármûveknek: {ORANGE}{STRING} naponta +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Alapértelmezett szervízelés repülõgépeknek: {ORANGE}{STRING} naponta +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Alapértelmezett szervízelés hajóknak: {ORANGE}{STRING} naponta + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Színes újságcikkek megjelenése: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Játék induló dátuma: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Egyenletes gazdaság (több, kisebb változás) + +STR_CONFIG_PATCHES_GUI :{BLACK}Megjelenítés +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Építkezés +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Jármûvek +STR_CONFIG_PATCHES_STATIONS :{BLACK}Állomások +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Gazdaság + +STR_CONFIG_PATCHES_DISABLED :kikapcsolva +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Válassz beállítási értéket + +STR_TOWNDIR_NAME :{BLACK}Név +STR_TOWNDIR_POPULATION :{BLACK}Lakosság +STR_TOWNDIR_SORT_TIP :{BLACK}Válassz rendezési sorrendet + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Úton {CHECKPOINT} felé +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Úton {CHECKPOINT} felé, {VELOCITY} + +STR_GO_TO_CHECKPOINT :{CHECKPOINT}on át + +STR_CHECKPOINTNAME_CITY :{TOWN}i ellenõrzõ pont +STR_CHECKPOINTNAME_CITY_SERIAL :{TOWN}i {COMMA16}. ellenõrzõ pont +STR_LANDINFO_CHECKPOINT :Ellenõrzõ pont + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Módosítd az ellenõrzõ pont nevét + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Nem lehet megváltoztatni az ellenõrzõ pont nevét... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Sín átalakítása ellenõrzõ ponttá +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Nem lehet vonat ellenõrzõ pontot építeni ide... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Nem lehet eltávolítani az ellenõrzõ pontot... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Sín építése egyszerûsített módón + +STR_TREES_RANDOM_TYPE :{BLACK}Véletlenszerû fafélék +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Véletlenszerûen kiválasztott fákat helyez el + +STR_CANT_BUILD_CANALS :{WHITE}Nem lehet csatornát építeni ide... +STR_BUILD_CANALS_TIP :{BLACK}Csatorna építése +STR_LANDINFO_CANAL :Csatorna + +STR_CANT_BUILD_LOCKS :{WHITE}Nem lehet zsilipet építeni ide... +STR_BUILD_LOCKS_TIP :{BLACK}Zsilip építése +STR_LANDINFO_LOCK :Zsilip + +STR_LANDINFO_COORDS :{BLACK}Koordináták: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Can't remove part of station... +STR_CANT_CONVERT_RAIL :{WHITE}Itt nem lehet átalakítani a sínt... +STR_CONVERT_RAIL_TIP :{BLACK}Sínek átalakítása a kiválasztott típusra + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Húzd ide a mozdonyt a teljes vonat eladásához + +STR_DRAG_DROP :{BLACK}Fogd és dobd +STR_STATION_DRAG_DROP :{BLACK}Állomás építése fogd és dobd módon + +STR_FAST_FORWARD :{BLACK}Játék gyorsítása +STR_MESSAGE_HISTORY :{WHITE}Elõzõ üzenetek + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Szénbánya építése +STR_CONSTRUCT_FOREST_TIP :{BLACK}Erdõ ültetése +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Olajfúró torony építése +STR_CONSTRUCT_FARM_TIP :{BLACK}Farm építése +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Rézércbánya építése +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Olajkút építése +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Aranybánya építése +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Gyémántbánya építése +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Vasércbánya építése +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Gyümölcsültetvény telepítése +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Gumiültetvény telepítése +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Vízforrás építése +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Vattacukor-erdõ telepítése +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Elemfarm építése +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Kólakút építése +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Mûanyagforrás építése +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Buborékgenerátor építése +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Tejkaramella fejtõ építése +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Cukorbánya építése + +STR_INDUSTRYDIR_NAME :{BLACK}Név +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Termelés +STR_INDUSTRYDIR_TYPE :{BLACK}Típus +STR_INDUSTRYDIR_CAPTION :{WHITE}Gazdasági épületek +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}A vonat átalakítása másfajta áru szállítására +STR_RAIL_REFIT :{WHITE}{STRING} (átalakítható) +STR_RAIL_REFIT_VEHICLE :{BLACK}Vonat átalakítása +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Válaszd ki, milyen árut szállítson a vonat +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}A vonat átalakítása a kijelölt áru szállítására +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Nem alakíthatod át a vonatot... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}{CURRENCY} kiadás +STR_0801_COST :{RED}{CURRENCY} kiadás +STR_0802_INCOME :{TINYFONT}{GREEN}{CURRENCY} bevétel +STR_0803_INCOME :{GREEN}{CURRENCY} bevétel +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Becsült ár: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Becsült ár: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Becsült bevétel: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Becsült bevétel: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Nem emelheted fel itt a földet... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Nem süllyesztheted le itt a földet... +STR_080A_ROCKS :Kövek +STR_080B_ROUGH_LAND :Durva föld +STR_080C_BARE_LAND :Csupasz föld +STR_080D_GRASS :Fû +STR_080E_FIELDS :Szántóföld +STR_080F_SNOW_COVERED_LAND :Havas föld +STR_0810_DESERT :Sivatag + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Rossz irányba lejt a föld +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nem lehetséges sínösszetétel +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Az ásás megsértené az alagutat +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Már tengerszinten van +STR_1004_TOO_HIGH :{WHITE}Túl magas +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Nincs megfelelõ sín +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}A vonat a jármûtelepen van +STR_1007_ALREADY_BUILT :{WHITE}...már van itt +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Elõbb le kell rombolnod a sínt +STR_1009_TOO_MANY_DEPOTS :{WHITE}Túl sok a raktár +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Vasútépítés +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Egysínû vasút építése +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}MagLev vasút építése +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Válassz egy vasúti hidat +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nem építhetsz ide jármûtelepet... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nem építhetsz ide vasútállomást... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nem rakhatsz ide szemafort... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nem rakhatsz ide sínt... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nem szedheted fel innen a sínt... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nem veheted le innen a szemafort... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Jármûtelep helyzete +STR_1015_RAILROAD_CONSTRUCTION :Vasútépítés +STR_1016_MONORAIL_CONSTRUCTION :Egysínû vasút építése +STR_1017_MAGLEV_CONSTRUCTION :MagLev vasút építése +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Sín lerakása +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Jármûtelep építése (vonatok vételére és karbantartására) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Vasútállomás építése +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Szemafor lerakása +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Vasúti híd építése +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Vasúti alagút építése +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Felszedés/lerakás közötti váltás síneknél és szemafornál +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Híd kiválasztása - kattints arra a hídra, amit meg akarsz építeni +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Válaszd ki a jármûtelep helyzetét +STR_1021_RAILROAD_TRACK :Vasúti sín +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Vasúti sín szemaforral +STR_1023_RAILROAD_TRAIN_DEPOT :Jármûtelep +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...a terület más cégé +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Vasúti sin szemaforral +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Vasúti sin elõrejelzõ szemaforral +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Vasúti sin kijáratjelzõ szemaforral +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Vasúti sin vegyes szemaforral + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Rossz irányba lejt a föld +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Elõbb le kell rombolnod az utat +STR_1802_ROAD_CONSTRUCTION :{WHITE}Útépítés +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Közúti híd építése +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Nem építhetsz ide utat... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nem rombolhatod le innen az utat... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Garázs helyzete +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nem építhetsz ide garázst... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Nem építhetsz ide buszmegállót... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nem építhetsz ide teherautó-rakodóhelyet... +STR_180A_ROAD_CONSTRUCTION :Útépítés +STR_180B_BUILD_ROAD_SECTION :{BLACK}Út építése +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Garázs építése (jármûvek vételére és karbantartására) +STR_180D_BUILD_BUS_STATION :{BLACK}Buszmegálló építése +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Teherautó-rakodóhely építése +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Közúti híd építése +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Közúti alagút építése +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Építés/felszedés közötti váltás utaknál +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Híd kiválasztása - kattints arra a hídra, amit meg akarsz építeni +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Válaszd ki a garázs helyzetét +STR_1814_ROAD :Út +STR_1815_ROAD_WITH_STREETLIGHTS :Út lámpákkal +STR_1816_TREE_LINED_ROAD :Fával szegélyezett út +STR_1817_ROAD_VEHICLE_DEPOT :Garázs +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Út/vasút keresztezõdés + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Városok +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Elõbb le kell rombolnod az épületet +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Lakosság: {ORANGE}{COMMA32}{BLACK} Házak: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Város átnevezése +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Nem nevezheted át a várost... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} önkormányzata nem engedélyezi +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Városnevek - kattints egy névre a város megnézéséhez +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}A fõ nézetet a városra állítja +STR_200C_CHANGE_TOWN_NAME :{BLACK}A város nevének megváltoztatása +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Utasok múlt hónapban: {ORANGE}{COMMA16}{BLACK} legfeljebb: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Levelek múlt hónapban: {ORANGE}{COMMA16}{BLACK} legfeljebb: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Magas irodaház +STR_2010_OFFICE_BLOCK :Irodaház +STR_2011_SMALL_BLOCK_OF_FLATS :Kis bérház +STR_2012_CHURCH :Templom +STR_2013_LARGE_OFFICE_BLOCK :Nagy irodaház +STR_2014_TOWN_HOUSES :Városi házak +STR_2015_HOTEL :Szálloda +STR_2016_STATUE :Szobor +STR_2017_FOUNTAIN :Szökõkút +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Irodaház +STR_201A_SHOPS_AND_OFFICES :Boltok és irodák +STR_201B_MODERN_OFFICE_BUILDING :Modern irodaház +STR_201C_WAREHOUSE :Közraktár +STR_201D_OFFICE_BLOCK :Irodaház +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Régi házak +STR_2020_LOCAL_AUTHORITY :{BLACK}Önkormányzat +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Az önkormányzat adatainak megmutatása +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} önkormányzata +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Vélemény a szállítási cégekrõl: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Támogatások +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Támogatás jár +STR_2027_FROM_TO :{ORANGE}{STRING} szállításáért {STRING} és {STRING} között +STR_2028_BY :{YELLOW} ({DATE_SHORT}ig) +STR_2029 :{STRING}i {STRING} +STR_202A_NONE :{ORANGE}--- +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Már támogatást kap +STR_202C_FROM_TO :{ORANGE}{STRING} szállításáért {STATION} és {STATION} között {YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW} ({DATE_SHORT}ig) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}A támogatás határideje lejárt:{}{}{STRING} szállításáért {STRING} és {STRING} között már nem jár támogatás. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Támogatás visszavonva:{}{}{STRING} szállítása {STATION} és {STATION} között már nem támogatott. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Támogatási ajánlat:{}{}Az elsõ {STRING} szállító {STRING} és {STRING} között egy éves támogatást kap a helyi önkormányzattól! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STATION} és {STATION} között másfélszeres hasznot hoz neki! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STATION} és {STATION} között kétszeres hasznot hoz neki! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STATION} és {STATION} között háromszoros hasznot hoz neki! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}{STRING} támogatást kapott!{}{}Így {STRING} szállítása {STATION} és {STATION} között négyszeres hasznot hoz neki! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} önkormányzata nem engedélyez új repteret a városban +STR_2036_COTTAGES :Vidéki házak +STR_2037_HOUSES :Házak +STR_2038_FLATS :Bérház +STR_2039_TALL_OFFICE_BLOCK :Magas irodaház +STR_203A_SHOPS_AND_OFFICES :Boltok és irodák +STR_203B_SHOPS_AND_OFFICES :Boltok és irodák +STR_203C_THEATER :Színház +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Irodák +STR_203F_HOUSES :Házak +STR_2040_CINEMA :Mozi +STR_2041_SHOPPING_MALL :Bevásárlóközpont +STR_2042_DO_IT :{BLACK}Tedd meg +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}A várossal tehetõ dolgok listája - kattints egy elemre a részletekhez +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}A fenti listában kijelölt intézkedés végrehajtása +STR_2045_ACTIONS_AVAILABLE :{BLACK}Lehetséges intézkedések: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Kis reklámhadjárat +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Közepes reklámhadjárat +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Nagy reklámhadjárat +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :A helyi utak helyreállíttatása +STR_204A_BUILD_STATUE_OF_COMPANY :Szobor építtetése a cég tulajdonosának +STR_204B_FUND_NEW_BUILDINGS :Új épületek építésének támogatása +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kizárólagos szállítási jogok vétele +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Az önkormányzat megvesztegetése +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Kis helyi reklámhadjárat indítása, hogy több utast és árut vonzz a megállóidba.{} Ára: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Közepes helyi reklámhadjárat indítása, hogy több utast és árut vonzz a megállóidba.{} Ára: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Nagy helyi reklámhadjárat indítása, hogy több utast és árut vonzz a megállóidba.{} Ára: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} A városi úthálózat helyreállításának támogatása. Több, mint hat hónapig jelentõsen összezavarja a közúti forgalmat.{} Ára: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Szobor építése a vállalatod tiszteletére.{} Ára: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Új kereskedelmi épületek építésének támogatása a városban.{} Ára: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Egy éves kizárólagos szállítási jogok vétele a városban. Az önkormányzat csak a te állomásaid használatát engedi meg az utasoknak és az áruknak.{} Ára: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} A megítélésed növelése az önkormányzat megvesztegetésével, komoly büntetést kockáztatva, ha ez kiderül.{} Ára: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Nem teheted ezt... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}Közlekedési zûrzavar {TOWN} városában!{}{}{STRING} által indított útjavítás keseríti meg hat hónapig az autóvezetõk életét! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (építés alatt) +STR_2059_IGLOO :Jégkunyhó +STR_205A_TEPEES :Indiánsátor +STR_205B_TEAPOT_HOUSE :Teáskanna-ház +STR_205C_PIGGY_BANK :Malacpersely + +##id 0x2800 +STR_2800_PLANT_TREES :Faültetés +STR_2801_PLACE_SIGN :Felirat lerakása +STR_2802_TREES :{WHITE}Fák +STR_2803_TREE_ALREADY_HERE :{WHITE}...már van itt +STR_2804_SITE_UNSUITABLE :{WHITE}...nem alkalmas rá a hely +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Nem ültethetsz ide fát... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...túl sok a felirat +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Nem rakhatsz ide feliratot... +STR_280A_SIGN :Felirat +STR_280B_EDIT_SIGN_TEXT :{WHITE}Felirat szerkesztése +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nem változtathatod meg a feliratot... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Válaszd ki, melyik fát ülteted +STR_280E_TREES :Fák +STR_280F_RAINFOREST :Esõerdõ +STR_2810_CACTUS_PLANTS :Kaktusz + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Vasútállomás beállítása +STR_3001_AIRPORT_SELECTION :{WHITE}Repülõtér beállítása +STR_3002_ORIENTATION :{BLACK}Helyzet +STR_3003_NUMBER_OF_TRACKS :{BLACK}Vágányok száma +STR_3004_PLATFORM_LENGTH :{BLACK}Vágányok hossza +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Túl közel van egy másik vasútállomáshoz +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Több állomással/rakodóhellyel érintkezik +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Túl sok állomás/rakodóhely van ebben a városban +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Túl sok az állomás/rakodóhely +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Túl közel van egy másik állomáshoz/rakodóhelyhez +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Elõbb le kell rombolnod a vasútállomást +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Túl közel van egy másik repülõtérhez +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Elõbb le kell rombolnod a repülõteret + +STR_3030_RENAME_STATION_LOADING :Állomás/rakodóhely átnevezése +STR_3031_CAN_T_RENAME_STATION :{WHITE}Nem nevezheted át az állomást... +STR_3032_RATINGS :{BLACK}Vélemény +STR_3033_ACCEPTS :{BLACK}Elfogadás +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}A szállítás helyi megítélése: + +############ range for rating starts +STR_3035_APPALLING :szörnyû +STR_3036_VERY_POOR :nagyon rossz +STR_3037_POOR :rossz +STR_3038_MEDIOCRE :közepes +STR_3039_GOOD :jó +STR_303A_VERY_GOOD :nagyon jó +STR_303B_EXCELLENT :kiváló +STR_303C_OUTSTANDING :kimagasló +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} többé nem fogad el {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} többé nem fogad el {STRING} és {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} most már elfogad {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} most már elfogad {STRING} és {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Buszmegálló helyzete +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Rakodóhely helyzete +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Túl közel van egy másik buszmegállóhoz +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Túl közel van egy másik teherautó-rakodóhoz +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Elõbb le kell rombolnod a buszmegállót +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Elõbb le kell rombolnod a teherautó-rakodóhelyet +STR_3048_STATIONS :{WHITE}{STRING} állomásai - {COMMA16} +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Nincs - +STR_304B_SITE_UNSUITABLE :{WHITE}...nem alkalmas rá a hely +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Túl közel van egy másik kikötõhöz +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Elõbb le kell rombolnod a kikötõt +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Vasútállomás helyzetének kiválasztása +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}A vasútállomás vágányainak száma +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}A vasútállomás hossza +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Buszmegálló helyzetének kiválasztása +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Teherautó-rakodó helyzetének kiválasztása +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}A fõ nézetet az állomásra állítja +STR_3054_SHOW_STATION_RATINGS :{BLACK}Vélemény megmutatása az állomásról +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Az állomás nevének megváltoztatása +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Az elfogadott áruk listájának mutatása +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Állomásnevek - kattints egy névre az állomás megnézéséhez +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Repülõtér méretének/típusának kiválasztása +STR_3059_SMALL :{BLACK}Kicsi +STR_305A_LARGE :{BLACK}Városi +STR_305AA_LARGE :{BLACK}Nagyvárosi repülõtér +STR_305AB_LARGE :{BLACK}Nemzetközi repülõter +STR_305B_SIZE :{BLACK}Méret +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Vasútállomás +STR_305F_AIRCRAFT_HANGAR :Reptéri hangár +STR_3060_AIRPORT :Repülõtér +STR_3061_TRUCK_LOADING_AREA :Teherautó-rakodóhely +STR_3062_BUS_STATION :Buszmegálló +STR_3063_SHIP_DOCK :Kikötõ +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}A kiválasztott helyen lefedett terület mutatása +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}A kiválasztott helyen lefedett terület elrejtése +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Lefedett terület mutatása: +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Egysínû állomás beállítása +STR_3068_DOCK :{WHITE}Kikötõ +STR_3069_BUOY :Bója +STR_306A_BUOY_IN_THE_WAY :{WHITE}...bója van az útban +STR_306B_HELIPORT :{BLACK}Helikopter-leszálló +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...az állomás túl kiterjedt + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Dokk helyzete +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...csak vízen építhetõ +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nem építhetsz ide dokkot... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Válaszd ki a dokk helyzetét +STR_3804_WATER :Víz +STR_3805_COAST_OR_RIVERBANK :Tenger- vagy folyópart +STR_3806_SHIP_DEPOT :Dokk +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...nem építhetõ vízen + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Játék mentése +STR_4001_LOAD_GAME :{WHITE}Játék betöltése +STR_4002_SAVE :{BLACK}Ment +STR_4003_DELETE :{BLACK}Töröl +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabájt szabad +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Nem olvasható a meghajtó +STR_4007_GAME_SAVE_FAILED :{WHITE}A mentés nem sikerült +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Nem sikerült törölni a fájlt +STR_4009_GAME_LOAD_FAILED :{WHITE}A betöltés nem sikerült +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Meghajtók, könyvtárak és mentések listája +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}A mentés neve +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}A kijelölt mentés törlése +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}A játék elmentése a választott néven +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Az új játék típusa +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Válassz egy pályát (zöld), elõre beállított játékot (kék) vagy véletlenszerû új játékot +STR_4010_GENERATE_RANDOM_NEW_GAME :Véletlenszerû új játék + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}...{STRING} van az útban +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :szénbánya +STR_4803_POWER_STATION :erõmû +STR_4804_SAWMILL :fûrésztelep +STR_4805_FOREST :erdõ +STR_4806_OIL_REFINERY :olajfinomító +STR_4807_OIL_RIG :olajfúró torony +STR_4808_FACTORY :gyár +STR_4809_PRINTING_WORKS :nyomda +STR_480A_STEEL_MILL :acélöntõ +STR_480B_FARM :farm +STR_480C_COPPER_ORE_MINE :rézércbánya +STR_480D_OIL_WELLS :olajkút +STR_480E_BANK :bank +STR_480F_FOOD_PROCESSING_PLANT :konzervgyár +STR_4810_PAPER_MILL :papírgyár +STR_4811_GOLD_MINE :aranybánya +STR_4812_BANK :bank +STR_4813_DIAMOND_MINE :gyémántbánya +STR_4814_IRON_ORE_MINE :vasércbánya +STR_4815_FRUIT_PLANTATION :gyümölcsültetvény +STR_4816_RUBBER_PLANTATION :gumiültetvény +STR_4817_WATER_SUPPLY :vízforrás +STR_4818_WATER_TOWER :víztorony +STR_4819_FACTORY :gyár +STR_481A_FARM :farm +STR_481B_LUMBER_MILL :favágó +STR_481C_COTTON_CANDY_FOREST :vattacukor-erdõ +STR_481D_CANDY_FACTORY :cukorkagyár +STR_481E_BATTERY_FARM :elemfarm +STR_481F_COLA_WELLS :kólakút +STR_4820_TOY_SHOP :játékbolt +STR_4821_TOY_FACTORY :játékgyár +STR_4822_PLASTIC_FOUNTAINS :mûanyagforrás +STR_4823_FIZZY_DRINK_FACTORY :üdítõital-gyár +STR_4824_BUBBLE_GENERATOR :buborékgenerátor +STR_4825_TOFFEE_QUARRY :tejkaramella fejtõ +STR_4826_SUGAR_MINE :cukorbánya + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Felhasznál: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Felhasznál: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Felhasznál: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Múlt havi termelés: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% elszállítva) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}A fõ nézetet a gazdasági épületre állítja +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Új {STRING} épül {TOWN} közelében! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Új {STRING} ültettek {TOWN} közelében! +STR_482F_COST :{BLACK}Ár: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nem építheted ide ezt a gazdasági épületet... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...erdõ csak a hóhatár fölé ültethetõ +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN}i {STRING} bejelentette, hogy hamarosan bezár! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}{TOWN}i {STRING} bejelentette, hogy ellátási gondok miatt hamarosan bezár! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}{TOWN}i {STRING} bejelentette, hogy a közeli fák hiánya miatt hamarosan bezár! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN}i {STRING} növeli a termelését! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Új szénréteget találtak {TOWN}i {STRING}ban!{}A termelés megkétszerezõdik! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Új olajtartalékokat találtak {TOWN}i {STRING} alatt!{}A termelés megkétszerezõdik! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}{TOWN}i {STRING} haladó gazdálkodási módszerekkel megkétszerezi termelését! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN}i {STRING} termelése a felére csökkent +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Egy rovaráradat {TOWN}i {STRING} pusztulását okozta!{}A termelés a felére csökkent +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...csak a térkép széléhez közel építhetõ +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} termelés nõtt! {TOWN}i {STRING} mostantól {COMMA16}%-al többet termel! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} termelés csökkent! {TOWN} {STRING} mostantól {COMMA16}%-al kevesebbet termel! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Vonat van az alagútban +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Közúti jármû van az alagútban +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Másik alagút van az útban +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Nem lehet kiásni a földet az alagút túloldalán +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Elõbb le kell rombolnod az alagutat +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Elõbb le kell rombolnod a hidat +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nem kezdõdhet és végzõdhet ugyanott +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sima föld vagy víz kell, hogy legyen a híd alatt +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}A kezdetének és a végének egy vonalban kell lennie +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Nem alkalmas a hely alagút bejáratának +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Függõ, acél +STR_500F_GIRDER_STEEL :Gerendás, acél +STR_5010_CANTILEVER_STEEL :Konzolos, acél +STR_5011_SUSPENSION_CONCRETE :Függõ, beton +STR_5012_WOODEN :Fa +STR_5013_CONCRETE :Beton +STR_5014_TUBULAR_STEEL :Csõ, acél +STR_BRIDGE_TUBULAR_SILICON :Csõ, Szilikon +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nem építhetsz ide hidat... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nem áshatsz ide alagutat... +STR_5017_RAILROAD_TUNNEL :Vasúti alagút +STR_5018_ROAD_TUNNEL :Közúti alagút +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Acél függõ vasúti híd +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Gerendás acél vasúti híd +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Konzolos acél vasúti híd +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Vasbeton függõ vasúti híd +STR_501F_WOODEN_RAIL_BRIDGE :Fa vasúti híd +STR_5020_CONCRETE_RAIL_BRIDGE :Beton vasúti híd +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Acél függõ közúti híd +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Gerendás acél közúti híd +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Konzolos acél közúti híd +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Vasbeton függõ közúti híd +STR_5025_WOODEN_ROAD_BRIDGE :Fa közúti híd +STR_5026_CONCRETE_ROAD_BRIDGE :Beton közúti híd +STR_5027_TUBULAR_RAIL_BRIDGE :Csõ vasúti híd +STR_5028_TUBULAR_ROAD_BRIDGE :Csõ közúti híd +STR_5029_STEEL :Acél + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Tárgy van az útban +STR_5801_TRANSMITTER :Rádióadó +STR_5802_LIGHTHOUSE :Világítótorony +STR_5803_COMPANY_HEADQUARTERS :Vállalat székháza +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...vállalat székháza van az útban +STR_5805_COMPANY_OWNED_LAND :Cég által lefoglalt föld +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Nem veheted meg ezt a földterületet... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...már a tiéd! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Névtelen{SKIP} +STR_SV_TRAIN_NAME :Vonat {COMMA16} +STR_SV_ROADVEH_NAME :Közúti jármû {COMMA16} +STR_SV_SHIP_NAME :Hajó {COMMA16} +STR_SV_AIRCRAFT_NAME :Repülõ {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :Észak-{STRING} +STR_SV_STNAME_SOUTH :Dél-{STRING} +STR_SV_STNAME_EAST :Kelet-{STRING} +STR_SV_STNAME_WEST :Nyugat-{STRING} +STR_SV_STNAME_CENTRAL :{STRING} i központ +STR_SV_STNAME_TRANSFER :{STRING}i átszálló +STR_SV_STNAME_HALT :{STRING}i megálló +STR_SV_STNAME_VALLEY :{STRING}i völgy +STR_SV_STNAME_HEIGHTS :{STRING}i hegy +STR_SV_STNAME_WOODS :{STRING}i erdõ +STR_SV_STNAME_LAKESIDE :{STRING}i tópart +STR_SV_STNAME_EXCHANGE :{STRING} csere +STR_SV_STNAME_AIRPORT :{STRING}i reptér +STR_SV_STNAME_OILFIELD :{STRING}i olajmezõ +STR_SV_STNAME_MINES :{STRING}i bánya +STR_SV_STNAME_DOCKS :{STRING}i kikötõ +STR_SV_STNAME_BUOY_1 :{STRING}i bója 1 +STR_SV_STNAME_BUOY_2 :{STRING}i bója 2 +STR_SV_STNAME_BUOY_3 :{STRING}i bója 3 +STR_SV_STNAME_BUOY_4 :{STRING}i bója 4 +STR_SV_STNAME_BUOY_5 :{STRING}i bója 5 +STR_SV_STNAME_BUOY_6 :{STRING}i bója 6 +STR_SV_STNAME_BUOY_7 :{STRING}i bója 7 +STR_SV_STNAME_BUOY_8 :{STRING}i bója 8 +STR_SV_STNAME_BUOY_9 :{STRING}i bója 9 +STR_SV_STNAME_ANNEXE :{STRING} mellék +STR_SV_STNAME_SIDINGS :{STRING} oldal +STR_SV_STNAME_BRANCH :{STRING} mellékág +STR_SV_STNAME_UPPER :{STRING}-felsõ +STR_SV_STNAME_LOWER :{STRING}-alsó +STR_SV_STNAME_HELIPORT :{STRING}i helikopter-leszálló +STR_SV_STNAME_FOREST :{STRING}i erdõség + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Nehézségi szint + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Könnyû +STR_6802_MEDIUM :{BLACK}Közepes +STR_6803_HARD :{BLACK}Nehéz +STR_6804_CUSTOM :{BLACK}Egyéni +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Ellenfelek száma legfeljebb: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Ellenfelek kezdésének ideje: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Városok száma: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Gazdasági épületek száma: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Kezdeti kölcsön: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Kezdõ kamatláb: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Jármû fenntartási költség: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}Ellenfelek építkezési sebessége: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Ellenfelek intelligenciája: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Jármûvek lerobbanása: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Támogatások szorzója: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Építkezés költsége: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Terep típusa: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Tenger/tavak mennyisége: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Gazdasági élet: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Vonatok fordítása: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katasztrófák: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Kevés +STR_6817_NORMAL :Normál +STR_6818_HIGH :Sok +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Nagyon lassú +STR_681C_SLOW :Lassú +STR_681D_MEDIUM :Közepes +STR_681E_FAST :Gyors +STR_681F_VERY_FAST :Nagyon gyors +STR_VERY_LOW :Nagyon alacsony +STR_6820_LOW :Alacsony +STR_6821_MEDIUM :Közepes +STR_6822_HIGH :Magas +STR_6823_NONE :Nincs +STR_6824_REDUCED :Ritka +STR_6825_NORMAL :Normál +STR_6826_X1_5 :1,5x +STR_6827_X2 :2x +STR_6828_X3 :3x +STR_6829_X4 :4x +STR_682A_VERY_FLAT :Nagyon sík +STR_682B_FLAT :Sík +STR_682C_HILLY :Dombos +STR_682D_MOUNTAINOUS :Hegyes +STR_682E_STEADY :Stabil +STR_682F_FLUCTUATING :Változó +STR_6830_IMMEDIATE :Azonnal +STR_6831_3_MONTHS_AFTER_PLAYER :3 hónappal utánad +STR_6832_6_MONTHS_AFTER_PLAYER :6 hónappal utánad +STR_6833_9_MONTHS_AFTER_PLAYER :9 hónappal utánad +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Vonal végén és állomásokon +STR_6835_AT_END_OF_LINE_ONLY :Csak vonal végén +STR_6836_OFF :Ki +STR_6837_ON :Be +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Legjobb pontok + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 :(1. játékos) +STR_7003_PLAYER_2 :(2. játékos) +STR_7004_NEW_FACE :{BLACK}Új arc +STR_7005_COLOR_SCHEME :{BLACK}Szín váltása +STR_7006_COLOR_SCHEME :{GOLD}Szín: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Új szín +STR_7008_COMPANY_NAME :{BLACK}Vállalat neve +STR_7009_PRESIDENT_NAME :{BLACK}Elnök neve +STR_700A_COMPANY_NAME :A vállalat neve +STR_700B_PRESIDENT_S_NAME :Az elnök neve +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Nem változtathatod meg a cég nevét... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Nem változtathatod meg az elnök nevét... +STR_700E_FINANCES :{WHITE}{STRING} pénzügyei{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Kiadás/Bevétel +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Építkezés +STR_7012_NEW_VEHICLES :{GOLD}Új jármûvek +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Vonat mûködtetési költség +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Közúti jármû mûk. költség +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Repülõgép mûk. költség +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Hajó mûködtetési költség +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Tulajdon fenntartása +STR_7018_TRAIN_INCOME :{GOLD}Vonatok bevétele +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Közúti jármûvek bevétele +STR_701A_AIRCRAFT_INCOME :{GOLD}Repülõgépek bevétele +STR_701B_SHIP_INCOME :{GOLD}Hajók bevétele +STR_701C_LOAN_INTEREST :{GOLD}Kölcsön kamata +STR_701D_OTHER :{GOLD}Egyéb +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Összesen: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Jövedelem grafikon +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Mûködési nyereség grafikon +STR_7026_BANK_BALANCE :{WHITE}Banki egyenleg +STR_7027_LOAN :{WHITE}Kölcsön +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}{SKIP}{SKIP}{SKIP}{CURRENCY} kölcsönzése +STR_702A_REPAY :{BLACK}{SKIP}{SKIP}{SKIP}{CURRENCY} törlesztése +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...{CURRENCY} a megengedett legnagyobb kölcsön +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nem kölcsönözhetsz több pénzt... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...már letörlesztetted az összeset +STR_702E_REQUIRED :{WHITE}...{CURRENCY} kellene hozzá +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Nem törleszthetsz a kölcsönbõl... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Új arc választása az elnöknek +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}A cég jármûvei színének megváltoztatása +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Az elnök nevének megváltoztatása +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}A cég nevének megváltoztatása +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Kattints az új színre +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}A kölcsön növelése +STR_7036_REPAY_PART_OF_LOAN :{BLACK}A kölcsön egy részének törlesztése +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Elnök) +STR_7038_INAUGURATED :{GOLD}Alapítás éve: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Jármûvek: +STR_703A_TRAIN :{WHITE}{COMMA16} vonat +STR_703B_TRAINS :{WHITE}{COMMA16} vonat +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} közúti jármû +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} közúti jármû +STR_703E_AIRCRAFT :{WHITE}{COMMA16} repülõgép +STR_703F_AIRCRAFT :{WHITE}{COMMA16} repülõgép +STR_7040_SHIP :{WHITE}{COMMA16} hajó +STR_7041_SHIPS :{WHITE}{COMMA16} hajó +STR_7042_NONE :{WHITE}Nincs +STR_7043_FACE_SELECTION :{WHITE}Arcválasztás +STR_7044_MALE :{BLACK}Férfi +STR_7045_FEMALE :{BLACK}Nõ +STR_7046_NEW_FACE :{BLACK}Új arc +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Új arc elvetése +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Új arc elfogadása +STR_7049_SELECT_MALE_FACES :{BLACK}Férfi arcok kiválasztása +STR_704A_SELECT_FEMALE_FACES :{BLACK}Nõi arcok kiválasztása +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Véletlenszerû új arc létrehozása +STR_704C_KEY :{BLACK}Jelkulcs +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}A grafikonok jelmagyarázata +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Jelmagyarázat a grafikonokhoz +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}A vállalat adatainak mutatása/elrejtése a grafikonon +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Elszállított áruk mennyisége +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Cégek teljesítménye (legjobb teljesítmény=1000) +STR_7052_COMPANY_VALUES :{WHITE}Vállalatok értéke +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}A cégek helyezése +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Egy szállítási cég bajban van! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} csõdöt jelent vagy el kell adni, ha teljesítménye nem nõ hamarosan! +STR_7058_PRESIDENT :{BLACK}{STRING} {}(Elnök) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Szállítási cégek egyesülése! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} céget felvásárolta {STRING} {CURRENCY}-ért! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Egy olyan szállítási céget keresünk, aki tovább vezetné a cégünket{}{}Megveszed {STRING} céget {CURRENCY}-ért? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Csõd! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} céget bezáratták a hitelezõi és minden vagyonát elárverezték! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Új szállítási vállalatot alapítottak! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} {TOWN} közelében kezd építkezni! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Nem veheted meg a céget... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Rakományok szállítási díja +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Úton töltött napok +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Fizetség 10 egység (vagy 10000 liter) áru 20 négyzetre való szállításáért +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Az adott áru grafikonjának mutatása be/ki +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Mérnök +STR_7067_TRAFFIC_MANAGER :Forgalomigazgató +STR_7068_TRANSPORT_COORDINATOR :Szállításszervezõ +STR_7069_ROUTE_SUPERVISOR :Útfelügyelõ +STR_706A_DIRECTOR :Igazgató +STR_706B_CHIEF_EXECUTIVE :Fõigazgató +STR_706C_CHAIRMAN :Alelnök +STR_706D_PRESIDENT :Elnök +STR_706E_TYCOON :Nagytõkés +STR_706F_BUILD_HQ :{BLACK}Székház építése +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}A cég székházának megépítése/ megnézése +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nem építheted ide a székházadat... +STR_7072_VIEW_HQ :{BLACK}Székház +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Gazdasági visszaesés!{}{}A közgazdászok gazdasági válságtól tartanak! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Vége a visszaesésnek!{}{}A kereskedelem fellendül, ami önbizalmat ad az iparnak, és erõsödik a gazdaság! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Kicsi/nagy ablakméret közötti váltás +STR_7076_COMPANY_VALUE :{GOLD}A vállalat értéke: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}25% megvétele a cégbõl +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}25% eladása a cégbõl +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}25% megvétele ebbõl a cégbõl +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}25% eladása ebbõl a cégbõl +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nem vehetsz 25%-ot ebbõl a cégbõl... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Nem adhatsz el 25%-ot ebbõl a cégbõl... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% {STRING} tulajdona) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% {STRING} tulajdona{} {COMMA16}% {STRING} tulajdona) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} céget felvásárolta {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Gõz) +STR_8001_MJS_250_DIESEL :MJS 250 (Dízel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Cammogó Csi-hu-hu +STR_8003_POWERNAUT_CHOO_CHOO :SemmiErõ Csi-hu-hu +STR_8004_MIGHTYMOVER_CHOO_CHOO :ErõGép Csi-hu-hu +STR_8005_PLODDYPHUT_DIESEL :Cammogó Dízel +STR_8006_POWERNAUT_DIESEL :SemmiErõ Dízel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Gõz) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Gõz) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Gõz) +STR_800A_SH_8P_STEAM :SH '8P' (Gõz) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Dízel) +STR_800C_DASH_DIESEL :'Dash' (Dízel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Dízel) +STR_800E_UU_37_DIESEL :UU '37' (Dízel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Dízel) +STR_8010_CS_4000_DIESEL :CS 4000 (Dízel) +STR_8011_CS_2400_DIESEL :CS 2400 (Dízel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Dízel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Dízel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Dízel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Dízel) +STR_8016_SH_125_DIESEL :SH '125' (Dízel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektromos) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektromos) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektromos) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektromos) +STR_801B_PASSENGER_CAR :Személyvagon +STR_801C_MAIL_VAN :Levélszállító vagon +STR_801D_COAL_CAR :Szénszállító vagon +STR_801E_OIL_TANKER :Olajszállító vagon +STR_801F_LIVESTOCK_VAN :Állatszállító vagon +STR_8020_GOODS_VAN :Áruszállító vagon +STR_8021_GRAIN_HOPPER :Gabonaszállító vagon +STR_8022_WOOD_TRUCK :Faszállító vagon +STR_8023_IRON_ORE_HOPPER :Vasércszállító vagon +STR_8024_STEEL_TRUCK :Acélszállító vagon +STR_8025_ARMORED_VAN :Páncélozott vagon +STR_8026_FOOD_VAN :Ételszállító vagon +STR_8027_PAPER_TRUCK :Papírszállító vagon +STR_8028_COPPER_ORE_HOPPER :Rézércszállító vagon +STR_8029_WATER_TANKER :Vízszállító vagon +STR_802A_FRUIT_TRUCK :Gyümölcsszállító vagon +STR_802B_RUBBER_TRUCK :Gumiszállító vagon +STR_802C_SUGAR_TRUCK :Cukorszállító vagon +STR_802D_COTTON_CANDY_HOPPER :Vattacukorszállító vagon +STR_802E_TOFFEE_HOPPER :Tejkaramella-szállító vagon +STR_802F_BUBBLE_VAN :Buborékszállító vagon +STR_8030_COLA_TANKER :Kólaszállító vagon +STR_8031_CANDY_VAN :Cukorkaszállító vagon +STR_8032_TOY_VAN :Játékszállító vagon +STR_8033_BATTERY_TRUCK :Elemszállító vagon +STR_8034_FIZZY_DRINK_TRUCK :Szénsavasital-szállító vagon +STR_8035_PLASTIC_TRUCK :Mûanyagszállító vagon +STR_8036_X2001_ELECTRIC :'X2001' (Elektromos) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektromos) +STR_8038_WIZZOWOW_Z99 :ZummDeGyors Z99 +STR_8039_PASSENGER_CAR :Személyvagon +STR_803A_MAIL_VAN :Levélszállító vagon +STR_803B_COAL_CAR :Szénszállító vagon +STR_803C_OIL_TANKER :Olajszállító vagon +STR_803D_LIVESTOCK_VAN :Állatszállító vagon +STR_803E_GOODS_VAN :Áruszállító vagon +STR_803F_GRAIN_HOPPER :Gabonaszállító vagon +STR_8040_WOOD_TRUCK :Faszállító vagon +STR_8041_IRON_ORE_HOPPER :Vasércszállító vagon +STR_8042_STEEL_TRUCK :Acélszállító vagon +STR_8043_ARMORED_VAN :Páncélozott vagon +STR_8044_FOOD_VAN :Ételszállító vagon +STR_8045_PAPER_TRUCK :Papírszállító vagon +STR_8046_COPPER_ORE_HOPPER :Rézércszállító vagon +STR_8047_WATER_TANKER :Vízszállító vagon +STR_8048_FRUIT_TRUCK :Gyümölcsszállító vagon +STR_8049_RUBBER_TRUCK :Gumiszállító vagon +STR_804A_SUGAR_TRUCK :Cukorszállító vagon +STR_804B_COTTON_CANDY_HOPPER :Vattacukorszállító vagon +STR_804C_TOFFEE_HOPPER :Tejkaramella-szállító vagon +STR_804D_BUBBLE_VAN :Buborékszállító vagon +STR_804E_COLA_TANKER :Kólaszállító vagon +STR_804F_CANDY_VAN :Cukorkaszállító vagon +STR_8050_TOY_VAN :Játékszállító vagon +STR_8051_BATTERY_TRUCK :Elemszállító vagon +STR_8052_FIZZY_DRINK_TRUCK :Szénsavasital-szállító vagon +STR_8053_PLASTIC_TRUCK :Mûanyagszállító vagon +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviátán' (Elektromos) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Küklopsz' (Elektromos) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegazus' (Elektromos) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Kiméra' (Elektromos) +STR_8058_WIZZOWOW_ROCKETEER :ZummDeGyors Rakéta +STR_8059_PASSENGER_CAR :Személyvagon +STR_805A_MAIL_VAN :Levélszállító vagon +STR_805B_COAL_CAR :Szénszállító vagon +STR_805C_OIL_TANKER :Olajszállító vagon +STR_805D_LIVESTOCK_VAN :Állatszállító vagon +STR_805E_GOODS_VAN :Áruszállító vagon +STR_805F_GRAIN_HOPPER :Gabonaszállító vagon +STR_8060_WOOD_TRUCK :Faszállító vagon +STR_8061_IRON_ORE_HOPPER :Vasércszállító vagon +STR_8062_STEEL_TRUCK :Acélszállító vagon +STR_8063_ARMORED_VAN :Páncélozott vagon +STR_8064_FOOD_VAN :Ételszállító vagon +STR_8065_PAPER_TRUCK :Papírszállító vagon +STR_8066_COPPER_ORE_HOPPER :Rézércszállító vagon +STR_8067_WATER_TANKER :Vízszállító vagon +STR_8068_FRUIT_TRUCK :Gyümölcsszállító vagon +STR_8069_RUBBER_TRUCK :Gumiszállító vagon +STR_806A_SUGAR_TRUCK :Cukorszállító vagon +STR_806B_COTTON_CANDY_HOPPER :Vattacukorszállító vagon +STR_806C_TOFFEE_HOPPER :Tejkaramella-szállító vagon +STR_806D_BUBBLE_VAN :Buborékszállító vagon +STR_806E_COLA_TANKER :Kólaszállító vagon +STR_806F_CANDY_VAN :Cukorkaszállító vagon +STR_8070_TOY_VAN :Játékszállító vagon +STR_8071_BATTERY_TRUCK :Elemszállító vagon +STR_8072_FIZZY_DRINK_TRUCK :Szénsavasital-szállító vagon +STR_8073_PLASTIC_TRUCK :Mûanyagszállító vagon +STR_8074_MPS_REGAL_BUS :MPS királyi busz +STR_8075_HEREFORD_LEOPARD_BUS :Hereford leopárd busz +STR_8076_FOSTER_BUS :Foster busz +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII szuperbusz +STR_8078_PLODDYPHUT_MKI_BUS :Cammogó MkI busz +STR_8079_PLODDYPHUT_MKII_BUS :Cammogó MkII busz +STR_807A_PLODDYPHUT_MKIII_BUS :Cammogó MkIII busz +STR_807B_BALOGH_COAL_TRUCK :Balogh szénszállító autó +STR_807C_UHL_COAL_TRUCK :Uhl szénszállító +STR_807D_DW_COAL_TRUCK :DW szénszállító +STR_807E_MPS_MAIL_TRUCK :MPS levélszállító +STR_807F_REYNARD_MAIL_TRUCK :Reynard levélszállító +STR_8080_PERRY_MAIL_TRUCK :Perry levélszállító +STR_8081_MIGHTYMOVER_MAIL_TRUCK :ErõGép levélszállító +STR_8082_POWERNAUGHT_MAIL_TRUCK :SemmiErõ levélszállító +STR_8083_WIZZOWOW_MAIL_TRUCK :ZummDeGyors levélszállító +STR_8084_WITCOMBE_OIL_TANKER :Witcombe olajszállító +STR_8085_FOSTER_OIL_TANKER :Foster olajszállító +STR_8086_PERRY_OIL_TANKER :Perry olajszállító +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott állatszállító +STR_8088_UHL_LIVESTOCK_VAN :Uhl állatszállító +STR_8089_FOSTER_LIVESTOCK_VAN :Foster állatszállító +STR_808A_BALOGH_GOODS_TRUCK :Balogh áruszállító +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead áruszállító +STR_808C_GOSS_GOODS_TRUCK :Goss áruszállító +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford gabonaszállító +STR_808E_THOMAS_GRAIN_TRUCK :Thomas gabonaszállító +STR_808F_GOSS_GRAIN_TRUCK :Goss gabonaszállító +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe faszállító +STR_8091_FOSTER_WOOD_TRUCK :Foster faszállító +STR_8092_MORELAND_WOOD_TRUCK :Moreland faszállító +STR_8093_MPS_IRON_ORE_TRUCK :MPS vasércszállító +STR_8094_UHL_IRON_ORE_TRUCK :Uhl vasércszállító +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy vasércszállító +STR_8096_BALOGH_STEEL_TRUCK :Balogh acélszállító +STR_8097_UHL_STEEL_TRUCK :Uhl acélszállító +STR_8098_KELLING_STEEL_TRUCK :Kelling acélszállító +STR_8099_BALOGH_ARMORED_TRUCK :Balogh páncélkocsi +STR_809A_UHL_ARMORED_TRUCK :Uhl páncélkocsi +STR_809B_FOSTER_ARMORED_TRUCK :Foster páncélkocsi +STR_809C_FOSTER_FOOD_VAN :Foster ételszállító +STR_809D_PERRY_FOOD_VAN :Perry ételszállító +STR_809E_CHIPPY_FOOD_VAN :Chippy ételszállító +STR_809F_UHL_PAPER_TRUCK :Uhl papírszállító +STR_80A0_BALOGH_PAPER_TRUCK :Balogh papírszállító +STR_80A1_MPS_PAPER_TRUCK :MPS papírszállító +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS rézércszállító +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl rézércszállító +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss rézércszállító +STR_80A5_UHL_WATER_TANKER :Uhl vízszállító +STR_80A6_BALOGH_WATER_TANKER :Balogh vízszállító +STR_80A7_MPS_WATER_TANKER :MPS vízszállító +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh gyümölcsszállító +STR_80A9_UHL_FRUIT_TRUCK :Uhl gyümölcsszállító +STR_80AA_KELLING_FRUIT_TRUCK :Kelling gyümölcsszállító +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh gumiszállító +STR_80AC_UHL_RUBBER_TRUCK :Uhl gumiszállító +STR_80AD_RMT_RUBBER_TRUCK :RMT gumiszállító +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :SemmiErõ cukorszállító +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :ErõGép cukorszállító +STR_80B0_WIZZOWOW_SUGAR_TRUCK :ZummDeGyors cukorszállító +STR_80B1_MIGHTYMOVER_COLA_TRUCK :SemmiErõ kólaszállító +STR_80B2_POWERNAUGHT_COLA_TRUCK :ErõGép kólaszállító +STR_80B3_WIZZOWOW_COLA_TRUCK :ZummDeGyors kólaszállító +STR_80B4_MIGHTYMOVER_COTTON_CANDY :SemmiErõ vattacukor-sz. +STR_80B5_POWERNAUGHT_COTTON_CANDY :ErõGép vattacukor-sz. +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :ZummDeGyors vattacukor-sz. +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :SemmiErõ tejkaramella-sz. +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :ErõGép tejkaramella-sz. +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :ZummDeGyors tejkaramella-sz. +STR_80BA_MIGHTYMOVER_TOY_VAN :SemmiErõ játékszállító +STR_80BB_POWERNAUGHT_TOY_VAN :ErõGép játékszállító +STR_80BC_WIZZOWOW_TOY_VAN :ZummDeGyors játékszállító +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :SemmiErõ cukorkaszállító +STR_80BE_POWERNAUGHT_CANDY_TRUCK :ErõGép cukorkaszállító +STR_80BF_WIZZOWOW_CANDY_TRUCK :ZummDeGyors cukorkaszállító +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :SemmiErõ elemszállító +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :ErõGép elemszállító +STR_80C2_WIZZOWOW_BATTERY_TRUCK :ZummDeGyors elemszállító +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :SemmiErõ szénsavasital-sz. +STR_80C4_POWERNAUGHT_FIZZY_DRINK :ErõGép szénsavasital-sz. +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :ZummDeGyors szénsavasital-sz. +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :SemmiErõ mûanyagszállító +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :ErõGép mûanyagszállító +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :ZummDeGyors mûanyagszállító +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :SemmiErõ buborékszállító +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :ErõGép buborékszállító +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :ZummDeGyors buborékszállító +STR_80CC_MPS_OIL_TANKER :MPS olajszállító hajó +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. olajszállító hajó +STR_80CE_MPS_PASSENGER_FERRY :MPS komp +STR_80CF_FFP_PASSENGER_FERRY :FFP komp +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 légpárnás hajó +STR_80D1_CHUGGER_CHUG_PASSENGER :Zity-zöty komp +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :SzétRáz komp +STR_80D3_YATE_CARGO_SHIP :Yate teherhajó +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell teherhajó +STR_80D5_MIGHTYMOVER_CARGO_SHIP :ErõGép teherhajó +STR_80D6_POWERNAUT_CARGO_SHIP :SemmiErõ teherhajó +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dárda +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxis +STR_80E9_AIRTAXI_A21 :Légitaxi A21 +STR_80EA_AIRTAXI_A31 :Légitaxi A31 +STR_80EB_AIRTAXI_A32 :Légitaxi A32 +STR_80EC_AIRTAXI_A33 :Légitaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :Légitaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hiperdárda 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Cammogó 100 +STR_80F9_PLODDYPHUT_500 :Cammogó 500 +STR_80FA_FLASHBANG_X1 :BummSzáguld X1 +STR_80FB_JUGGERPLANE_M1 :LégiHáz M1 +STR_80FC_FLASHBANG_WIZZER :CsíkHúzó +STR_80FD_TRICARIO_HELICOPTER :Tricario Helikopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helikopter +STR_80FF_POWERNAUT_HELICOPTER :SemmiErõ Helikopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE :{WHITE}Üzenet egy jármûgyártótól +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Most készültek el egy új {STRING} tervei - érdekelne a jármû egy éves kizárólagos használata, hogy megnézhessük a képességeit, mielõtt mindenki számára elérhetõvé tesszük ? +STR_8102_RAILROAD_LOCOMOTIVE :vasúti mozdony +STR_8103_ROAD_VEHICLE :közúti jármû +STR_8104_AIRCRAFT :repülõgép +STR_8105_SHIP :hajó +STR_8106_MONORAIL_LOCOMOTIVE :egysínû mozdony +STR_8107_MAGLEV_LOCOMOTIVE :MagLev mozdony + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN}i jármûtelep +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Az emberek ünnepelnek . . .{}Megérkezett az elsõ vonat {STATION} állomásra! +STR_8802_DETAILS :{WHITE}{STRING} adatai +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Vonat van az útban +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Menj {STATION} állomásra +STR_8807_GO_TO_UNLOAD :Menj {STATION} állomásra (Lepakol) +STR_8808_GO_TO_LOAD :Menj {STATION} állomásra (Telepakol) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Menj megállás nélkül {STATION} állomásra +STR_880B_GO_NON_STOP_TO_UNLOAD :Menj megállás nélkül {STATION} állomásra (Lepakol) +STR_880C_GO_NON_STOP_TO_LOAD :Menj megállás nélkül {STATION} állomásra (Telepakol) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Menj {TOWN}i jármûtelepre +STR_SERVICE_AT_TRAIN_DEPOT :Javítsd a vonatot a {TOWN}i jármûtelepen +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Menj megállás nélkül {TOWN}i jármûtelepre +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Mindig javítsd a vonatot a {TOWN}i jármûtelepen + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Úton a {TOWN}i jármûtelepre +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Úton a {TOWN}i jármûtelepre, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Üres +STR_8813_FROM :{LTBLUE}{CARGO} {STATION} állomásról +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}{COMMA16}. vonat a jármûtelepen várakozik +STR_8815_NEW_VEHICLES :{BLACK}Új jármûvek +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Ár: {GOLD}{CURRENCY}{BLACK} Súly: {GOLD}{COMMA16}t{}{BLACK}Sebesség:{GOLD}{VELOCITY}{BLACK} Teljesítmény:{GOLD}{COMMA16}le{}{BLACK}Mûködtetési költség: {GOLD}{CURRENCY}/év{}{BLACK}Kapacitás: {GOLD}{STRING}{}{BLACK}Tervezés éve: {GOLD}{NUMU16}{BLACK} Élettartam: {GOLD}{COMMA16} év{}{BLACK}Legnagyobb megbízhatóság: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Információk +STR_8819_TRAIN_TOO_LONG :{WHITE}Túl hosszú a vonat +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Csak a jármûtelepen álló vonatokat lehet megváltoztatni +STR_881B_TRAINS :{WHITE}{STRING} vonatai +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Új vasúti jármûvek +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Új egysínû jármûvek +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Új MagLev jármûvek +STR_881F_BUILD_VEHICLE :{BLACK}Megvesz +STR_8820_RENAME :{BLACK}Átnevez +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Ár: {GOLD}{CURRENCY}{}{BLACK}Súly: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapacitás: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Kihagy +STR_8824_DELETE :{BLACK}Töröl +STR_8825_NON_STOP :{BLACK}Non-stop +STR_8826_GO_TO :{BLACK}Új cél +STR_8827_FULL_LOAD :{BLACK}Telepakol +STR_8828_UNLOAD :{BLACK}Lepakol +STR_8829_ORDERS :{WHITE}{STRING} menetrendje +STR_882A_END_OF_ORDERS :{SETX 10}- - Menetrend vége - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Javítás +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Nem veheted meg a vasúti jármûvet... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vásárlás éve: {LTBLUE}{NUMU16}{BLACK} Érték: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Érték: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Felpakol / Lepakol +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Nem küldheted a vonatot a jármûtelepre... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Nincs több hely új célpontnak +STR_8832_TOO_MANY_ORDERS :{WHITE}Túl sok a célpont +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Nem adhatsz meg új célpontot... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Nem törölheted ezt a célpontot... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Nem módosíthatod ezt a célpontot... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Elõbb jármûtelepet kell építened +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Nem mozgathatod a jármûvet... +STR_8838_N_A :Nincs{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Nem adhatod el a vasúti jármûvet... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Nem találok utat a helyi jármûtelepre +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Nem indíthatod el/ állíthatod meg a vonatot... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Javítási idõköz: {LTBLUE}{COMMA16} nap{BLACK} Utolsó javítás: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vonatok - kattints egy vonatra az adataihoz +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Új vonatok vásárlása (jármûtelep szükséges hozzá) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vonatok - kattints egy vonatra az adataihoz, húzással áthelyezheted a jármûveket +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Új vasúti jármû vásárlása +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Dobj ide egy jármûvet az eladásához +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}A fõ nézetet a jármûtelepre állítja +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Vasúti jármû kiválasztása - kattints egy jármûre az adataihoz +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}A kijelölt vasúti jármû megvétele +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}A vasúti jármû márkanevének megváltoztatása +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Megmutatja, mit csinál éppen a vonat - kattints ide az elindításhoz/ megállításhoz +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}A vonat menetrendjének megmutatása +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}A fõ nézetet a vonatra állítja +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}A jármûtelepre küldi a vonatot +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}A vonat rákényszerítése, hogy ne várja meg a szemafor zöld jelzését +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}A vonat megfordítása +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}A vonat adatai +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Javítási idõköz növelése +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Javítási idõköz csökkentése +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}A szállított rakomány részletei +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}A vonat kocsiainak részletei +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}A kocsik kapacitása +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Menetrend - kattints egy célpontra a kijelöléséhez +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Az aktuális célpont kihagyása és ugrás a következõre +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}A kijelölt célpont törlése +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}A kijelölt célpont felé megállás nélkül kell haladni +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Új célpont beillesztése a kijelölt elé vagy a lista végére +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}A kijelölt célponton meg kell várni, amíg telerakják a jármûvet +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}A kijelölt célponton le kell pakolni a rakományt +STR_SERVICE_HINT :{BLACK}Célpont kihagyása, ha javítás szükséges +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Új {STRING} használható! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Ár: {CURRENCY} Súly: {COMMA16}t{}Sebesség: {VELOCITY} Teljesítmény: {COMMA16}le{}Mûködtetési költség: {CURRENCY}/év{}Kapacitás: {STRING} +STR_885C_BROKEN_DOWN :{RED}Lerobbant +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Kor: {LTBLUE}{STRING}{BLACK} Mûködtetési költség: {LTBLUE}{CURRENCY}/év +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Súly: {LTBLUE}{COMMA16}t {BLACK}Teljesítmény: {LTBLUE}{COMMA32} le{BLACK} Végsebesség: {LTBLUE} {VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Ezévi haszon: {LTBLUE}{CURRENCY} (tavalyi: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Megbízhatóság: {LTBLUE}{COMMA8}% {BLACK}Lerobbanások az utolsó javítás óta: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Áll +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nem indíthatod el a vonatot veszélyben... +STR_8863_CRASHED :{RED}Balesetet szenvedett! + +STR_8865_NAME_TRAIN :{WHITE}Vonat átnevezése +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Nem nevezheted át a vonatot... +STR_8867_NAME_TRAIN :{BLACK}Vonat átnevezése +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Vonatbaleset!{}{COMMA16} ember halt meg az ütközésnél +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Nem fordíthatod meg a vonatot... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Márkanév megváltoztatása +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Nem változtathatod meg a márkanevet... + +STR_TRAIN_STOPPING :{RED}Lassít +STR_TRAIN_STOPPING_VEL :{RED}Lassít, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Közúti jármû van az útban +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} közúti jármûvei +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN}i garázs +STR_9004_NEW_VEHICLES :{BLACK}Új jármûvek +STR_9005_INFORMATION :{BLACK}Információ +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Új közúti jármûvek +STR_9007_BUILD_VEHICLE :{BLACK}Megvesz +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Ár: {GOLD}{CURRENCY}{BLACK} Sebesség: {GOLD}{VELOCITY}{}{BLACK}Mûködtetési költség: {GOLD}{CURRENCY}/év{}{BLACK}Kapacitás: {GOLD}{STRING}{}{BLACK}Tervezés éve: {GOLD}{NUMU16}{BLACK} Élettartam: {GOLD}{COMMA16} év{}{BLACK}Legnagyobb megbízhatóság: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nem veheted meg a közúti jármûvet... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Elõbb garázst kell építened +STR_900B_ORDERS :{WHITE}{STRING} menetrendje +STR_900C_DETAILS :{WHITE}{STRING} adatai +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Kor: {LTBLUE}{STRING}{BLACK} Mûködtetési költség: {LTBLUE}{CURRENCY}/év +STR_900E_MAX_SPEED :{BLACK}Végsebesség: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Ezévi haszon: {LTBLUE}{CURRENCY} (tavalyi: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Megbízhatóság: {LTBLUE}{COMMA8}% {BLACK}Lerobbanások az utolsó javítás óta: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vásárlás éve: {LTBLUE}{NUMU16}{BLACK} Érték: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapacitás: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...garázsban kellene állnia ehhez +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Nem adhatod el a közúti jármûvet... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Nem indíthatod el/ állíthatod meg a közúti jármûvet... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}{COMMA16}. közúti jármû a garázsban várakozik +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Úton a {TOWN}i garázsba +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Úton a {TOWN}i garázsba, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Nem küldheted a jármûvet a garázsba... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nem találom a helyi garázst +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Közúti jármûvek - kattints egy jármûre az adataihoz +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Új közúti jármûvek vásárlása (garázs kell hozzá) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Megmutatja, mit csinál éppen a jármû - kattints ide az elindításhoz/ megállításhoz +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}A jármû menetrendjének megmutatása +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}A fõ nézetet a jármûre állítja +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Garázsba küldi a jármûvet +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Visszafordítja a jármûvet +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}A közúti jármû adatai +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Jármûvek - kattints egy jármûre az adataihoz +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Új közúti jármû vásárlása +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Dobj ide egy jármûvet az eladásához +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}A fõ nézetet a garázsra állítja +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Közúti jármû kiválasztása - kattints egy jármûre az adataihoz +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}A kijelölt közúti jármû megvétele +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Új közúti jármû használható! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Ár: {CURRENCY}{}Sebesség: {VELOCITY}{}Mûködtetési költség: {CURRENCY}/év{}Kapacitás: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Közúti jármû átnevezése +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Nem nevezheted át a közúti jármûvet... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Közúti jármû átnevezése +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Az emberek ünnepelnek . . .{}Megérkezett az elsõ busz {STATION} állomásra! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Az emberek ünnepelnek . . .{}Megérkezett az elsõ teherautó {STATION} állomásra! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Közúti baleset!{}A vezetõ meghalt a vonattal való ütközéskor +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Közúti baleset!{}{COMMA16} ember meghalt a vonattal való ütközéskor +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Nem fordíthatod vissza a jármûvet... +STR_9034_RENAME :{BLACK}Átnevez +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}A közúti jármû márkanevének megváltoztatása +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Márkanév megváltoztatása +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Nem változtathatod meg a márkanevet... +STR_9038_GO_TO_ROADVEH_DEPOT :Menj a {TOWN}i garázsba +STR_SERVICE_AT_ROADVEH_DEPOT :Javítsd a jármûvet a {TOWN}i garázsban + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Kikötõépítés +STR_9801_DOCK_CONSTRUCTION :{WHITE}Kikötõépítés +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Nem építhetsz ide kikötõt... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN}i dokk +STR_9804_NEW_SHIPS :{BLACK}Új hajók +STR_9805_SHIPS :{WHITE}{STRING} hajói +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Nem vehetsz hajókat... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Elõbb dokkot kell építened +STR_9808_NEW_SHIPS :{WHITE}Új hajók +STR_9809_BUILD_SHIP :{BLACK}Megvesz +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Ár: {GOLD}{CURRENCY}{BLACK} Sebesség: {GOLD}{VELOCITY}{}{BLACK}Kapacitás: {GOLD}{STRING} {STRING}{}{BLACK}Mûködtetési költség: {GOLD}{CURRENCY}/év{}{BLACK}Tervezés éve: {GOLD}{NUMU16}{BLACK} Élettartam: {GOLD}{COMMA16} év{}{BLACK}Legnagyobb megbízhatóság: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}A dokkban kellene állnia ehhez +STR_980C_CAN_T_SELL_SHIP :{WHITE}Nem adhatod el a hajót... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Nem veheted meg a hajót... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Hajó van az útban +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} menetrendje +STR_9811_DETAILS :{WHITE}{STRING} adatai +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Kor: {LTBLUE}{STRING}{BLACK} Mûködtetési költség: {LTBLUE}{CURRENCY}/év +STR_9813_MAX_SPEED :{BLACK}Végsebesség: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Ezévi haszon: {LTBLUE}{CURRENCY} (tavalyi: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Megbízhatóság: {LTBLUE}{COMMA8}% {BLACK}Lerobbanások az utolsó javítás óta: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vásárlás éve: {LTBLUE}{NUMU16}{BLACK} Érték: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapacitás: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Nem indíthatod el/ állíthatod meg a hajót... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Nem küldheted a hajót a dokkba... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nem találom a helyi dokkot +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Úton a {TOWN}i dokkba +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Úton a {TOWN}i dokkba, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}{COMMA16}. hajó a dokkban várakozik +STR_981D_BUILD_SHIP_DOCK :{BLACK}Kikötõ építése +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Dokk építése (hajók vételére és karbantartására) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Hajók - kattints egy hajóra az adataihoz +STR_9820_BUILD_NEW_SHIP :{BLACK}Új hajó vásárlása +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Dobj ide egy hajót az eladásához +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}A fõ nézetet a dokkra állítja +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Hajók - kattints egy hajóra az adataihoz +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Új hajók vásárlása (dokk szükséges hozzá) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Hajó kiválasztása - kattints egy hajóra az adataihoz +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}A kijelölt hajó megvétele +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Megmutatja, mit csinál éppen a hajó - kattints ide az elindításhoz/ megállításhoz +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}A hajó menetrendjének megmutatása +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}A fõ nézetet a hajóra állítja +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Dokkba küldi a hajót +STR_982B_SHOW_SHIP_DETAILS :{BLACK}A hajó adatai +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Új hajó használható! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Ár: {CURRENCY} Végsebesség: {VELOCITY}{}Kapacitás: {STRING}{}Mûködtetési költség: {CURRENCY}/év +STR_982F_NAME_SHIP :{BLACK}Hajó átnevezése + +STR_9831_NAME_SHIP :{WHITE}Hajó átnevezése +STR_9832_CAN_T_NAME_SHIP :{WHITE}Nem nevezheted át a hajót... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Az emberek ünnepelnek . . .{}Megérkezett az elsõ hajó {STATION} állomásra! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Bója lerakása, ami az útvonal pontosítására használható +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Nem rakhatsz ide bóját... +STR_9836_RENAME :{BLACK}Átnevez +STR_9837_RENAME_SHIP_TYPE :{BLACK}A hajó márkanevének megváltoztatása +STR_9838_RENAME_SHIP_TYPE :{WHITE}Márkanév megváltoztatása +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Nem változtathatod meg a márkanevet... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}A hajó átalakítása másfajta rakomány szállítására +STR_983B_REFIT :{WHITE}{STRING} átalakítása +STR_983C_REFIT_SHIP :{BLACK}Hajó átalakítása +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Válaszd ki, milyen árut szállítson a hajó +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED :{BLACK}A hajó átalakítása a kijelölt áru szállítására +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Átalakítás, hogy szállíthasson: +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Új kapacitás: {GOLD}{STRING}{}{BLACK}Átalakítás költsége: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Nem alakíthatod át a hajót... +STR_9842_REFITTABLE :(átalakítható) +STR_GO_TO_SHIP_DEPOT :Menj a {TOWN}i kikötõbe +SERVICE_AT_SHIP_DEPOT :Service at {TOWN} Ship Depot + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Reptér építése +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nem építhetsz ide repülõteret... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} hangárja +STR_A003_NEW_AIRCRAFT :{BLACK}Új repülõgépek +STR_A004_INFORMATION :{BLACK}Információ +STR_A005_NEW_AIRCRAFT :{WHITE}Új repülõgépek +STR_A006_BUILD_AIRCRAFT :{BLACK}Megvesz +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Ár: {GOLD}{CURRENCY}{BLACK} Sebesség: {GOLD}{VELOCITY}{}{BLACK}Kapacitás: {GOLD}{COMMA16} utas, {COMMA16} csomag levél{}{BLACK}Mûködtetési költség: {GOLD}{CURRENCY}/év{}{BLACK}Tervezés éve: {GOLD}{NUMU16}{BLACK} Élettartam: {GOLD}{COMMA16} év{}{BLACK}Legnagyobb megbízhatóság: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Nem veheted meg a repülõgépet... +STR_A009_AIRCRAFT :{WHITE}{STRING} repülõgépei +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} menetrendje +STR_A00C_DETAILS :{WHITE}{STRING} adatai +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Kor: {LTBLUE}{STRING}{BLACK} Mûködtetési költség: {LTBLUE}{CURRENCY}/év +STR_A00E_MAX_SPEED :{BLACK}Végsebesség: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Ezévi haszon: {LTBLUE}{CURRENCY} (tavalyi: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Megbízhatóság: {LTBLUE}{COMMA8}% {BLACK}Lerobbanások az utolsó javítás óta: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vásárlás éve: {LTBLUE}{NUMU16}{BLACK} Érték: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Nem küldheted a repülõgépet a hangárba... +STR_HEADING_FOR_HANGAR :{LTBLUE}Úton a {STATION} hangárjába +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Úton a {STATION} hangárjába, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}{COMMA16}. repülõgép a hangárban várakozik +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Repülõgép van az útban +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Nem indíthatod el/ állíthatod meg a repülõgépet... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}... a levegõben van +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Elõbb repülõteret kell építened +STR_A019_CAPACITY :{BLACK}Kapacitás: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapacitás: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}A a hangárban kellene állnia ehhez +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Nem adhatod el a repülõgépet... +STR_A01D_AIRPORT_CONSTRUCTION :Repülõtér építése +STR_A01E_BUILD_AIRPORT :{BLACK}Repülõtér építése +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Repülõgépek - kattints egy repülõgépre az adataihoz +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Új repülõgépek vásárlása (hangár szükséges hozzá) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Repülõgépek - kattints egy repülõgépre az adataihoz +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Új repülõgépek vásárlása +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Dobj ide egy repülõgépet az eladásához +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}A fõ nézetet a hangárra állítja +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Repülõgép kiválasztása - kattints egy repülõgépre az adataihoz +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}A kijelölt repülõgép megvétele +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Megmutatja, mit csinál éppen a repülõgép - kattints ide az elindításhoz/ megállításhoz +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}A repülõgép menetrendjének megmutatása +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}A fõ nézetet a repülõgépre állítja +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Hangárba küldi a repülõgépet +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}A repülõgép adatai +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Új repülõgép használható! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Ár: {CURRENCY} Végsebesség: {VELOCITY}{}Kapacitás: {COMMA16} utas, {COMMA16} csomag levél{}Mûködtetési költség: {CURRENCY}/év + +STR_A030_NAME_AIRCRAFT :{WHITE}Repülõgép átnevezése +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Nem nevezheted át a repülõgépet... +STR_A032_NAME_AIRCRAFT :{BLACK}Repülõgép átnevezése +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Az emberek ünnepelnek . . .{}Megérkezett az elsõ repülõgép {STATION} állomásra! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Lezuhant egy repülõgép!{}{COMMA16} ember halt meg a zuhanás után {STATION} állomáson +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Célpontok: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Átnevez +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}A repülõgép márkanevének megváltoztatása +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Márkanév megváltoztatása +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Nem változtathatod meg a márkanevet... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}A repülõgép átalakítása másfajta rakomány szállítására +STR_A03C_REFIT :{WHITE}{STRING} átalakítása +STR_A03D_REFIT_AIRCRAFT :{BLACK}Repülõgép átalakítása +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Válaszd ki, milyen árut szállítson a repülõgép +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}A repülõgép átalakítása a kijelölt áru szállítására +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Átalakítás, hogy szállíthasson: +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Új kapacitás: {GOLD}{STRING}{}{BLACK}Átalakítás költsége: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Nem alakíthatod át a repülõgépet... +STR_A043_REFITTABLE :(átalakítható) +STR_GO_TO_AIRPORT_HANGAR :Menj a {STATION} repülõtér hangárjába +SERVICE_AT_AIRPORT_HANGAR :Service at {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelinbaleset {STATION} közelében! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}'UFO' ütközés pusztított el egy közúti jármûvet! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Olajfinomító robbant fel {TOWN} közelében! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS :{BLACK}{BIGFONT}Gyanús körülmények között felrobbant egy gyár {TOWN} közelében! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' szállt le {TOWN} közelében! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Egy szénbánya lesüllyedése földcsuszamlást okozott {TOWN} közelében! + +STR_BRIBE_FAILED :{WHITE}A megvesztegetési kísérleted +STR_BRIBE_FAILED_2 :{WHITE}lefülelte egy helyi nyomozó! diff --git a/lang/italian.txt b/lang/italian.txt new file mode 100644 --- /dev/null +++ b/lang/italian.txt @@ -0,0 +1,2358 @@ +##name Italian +##ownname Italian + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Fuori dal bordo della mappa +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Troppo vicino al bordo della mappa +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Denaro insufficiente - richiesto {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Richiesto terreno piano +STR_0008_WAITING :{BLACK}In attesa: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (on viaggio da +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accettati: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accettati: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passeggeri +STR_0010_COAL :Carbone +STR_0011_MAIL :Posta +STR_0012_OIL :Petrolio +STR_0013_LIVESTOCK :Bestiame +STR_0014_GOODS :Beni +STR_0015_GRAIN :Grano +STR_0016_WOOD :Legna +STR_0017_IRON_ORE :Ferro Grezzo +STR_0018_STEEL :Acciaio +STR_0019_VALUABLES :Valori +STR_001A_COPPER_ORE :Rame Grezzo +STR_001B_MAIZE :Mais +STR_001C_FRUIT :Frutta +STR_001D_DIAMONDS :Diamanti +STR_001E_FOOD :Cibo +STR_001F_PAPER :Carta +STR_0020_GOLD :Oro +STR_0021_WATER :Acqua +STR_0022_WHEAT :Frumento +STR_0023_RUBBER :Gomma +STR_0024_SUGAR :Zucchero +STR_0025_TOYS :Giocattoli +STR_0026_CANDY :Caramelle +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Cotone Candito +STR_0029_BUBBLES :Bolle +STR_002A_TOFFEE :Toffee +STR_002B_BATTERIES :Batterie +STR_002C_PLASTIC :Plastica +STR_002D_FIZZY_DRINKS :Bibite Frizzanti +STR_002E : +STR_002F_PASSENGER :Passeggeri +STR_0030_COAL :Carbone +STR_0031_MAIL :Posta +STR_0032_OIL :Petrolio +STR_0033_LIVESTOCK :Bestiame +STR_0034_GOODS :Beni +STR_0035_GRAIN :Grano +STR_0036_WOOD :Legna +STR_0037_IRON_ORE :Ferro Grezzo +STR_0038_STEEL :Acciaio +STR_0039_VALUABLES :Valori +STR_003A_COPPER_ORE :Rame Grezzo +STR_003B_MAIZE :Mais +STR_003C_FRUIT :Frutta +STR_003D_DIAMOND :Diamanti +STR_003E_FOOD :Cibo +STR_003F_PAPER :Carta +STR_0040_GOLD :Oro +STR_0041_WATER :Acqua +STR_0042_WHEAT :Frumento +STR_0043_RUBBER :Gomma +STR_0044_SUGAR :Zucchero +STR_0045_TOY :Giocattolo +STR_0046_CANDY :Caramelle +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Cotone Candito +STR_0049_BUBBLE :Bolle +STR_004A_TOFFEE :Toffee +STR_004B_BATTERY :Batterie +STR_004C_PLASTIC :Plastica +STR_004D_FIZZY_DRINK :Bevande Frizzanti +STR_004E : +STR_004F_PASSENGER :{COMMA16} passeggero +STR_0050_TON_OF_COAL :{COMMA16} ton. di carbone +STR_0051_BAG_OF_MAIL :{COMMA16} sacco postale +STR_0052_OF_OIL :{VOLUME} di petrolio +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} capo di bestiame +STR_0054_CRATE_OF_GOODS :{COMMA16} cassa di beni +STR_0055_TON_OF_GRAIN :{COMMA16} ton. di grano +STR_0056_TON_OF_WOOD :{COMMA16} ton. di legna +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton. di ferro grezzo +STR_0058_TON_OF_STEEL :{COMMA16} ton. di acciaio +STR_0059_BAG_OF_VALUABLES :{COMMA16} borsa di valori +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton. di rame grezzo +STR_005B_TON_OF_MAIZE :{COMMA16} ton. di mais +STR_005C_TON_OF_FRUIT :{COMMA16} ton. di frutta +STR_005D_BAG_OF_DIAMONDS :{COMMA16} borsa di diamanti +STR_005E_TON_OF_FOOD :{COMMA16} ton. di cibo +STR_005F_TON_OF_PAPER :{COMMA16} ton. di carta +STR_0060_BAG_OF_GOLD :{COMMA16} borsa d'oro +STR_0061_OF_WATER :{VOLUME} di acqua +STR_0062_TON_OF_WHEAT :{COMMA16} ton. di frumento +STR_0063_OF_RUBBER :{VOLUME} di gomma +STR_0064_TON_OF_SUGAR :{COMMA16} ton. di zucchero +STR_0065_TOY :{COMMA16} giocattolo +STR_0066_BAG_OF_CANDY :{COMMA16} busta di caramelle +STR_0067_OF_COLA :{VOLUME} di cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton. di cotone candito +STR_0069_BUBBLE :{COMMA16} bolla +STR_006A_TON_OF_TOFFEE :{COMMA16} ton. di toffee +STR_006B_BATTERY :{COMMA16} batteria +STR_006C_OF_PLASTIC :{VOLUME} di plastica +STR_006D_FIZZY_DRINK :{COMMA16} bibite frizzanti +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passeggeri +STR_0070_TONS_OF_COAL :{COMMA16} ton. di carbone +STR_0071_BAGS_OF_MAIL :{COMMA16} sacchi postali +STR_0072_OF_OIL :{VOLUME} di petrolio +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} capi di bestiame +STR_0074_CRATES_OF_GOODS :{COMMA16} casse di beni +STR_0075_TONS_OF_GRAIN :{COMMA16} ton. di grano +STR_0076_TONS_OF_WOOD :{COMMA16} ton. di legna +STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton. di ferro grezzo +STR_0078_TONS_OF_STEEL :{COMMA16} ton. di acciaio +STR_0079_BAGS_OF_VALUABLES :{COMMA16} borse di valori +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton. di rame grezzo +STR_007B_TONS_OF_MAIZE :{COMMA16} ton. di mais +STR_007C_TONS_OF_FRUIT :{COMMA16} ton. di frutta +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} borse di diamanti +STR_007E_TONS_OF_FOOD :{COMMA16} ton. di cibo +STR_007F_TONS_OF_PAPER :{COMMA16} ton. di carta +STR_0080_BAGS_OF_GOLD :{COMMA16} borse d'oro +STR_0081_OF_WATER :{VOLUME} d'acqua +STR_0082_TONS_OF_WHEAT :{COMMA16} ton. di frumento +STR_0083_OF_RUBBER :{VOLUME} di gomma +STR_0084_TONS_OF_SUGAR :{COMMA16} ton. di zucchero +STR_0085_TOYS :{COMMA16} giocattoli +STR_0086_BAGS_OF_CANDY :{COMMA16} buste di caramelle +STR_0087_OF_COLA :{VOLUME} di cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton. di cotone candito +STR_0089_BUBBLES :{COMMA16} bolle +STR_008A_TONS_OF_TOFFEE :{COMMA16} ton. di toffee +STR_008B_BATTERIES :{COMMA16} batterie +STR_008C_OF_PLASTIC :{VOLUME} di plastica +STR_008D_FIZZY_DRINKS :{COMMA16} bevande frizzanti +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Mappa - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Opzioni di gioco +STR_00B2_MESSAGE :{YELLOW}Messaggio +STR_00B3_MESSAGE_FROM :{YELLOW}Messaggio da {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Non puoi fare questo.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Non puoi ripulire l'area.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Copyright Originale{COPYRIGHT} 1995 Chris Sawyer, Tutti i diritti riservati +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD versione {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Concepito originariamente da Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafica di Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Esci +STR_00C8_YES :{BLACK}Si +STR_00C9_NO :{BLACK}No +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Sei sicuro di voler uscire dal gioco e tornare a {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nulla +STR_00D1_DARK_BLUE :Blu scuro +STR_00D2_PALE_GREEN :Verde pallido +STR_00D3_PINK :Rosa +STR_00D4_YELLOW :Giallo +STR_00D5_RED :Rosso +STR_00D6_LIGHT_BLUE :Azzurro +STR_00D7_GREEN :Verde +STR_00D8_DARK_GREEN :Verde scuro +STR_00D9_BLUE :Blu +STR_00DA_CREAM :Crema +STR_00DB_MAUVE :Malva +STR_00DC_PURPLE :Porpora +STR_00DD_ORANGE :Arancio +STR_00DE_BROWN :Marrone +STR_00DF_GREY :Grigio +STR_00E0_WHITE :Bianco +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Troppi veicoli del gioco +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Locazione +STR_00E5_CONTOURS :Contorni +STR_00E6_VEHICLES :Veicoli +STR_00E7_INDUSTRIES :Industrie +STR_00E8_ROUTES :Percorsi +STR_00E9_VEGETATION :Vegetazione +STR_00EA_OWNERS :Proprietari +STR_00EB_ROADS :{BLACK}{TINYFONT}Strade +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Ferrovie +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stazioni/Aereoporti/Moli +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Edifici/Industrie +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Veicoli +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Treni +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Veicoli Stradali +STR_00F7_SHIPS :{BLACK}{TINYFONT}Navi +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Aereo +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Percorsi di trasporto +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Miniera di Carbone +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Centrale Elettrica +STR_00FC_FOREST :{BLACK}{TINYFONT}Foresta +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Falegnameria +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Raffineria +STR_00FF_FARM :{BLACK}{TINYFONT}Fattoria +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabbrica +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Casa Editrice +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Pozzi Petroliferi +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Miniera di Ferro Grezzo +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Acciaieria +STR_0105_BANK :{BLACK}{TINYFONT}Banca +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Cartiera +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Miniera d'Oro +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Azienda Alimentare +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Miniera di Diamanti +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Miniera di Rame Grezzo +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Piantaggio di Frutta +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Piantaggio di Gomma +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Falda Acquifera +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Cisterna d'Acqua +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Segheria +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Foresta di Cotone Candito +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Fabbrica di Caramelle +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Fattoria delle Batterie +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Pozzi di Cola +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Negozio di Giocattoli +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Fabbrica di Giocattoli +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Sorgenti di Plastica +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Fabbrica di Bevande Friz. +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Generatore di Bolle +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Estrattore di Toffee +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Miniera di Zucchero +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Stazione Ferroviaria +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Area di carico per Camion +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Stazione Bus +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Aereoporto/Eliporto +STR_011F_DOCK :{BLACK}{TINYFONT}Molo +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Terreno Accidentato +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Terreno Erboso +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Terreno Spoglio +STR_0123_FIELDS :{BLACK}{TINYFONT}Campi +STR_0124_TREES :{BLACK}{TINYFONT}Alberi +STR_0125_ROCKS :{BLACK}{TINYFONT}Roccie +STR_0126_WATER :{BLACK}{TINYFONT}Acqua +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Senza Proprietario +STR_0128_TOWNS :{BLACK}{TINYFONT}Città +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrie +STR_012A_DESERT :{BLACK}{TINYFONT}Deserto +STR_012B_SNOW :{BLACK}{TINYFONT}Neve +STR_012C_MESSAGE :{WHITE}Messaggio +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Annulla +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Rinomina +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Troppi nomi definiti +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Scelto nome già in uso + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperiale (miglia) +STR_013A_METRIC_KILOMETERS :Metrico (kilometri) +STR_013B_OWNED_BY :{WHITE}...posseduto da {STRING} +STR_013C_CARGO :{BLACK}Cargo +STR_013D_INFORMATION :{BLACK}Informazioni +STR_013E_CAPACITIES :{BLACK}Capienza +STR_013E_TOTAL_CARGO :{BLACK}Carico totale +STR_013F_CAPACITY :{BLACK}Capacità: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Carico totale (capacità) di questo treno: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nuovo Gioco +STR_0141_LOAD_GAME :{BLACK}Carica Gioco +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demonstrazione +STR_0143_1_PLAYER :{BLACK}1 Giocatore +STR_0144_2_PLAYERS :{BLACK}2 Giocatori + +STR_0148_GAME_OPTIONS :{BLACK}Opzioni di gioco + +STR_0150_SOMEONE :qualcuno{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Mappa del mondo +STR_0152_TOWN_DIRECTORY :Elenco Città +STR_0153_SUBSIDIES :Sussidi + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Grafico profitto operazionale +STR_0155_INCOME_GRAPH :Grafico degli incassi +STR_0156_DELIVERED_CARGO_GRAPH :Grafico merce consegnata +STR_0157_PERFORMANCE_HISTORY_GRAPH :Grafico prestazioni +STR_0158_COMPANY_VALUE_GRAPH :Grafico valore società +STR_0159_CARGO_PAYMENT_RATES :Grafico % pagamento merce +STR_015A_COMPANY_LEAGUE_TABLE :Classifica società +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Salva partita +STR_015D_LOAD_GAME :Carica partita +STR_015E_QUIT_GAME :Abbandona partita +STR_015F_QUIT :Esci +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Sei sicuro di voler abbandonare la partita in corso? +STR_0161_QUIT_GAME :{WHITE}Abbandona partita + +############ range for months starts +STR_0162_JAN :Gen +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :Mag +STR_0167_JUN :Giu +STR_0168_JUL :Lug +STR_0169_AUG :Ago +STR_016A_SEP :Set +STR_016B_OCT :Ott +STR_016C_NOV :Nov +STR_016D_DEC :Dic +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pausa +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Salva partita, abandona la partita, esci +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Mostra elenco delle stazioni delle società +STR_0174_DISPLAY_MAP :{BLACK}Mostra mappa +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Mostra mappa, elenco Città +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Mostra elenco Città +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Mostra info finanziarie delle società +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Mostra info generali sulle società +STR_0179_DISPLAY_GRAPHS :{BLACK}Mostra grafici +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Mostra Classifica della società +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Mostra elenco dei treni delle società +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Mostra elenco dei veicoli stradali delle società +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Mostra elenco delle navi delle società +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Mostra lista degli aerei delle società +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Avvicina visuale +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Allontana visuale +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Costruisci percorsi ferroviari +STR_0182_BUILD_ROADS :{BLACK}Costruisci strade +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Costruisci moli +STR_0184_BUILD_AIRPORTS :{BLACK}Costruisci aereoporti +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Pianta alberi, piazza scritte ecc... +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Info sul terreno +STR_0187_OPTIONS :{BLACK}Opzioni +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Non puoi cambiare l'intervallo di manutenzione... +STR_018B_CLOSE_WINDOW :{BLACK}Chiudi finestra +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Nome finestra - trascinala per muovere la finestra +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Demolisci edifici ecc... su una casella del terreno +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Abbassa un angolo del terreno +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Alza un angolo del terreno +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Barra di scorrimento - scorre la lista sù/giù +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Mostra contorni dei terreni sulla mappa +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Mostra veicoli sulla mappa +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Mostra industrie sulla mappa +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Mostra percorsi di viaggio sulla mappa +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Mostra vegetazione sulla mappa +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Mostra proprietari dei terreni sulla mappa +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Visualizza nomi delle Città sulla mappa (on/off) +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Profitto quest'anno: {CURRENCY} (anno scorso: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} anno ({COMMA16}) +STR_019A_YEARS :{COMMA16} anni ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} anni ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Veicolo Stradale +STR_019D_AIRCRAFT :Aereo +STR_019E_SHIP :Nave +STR_019F_TRAIN :Treno +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} stà diventando vecchio +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} Stà diventando molto vecchio +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} è troppo vecchio e necessita di essere rimpiazzato urgentemente +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Info sull'area di terreno +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Costo per ripulirlo: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Costo per ripulirlo: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Prioprietario: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Autorità locale: {LTBLUE}{STRING} +STR_01A9_NONE :Nessuno +STR_01AA_NAME :{BLACK}Nome +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1 +STR_01AD_2ND :2 +STR_01AE_3RD :3 +STR_01AF_4TH :4 +STR_01B0_5TH :5 +STR_01B1_6TH :6 +STR_01B2_7TH :7 +STR_01B3_8TH :8 +STR_01B4_9TH :9 +STR_01B5_10TH :10 +STR_01B6_11TH :11 +STR_01B7_12TH :12 +STR_01B8_13TH :13 +STR_01B9_14TH :14 +STR_01BA_15TH :15 +STR_01BB_16TH :16 +STR_01BC_17TH :17 +STR_01BD_18TH :18 +STR_01BE_19TH :19 +STR_01BF_20TH :20 +STR_01C0_21ST :21 +STR_01C1_22ND :22 +STR_01C2_23RD :23 +STR_01C3_24TH :24 +STR_01C4_25TH :25 +STR_01C5_26TH :26 +STR_01C6_27TH :27 +STR_01C7_28TH :28 +STR_01C8_29TH :29 +STR_01C9_30TH :30 +STR_01CA_31ST :31 +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Seleziona dimensione mappa grande/piccola +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Seleziona Tutorial/Demonstrazione + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Merci accettate: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Merci accettate: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Merci accettate: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Suoni/musica +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Mostra finestra Suoni/musica +STR_01D5_ALL :{TINYFONT}Tutte +STR_01D6_OLD_STYLE :{TINYFONT}Vecchio Stile +STR_01D7_NEW_STYLE :{TINYFONT}Nuovo Stile +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Personaliz. 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Personaliz. 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Volume Musica +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Volume Effetti +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Torna al brano precedente +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Passa al brano successivo +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Ferma la musica +STR_01E1_START_PLAYING_MUSIC :{BLACK}Avvia la musica +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Trascina le barre scorrevoli per regolare il volume +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Brano{SETX 88}Titolo +STR_01E9_SHUFFLE :{TINYFONT}Casuale +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Programma +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Selezione programma musicale +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Indice brani +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programma - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Elimina +STR_01F1_SAVE :{TINYFONT}{BLACK}Salva +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Attuale programma musicale +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Seleziona progrmma 'Tutti i brani' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Seleziona programma 'vecchio style' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Seleziona programma 'nuovo style' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Seleziona programma 'Personaliz. 1' (definito dall'utente) +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Seleziona programma 'Personaliz. 2' (definito dall'utente) +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Elimina programmazioni attuali (solo personalizzato 1 o personalizzato 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Salva le impostazioni +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Clicca sul brano per aggiungerlo al programma corrente (solamente personallizzato 1 o personalizzato 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Seleziona programmazione casuale on/off +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Mostra finestra 'selezione brani' +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Clicca sul servizio per vedere l'industria/città +STR_01FE_DIFFICULTY :{BLACK}Difficoltà ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Ultimi messaggi/nuovi rapporti +STR_0201_MESSAGE_SETTINGS :Impostazioni messaggi +STR_MESSAGE_HISTORY_MENU :Cronologia messaggi +STR_0202_SEND_MESSAGE :Invia Messaggio +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Mostra ultimo messaggio/rapporto, mostra Impostazione messaggi +STR_0204_MESSAGE_OPTIONS :{WHITE}Impostazione messaggi +STR_0205_MESSAGE_TYPES :{BLACK}Tipi di messaggio:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrivo primo veicolo a stazioni del giocatore +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Arrivo primo veicolo a stazioni della concorrenza +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Incidenti / disastri +STR_0209_COMPANY_INFORMATION :{YELLOW}Informazioni sulle società +STR_020A_ECONOMY_CHANGES :{YELLOW}Cambiamenti economici +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Avvisi / informazioni sui veicoli del giocatore +STR_020C_NEW_VEHICLES :{YELLOW}Nuovi veicoli +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Cambiamenti della merce accettata +STR_020E_SUBSIDIES :{YELLOW}Sussidi +STR_020F_GENERAL_INFORMATION :{YELLOW}Informazioni generali +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...troppo lontano dalla destinazione precedente +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Top Ten delle compagnie che hanno raggiunto l'anno 2050{}({STRING} Livello) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Uomo d'affari +STR_0214_ENTREPRENEUR :Imprenditore +STR_0215_INDUSTRIALIST :Industriale +STR_0216_CAPITALIST :Capitalista +STR_0217_MAGNATE :Magnate +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Magnate del secolo +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} archivi '{STRING}' stato! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} di {STRING} archivi '{STRING}' stato! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Crea Scenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Editor Scenario +STR_0223_LAND_GENERATION :{WHITE}Genera paesaggio +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Terreno Casuale +STR_0227_RESET_LAND :{BLACK}Resetta Terreno +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Aumenta ampiezza del terreno da abbassare/alzare +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Decrementa ampiezza del terreno da abbassare/alzare +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Genera territorio a caso +STR_022B_RESET_LANDSCAPE :{BLACK}Resetta paesaggio +STR_022C_RESET_LANDSCAPE :{WHITE}Resetta paesaggio +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Sei sicuro di voler resettare il paesaggio? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Generazione paesaggio +STR_022F_TOWN_GENERATION :{BLACK}Generazione città +STR_0230_INDUSTRY_GENERATION :{BLACK}Generazione industrie +STR_0231_ROAD_CONSTRUCTION :{BLACK}Costruzioni stradali +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetazione ed altri oggetti +STR_0233_TOWN_GENERATION :{WHITE}Generazione Città +STR_0234_NEW_TOWN :{BLACK}Nuova Città +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Costruisci nuova città +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Non puoi costruire una città qui... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...troppo vicino al bordo della mappa +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...troppo vicino a un'altra città +STR_0239_SITE_UNSUITABLE :{WHITE}...sito inadatto +STR_023A_TOO_MANY_TOWNS :{WHITE}...troppe città +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Incrementa dimensione della città +STR_023C_EXPAND :{BLACK}Espandi +STR_023D_RANDOM_TOWN :{BLACK}Città Casuale +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Costruisci città in un luogo casuale +STR_023F_INDUSTRY_GENERATION :{WHITE}Generazione Industrie +STR_0240_COAL_MINE :{BLACK}Miniera di Carbone +STR_0241_POWER_STATION :{BLACK}Centrale Elettrica +STR_0242_SAWMILL :{BLACK}Falegnameria +STR_0243_FOREST :{BLACK}Foresta +STR_0244_OIL_REFINERY :{BLACK}Raffineria +STR_0245_OIL_RIG :{BLACK}Piattaforma Petrolifera +STR_0246_FACTORY :{BLACK}Fabbrica +STR_0247_STEEL_MILL :{BLACK}Acciaieria +STR_0248_FARM :{BLACK}Fattoria +STR_0249_IRON_ORE_MINE :{BLACK}Miniera di Ferro Grezzo +STR_024A_OIL_WELLS :{BLACK}Pozzi petroliferi +STR_024B_BANK :{BLACK}Banca +STR_024C_PAPER_MILL :{BLACK}Cartiera +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Azienda Alimentare +STR_024E_PRINTING_WORKS :{BLACK}Casa Editrice +STR_024F_GOLD_MINE :{BLACK}Miniera d'Oro +STR_0250_LUMBER_MILL :{BLACK}Segheria +STR_0251_FRUIT_PLANTATION :{BLACK}Piantaggione di Frutta +STR_0252_RUBBER_PLANTATION :{BLACK}Piantaggione di Gomma +STR_0253_WATER_SUPPLY :{BLACK}Falda Acquifera +STR_0254_WATER_TOWER :{BLACK}Cisterna d'Acqua +STR_0255_DIAMOND_MINE :{BLACK}Miniera di Diamanti +STR_0256_COPPER_ORE_MINE :{BLACK}Miniera di Rame Grezzo +STR_0257_COTTON_CANDY_FOREST :{BLACK}Foresta di Cotone Candito +STR_0258_CANDY_FACTORY :{BLACK}Fabbrica Caramelle +STR_0259_BATTERY_FARM :{BLACK}Fattoria delle batterie +STR_025A_COLA_WELLS :{BLACK}Pozzi di Cola +STR_025B_TOY_SHOP :{BLACK}Negozio di Giocattoli +STR_025C_TOY_FACTORY :{BLACK}Fabbrica di Giocattoli +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Sorgenti di Plastica +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Fabbrica Bibite Frizzanti +STR_025F_BUBBLE_GENERATOR :{BLACK}Generatore di Bolle +STR_0260_TOFFEE_QUARRY :{BLACK}Estrattore di Toffee +STR_0261_SUGAR_MINE :{BLACK}Miniera di Zucchero +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Costruisci Miniera di Carbone +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Costruisci Centrale Elettrica +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Costruisci Falegnameria +STR_0265_PLANT_FOREST :{BLACK}Pianta Foresta +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Costruisci Raffineria +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Costruisci Piattaforma Petrolifera (può essere costruita soltanto vicino al bordo della mappa) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Costruisci Fabbrica +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Costruisci Acciaieria +STR_026A_CONSTRUCT_FARM :{BLACK}Costruisci Fattoria +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Costruisci Miniera di Ferro Grezzo +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Costruisci Pozzo Petrolifero +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Costruisci Banca (può essere costruita solo in città con una popolazione maggiori di 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Costruisci Cartiera +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Costruisci Azienda Alimentare +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Costruisci Casa Editrice +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Costruisci Miniera d'Oro +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Costruisci Banca (può essere costruita solo nelle città) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Costruisci Segheria (per tagliare la foresta pluviale e produrre legna) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Pianta Piantaggione di Frutta +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Pianta Piantaggione di Gomma +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Costruisci Falda Acquifera +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Costruisci Cisterna d'Acqua (può essere costruita solo nelle città) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Costruisci Miniera di Diamanti +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Costruisci Miniera di Rame Grezzo +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Costruisci Foresta di Cotone Candito +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Costruisci Fabbrica di Caramelle +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Costruisci Fattoria delle batterie +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Costruisci Pozzi di Cola +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Costruisci Negozio di Giocattoli +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Costruisci Fabbrica di Giocattoli +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Costruisci Sorgenti di Plastica +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Costruisci Fabbrica Bibite Frizzanti +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Costruisci Generatore di Bolle +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Costruisci Estrattore di Toffee +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Costruisci Miniera di Zucchero +STR_0285_CAN_T_BUILD_HERE :{WHITE}Non puoi costruire {STRING} qui... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...devi costruire prima una città +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...ammessa solo una per città +STR_0288_PLANT_TREES :{BLACK}Pianta Alberi +STR_0289_PLACE_SIGN :{BLACK}Piazza Segnale +STR_028A_RANDOM_TREES :{BLACK}Alberi Casuali +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Pianta alberi casualmente nel paesaggio +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Piazza terreno roccioso nel paesaggio +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Piazza Faro +STR_028E_PLACE_TRANSMITTER :{BLACK}Piazza Trasmettitore +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definisci area desertica +STR_0290_DELETE :{BLACK}Elimina +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Elimina questa città completamente +STR_0292_SAVE_SCENARIO :Salva scenario +STR_0293_LOAD_SCENARIO :CArica scenario +STR_0294_QUIT_EDITOR :Esci dall'editor +STR_0295 : +STR_0296_QUIT :Esci +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Salva scenario, carica scenario, abbandona l'editore di scenari, esci +STR_0298_LOAD_SCENARIO :{WHITE}Carica Scenario +STR_0299_SAVE_SCENARIO :{WHITE}Salva Scenario +STR_029A_PLAY_SCENARIO :{BLACK}Gioca Scenario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Sei sicuro di voler abbondonare questo scenario? +STR_029C_QUIT_EDITOR :{WHITE}Esci dall'editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...può essere costruita solo in città con una popolazione di almeno 1200 +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Sposta la data d'inizio indietro di un'anno +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Sposta la data d'inizio avanti di un'anno +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...gli estremi del ponte devono toccare entrambi la terra +STR_02A1_SMALL :{BLACK}Piccola +STR_02A2_MEDIUM :{BLACK}Media +STR_02A3_LARGE :{BLACK}Grande +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Seleziona dimensione città +STR_02A5_TOWN_SIZE :{YELLOW}Dimensione città: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Mostra ultimo messaggio o un report +STR_02B8_SUMMARY :{BLACK}Sommario +STR_02B9_FULL :{BLACK}Completo +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Elenco Città +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Nomi veicoli +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Predefiniti +STR_02BF_CUSTOM :Personalizzati +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Salva nomi personalizzati +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Selezione nomi personalizzati +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Salva nomi personalizzati dei veicoli + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Opzioni +STR_02C4_GAME_OPTIONS :Opzioni di gioco +STR_02C5_DIFFICULTY_SETTINGS :Scelta difficoltà +STR_02C6_DIFFICULTY_SETTINGS :Scelta difficoltà +STR_02C7_CONFIG_PATCHES :Configura patch +STR_02C8_CONFIG_PATCHES :Configura patch +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Mostra nomi città +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Mostra nomi città +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Mostra nomi stazioni +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Mostra nomi stazioni +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Mostra cartelli +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Mostra cartelli +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Mostra Checkpoint +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Mostra Checkpoints +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Animazione completa +STR_02D0_FULL_ANIMATION :{SETX 12}Animazione completa +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Massimo dettaglio +STR_02D2_FULL_DETAIL :{SETX 12}Massimo dettaglio +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Edifici trasparenti +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Edifici trasparenti +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Informazioni sull'area +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :ScreenShot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :ScreenShot Gigante (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Info su 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}On +STR_02DB_OFF :{BLACK}Off +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Mostra sussidi +STR_02DD_SUBSIDIES :Sussidi +STR_02DE_MAP_OF_WORLD :Mappa del mondo +STR_02DF_TOWN_DIRECTORY :Elenco Città +STR_02E0_CURRENCY_UNITS :{BLACK}Valuta +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Selezione valuta +STR_02E3_DISTANCE_UNITS :{BLACK}Unità di misura +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Selezione unità di misura +STR_02E6_ROAD_VEHICLES :{BLACK}Veicoli stradali con +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Seleziona lato della strada sul quale devono guidare i veicoli stradali +STR_02E9_DRIVE_ON_LEFT :Guida a sinistra +STR_02EA_DRIVE_ON_RIGHT :Guida a destra +STR_02EB_TOWN_NAMES :{BLACK}Nomi Città +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Seleziona il tipo di stile per i nomi delle città + +STR_02F4_AUTOSAVE :{BLACK}Salvataggi automatici +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Seleziona intervallo salvataggi automatici +STR_02F7_OFF :Off +STR_02F8_EVERY_3_MONTHS :Ogni 3 mesi +STR_02F9_EVERY_6_MONTHS :Ogni 6 mesi +STR_02FA_EVERY_12_MONTHS :Ogni 12 mesi +STR_02FB_START_A_NEW_GAME :{BLACK}Inizia nuovo gioco +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Carica partita salvata +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Guarda dimostrazione/tutorial +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Crea uno scenario personalizzato +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Seleziona giocatore singolo +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Seleziona due giocatori +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Mostra opzioni di gioco +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Mostra opzioni difficoltà +STR_0303_START_A_NEW_GAME_USING :{BLACK}Inizia una partita con uno scenario personalizzato +STR_0304_QUIT :{BLACK}Esci +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Esci da 'OpenTTD' +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Guarda dimostrazione/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...può essere costruito solo in città +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Seleziona paesaggio 'temperato' +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Seleziona paesaggio 'sub-artico' +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Seleziona paesaggio 'sub-tropicale' +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Seleziona paesaggio 'Città dei Giocattoli' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Finanzia la costruzione di nuove industrie + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Finanzia nuove industrie +STR_INDUSTRY_DIR :Elenco Industrie +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Finanzia nuove industrie +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...può essere costruito solo in città +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...può essere costruito solo nella foresta pluviale +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...può essere costruito solo in aree desertiche +STR_0319_PAUSED :{YELLOW}* * IN PAUSA * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot salvato correttamente in '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot non riuscito! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Compra terreno per usi futuri +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Servizio stradale +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Servizio ferroviario +STR_032C_3_AIR_SERVICE :{BLACK}3: Servizio aereo +STR_032D_4_SHIP_SERVICE :{BLACK}4: Servizio navale +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Servizio ferroviario (avanzato) +STR_032F_AUTOSAVE :{RED}SALVATAGGIO AUTOMATICO... +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Seleziona il programma 'Ezy Street' + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Inglese +STR_TOWNNAME_FRENCH :Francese +STR_TOWNNAME_GERMAN :Tedesco +STR_TOWNNAME_AMERICAN :Americano +STR_TOWNNAME_LATIN_AMERICAN :Latino-Americano +STR_TOWNNAME_SILLY :Stupidi +STR_TOWNNAME_SWEDISH :Svedese +STR_TOWNNAME_DUTCH :Olandese +STR_TOWNNAME_FINNISH :Finlandese +STR_TOWNNAME_POLISH :Polacco +STR_TOWNNAME_SLOVAKISH :Slovacco +STR_TOWNNAME_HUNGARIAN :Ungherese +STR_TOWNNAME_AUSTRIAN :Austriaci +############ end of townname region + +STR_CURR_POUNDS :Sterline ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollari ($) +STR_CURR_FF :Franchi (FF) +STR_CURR_DM :Marco Tedesco (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Peseta (Pt) +STR_CURR_FT :Fiorino Ungherese (Ft) +STR_CURR_ZL :Zloty Polacca (zl) +STR_CURR_ATS :Scellino Austriano (ATS) +STR_CURR_BEF :Franco Belga (BEF) +STR_CURR_DKK :Corona Danese (DKK) +STR_CURR_FIM :Marco Finlandese(FIM) +STR_CURR_GRD :Drachma Greca (GRD) +STR_CURR_CHF :Franco Svizzero (CHF) +STR_CURR_NLG :Fiorino olandese (NLG) +STR_CURR_ITL :Lira Italiana (ITL) +STR_CURR_SEK :Corona Svedese (SEK) +STR_CURR_RUR :Rupie Russe (RUR) +STR_CURR_CZK :Corona Ceca (CZK) +STR_CURR_ISK :Corona Islandese (ISK) +STR_CURR_NOK :Corona Norvegese (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Lingua +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Seleziona la lingua da utilizzare + +STR_OPTIONS_RES :{BLACK}Risoluzione video +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Seleziona la risoluzione video da utilizzare + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Formato screenshot +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Selezionare il formato da usare per le screenshot + +STR_AUTOSAVE_1_MONTH :Ogni mese +STR_AUTOSAVE_FAILED :{WHITE}Salvataggio automatico fallito. + +STR_MONTH_JAN :Gennaio +STR_MONTH_FEB :Febbraio +STR_MONTH_MAR :Marzo +STR_MONTH_APR :Aprile +STR_MONTH_MAY :Maggio +STR_MONTH_JUN :Giugno +STR_MONTH_JUL :Luglio +STR_MONTH_AUG :Agosto +STR_MONTH_SEP :Settembre +STR_MONTH_OCT :Ottobre +STR_MONTH_NOV :Novembre +STR_MONTH_DEC :Dicembre + +STR_HEADING_FOR_STATION :{LTBLUE}Direzione {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Direzione {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Nessun ordine +STR_NO_ORDERS_VEL :{LTBLUE}Nessun ordine, {VELOCITY} + +STR_PASSENGERS :passeggeri +STR_BAGS :borse +STR_TONS :tonnellate +STR_LITERS :litri +STR_ITEMS :oggetti +STR_CRATES : casse +STR_RES_OTHER :altro +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Non puoi condividere lista ordini... +STR_CANT_COPY_ORDER_LIST :{WHITE}non puoi copiare lista ordini... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Fine degli Ordini Condivisi - - + +STR_TRAIN_IS_LOST :{WHITE}Il Treno {COMMA16} si è perso. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Il profitto del treno {COMMA16} per l'anno scorso è stato {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Configura patch +STR_CONFIG_PATCHES_TIP :{BLACK}Configura le patch +STR_CONFIG_PATCHES_CAPTION :{WHITE}Configurazione patch + +STR_CONFIG_PATCHES_OFF :No +STR_CONFIG_PATCHES_ON :Si +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Mostra velocità veicoli sulla barra di stato: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Consenti costruzioni sulle coste/pendii: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Consenti rimozione industrie, strade speciali, ecc.: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Attiva costruzione treni molto lunghi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Abilita accelerazione realistica per i treni: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Unisci stazioni ferroviarie quando sono vicine: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Lascia stazione quanto uno dei tipi di merce è a pieno carico: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Disattiva la manutenzione automatica dei treni: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Fai arrivare le merci in stazione solo quando richieste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Consenti costruzione ponti molto lunghi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Consenti ordine vai al Deposito: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Consenti la costruzione di industrie produttrici di materia prima: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Consenti più industrie dello stessi tipo per città: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Consenti costr. industrie dello stesso tipo anche se molto vicine: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Mostra sempre formato esteso della data nella barra di stato: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Mostra segnali sul lato guida: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Mostra finestra info finanziare alla fine di ogni anno: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}Gestisci funzione 'non-stop' come la TTDPatch: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Accoda veicoli stradali quando l'area di carico è occupata: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Scorri orizontalmente la finestra quanto il mouse è degli angoli: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Consenti corruzione autorità locale: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Nuovo sistema individuazione deposito: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Stazioni non uniformi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Nuovo algoritmo pathfinding dei treni: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Consenti costruzione quando in pausa: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Consenti sempre costruzione piccoli aeroporti: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Un treno è ritenuto perso se non si ottengono progressi dopo: {ORANGE}{STRING} giorni +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Avvisa se i guadagni di un treno sono in negativo: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Rinnova i veicoli quando diventano troppo vecchi +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Durata messaggio di errore: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Dimensione limite delle nevi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Copertura massima di una stazione: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Manutenzione elicotteri direttamente all’eliporto: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Max treni per giocatore: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Max veicoli stradali per giocatore: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Max aeroplani per giocatore: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Max navi per giocatore: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Disabilita treni per l’IA: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Disabilita veicoli stradali per l’IA: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Disabilita aeroplani per l’IA: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Disabilita navi per l’IA: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Intervallo di servizio predefinito per i treni: {ORANGE}{STRING} giorni +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Intervallo di servizio predefinito per i veicoli: {ORANGE}{STRING} giorni +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Intervallo di servizio predefinito per gli aerei: {ORANGE}{STRING} giorni +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Intervallo di servizio predefinito per le navi: {ORANGE}{STRING} giorni + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Notizie colorate pubblicate dal: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Data di inizio: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Abilita nuova economia stabile (diverse piccole modifiche): + +STR_CONFIG_PATCHES_GUI :{BLACK}Interfaccia +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Costruzione +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Veicoli +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stazioni +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Economia + +STR_CONFIG_PATCHES_DISABLED :disabilitato +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Cambia valori impostazioni + + +STR_CHEATS :{WHITE}Cheats +STR_CHEATS_TIP :{BLACK}La casella indica se hai già utilizzato questo trucco in passato +STR_CHEATS_WARNING :{BLACK}Attenzione! Stai per denunciare i tuoi avversari. Ricordati che un così grande disonore verrà ricordato per l’eternità. +STR_CHEAT_MONEY :{LTBLUE}Aumenta soldi di {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Gioca come giocatore: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Bulldozer magico (rimuove industrie e altri): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}I tunnel possono incrociarsi tra loro: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Nome +STR_TOWNDIR_POPULATION :{BLACK}Popolazione +STR_TOWNDIR_SORT_TIP :{BLACK}Seleziona il tipo di ordinamento + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Direzione {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Direzione {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Vai al {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Checkpoint {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Checkpoint {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Checkpoint + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Modifica nome checkpoint + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Non puoi cambiare il nome del checkpoint... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Converti binario in checkpoint +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Non puoi costruire checkpoint qui... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Non puoi rimuovere checkpoint... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Costruisci binario usando la modalità automatica + +STR_TREES_RANDOM_TYPE :{BLACK}Alberi di tipo casuale +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Pianta alberi di tipo casuale + +STR_CANT_BUILD_CANALS :{WHITE}Impossibile costruire un canale qui... +STR_BUILD_CANALS_TIP :{BLACK}Costruisci canali +STR_LANDINFO_CANAL :Canale + +STR_CANT_BUILD_LOCKS :{WHITE}Impossibile costruire una chiusa qui... +STR_BUILD_LOCKS_TIP :{BLACK}Costruisci chiusa +STR_LANDINFO_LOCK :Chiusa + +STR_LANDINFO_COORDS :{BLACK}Coordinate: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Impossibile rimuovere una porzione di stazione... +STR_CANT_CONVERT_RAIL :{WHITE}Impossibile convertire il tipo di rotaie... +STR_CONVERT_RAIL_TIP :{BLACK}Converti/aggiorna il tipo di rotaie + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Trascina qui la locomotiva per vendere l’intero treno + +STR_DRAG_DROP :{BLACK}Drag & Drop +STR_STATION_DRAG_DROP :{BLACK}Costruisci una stazione con il drag & drop + +STR_FAST_FORWARD :{BLACK}Aumenta la velocità di gioco +STR_MESSAGE_HISTORY :{WHITE}Cronologia messaggi + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Costruisci Miniera di Carbone +STR_CONSTRUCT_FOREST_TIP :{BLACK}Posiziona Foresta +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Costruisci Piattaforma Petrolifera +STR_CONSTRUCT_FARM_TIP :{BLACK}Fonda Fattoria +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Costruisci Miniera di Rame +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Costruisci Pozzo Petrolifero +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Costruisci Miniera d’Oro +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Costruisci Miniera di Diamanti +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Costruisci Miniera d’Argento +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Fonda Piantagione di Frutta +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Fund Rubber Plantation +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Fund Water Supply +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plant Cotton Candy Forest +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Fund Battery Farm +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Drill for Cola +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Fund Plastic Fountains +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Construct Bubble Generator +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Fund Toffee Quarry +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Costruisci Raffineria di Zucchero + +STR_INDUSTRYDIR_NAME :{BLACK}Nome +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produzione +STR_INDUSTRYDIR_TYPE :{BLACK}Tipo +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrie +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...troppo vicina ad un’altra industria. + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Riadatta il treno per trasportare un differente tipo di carico +STR_RAIL_REFIT :{WHITE}{STRING} (Riadatta) +STR_RAIL_REFIT_VEHICLE :{BLACK}Riadatta treno +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Seleziona tipo di carico per il treno +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Riadatta il treno per trasportare il tipo di carico selezionato +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Impossibile riadattare il treno... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Costo: {CURRENCY} +STR_0801_COST :{RED}Costo: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Incasso: {CURRENCY} +STR_0803_INCOME :{GREEN}Incasso: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Costo Stimato: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Costo Stimato: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Incasso Stimato: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Incasso Stimato: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Non puoi alzare terreno qui... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Non puoi abbassare terreno qui... +STR_080A_ROCKS :Roccie +STR_080B_ROUGH_LAND :Terreno accidentato +STR_080C_BARE_LAND :Terreno spoglio +STR_080D_GRASS :Erba +STR_080E_FIELDS :Campi +STR_080F_SNOW_COVERED_LAND :Terreno innevato +STR_0810_DESERT :Deserto + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinato nella direzione errata +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Combinazione di binari impossibile +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Gli scavi danneggerebbero la galleria +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Già al livello del mare +STR_1004_TOO_HIGH :{WHITE}Troppo alto +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Tipo di binari non adatti +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Treno nel deposito +STR_1007_ALREADY_BUILT :{WHITE}...già costruito +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Rimuovere binari prima +STR_1009_TOO_MANY_DEPOTS :{WHITE}Troppi depositi +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Costruzioni ferroviarie +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Costruzione monorotaia +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Costruzioni MagLev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Seleziona ponte ferroviario +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Non puoi costruire deposito qui... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Non puoi costruire stazione qui... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Non puoi piazzare segnali qui.. +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Non puoi costruire i binari qui... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Non puoi rimuovere binari da qui +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Non puoi rimuovere segnali da qui... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Orientamento Deposito +STR_1015_RAILROAD_CONSTRUCTION :Costruzioni ferroviarie +STR_1016_MONORAIL_CONSTRUCTION :Costruzione monorotaia +STR_1017_MAGLEV_CONSTRUCTION :Costruzioni MagLev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Costruisci binari +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Costruisci deposito treni (per costruzione e manutenzione) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Costruisci stazione ferroviaria +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Costruisci segnale ferroviario +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Costruisci ponte ferroviario +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Costruisci tunnel ferroviario +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Seleziona costruisci/rimuovi per binari e segnali +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Selezione ponte - clicca sul ponte selezionato per costruirlo +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Seleziona orientamento deposito ferroviario +STR_1021_RAILROAD_TRACK :Binari +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Binari con segnali +STR_1023_RAILROAD_TRAIN_DEPOT :Deposito ferroviario +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...area di proprietà di un altra società +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Binario ferroviario con segnali normali +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Binario ferroviario con presegnali +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Binario ferroviario con segnali di uscita +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Binario ferroviario con segnali combinati + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinato nella direzione errata +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Devi rimuovere la strada prima +STR_1802_ROAD_CONSTRUCTION :{WHITE}Costruzioni Stradali +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Seleziona ponte stradale +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Non puoi costruire strada da qui... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Non puoi rimuovere strada da qui... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientamento Deposito +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Non puoi costruire deposito stradale qui... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Non puoi costruire fermata bus... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Non puoi costruire stazione di carico... +STR_180A_ROAD_CONSTRUCTION :Costruzioni stradali +STR_180B_BUILD_ROAD_SECTION :{BLACK}Costruisci sezione stradale +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Costruisci deposito veicoli stradali (per costruzione e manutenzione) +STR_180D_BUILD_BUS_STATION :{BLACK}Costruisci fermata bus +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Costruisci stazione di carico +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Costruisci ponte stradale +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Costruisci tunnel stradale +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Seleziona costruisci\demolisci per le costruzioni stradali +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Selezione ponte - clicca sul tipo di ponte per costruirlo +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Seleziona orientamento deposito veicoli stradali +STR_1814_ROAD :Strada +STR_1815_ROAD_WITH_STREETLIGHTS :Strada con lampioni +STR_1816_TREE_LINED_ROAD :Strada alberata +STR_1817_ROAD_VEHICLE_DEPOT :Deposito Veicoli +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Passaggio a livello + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Città +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}E' necessario demolire l'edificio prima +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Popolazione: {ORANGE}{COMMA32}{BLACK} Case: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Rinomina città +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Non puoi rinominare città... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}L'autorità locale di {TOWN} non ti autorizza a farlo +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Elenco città - clicca sul nome per centrare la visuale sulla città +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centra la visuale sulla città +STR_200C_CHANGE_TOWN_NAME :{BLACK}Cambia nome alla città +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passeggeri ultimo mese: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Posta ultimo mese: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Blocco di uffici alto +STR_2010_OFFICE_BLOCK :Blocco di uffici +STR_2011_SMALL_BLOCK_OF_FLATS :Piccolo blocco di appartamenti +STR_2012_CHURCH :Chiesa +STR_2013_LARGE_OFFICE_BLOCK :Blocco di uffici grande +STR_2014_TOWN_HOUSES :Case +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Statua +STR_2017_FOUNTAIN :Fountana +STR_2018_PARK :Parco +STR_2019_OFFICE_BLOCK :Blocco di uffici +STR_201A_SHOPS_AND_OFFICES :Negozi e uffici +STR_201B_MODERN_OFFICE_BUILDING :Uffici moderni +STR_201C_WAREHOUSE :Magazzino +STR_201D_OFFICE_BLOCK :Blocco di uffici +STR_201E_STADIUM :Stadio +STR_201F_OLD_HOUSES :Case antiche +STR_2020_LOCAL_AUTHORITY :{BLACK}Autorità locale +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Mostra informazioni sull'autorità locale +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} autorità locale +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Valutazione servizi di trasporto delle società: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Sussidi +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Sussidi offerti per il servizio:- +STR_2027_FROM_TO :{ORANGE}{STRING} da {STRING} a {STRING} +STR_2028_BY :{YELLOW} (del {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Nessuno +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Servizi già sussidiati:- +STR_202C_FROM_TO :{ORANGE}{STRING} da {STATION} a {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, fino al {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Offerta di sussidio scaduta:{}{}{STRING} da {STRING} a {STRING} non sarà più sovvenzionato. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Sussidio terminato:{}{}servizio di {STRING} da {STATION} a {STATION} non è più sovvenzionato. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Offerta di sussidio:{}{}Primo servizio di {STRING} da {STRING} a {STRING} riceverà un'anno di sussidio dall'autorità locale! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Sussidio aggiudicato da {STRING}!{}{}servizio di {STRING} da {STATION} a {STATION} verrà pagato il 50% in più per il prossimo anno! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Sussidio aggiudicato da {STRING}!{}{}servizio di {STRING} da {STATION} a {STATION} verrà pagato il doppio per il prossimo anno! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Sussidio aggiudicato da {STRING}!{}{}servizio di {STRING} da {STATION} a {STATION} verrà pagato il triplo per il prossimo anno! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Sussidio aggiudicato da {STRING}!{}{}servizio di {STRING} da {STATION} a {STATION} verrà pagato il quadruplo per il prossimo anno! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}L'autorita locale di {TOWN} rifiuta la costruzione di un altro areoporto nella città +STR_2036_COTTAGES :Cottage +STR_2037_HOUSES :Case +STR_2038_FLATS :Appartamenti +STR_2039_TALL_OFFICE_BLOCK :Blocco di uffici alto +STR_203A_SHOPS_AND_OFFICES :Negozi e uffici +STR_203B_SHOPS_AND_OFFICES :Negozi e uffici +STR_203C_THEATER :Teatro +STR_203D_STADIUM :Stadio +STR_203E_OFFICES :Offici +STR_203F_HOUSES :Case +STR_2040_CINEMA :Cinema +STR_2041_SHOPPING_MALL :Centro commerciale +STR_2042_DO_IT :{BLACK}Fallo! +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Lista azioni eseguibili in questa città - clicca sopra per i dettagli +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Trascina l'azione evidenziata nella lista sovrastante +STR_2045_ACTIONS_AVAILABLE :{BLACK}Azioni disponibili: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Piccola campagna pubblicitaria +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Campagna pubblicitaria media +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Grande campagna pubblicitaria +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Finanzia ricostruzione delle strade locali +STR_204A_BUILD_STATUE_OF_COMPANY :Costruisci statua del propietario della società +STR_204B_FUND_NEW_BUILDINGS :Finanzia nuove costruzioni +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Compra l'esclusiva sui trasporti +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Corrompi l’autorità locale +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Inizia una piccola campagnia pubblicitaria per attirare più gente e merci ai tuoi servizi di trasporto.{} Costo: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Inizia una media campagnia pubblicitaria per attirare più gente e merci ai tuoi servizi di trasporto.{} Costo: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Inizia una grande campagnia pubblicitaria per attirare più gente e cargo ai tuoi servizi di trasporto.{} Costo: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Finanzia la ricostruzione della rete stradale cittadina. Causa un cosiderabile disagio al traffico stradale per 6 mesi.{} Costo: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Costruisci una statua in onore della tua società.{} Costo: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Finanzia la costruzione di nuove strutture commerciali nella città.{} Costo: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Compra 1 anno di esclusiva sui trasporti nella città. Compra 1 anno di esclusiva sui diritti di trasporto in città. L'autorità cittadina autorizzerà passeggeri e merci a usare solo le tue stazioni.{} Costo: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Corrompi l’autorità locale per incrementare la tua valutazione con il rischio di una severa multa se scoperto.{} Costo: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Non puoi farlo... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Traffico nel caos a {TOWN}!{}{}La ricostruzione stradale finanziata da {STRING} porterà 6 mesi di disagio agli automobilisti! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (in costruzione) +STR_2059_IGLOO :Igloo +STR_205A_TEPEES :Tepees +STR_205B_TEAPOT_HOUSE :Casa-teiera +STR_205C_PIGGY_BANK :Banca-porcellino + +##id 0x2800 +STR_2800_PLANT_TREES :Pianta alberi +STR_2801_PLACE_SIGN :Piazza cartello +STR_2802_TREES :{WHITE}Alberi +STR_2803_TREE_ALREADY_HERE :{WHITE}...albero già qui +STR_2804_SITE_UNSUITABLE :{WHITE}...sito inadatto +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Non puoi piantare albero qui... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...troppi cartelli +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Non puoi piazzare un cartello qui... +STR_280A_SIGN :Cartello +STR_280B_EDIT_SIGN_TEXT :{WHITE}Modifica testo Cartello +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Non puoi modificare il testo del cartello... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Seleziona il tipo di albero da piantare +STR_280E_TREES :Alberi +STR_280F_RAINFOREST :Foresta pluviale +STR_2810_CACTUS_PLANTS :Cactus + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Selezione Stazione +STR_3001_AIRPORT_SELECTION :{WHITE}Selezione Aereoporto +STR_3002_ORIENTATION :{BLACK}Orientamento +STR_3003_NUMBER_OF_TRACKS :{BLACK}Numero binari +STR_3004_PLATFORM_LENGTH :{BLACK}Lunghezza +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Troppo vicino a un'altra stazione +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Unisci stazione esistente/area di carico +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Troppe stazioni/aree di carico in questa città +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Troppe stazioni/aree di carico +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Troppo vicino ad un'altra stazione/Area di carico +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Devi demolire stazione ferroviaria prima +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Troppo vicino ad un altro aereoporto +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Devi demolire aereoporto prima + +STR_3030_RENAME_STATION_LOADING :Rinomina stazione/area di carico +STR_3031_CAN_T_RENAME_STATION :{WHITE}Non puoi rinominare stazione... +STR_3032_RATINGS :{BLACK}Valutazione +STR_3033_ACCEPTS :{BLACK}Accettati +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Valutazione del servizio trasporti locale + +############ range for rating starts +STR_3035_APPALLING :Terribile +STR_3036_VERY_POOR :Molto scarso +STR_3037_POOR :Scarso +STR_3038_MEDIOCRE :Mediocre +STR_3039_GOOD :Buono +STR_303A_VERY_GOOD :Molto buono +STR_303B_EXCELLENT :Eccellente +STR_303C_OUTSTANDING :Eccezionale +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} non accetta più {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} non accetta più {STRING} o {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} adesso accetta {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} adesso accetta {STRING} e {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Orientamento fermata +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Orient. Stazione Camion +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Troppo vicina a un'altra stazione bus +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Troppo vicina a un'altra stazione camion +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Devi demolire stazione bus prima +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Devi demolire stazione camion prima +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stazioni +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Nulla - +STR_304B_SITE_UNSUITABLE :{WHITE}...sito inadatto +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Troppo vicino a un'altro molo +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Devi demolire il molo prima +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Seleziona orientamento della stazione ferroviaria +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Seleziona numero di binari della stazione +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Seleziona lunghezza della stazione +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Seleziona orientamento stazione bus +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Seleziona orientamento stazione camion +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centra visuale sulla stazione +STR_3054_SHOW_STATION_RATINGS :{BLACK}Mostra valutazione servizio +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Cambia il nome della stazione +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Mostra la lista della merce accettata +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Nomi stazioni - clicca sul nome per centrare la visuale sulla stazione +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Seleziona dimensione/tipo di aeroporto +STR_3059_SMALL :{BLACK}Piccolo +STR_305A_LARGE :{BLACK}Grande +STR_305AA_LARGE :{BLACK}Aeroporto metropolitano +STR_305AB_LARGE :{BLACK}Aeroporto internazionale +STR_305B_SIZE :{BLACK}Dimensioni +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Stazione ferroviaria +STR_305F_AIRCRAFT_HANGAR :Hangar +STR_3060_AIRPORT :Aeroporto +STR_3061_TRUCK_LOADING_AREA :Area di carico per camion +STR_3062_BUS_STATION :Fermata bus +STR_3063_SHIP_DOCK :Molo +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Evidenzia l'area di copertura del sito proposto +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Non evidenziare l'area di copertura del sito proposto +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Evidenzia area coperta +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Selezione stazione per monorotaia +STR_3068_DOCK :{WHITE}Molo +STR_3069_BUOY :Boa +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boa in mezzo +STR_306B_HELIPORT :{BLACK}Eliporto +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stazione troppo estesa + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orientamento deposito navale +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...deve essere costruito sull'acqua +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Non puoi costruire deposito navale qui... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Seleziona orientamento del deposito navale +STR_3804_WATER :Acqua +STR_3805_COAST_OR_RIVERBANK :Costa +STR_3806_SHIP_DEPOT :Deposito navale +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...non puoi costruire sull'acqua + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Salva partita +STR_4001_LOAD_GAME :{WHITE}Carica partita +STR_4002_SAVE :{BLACK}Salva +STR_4003_DELETE :{BLACK}Elimina +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes liberi +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Impossibile leggere dal disco +STR_4007_GAME_SAVE_FAILED :{WHITE}Salvataggio fallito +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Impossibile eliminare il file +STR_4009_GAME_LOAD_FAILED :{WHITE}Caricamento fallito +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Elenco unità disco, cartelle e file save-game +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Nome correntemente scelto per il salvataggio +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Elimina il file selezionato +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}salva il gioco corrente usando il nome selezionato +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Selezione il tipo di gioco +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Seleziona scenario (verde), Partita pre-impostata (blu),Scenario casuale +STR_4010_GENERATE_RANDOM_NEW_GAME :Crea partita casuale + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} in mezzo +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Miniera di Carbone +STR_4803_POWER_STATION :Centrale Elettrica +STR_4804_SAWMILL :Falegnameria +STR_4805_FOREST :Foresta +STR_4806_OIL_REFINERY :Raffineria +STR_4807_OIL_RIG :Piattaforma Petrolifera +STR_4808_FACTORY :Fabbrica +STR_4809_PRINTING_WORKS :Casa Editrica +STR_480A_STEEL_MILL :Acciaieria +STR_480B_FARM :Fattoria +STR_480C_COPPER_ORE_MINE :Miniera di Rame Grezzo +STR_480D_OIL_WELLS :Pozzi Petroliferi +STR_480E_BANK :Banca +STR_480F_FOOD_PROCESSING_PLANT :Azienda Alimentare +STR_4810_PAPER_MILL :Cartiera +STR_4811_GOLD_MINE :Miniera d'Oro +STR_4812_BANK :Banca +STR_4813_DIAMOND_MINE :Miniera di Diamanti +STR_4814_IRON_ORE_MINE :Miniera di Ferro Grezzo +STR_4815_FRUIT_PLANTATION :Piantaggio di Frutta +STR_4816_RUBBER_PLANTATION :Piantaggio di Gomma +STR_4817_WATER_SUPPLY :Falda Acquifera +STR_4818_WATER_TOWER :Cisterna d'Acqua +STR_4819_FACTORY :Fabbrica +STR_481A_FARM :Fattoria +STR_481B_LUMBER_MILL :Segheria +STR_481C_COTTON_CANDY_FOREST :Foresta Cotone Candito +STR_481D_CANDY_FACTORY :Fabbrica Caramelle +STR_481E_BATTERY_FARM :Fattoria delle Batterie +STR_481F_COLA_WELLS :Pozzi di Cola +STR_4820_TOY_SHOP :Negozio di Giocattoli +STR_4821_TOY_FACTORY :Fabbrica di Giocattoli +STR_4822_PLASTIC_FOUNTAINS :Sorgenti di Plastica +STR_4823_FIZZY_DRINK_FACTORY :Fabbrica Bevande Frizzanti +STR_4824_BUBBLE_GENERATOR :Generatore di Bolle +STR_4825_TOFFEE_QUARRY :Estrattore di Toffee +STR_4826_SUGAR_MINE :Miniera di Zucchero + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Richiede: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Richiede: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Richiede: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produzione ultimo mese: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% trasportato) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centra visule sull'industria +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Nuova {STRING} in costruzione vicino a {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Nuova {STRING} è stata piantata vicino a {TOWN}! +STR_482F_COST :{BLACK}Costo: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Non puoi costruire tipo di industria qui... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...la foresta può essere piantata solo in una zona innevata +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} annuncia imminente chiusura!! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Per problemi di rifornimenti {TOWN} {STRING} annuncia imminente chiusura! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}La mancanza di alberi vicini costringe {TOWN} {STRING} ad imminente chiusura! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} produzione incrementata! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nuovo giacimento di carbone trovato a {TOWN} {STRING}!{}Produzione destinata a duplicare! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nuovo giacimento di petrolio trovato a {TOWN} {STRING}!{}Produzione destinata a duplicare! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Metodi di coltivazione migliorati a {TOWN} {STRING} produzione destinata a duplicare! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} produzione scesa del 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Invasione d'insetti causa devastazione a {TOWN} {STRING}!{}Produzione scesa del 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...può essere posizionata solo vicino al bordo della mappa +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}La produzione di {STRING} a {TOWN} {STRING} è aumentata del {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}La produzione di {STRING} a {TOWN} {STRING} è diminuita del {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Treno nel tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Veicolo nel tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Altro tunnel in mezzo +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Impossibile scavare l'uscita del tunnel +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Devi demolire il tunnel prima +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Devi demolire il ponte prima +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Non si può partire e finire nello stesso punto +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Sotto i ponti è richiesto terreno piano o acqua +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Inizio e fine devono essere allineati +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Sito inadatto per l'entrata del tunnel +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Sospeso in Acciaio +STR_500F_GIRDER_STEEL :In Acciaio +STR_5010_CANTILEVER_STEEL :In travi d'acciaio +STR_5011_SUSPENSION_CONCRETE :Sospeso in Cemento +STR_5012_WOODEN :Di legno +STR_5013_CONCRETE :In cemento +STR_5014_TUBULAR_STEEL :Tubolare in acciaio +STR_BRIDGE_TUBULAR_SILICON :Tubolare in silicone +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Non puoi costruire ponte qui... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Non puoi costruire tunnel qui... +STR_5017_RAILROAD_TUNNEL :Tunnel ferroviario +STR_5018_ROAD_TUNNEL :Tunnel stradale +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Ponte ferroviario sospeso in acciaio +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Ponte ferroviario in acciaio +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Ponte ferroviario in travi d'acciaio +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Ponte ferroviario sospeso in cemento armato +STR_501F_WOODEN_RAIL_BRIDGE :Ponte ferroviario in legno +STR_5020_CONCRETE_RAIL_BRIDGE :Ponte ferroviario in cemento +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Ponte stradale sopeso in acciaio +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Ponte stradale in acciaio +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Ponte stradale in travi d'acciaio +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Ponte stradale sospeso in cemento armato +STR_5025_WOODEN_ROAD_BRIDGE :Ponte stradale in legno +STR_5026_CONCRETE_ROAD_BRIDGE :Ponte stradale in cemento +STR_5027_TUBULAR_RAIL_BRIDGE :Ponte ferroviario tubolare +STR_5028_TUBULAR_ROAD_BRIDGE :Ponte stradale tubolare +STR_5029_STEEL :Acciaio + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Oggetto in mezzo +STR_5801_TRANSMITTER :Trasmettitore +STR_5802_LIGHTHOUSE :Faro +STR_5803_COMPANY_HEADQUARTERS :Sede della società +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...Sede principale della società in mezzo +STR_5805_COMPANY_OWNED_LAND :Terreno posseduto dalla società +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Non puoi acquistare questo terreno... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...lo possiedi già! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Senza nome{SKIP} +STR_SV_TRAIN_NAME :Treno {COMMA16} +STR_SV_ROADVEH_NAME :Veicolo Stradale {COMMA16} +STR_SV_SHIP_NAME :Nave {COMMA16} +STR_SV_AIRCRAFT_NAME :Aereo {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Nord +STR_SV_STNAME_SOUTH :{STRING} Sud +STR_SV_STNAME_EAST :{STRING} Est +STR_SV_STNAME_WEST :{STRING} Ovest +STR_SV_STNAME_CENTRAL :{STRING} Centrale +STR_SV_STNAME_TRANSFER :{STRING} Transfer +STR_SV_STNAME_HALT :{STRING} Fermata +STR_SV_STNAME_VALLEY :{STRING} Valle +STR_SV_STNAME_HEIGHTS :{STRING} Altura +STR_SV_STNAME_WOODS :{STRING} Bosco +STR_SV_STNAME_LAKESIDE :{STRING} Lago +STR_SV_STNAME_EXCHANGE :{STRING} Exchange +STR_SV_STNAME_AIRPORT :{STRING} Aereoporto +STR_SV_STNAME_OILFIELD :{STRING} Giacimento petrolifero +STR_SV_STNAME_MINES :{STRING} Miniere +STR_SV_STNAME_DOCKS :{STRING} Mol +STR_SV_STNAME_BUOY_1 :{STRING} Boa 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boa 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boa 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boa 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boa 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boa 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boa 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boa 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boa 9 +STR_SV_STNAME_ANNEXE :{STRING} Annexe +STR_SV_STNAME_SIDINGS :{STRING} Raccordo +STR_SV_STNAME_BRANCH :{STRING} Ramo +STR_SV_STNAME_UPPER :Alta {STRING} +STR_SV_STNAME_LOWER :Bassa {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliporto +STR_SV_STNAME_FOREST :{STRING} Foresta + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Livello di difficoltà + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Facile +STR_6802_MEDIUM :{BLACK}Medio +STR_6803_HARD :{BLACK}Difficile +STR_6804_CUSTOM :{BLACK}Personalizzato +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Numero max di avversari: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Partenza avversari: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Numero di città: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Numero di industrie: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Interesse iniziale massimo: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Tasso d'interesse iniziale: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Consumi dei veicoli: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Velocità di costruzione degli avversari: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligenza degli avversari: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Guasti dei veicoli: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Moltiplicatori sussidi: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Costi di costruzione: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Tipo di terreno: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Quantità mare/laghi: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Economia: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Inversione treni: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Disastri: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Basso +STR_6817_NORMAL :Normale +STR_6818_HIGH :Alto +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Molto lenta +STR_681C_SLOW :Lenta +STR_681D_MEDIUM :Media +STR_681E_FAST :Veloce +STR_681F_VERY_FAST :Molto veloce +STR_VERY_LOW :Molto basso +STR_6820_LOW :Basso +STR_6821_MEDIUM :Medio +STR_6822_HIGH :Alto +STR_6823_NONE :Nessuno +STR_6824_REDUCED :Ridotto +STR_6825_NORMAL :Normale +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Molto pianeggiante +STR_682B_FLAT :Pianeggiante +STR_682C_HILLY :Collinoso +STR_682D_MOUNTAINOUS :Montagnoso +STR_682E_STEADY :Stabile +STR_682F_FLUCTUATING :Fluttuante +STR_6830_IMMEDIATE :Immediatamente +STR_6831_3_MONTHS_AFTER_PLAYER :3 mesi dopo il giocatore +STR_6832_6_MONTHS_AFTER_PLAYER :6 mesi dopo il giocatore +STR_6833_9_MONTHS_AFTER_PLAYER :9 mesi dopo il giocatore +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Alla fine della linea, e alle stazioni +STR_6835_AT_END_OF_LINE_ONLY :Solo alla fine della linea +STR_6836_OFF :Off +STR_6837_ON :On +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Mostra punteggi migliori + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Giocatore 1) +STR_7003_PLAYER_2 : (Giocatore 2) +STR_7004_NEW_FACE :{BLACK}Nuova Faccia +STR_7005_COLOR_SCHEME :{BLACK}Colore Società +STR_7006_COLOR_SCHEME :{GOLD}Colore Società: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nuovo Colore Società +STR_7008_COMPANY_NAME :{BLACK}Nome Società +STR_7009_PRESIDENT_NAME :{BLACK}Nome Presidente +STR_700A_COMPANY_NAME :Nome della società +STR_700B_PRESIDENT_S_NAME :Nome del presidente +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Non puoi cambiare il nome della società... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Non puoi cambiare in nome del presidente... +STR_700E_FINANCES :{WHITE}{STRING} Finanze{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Spese/Ricavi +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Costruzioni +STR_7012_NEW_VEHICLES :{GOLD}Nuovi Veicoli +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Consumi Treni +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Consumi Veicoli +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Consumi Aerei +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Consumi Navi +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Manutenzione Propietà +STR_7018_TRAIN_INCOME :{GOLD}Ricavi Treni +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Ricavi Veicoli +STR_701A_AIRCRAFT_INCOME :{GOLD}Ricavi Aerei +STR_701B_SHIP_INCOME :{GOLD}Ricavi Navi +STR_701C_LOAN_INTEREST :{GOLD}Interessi sul Prestito +STR_701D_OTHER :{GOLD}Altro +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Totale: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Grafico Incassi +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Grafico Profitti Operazionali +STR_7026_BANK_BALANCE :{WHITE}Bilancio Bancario +STR_7027_LOAN :{WHITE}Prestito +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Richiedi {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Ripaga {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...il prestito massimo concesso è di {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Non puoi chiedere altro denaro... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...debito già ripagato +STR_702E_REQUIRED :{WHITE}...{CURRENCY} richiesti +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Non puoi ripagare debito... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Seleziona una nuova faccia per il presidente +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Cambia colore dei veicoli della società +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Cambia il nome del presidente +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Cambia il nome della compagnia +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Fare clic per selezionare il nuovo colore +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Aumenta dimensioni del debito +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Ripaga parte del debito +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(President) +STR_7038_INAUGURATED :{GOLD}Inaugurata: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Veicoli: +STR_703A_TRAIN :{WHITE}{COMMA16} treno +STR_703B_TRAINS :{WHITE}{COMMA16} treni +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} Veicolo stradale +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} Veicoli stradali +STR_703E_AIRCRAFT :{WHITE}{COMMA16} aereo +STR_703F_AIRCRAFT :{WHITE}{COMMA16} aerei +STR_7040_SHIP :{WHITE}{COMMA16} nave +STR_7041_SHIPS :{WHITE}{COMMA16} navi +STR_7042_NONE :{WHITE}Nessuno +STR_7043_FACE_SELECTION :{WHITE}Seleziona Faccia +STR_7044_MALE :{BLACK}Maschio +STR_7045_FEMALE :{BLACK}Femmina +STR_7046_NEW_FACE :{BLACK}Nuova Faccia +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Annulla selezione Faccia +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Accetta nuova Faccia +STR_7049_SELECT_MALE_FACES :{BLACK}Seleziona volti maschili +STR_704A_SELECT_FEMALE_FACES :{BLACK}Seleziona volti femminili +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Genera faccia a caso +STR_704C_KEY :{BLACK}Chiavi +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Mostra chiave del grafico +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Chiave del grafico società +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Clicca qui per selezionare entrata nel grafico della società on/off +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Unità di merce trasportata +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Valutazione prestazioni società (Massima valutazione=1000) +STR_7052_COMPANY_VALUES :{WHITE}Valore della società +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Classifica società +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Società di trasporti in difficolta! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} verrà venduta o dichiarerà bancarotta a meno che le prestazioni non miglioreranno presto! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Presidente) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Fusione tra società di trasporti +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} è stata venduta a {STRING} per {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Stiamo cercando una società di trasporti per vendere la nostra società.{}{} Vorrebbe acquistare {STRING} per {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bancarotta! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} è stata chiusa dai creditori e tutti i suoi beni venduti! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Lanciata nuova società di trasporti! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} inizia a costruire vicino a {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Non puoi comprare la società... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Percentuale Pagamento Merce +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Giorni di viaggio +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Pagamento per la consegna di dieci unità (o 10,000 litri) di merce alla distanza di 20 quadrati +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Seleziona grafico tipo di merce on/off +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingeniere +STR_7067_TRAFFIC_MANAGER :Direttore del traffico +STR_7068_TRANSPORT_COORDINATOR :Coordinatore Dei trasporti +STR_7069_ROUTE_SUPERVISOR :Supervisore Dei Percorsi +STR_706A_DIRECTOR :Direttore +STR_706B_CHIEF_EXECUTIVE :Capo Esecutivo +STR_706C_CHAIRMAN :Direttore Esecutivo +STR_706D_PRESIDENT :Presidente +STR_706E_TYCOON :magnate +STR_706F_BUILD_HQ :{BLACK}Costr. Sede +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Costruisci/guarda la sede della società +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Non puoi costruire la sede della compagnia... +STR_7072_VIEW_HQ :{BLACK}Guarda Sede +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Recessione Mondiale!{}{}Gli esperti finanziari temono la peggior crisi economica! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Recessione Finita!{}{}Rialzo negli scambi dà fiducia alle industrie per un rafforzamento economico! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Seleziona dimensione grande/piccola della finestra +STR_7076_COMPANY_VALUE :{GOLD}Valore società: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Compra il 25% delle azioni +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Vendi il 25% delle azioni +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Compra il 25% delle azioni della società +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Vendi il 25% delle azioni della società +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Non puoi comprare il 25% delle azioni della società... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Non puoi vendere il 25% delle azioni della società... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% posseduto da {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% posseduto da {STRING}{} {COMMA16}% posseduto da {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} è stata rilevata da {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Vapore) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Vapore) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Vapore) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Vapore) +STR_800A_SH_8P_STEAM :SH '8P' (Vapore) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elettrica) +STR_8018_SH_40_ELECTRIC :SH '40' (Elettrica) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elettrica) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elettrica) +STR_801B_PASSENGER_CAR :Carrozza Passeggeri +STR_801C_MAIL_VAN :Vagone Postale +STR_801D_COAL_CAR :Vagone Carbone +STR_801E_OIL_TANKER :Cisterna Petrolio +STR_801F_LIVESTOCK_VAN :Vano Bestiame +STR_8020_GOODS_VAN :Vano Beni +STR_8021_GRAIN_HOPPER :Vagone Grano +STR_8022_WOOD_TRUCK :Vagone Legna +STR_8023_IRON_ORE_HOPPER :Vagone Ferro +STR_8024_STEEL_TRUCK :Vagone Acciaio +STR_8025_ARMORED_VAN :Vagone Blindato +STR_8026_FOOD_VAN :Vano Alimentari +STR_8027_PAPER_TRUCK :Vagone Carta +STR_8028_COPPER_ORE_HOPPER :Vagone Rame +STR_8029_WATER_TANKER :Cisterna Acqua +STR_802A_FRUIT_TRUCK :Vagone Frutta +STR_802B_RUBBER_TRUCK :Vagone Gomma +STR_802C_SUGAR_TRUCK :Vagone Zucchero +STR_802D_COTTON_CANDY_HOPPER :Vagone Cotone Cand. +STR_802E_TOFFEE_HOPPER :Vano Toffee +STR_802F_BUBBLE_VAN :Vano Bolle +STR_8030_COLA_TANKER :Cisterna Cola +STR_8031_CANDY_VAN :Vano Dolciumi +STR_8032_TOY_VAN :Vano Giocattoli +STR_8033_BATTERY_TRUCK :Vagone Batterie +STR_8034_FIZZY_DRINK_TRUCK :Vagone Bibite Friz. +STR_8035_PLASTIC_TRUCK :Vagone Plastica +STR_8036_X2001_ELECTRIC :'X2001' (Elettrica) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elettrica) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Carrozza Passeggeri +STR_803A_MAIL_VAN :Vagone Postale +STR_803B_COAL_CAR :Vagone Postale +STR_803C_OIL_TANKER :Cisterna Petrolio +STR_803D_LIVESTOCK_VAN :Vano Bestiame +STR_803E_GOODS_VAN :Vano Beni +STR_803F_GRAIN_HOPPER :Vagone Grano +STR_8040_WOOD_TRUCK :Vagone Legna +STR_8041_IRON_ORE_HOPPER :Vagone Ferro +STR_8042_STEEL_TRUCK :Vagone Acciaio +STR_8043_ARMORED_VAN :Vagone Blindato +STR_8044_FOOD_VAN :Vano Alimentari +STR_8045_PAPER_TRUCK :Vagone Carta +STR_8046_COPPER_ORE_HOPPER :Vagone Rame +STR_8047_WATER_TANKER :Cisterna Acqua +STR_8048_FRUIT_TRUCK :Vagone Frutta +STR_8049_RUBBER_TRUCK :Vagone Gomma +STR_804A_SUGAR_TRUCK :Vagone Zucchero +STR_804B_COTTON_CANDY_HOPPER :Vagone Cotone Cand. +STR_804C_TOFFEE_HOPPER :Vano Toffee +STR_804D_BUBBLE_VAN :Vano Bolle +STR_804E_COLA_TANKER :Cisterna Cola +STR_804F_CANDY_VAN :Vano Dolciumi +STR_8050_TOY_VAN :Vano Giocattoli +STR_8051_BATTERY_TRUCK :Vagone Batterie +STR_8052_FIZZY_DRINK_TRUCK :Vagone Bibite Friz. +STR_8053_PLASTIC_TRUCK :Vagone Plastica +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elettrica) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elettrica) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elettrica) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elettrica) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Carrozza Passeggeri +STR_805A_MAIL_VAN :Vagone Postale +STR_805B_COAL_CAR :Vagone Postale +STR_805C_OIL_TANKER :Cisterna Petrolio +STR_805D_LIVESTOCK_VAN :Vano Bestiame +STR_805E_GOODS_VAN :Vano Beni +STR_805F_GRAIN_HOPPER :Vagone Grano +STR_8060_WOOD_TRUCK :Vagone Legna +STR_8061_IRON_ORE_HOPPER :Vagone Ferro +STR_8062_STEEL_TRUCK :Vagone Acciaio +STR_8063_ARMORED_VAN :Vagone Blindato +STR_8064_FOOD_VAN :Vano Alimentari +STR_8065_PAPER_TRUCK :Vagone Carta +STR_8066_COPPER_ORE_HOPPER :Vagone Rame +STR_8067_WATER_TANKER :Cisterna Acqua +STR_8068_FRUIT_TRUCK :Vagone Frutta +STR_8069_RUBBER_TRUCK :Vagone Gomma +STR_806A_SUGAR_TRUCK :Vagone Zucchero +STR_806B_COTTON_CANDY_HOPPER :Vagone Cotone Cand. +STR_806C_TOFFEE_HOPPER :Vano Toffee +STR_806D_BUBBLE_VAN :Vano Bolle +STR_806E_COLA_TANKER :Cisterna Cola +STR_806F_CANDY_VAN :Vano Dolciumi +STR_8070_TOY_VAN :Vano Giocattoli +STR_8071_BATTERY_TRUCK :Vagone Batterie +STR_8072_FIZZY_DRINK_TRUCK :Vagone Bibite Friz. +STR_8073_PLASTIC_TRUCK :Vagone Plastica +STR_8074_MPS_REGAL_BUS :Bus MPS Regal +STR_8075_HEREFORD_LEOPARD_BUS :Bus Hereford Leopard +STR_8076_FOSTER_BUS :Bus Foster +STR_8077_FOSTER_MKII_SUPERBUS :Superbus Foster MkII +STR_8078_PLODDYPHUT_MKI_BUS :Bus Ploddyphut MkI +STR_8079_PLODDYPHUT_MKII_BUS :Bus Ploddyphut MkII +STR_807A_PLODDYPHUT_MKIII_BUS :Bus Ploddyphut MkIII +STR_807B_BALOGH_COAL_TRUCK :Camion Carbone Balogh +STR_807C_UHL_COAL_TRUCK :Camion Carbone Uhl +STR_807D_DW_COAL_TRUCK :Camion Carbone DW +STR_807E_MPS_MAIL_TRUCK :Furgone Postale MPS +STR_807F_REYNARD_MAIL_TRUCK :Furgone Postale Reynard +STR_8080_PERRY_MAIL_TRUCK :Furgone Postale Perry +STR_8081_MIGHTYMOVER_MAIL_TRUCK :Furg. Postale MightyMover +STR_8082_POWERNAUGHT_MAIL_TRUCK :Furg. Postale Powernaught +STR_8083_WIZZOWOW_MAIL_TRUCK :Furgone Postale Wizzowow +STR_8084_WITCOMBE_OIL_TANKER :Autocisterna Witcombe +STR_8085_FOSTER_OIL_TANKER :Autocisterna Foster +STR_8086_PERRY_OIL_TANKER :Autocisterna Perry +STR_8087_TALBOTT_LIVESTOCK_VAN :Furgone Bestiame Talbott +STR_8088_UHL_LIVESTOCK_VAN :Furgone Bestiame Uhl +STR_8089_FOSTER_LIVESTOCK_VAN :Furgone Bestiame Foster +STR_808A_BALOGH_GOODS_TRUCK :Camion Beni Balogh +STR_808B_CRAIGHEAD_GOODS_TRUCK :Camion Beni Craighead +STR_808C_GOSS_GOODS_TRUCK :Camion Beni Goss +STR_808D_HEREFORD_GRAIN_TRUCK :Camion Grano Hereford +STR_808E_THOMAS_GRAIN_TRUCK :Camion Grano Thomas +STR_808F_GOSS_GRAIN_TRUCK :Camion Grano Goss +STR_8090_WITCOMBE_WOOD_TRUCK :Camion Legna Witcombe +STR_8091_FOSTER_WOOD_TRUCK :Camion Legna Foster +STR_8092_MORELAND_WOOD_TRUCK :Camion Legna Moreland +STR_8093_MPS_IRON_ORE_TRUCK :Camion Ferro MPS +STR_8094_UHL_IRON_ORE_TRUCK :Camion Ferro Uhl +STR_8095_CHIPPY_IRON_ORE_TRUCK :Camion Ferro Chippy +STR_8096_BALOGH_STEEL_TRUCK :Camion Acciaio Balogh +STR_8097_UHL_STEEL_TRUCK :Camion Acciaio Uhl +STR_8098_KELLING_STEEL_TRUCK :Camion Acciaio Kelling +STR_8099_BALOGH_ARMORED_TRUCK :Autoblindo Balogh +STR_809A_UHL_ARMORED_TRUCK :Autoblindo Uhl +STR_809B_FOSTER_ARMORED_TRUCK :Autoblindo Foster +STR_809C_FOSTER_FOOD_VAN :Furg. Alimentari Foster +STR_809D_PERRY_FOOD_VAN :Furg. Alimentari Perry +STR_809E_CHIPPY_FOOD_VAN :Furg. Alimentari Chippy +STR_809F_UHL_PAPER_TRUCK :Camion Carta Uhl +STR_80A0_BALOGH_PAPER_TRUCK :Camion Carta Balogh +STR_80A1_MPS_PAPER_TRUCK :Camion Carta MPS +STR_80A2_MPS_COPPER_ORE_TRUCK :Camion Rame MPS +STR_80A3_UHL_COPPER_ORE_TRUCK :Camion Rame Uhl +STR_80A4_GOSS_COPPER_ORE_TRUCK :Camion Rame Goss +STR_80A5_UHL_WATER_TANKER :Autobotte Uhl +STR_80A6_BALOGH_WATER_TANKER :Autobotte Balogh +STR_80A7_MPS_WATER_TANKER :Autobotte MPS +STR_80A8_BALOGH_FRUIT_TRUCK :Camion Frutta Balogh +STR_80A9_UHL_FRUIT_TRUCK :Camion Frutta Uhl +STR_80AA_KELLING_FRUIT_TRUCK :Camion Frutta Kelling +STR_80AB_BALOGH_RUBBER_TRUCK :Camion Gomma Balogh +STR_80AC_UHL_RUBBER_TRUCK :Camion Gomma Uhl +STR_80AD_RMT_RUBBER_TRUCK :Camion Gomma RMT +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :Camion Zucchero MightyMover +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Camion Zucchero Powernaught +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Camion Zucchero Wizzowow +STR_80B1_MIGHTYMOVER_COLA_TRUCK :Autobotte-Cola MightyMover +STR_80B2_POWERNAUGHT_COLA_TRUCK :Autobotte-Cola Powernaught +STR_80B3_WIZZOWOW_COLA_TRUCK :Autobotte-Cola Wizzowow +STR_80B4_MIGHTYMOVER_COTTON_CANDY :Camion Cotone Can. MightyMover +STR_80B5_POWERNAUGHT_COTTON_CANDY :Camion Cotone Can. Powernaught +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Camion Cotone Can. Wizzowow +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :Camion Toffee MightyMover +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Camion Toffee Powernaught +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Camion Toffee Wizzowow +STR_80BA_MIGHTYMOVER_TOY_VAN :Furgone Giocattoli MightyMover +STR_80BB_POWERNAUGHT_TOY_VAN :Furgone Giocattoli Powernaught +STR_80BC_WIZZOWOW_TOY_VAN :Furgone Giocattoli Wizzowow +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :Camion Dolci MightyMover +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Camion Dolci Powernaught +STR_80BF_WIZZOWOW_CANDY_TRUCK :Camion Dolci Wizzowow +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :Camion Batterie MightyMover +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Camion Batterie Powernaught +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Camion Batterie Wizzowow +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :Camion Bibite Friz.MightyMover +STR_80C4_POWERNAUGHT_FIZZY_DRINK :camion Bibite Friz.Powernaught +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Camion Bibite Friz.Wizzowow +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :Camion Plastica MightyMover +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Camion Plastica Powernaught +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Camion Plastica Wizzowow +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :Camion Bolle MightyMover +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Camion Bolle Powernaught +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Camion Bolle Wizzowow +STR_80CC_MPS_OIL_TANKER :Petroliera MPS +STR_80CD_CS_INC_OIL_TANKER :Petroliera CS-Inc. +STR_80CE_MPS_PASSENGER_FERRY :Traghetto FFP +STR_80CF_FFP_PASSENGER_FERRY :Traghetto FFP +STR_80D0_BAKEWELL_300_HOVERCRAFT :Hovercraft Bakewell 300 +STR_80D1_CHUGGER_CHUG_PASSENGER :Traghetto Chugger-Chug +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Traghetto Shivershake +STR_80D3_YATE_CARGO_SHIP :Nave Mercantile Yate +STR_80D4_BAKEWELL_CARGO_SHIP :Nave Mercantile Bakewell +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Nave Mercantile Mightymover +STR_80D6_POWERNAUT_CARGO_SHIP :Name Mercantile Powernaut +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Elicottero Tricario +STR_80FE_GURU_X2_HELICOPTER :Elicottero Guru X2 +STR_80FF_POWERNAUT_HELICOPTER :Elicottero Powernaut +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Messaggio dal fornitore del veicolo +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Abbiamo appena progettato un nuovo {STRING} - Le interessa un'anno di esclusiva sull'uso del veicolo? Così possiamo vedere come và prima di renderlo disponibile a tutti? +STR_8102_RAILROAD_LOCOMOTIVE :locomotiva +STR_8103_ROAD_VEHICLE :veicolo stradale +STR_8104_AIRCRAFT :aereo +STR_8105_SHIP :nave +STR_8106_MONORAIL_LOCOMOTIVE :locomotiva per monorotaia +STR_8107_MAGLEV_LOCOMOTIVE :locomotiva per maglev + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Deposito Treni +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}I cittadini festeggiano . . .{}Primo treno arrivato a {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Details) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Treno in mezzo +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Vai a {STATION} +STR_8807_GO_TO_UNLOAD :Vai a {STATION} (Scarica) +STR_8808_GO_TO_LOAD :Vai a {STATION} (Carica) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Vai non-stop a {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Vai non-stop a {STATION} (Scarica) +STR_880C_GO_NON_STOP_TO_LOAD :Vai non-stop a {STATION} (Carica) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Vai a {TOWN} Deposito Ferroviario +STR_SERVICE_AT_TRAIN_DEPOT :Manutenzione a {TOWN} Deposito Ferroviario +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Vai non-stop a {TOWN} Deposito Ferroviario +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Manutenzione non-stop a {TOWN} Deposito Ferroviario + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Direzione {TOWN} Deposito +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Direzione {TOWN} Deposito, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Vuoto +STR_8813_FROM :{LTBLUE}{CARGO} da {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Treno {COMMA16} stà aspettando nel deposito +STR_8815_NEW_VEHICLES :{BLACK}Nuovi Veicoli +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Costo: {GOLD}{CURRENCY}{BLACK} Peso: {GOLD}{COMMA16}t{}{BLACK}Velocità: {GOLD}{VELOCITY}{BLACK} Potenza: {GOLD}{COMMA16}cv{}{BLACK}Consumi: {GOLD}{CURRENCY}/anno{}{BLACK}Capienza: {GOLD}{STRING}{}{BLACK}Progettato nel: {GOLD}{NUMU16}{BLACK} Vita: {GOLD}{COMMA16} anni{}{BLACK}Max. Affidabilità: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informazioni +STR_8819_TRAIN_TOO_LONG :{WHITE}Treno troppo lungo +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Un treno può essere modificato solo quando è fermo nel deposito +STR_881B_TRAINS :{WHITE}{STRING} - Treni +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nuovo Veicolo Ferroviario +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nuovo Veicolo Per Monorotaia +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nuovo Veicolo Per Maglev +STR_881F_BUILD_VEHICLE :{BLACK}Costruisci Veicolo +STR_8820_RENAME :{BLACK}Rinomina +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Costo: {GOLD}{CURRENCY}{}{BLACK}Peso: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Capienza: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Salta +STR_8824_DELETE :{BLACK}Elimina +STR_8825_NON_STOP :{BLACK}Non-Stop +STR_8826_GO_TO :{BLACK}Vai a +STR_8827_FULL_LOAD :{BLACK}Carica +STR_8828_UNLOAD :{BLACK}Scarica +STR_8829_ORDERS :{WHITE}{STRING} (Orders) +STR_882A_END_OF_ORDERS :{SETX 10}- - Fine degli Ordini - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Manutenzione +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Non puoi costruire veicolo ferroviario... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Costr. nel: {LTBLUE}{NUMU16}{BLACK} Valore: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Valore: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Carica / Scarica +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Non puoi mandare treno al deposito... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Spazio per gli ordini terminato +STR_8832_TOO_MANY_ORDERS :{WHITE}Troppi ordini +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Non puoi inserire nuovo ordine... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Non puoi cancellare quest'ordine... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Non puoi modificare quest'ordine... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Devi costruire un deposito ferroviario prima +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Non puoi spostare il veicolo... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Non puoi vendere veicolo ferroviario... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Non riesce a trovare il deposito locale +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Non puoi far fermare/ripartire il treno... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Intervallo Manutenz.: {LTBLUE}{COMMA16}giorni{BLACK} Ultima Manut.: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Treni - fai clic sul treno per le informazioni +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Costruisci nuovi treni (Necessario deposito) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Treni - fai clic sul treno per le informazioni, trascina i veicoli per aggiungerli/rimuoverli dal treno +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Costruisci nuovo veicolo ferroviario +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Trascina veicolo qui per venderlo +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centra visuale sul deposito ferroviario +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Lista treni - fai clic sul veicolo per le informazioni +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Costruisci veicolo ferroviario evidenziato +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Rinomina tipo di veicolo +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Azione corrente del treno - Clicca qui per fermarlo/farlo partire +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Mostra ordini del treno +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centra visuale sul treno +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Manda treno al deposito +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Forza il treno a proseguire senza aspettare il segnale +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Inverti direzione del treno +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Mostra dettagli del treno +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Aumenta intervallo di manutenzione +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Riduci intervallo di manutenzione +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Mostra dettagli del carico trasportato +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Mostra dettagli di ogni veicolo +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Mostra capienza di ogni veicolo +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Mostra la capacità massima del treno per tipo di carico +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Lista ordini - fai clic sull'ordine per evidenziarlo +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Salta l'ordine corrente e inizia il successivo +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Elimina l'ordine evidenziato +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Fai diventare l'ordine evidenziato 'non-stop' +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Aggiungi un nuovo ordine prima di quello evidenziato o aggiungilo alla fine della lista +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Fai diventare l'ordine evidenziato 'forza il veicolo ad attendere il carico completo' +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Fai diventare l'ordine evidenziato 'forza il veicolo a scaricare' +STR_SERVICE_HINT :{BLACK}Ignora l’ordine finché non sia necessaria la manutenzione +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nuova {STRING} ora disponibile! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Costo: {CURRENCY} Peso: {COMMA16}t{}Velocità: {VELOCITY} Potenza: {COMMA16}hp{}Consumi: {CURRENCY}/anno{}Capienza: {STRING} +STR_885C_BROKEN_DOWN :{RED}Guasto! +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Età: {LTBLUE}{STRING}{BLACK} Consumi: {LTBLUE}{CURRENCY}/anno +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Peso: {LTBLUE}{COMMA16}t {BLACK}Potenza: {LTBLUE}{COMMA32}cv{BLACK} Velocità Max: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profitto quest'anno: {LTBLUE}{CURRENCY} (anno scorso: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Affidabilità: {LTBLUE}{COMMA8}% {BLACK}Guasti dall'ultima manutenzione: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Fermato +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Non puoi fargli passare i segnali al rischio di... +STR_8863_CRASHED :{RED}Distrutto! + +STR_8865_NAME_TRAIN :{WHITE}Nome Treno +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Non puoi rinominare il treno... +STR_8867_NAME_TRAIN :{BLACK}Nome Treno +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Treno schiantato!{}{COMMA16} morti in una palla di fuoco dopo la collisione +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Non puoi invertire la direzione del treno... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Rinomina il tipo di veicolo +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Non puoi rinominare tipo di veicolo... + +STR_TRAIN_STOPPING :{RED}In frenata +STR_TRAIN_STOPPING_VEL :{RED}In frenata, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Veicolo in mezzo +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Veicoli stradali +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Deposito Veicoli Stradali +STR_9004_NEW_VEHICLES :{BLACK}Nuovo Veicolo Stradale +STR_9005_INFORMATION :{BLACK}Informazioni +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nuovo Veicolo Stradale +STR_9007_BUILD_VEHICLE :{BLACK}Costruisci Veicolo +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Costo: {GOLD}{CURRENCY}{BLACK} Velocità: {GOLD}{VELOCITY}{}{BLACK}Consumi: {GOLD}{CURRENCY}/anno{}{BLACK}Capienza: {GOLD}{STRING}{}{BLACK}Progettato nel: {GOLD}{NUMU16}{BLACK} Vita: {GOLD}{COMMA16} anni{}{BLACK}Affidabilità Max: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Non puoi costruire veicolo... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Devi costruire un deposito prima +STR_900B_ORDERS :{WHITE}{STRING} (Ordini) +STR_900C_DETAILS :{WHITE}{STRING} (Dettagli) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Età: {LTBLUE}{STRING}{BLACK} Consumi: {LTBLUE}{CURRENCY}/anno +STR_900E_MAX_SPEED :{BLACK}Velocità Max: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profitto quest'anno: {LTBLUE}{CURRENCY} (anno scorso: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Affidabilità: {LTBLUE}{COMMA8}% {BLACK}Guasti dall'ultima manutenz.: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Costr. nel: {LTBLUE}{NUMU16}{BLACK} Valore: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Capienza: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...deve essere fermo nel deposito +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Non puoi vendere veicolo +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Non puoi far fermare/avviare veicolo... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Veicolo stradale {COMMA16} stà aspettando nel deposito +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Direzione {TOWN} Deposito +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Direzione {TOWN} Deposito, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Non puoi mandare il veicolo al deposito... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Non riesce a trovare il deposito locale +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Veicoli stradali - clicca sul veicolo per le informazioni +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Costruisci nuovi veicoli stradali (richiesto deposito veicoli stradali) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Azione corrente del veicolo - fai clic qui per far fermare/ripartire il veicolo +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Mostra ordini del veicolo +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centra visuale sul veicolo +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Manda veicolo al deposito +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Fai girare il veicolo +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Mostra dettagli del veicolo +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Veicoli - fai clic sul veicolo per le informazioni +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Costruisci nuovo veicolo stradale +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Trascina veicolo stradale qui per venderlo +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centra visuale sul deposito +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Lista veicoli - fai clic sul veicolo per le informazioni +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Costruisci veicolo stradale evidenziato +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Nuovo veicolo stradale disponibile! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Costo: {CURRENCY}{}Velocità: {VELOCITY}{}Consumi: {CURRENCY}/anno{}Capienza: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Nome Veicolo +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Non puoi rinominare automezzo... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Nome veicolo +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}I cittadini festeggiano . . .{}Primo bus arrivato a {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}I cittadini festeggiano. . .{}Primo camion arrivato a {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Veicolo distrutto!{}Il conducente muore in una palla di fuoco dopo la collisione +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Veicolo distrutto!{}{COMMA16} morti in una palla di fuoco dopo la collisione col treno +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Non puoi far girare il veicolo... +STR_9034_RENAME :{BLACK}Rinomina +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Rinomina tipo di veicolo +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Rinomina tipo di veicolo +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Non puoi rinominare tipo di veicolo... +STR_9038_GO_TO_ROADVEH_DEPOT :Vai a {TOWN} Deposito Veicoli +STR_SERVICE_AT_ROADVEH_DEPOT :Manutenzione a {TOWN} Deposito Stradale + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Costruzione moli +STR_9801_DOCK_CONSTRUCTION :{WHITE}Costruzione moli +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Non puoi costruire molo qui... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Deposito Navale +STR_9804_NEW_SHIPS :{BLACK}Nuove Navi +STR_9805_SHIPS :{WHITE}{STRING} - Navi +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Non puoi costruire nave... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Devi costruire un deposito prima +STR_9808_NEW_SHIPS :{WHITE}Nuove Navi +STR_9809_BUILD_SHIP :{BLACK}Costruisci Nave +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Costo: {GOLD}{CURRENCY}{BLACK} Velocità: {GOLD}{VELOCITY}{}{BLACK}Capienza: {GOLD}{STRING} {STRING}{}{BLACK}Consumi: {GOLD}{CURRENCY}/anno{}{BLACK}Progettata nel: {GOLD}{NUMU16}{BLACK} Vita: {GOLD}{COMMA16} anni{}{BLACK}Affidabilità Max: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}La nave deve essere ferma nel deposito +STR_980C_CAN_T_SELL_SHIP :{WHITE}Non puoi vendere la nave... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Non puoi costruire nave... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Nave in mezzo +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Ordini) +STR_9811_DETAILS :{WHITE}{STRING} (Dettagli) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Età: {LTBLUE}{STRING}{BLACK} Consumi: {LTBLUE}{CURRENCY}/anno +STR_9813_MAX_SPEED :{BLACK}Velocità Max: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profitto quest'anno: {LTBLUE}{CURRENCY} (anno scorso: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Affidabilità: {LTBLUE}{COMMA8}% {BLACK}Guasti dall'ultima manutenz.: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Costr. nel: {LTBLUE}{NUMU16}{BLACK} Valore: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Capienza: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Non puoi far fermare/ripartire la nave... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Non puoi mandare nave al deposito... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Non riesce a trovare il deposito locale +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Direzione {TOWN} Deposito +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Direzione {TOWN} Deposito, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Nave {COMMA16} stà aspettano nel deposito +STR_981D_BUILD_SHIP_DOCK :{BLACK}Costruisci molo +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Costruisci deposito navale (per costruzione e manutenzione) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Navi - fai clic sulla nave per le informazioni +STR_9820_BUILD_NEW_SHIP :{BLACK}Costruisci nuova nave +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Trascina nave qui per venderla +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centra visuale sul deposito +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Navi - fai clic sulla nave per le informazioni +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Costruisci nuove navi (richiede deposito navale) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Lista navi - fai clic sulla nave per le informazioni +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Costruisci la nave evidenziata +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Azione corrente della nave - fai clic qui per farla fermare/ripartire +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Mostra ordini della nave +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centra visuale sulla nave +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Manda nave al deposito +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Mostra dettagli sulla nave +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nuova nave disponibile! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Costo: {CURRENCY} Velocità Max: {VELOCITY}{}Capienza: {STRING}{}Consumi: {CURRENCY}/anno +STR_982F_NAME_SHIP :{BLACK}Nome Nave + +STR_9831_NAME_SHIP :{WHITE}Nome Nave +STR_9832_CAN_T_NAME_SHIP :{WHITE}Non puoi rinominare nave... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}˜I cittadini festeggiano . . .{}Prima nave arrivata a {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Posiziona boa, può essere usata come way point. +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Non puoi posizionare boa qui... +STR_9836_RENAME :{BLACK}Rinomina +STR_9837_RENAME_SHIP_TYPE :{BLACK}Rinomina tipo di nave +STR_9838_RENAME_SHIP_TYPE :{WHITE}Rinomina tipo di nave +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Non puoi rinominare tipo di nave... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Converti nave mercantile per caricare un tipo di merce diversa +STR_983B_REFIT :{WHITE}{STRING} (Converti) +STR_983C_REFIT_SHIP :{BLACK}Converti Nave +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Seleziona tipo di merce da caricare +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Converti la nave per trasportare tipo di merce evidenziata +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Seleziona tipo di merce da caricare:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nuova Capienza: {GOLD}{STRING}{}{BLACK}Costo conversione: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Non puoi convertire la nave... +STR_9842_REFITTABLE :(convertibile) +STR_GO_TO_SHIP_DEPOT :Vai a {TOWN} Deposito Navale +SERVICE_AT_SHIP_DEPOT :Manutenzione a {TOWN} Deposito Navale + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Costruz. areoportuali +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Non puoi costruire aeroporto qui... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Hangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nuovo Aereo +STR_A004_INFORMATION :{BLACK}Informazioni +STR_A005_NEW_AIRCRAFT :{WHITE}Nuovo Aereo +STR_A006_BUILD_AIRCRAFT :{BLACK}Construisci Aereo +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Costo: {GOLD}{CURRENCY}{BLACK} Velocità: {GOLD}{VELOCITY}{}{BLACK}Capienza: {GOLD}{COMMA16} passeggeri, {COMMA16} sacchi postali{}{BLACK}Consumi: {GOLD}{CURRENCY}/anno{}{BLACK}Progettato nel: {GOLD}{NUMU16}{BLACK} Vita: {GOLD}{COMMA16} Anni{}{BLACK}Affidabilità Max: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Non puoi costruire aereo +STR_A009_AIRCRAFT :{WHITE}{STRING} - Aereo +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Ordini) +STR_A00C_DETAILS :{WHITE}{STRING} (Dettagli) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Età: {LTBLUE}{STRING}{BLACK} Consumi: {LTBLUE}{CURRENCY}/anno +STR_A00E_MAX_SPEED :{BLACK}Velocità Max: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profitto quest'anno: {LTBLUE}{CURRENCY} (anno scorso: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Affidabilità: {LTBLUE}{COMMA8}% {BLACK}Guasti dall'ultima manutenz.: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Costr. nel: {LTBLUE}{NUMU16}{BLACK} Valore: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Non puoi mandare aereo nell'hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Direzione {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Direzione {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Aereo {COMMA16} sta aspettano nell'hangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Aereo in mezzo +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Non puoi far fermare/ripartire aereo... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Aereo in volo +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Costruisci aeroporto prima +STR_A019_CAPACITY :{BLACK}Capienza: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Capienza: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Dev'essere fermo nell'hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Non puoi vendere aereo... +STR_A01D_AIRPORT_CONSTRUCTION :Costruzioni areoportuali +STR_A01E_BUILD_AIRPORT :{BLACK}Costruisci aeroporto +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aereo - fai clic sull'aereo per le informazioni +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Costruisci nuovo aereo (richiesto aeroporto con hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Aereo - clicca sull'aereo per le informazioni +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Costruisci nuovo aereo +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Trascina qui l'aereo per venderlo +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centra visuale sull'hangar +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Lista aerei - fai clic sull'aereo per le informazioni +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Costruisci l'aereo evidenziato +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Azione corrente dell'aereo - fai clic qui per far fermare/ripartire l'aereo +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Mostra ordini dell'aereo +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centra visuale sull'aereo +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Manda aereo all'hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Mostra dettagli dell'aereo +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nuovo aereo disponibile! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Costo: {CURRENCY} Velocità Max: {VELOCITY}{}Capienza: {COMMA16} passeggeri, {COMMA16} sacchi postali{}Consumi: {CURRENCY}/anno + +STR_A030_NAME_AIRCRAFT :{WHITE}Nome aereo +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Non puoi dare un nome all'aereo... +STR_A032_NAME_AIRCRAFT :{BLACK}Nome aereo +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}I cittadini festeggiano . . .{}Primo aereo atterrato a {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Aereo precipitato!{}{COMMA16} morti in una palla di fuoco a {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinazioni: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Rinomina +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Rinomina tipo di aereo +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Rinomina tipo di aereo +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Non puoi rinominare tipo di aereo... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Converti aereo per trasportare un tipo di merce diversa +STR_A03C_REFIT :{WHITE}{STRING} (Converti) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Converti aereo +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Seleziona tipo di merce da caricare +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Converti aereo per trasportare tipo di merce evidenziata +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Seleziona il tipo di merce da caricare:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nuova capacità: {GOLD}{STRING}{}{BLACK}Costo conversione: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Non puoi convertire aereo... +STR_A043_REFITTABLE :(convertibile) +STR_GO_TO_AIRPORT_HANGAR :Vai a {STATION} Hangar +SERVICE_AT_AIRPORT_HANGAR :Manutenzione a {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Disastro Zeppelin a {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Veicolo distrutto in una collisione con un 'UFO' +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Raffineria esplosa vicino a {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabbrica distrutta in circostanze sospette vicino a {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' atterra vicino a {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Cedimento in una miniera di carbone lascia tracce di distruzione vicino a {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Il tentativo di corruzione è stato +STR_BRIBE_FAILED_2 :{WHITE}scoperto dagli ispettori regionali. + diff --git a/lang/norwegian.txt b/lang/norwegian.txt new file mode 100644 --- /dev/null +++ b/lang/norwegian.txt @@ -0,0 +1,2357 @@ +##name Norwegian +##ownname Norsk + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Utemfor kartet +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}For nært kanten av kartet +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Du har ikke nok penger - det behøves {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Flatt land behøves +STR_0008_WAITING :{BLACK}Venter: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (varer fra +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Aksepterer: {WHITE} +STR_000D_ACCEPTS :{BLACK}Aksepterer: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passasjerer +STR_0010_COAL :Kull +STR_0011_MAIL :Post +STR_0012_OIL :Olje +STR_0013_LIVESTOCK :Buskap +STR_0014_GOODS :Gods +STR_0015_GRAIN :Korn +STR_0016_WOOD :Tre +STR_0017_IRON_ORE :Jern malm +STR_0018_STEEL :Stål +STR_0019_VALUABLES :Verdi saker +STR_001A_COPPER_ORE :Kobber malm +STR_001B_MAIZE :Mais +STR_001C_FRUIT :Frukt +STR_001D_DIAMONDS :Diamanter +STR_001E_FOOD :Mat +STR_001F_PAPER :Papir +STR_0020_GOLD :Gull +STR_0021_WATER :Vann +STR_0022_WHEAT :Hvete +STR_0023_RUBBER :Gummi +STR_0024_SUGAR :Sukker +STR_0025_TOYS :Leketøy +STR_0026_CANDY :Søtsaker +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Spunnet sukker +STR_0029_BUBBLES :Bobler +STR_002A_TOFFEE :Karamell +STR_002B_BATTERIES :Batterier +STR_002C_PLASTIC :Plastikk +STR_002D_FIZZY_DRINKS :Mineralvann +STR_002E : +STR_002F_PASSENGER :Passasjerer +STR_0030_COAL :Kull +STR_0031_MAIL :Post +STR_0032_OIL :Olje +STR_0033_LIVESTOCK :Buskap +STR_0034_GOODS :Gods +STR_0035_GRAIN :Korn +STR_0036_WOOD :Ved +STR_0037_IRON_ORE :Jern malm +STR_0038_STEEL :Stål +STR_0039_VALUABLES :Verdi saker +STR_003A_COPPER_ORE :Kobber malm +STR_003B_MAIZE :Mais +STR_003C_FRUIT :Frukt +STR_003D_DIAMOND :Diamant +STR_003E_FOOD :Mat +STR_003F_PAPER :Papir +STR_0040_GOLD :Gull +STR_0041_WATER :Vann +STR_0042_WHEAT :Hvete +STR_0043_RUBBER :Gummi +STR_0044_SUGAR :Sukker +STR_0045_TOY :Leketøy +STR_0046_CANDY :Søtsaker +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Spunnet sukker +STR_0049_BUBBLE :Boble +STR_004A_TOFFEE :Karamell +STR_004B_BATTERY :Batteri +STR_004C_PLASTIC :Plastikk +STR_004D_FIZZY_DRINK :Mineralvann +STR_004E : +STR_004F_PASSENGER :{COMMA16} passasjer +STR_0050_TON_OF_COAL :{COMMA16} tonn kull +STR_0051_BAG_OF_MAIL :{COMMA16} postsekk +STR_0052_OF_OIL :{VOLUME} olje +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} enhet buskap +STR_0054_CRATE_OF_GOODS :{COMMA16} kasse gods +STR_0055_TON_OF_GRAIN :{COMMA16} tonn korn +STR_0056_TON_OF_WOOD :{COMMA16} tonn ved +STR_0057_TON_OF_IRON_ORE :{COMMA16} tonn jern malm +STR_0058_TON_OF_STEEL :{COMMA16} tonn stål +STR_0059_BAG_OF_VALUABLES :{COMMA16} sekk med verdisaker +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonn kobber malm +STR_005B_TON_OF_MAIZE :{COMMA16} tonn mais +STR_005C_TON_OF_FRUIT :{COMMA16} tonn frukt +STR_005D_BAG_OF_DIAMONDS :{COMMA16} sekk med diamanter +STR_005E_TON_OF_FOOD :{COMMA16} tonn mat +STR_005F_TON_OF_PAPER :{COMMA16} tonn papir +STR_0060_BAG_OF_GOLD :{COMMA16} sekk med gull +STR_0061_OF_WATER :{VOLUME} vann +STR_0062_TON_OF_WHEAT :{COMMA16} tonn hvete +STR_0063_OF_RUBBER :{VOLUME} gummi +STR_0064_TON_OF_SUGAR :{COMMA16} tonn sukker +STR_0065_TOY :{COMMA16} leketøy +STR_0066_BAG_OF_CANDY :{COMMA16} sekk med søtsaker +STR_0067_OF_COLA :{VOLUME} cola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonn spunnet sukker +STR_0069_BUBBLE :{COMMA16} boble +STR_006A_TON_OF_TOFFEE :{COMMA16} tonn karamell +STR_006B_BATTERY :{COMMA16} batteri +STR_006C_OF_PLASTIC :{VOLUME} plastikk +STR_006D_FIZZY_DRINK :{COMMA16} mineralvann +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passasjerer +STR_0070_TONS_OF_COAL :{COMMA16} tonn kull +STR_0071_BAGS_OF_MAIL :{COMMA16} postsekker +STR_0072_OF_OIL :{VOLUME} olje +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} enheter buskap +STR_0074_CRATES_OF_GOODS :{COMMA16} kasser gods +STR_0075_TONS_OF_GRAIN :{COMMA16} tonn korn +STR_0076_TONS_OF_WOOD :{COMMA16} tonn ved +STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonn jern malm +STR_0078_TONS_OF_STEEL :{COMMA16} tonn stål +STR_0079_BAGS_OF_VALUABLES :{COMMA16} sekker med verdisaker +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonn kobber malm +STR_007B_TONS_OF_MAIZE :{COMMA16} tonn mais +STR_007C_TONS_OF_FRUIT :{COMMA16} tonn frukt +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} sekker med diamanter +STR_007E_TONS_OF_FOOD :{COMMA16} tonn mat +STR_007F_TONS_OF_PAPER :{COMMA16} tonn papir +STR_0080_BAGS_OF_GOLD :{COMMA16} sekker gull +STR_0081_OF_WATER :{VOLUME} vann +STR_0082_TONS_OF_WHEAT :{COMMA16} tonn hvete +STR_0083_OF_RUBBER :{VOLUME} gummi +STR_0084_TONS_OF_SUGAR :{COMMA16} tonn sukker +STR_0085_TOYS :{COMMA16} leketøy +STR_0086_BAGS_OF_CANDY :{COMMA16} sekker søtsaker +STR_0087_OF_COLA :{VOLUME} cola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonn spunnet sukker +STR_0089_BUBBLES :{COMMA16} bobler +STR_008A_TONS_OF_TOFFEE :{COMMA16} tonn karameller +STR_008B_BATTERIES :{COMMA16} batteri +STR_008C_OF_PLASTIC :{VOLUME} plastikk +STR_008D_FIZZY_DRINKS :{COMMA16} mineralvann +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}KL +STR_0091_ML :{TINYFONT}PT +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}BS +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}KN +STR_0096_WD :{TINYFONT}VD +STR_0097_OR :{TINYFONT}JM +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VS +STR_009A_CO :{TINYFONT}KM +STR_009B_MZ :{TINYFONT}MS +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}MT +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GL +STR_00A1_WR :{TINYFONT}VN +STR_00A2_WH :{TINYFONT}HV +STR_00A3_RB :{TINYFONT}GM +STR_00A4_SG :{TINYFONT}SK +STR_00A5_TY :{TINYFONT}LT +STR_00A6_SW :{TINYFONT}SS +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}SP +STR_00A9_BU :{TINYFONT}BO +STR_00AA_TF :{TINYFONT}KM +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}MV +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Kart - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Spill innstillinger +STR_00B2_MESSAGE :{YELLOW}Melding +STR_00B3_MESSAGE_FROM :{YELLOW}Melding fra {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Kan ikke gjøre det.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kan ikke rydde området.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Opprinnelig copyright {COPYRIGHT} 1995 Chris Sawyer, Alle rettigheter reservert +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD versjon {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Opprinnelig designet av Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafikk laget av Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Avslutte +STR_00C8_YES :{BLACK}Ja +STR_00C9_NO :{BLACK}Nei +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil avslutte og returnere til {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Ingenting +STR_00D1_DARK_BLUE :Mørk blå +STR_00D2_PALE_GREEN :Lys grønn +STR_00D3_PINK :Rosa +STR_00D4_YELLOW :Gul +STR_00D5_RED :Rød +STR_00D6_LIGHT_BLUE :Lys blå +STR_00D7_GREEN :Grønn +STR_00D8_DARK_GREEN :Mørk grønn +STR_00D9_BLUE :Blå +STR_00DA_CREAM :Fløte +STR_00DB_MAUVE :Lilla +STR_00DC_PURPLE :Purpur +STR_00DD_ORANGE :Oransje +STR_00DE_BROWN :Brun +STR_00DF_GREY :Grå +STR_00E0_WHITE :Hvit +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}For mange kjøretøy i spillet +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Sted +STR_00E5_CONTOURS :Konturer +STR_00E6_VEHICLES :Kjøretøyer +STR_00E7_INDUSTRIES :Industrier +STR_00E8_ROUTES :Ruter +STR_00E9_VEGETATION :Vegetasjon +STR_00EA_OWNERS :Eiere +STR_00EB_ROADS :{BLACK}{TINYFONT}Veier +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Jernbaner +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stasjoner/Flyplasser/Havner +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Byggninger/Industribygg +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Kjøretøy +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Tog +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Veigående kjøretøy +STR_00F7_SHIPS :{BLACK}{TINYFONT}Skip +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Fly +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transport ruter +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kull gruve +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Kraftstasjon +STR_00FC_FOREST :{BLACK}{TINYFONT}Skog +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Sagbruk +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Oljeraffineri +STR_00FF_FARM :{BLACK}{TINYFONT}Gård +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabrikk +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Trykkeri +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Olje brønn +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Jern gruve +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Smelteverk +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Papirfabrikk +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Gull gruve +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Matforedlingsfabrikk +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamant gruve +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kobber gruve +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Frukt plantasje +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Gummi plantasje +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vannreservoar +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vanntårn +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Sagbruk +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Spunnet sukker skog +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Søtsak fabrikk +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batteri gård +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Cola brønner +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Leketøysbutikk +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Leketøysfabrikk +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastikk fontener +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Mineralvann fabrikk +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Boble generator +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamellbrudd +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Sukker gruve +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Jernbanestasjon +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Laste terminal +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Bussstasjon +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Flyplass/Heliport +STR_011F_DOCK :{BLACK}{TINYFONT}Havn +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Utmark +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Gress +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Bart land +STR_0123_FIELDS :{BLACK}{TINYFONT}Jorder +STR_0124_TREES :{BLACK}{TINYFONT}Trær +STR_0125_ROCKS :{BLACK}{TINYFONT}Steiner +STR_0126_WATER :{BLACK}{TINYFONT}Vann +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Ingen eier +STR_0128_TOWNS :{BLACK}{TINYFONT}Byer +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrier +STR_012A_DESERT :{BLACK}{TINYFONT}Ørken +STR_012B_SNOW :{BLACK}{TINYFONT}Snø +STR_012C_MESSAGE :{WHITE}Melding +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Avbryt +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Bytt navn +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}For mange navn definert +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Navnet er allerede i bruk + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (miles) +STR_013A_METRIC_KILOMETERS :Metrisk (kilometer) +STR_013B_OWNED_BY :{WHITE}...eies av {STRING} +STR_013C_CARGO :{BLACK}Varer +STR_013D_INFORMATION :{BLACK}Informasjon +STR_013E_CAPACITIES :{BLACK}Kapasitet +STR_013E_TOTAL_CARGO :{BLACK}Total last +STR_013F_CAPACITY :{BLACK}Kapasitet: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Total kapasitet på dette toget: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nytt spill +STR_0141_LOAD_GAME :{BLACK}Last inn spill +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demonstration +STR_0143_1_PLAYER :{BLACK}1 Spiller +STR_0144_2_PLAYERS :{BLACK}2 Spillere + +STR_0148_GAME_OPTIONS :{BLACK}Spill innstillinger + +STR_0150_SOMEONE :noen{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Verdenskart +STR_0152_TOWN_DIRECTORY :By oversikt +STR_0153_SUBSIDIES :Subsidier + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Graf over overskudd +STR_0155_INCOME_GRAPH :Graf over inntekter +STR_0156_DELIVERED_CARGO_GRAPH :Graf over leverte varer +STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf over prestasjonhistorikk +STR_0158_COMPANY_VALUE_GRAPH :Graf over firmaverdi +STR_0159_CARGO_PAYMENT_RATES :Fraktfortjeneste +STR_015A_COMPANY_LEAGUE_TABLE :Tabell over ledende firma +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Lagre spill +STR_015D_LOAD_GAME :Laste inn spill +STR_015E_QUIT_GAME :Avslutte gjeldende spill +STR_015F_QUIT :Avslutte openTTD +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil avslutte dette spillet ? +STR_0161_QUIT_GAME :{WHITE}Avslutt spill + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :Mai +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Okt +STR_016C_NOV :Nov +STR_016D_DEC :Des +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pause spillet +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Lagre spill, avbryt spillet, avslutte +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over firmaets stasjoner +STR_0174_DISPLAY_MAP :{BLACK}Vis kart +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Vis kart og by oversikt +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Vis by oversikt +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Vis firmaet sin økonomiske information +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Vis firmaet sin generelle information +STR_0179_DISPLAY_GRAPHS :{BLACK}Vis grafer +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Vis firma rangering +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over firmaets tog +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over firmaets biler +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over firmaets båter +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Vis liste over firmaets fly +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Zoom inn +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Zoom ut +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Bygg jernbane spor +STR_0182_BUILD_ROADS :{BLACK}Bygg vei +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Bygg havner +STR_0184_BUILD_AIRPORTS :{BLACK}Bygg flyplasser +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plant trær, plasser skilt, etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Informasjon om område +STR_0187_OPTIONS :{BLACK}Innstillinger +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Kan ikke endre service intervall +STR_018B_CLOSE_WINDOW :{BLACK}Lukk vindu +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Vindu tittel - dra her for å flytte vindu +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Riv bygninger o.l. +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Senk et hjørne av et landstykke +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Hev et hjørne av et landstykke +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scroll bar - scroller listen opp/ned +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Vis land konturer på kartet +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Vis kjøretøy på kartet +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Vis industri på kartet +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Vis transport ruter på kartet +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Vis vegetasjon på kartet +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Vis land eiere på kartet +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Skru by navn av/på på kartet +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Overskudd i år: {CURRENCY} (sist år: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} år ({COMMA16}) +STR_019A_YEARS :{COMMA16} år ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} år ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Kjøretøy +STR_019D_AIRCRAFT :Fly +STR_019E_SHIP :Skip +STR_019F_TRAIN :Tog +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} er gammel +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} er veldig gammel +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} er stein gammel og må byttes ut +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Land område informasjon +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Pris for å rydde området: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Pris for å rydde området: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Eier: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Kommune: {LTBLUE}{STRING} +STR_01A9_NONE :Ingen +STR_01AA_NAME :{BLACK}Navn +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1. +STR_01AD_2ND :2. +STR_01AE_3RD :3. +STR_01AF_4TH :4. +STR_01B0_5TH :5. +STR_01B1_6TH :6. +STR_01B2_7TH :7. +STR_01B3_8TH :8. +STR_01B4_9TH :9. +STR_01B5_10TH :10. +STR_01B6_11TH :11. +STR_01B7_12TH :12. +STR_01B8_13TH :13. +STR_01B9_14TH :14. +STR_01BA_15TH :15. +STR_01BB_16TH :16. +STR_01BC_17TH :17. +STR_01BD_18TH :18. +STR_01BE_19TH :19. +STR_01BF_20TH :20. +STR_01C0_21ST :21. +STR_01C1_22ND :22. +STR_01C2_23RD :23. +STR_01C3_24TH :24. +STR_01C4_25TH :25. +STR_01C5_26TH :26. +STR_01C6_27TH :27. +STR_01C7_28TH :28. +STR_01C8_29TH :29. +STR_01C9_30TH :30. +STR_01CA_31ST :31. +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Veksle mellom stor og lite kart +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Velg veiledning/demonstrasjon + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Akseptert gods: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Akseptert gods: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Akseptert gods: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Lyd/Musikk +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Vis Lyd/Musikk innstillinger +STR_01D5_ALL :{TINYFONT}Alle +STR_01D6_OLD_STYLE :{TINYFONT}Old Style +STR_01D7_NEW_STYLE :{TINYFONT}New Style +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Egendefinert 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Egendefinert 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Musikk Volum +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Effekt Volum +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Spill forrige spor +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Spill neste spor +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Slutte og spille musikk +STR_01E1_START_PLAYING_MUSIC :{BLACK}Starte og spille musikk +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Dra for å endre volum på musikk og lyd effekter +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Spor{SETX 88}Tittel +STR_01E9_SHUFFLE :{TINYFONT}Tilfeldig +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Musikkprogram +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Spor register +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Tøm +STR_01F1_SAVE :{TINYFONT}{BLACK}Lagre +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Gjeldene program med musikk spor +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Velg alle spor +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Velg 'old style music' program +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Velg 'new style music' program +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Velg 'Egendefinert 1' (brukerdefinert) program +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Velg 'Egendefinert 2' (brukerdefinert) program +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Slett gjeldende program (Gjelder bare Egendefinert 1 og 2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Lagre musikk instillinger +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klikk på musikk spor for å legge til gjeldene program (Gjelder bare egendefinert 1 og 2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Skru tilfeldig program av/på +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Vis musikk spor meny +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Trykk for å sentere bildet rundt industri/by +STR_01FE_DIFFICULTY :{BLACK}Vanskelighetsgrad ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Siste melding/nyhet +STR_0201_MESSAGE_SETTINGS :Meldings innstillinger +STR_MESSAGE_HISTORY_MENU :Tidligere meldinger +STR_0202_SEND_MESSAGE :Send melding +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Vis siste melding/nyhet, vis meldingsinnstillinger +STR_0204_MESSAGE_OPTIONS :{WHITE}Meldingsinnstillinger +STR_0205_MESSAGE_TYPES :{BLACK}Meldingstyper:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankommst av første kjøretøy på spiller sin stasjon +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankommst av første kjøretøy på motstander sin stasjon +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Ulykker / Katastrofer +STR_0209_COMPANY_INFORMATION :{YELLOW}Firma informasjon +STR_020A_ECONOMY_CHANGES :{YELLOW}Økonomiske endringer +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Råd / informasjon om spiller sine kjøretøy +STR_020C_NEW_VEHICLES :{YELLOW}Nye kjøretøy +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Endringer i godtatt last +STR_020E_SUBSIDIES :{YELLOW}Subsidier +STR_020F_GENERAL_INFORMATION :{YELLOW}Generell informasjon +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...for langt i fra forrige destinasjon +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Beste firma som kom til 2050{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Forretningsmann +STR_0214_ENTREPRENEUR :Entreprenør +STR_0215_INDUSTRIALIST :Industrialist +STR_0216_CAPITALIST :Kapitalist +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Århundrets finansfyrste +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} oppnår '{STRING}' status! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} av {STRING} oppnår '{STRING}' status! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Lag scenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Scenario redigerer +STR_0223_LAND_GENERATION :{WHITE}Land generering +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Tilfeldig landforming +STR_0227_RESET_LAND :{BLACK}Tilbakestill land +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Øk størrelse av land areal til å heve/senke +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Minsk størrelse av land areal til å heve/senke +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Generer land tilfeldig +STR_022B_RESET_LANDSCAPE :{BLACK}Tilbakestill landskap +STR_022C_RESET_LANDSCAPE :{WHITE}Tilbakestill landskap +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Er du sikkert på du vil tilbakestille landskapet? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Landskap generering +STR_022F_TOWN_GENERATION :{BLACK}By generering +STR_0230_INDUSTRY_GENERATION :{BLACK}Industri generering +STR_0231_ROAD_CONSTRUCTION :{BLACK}Vei bygging +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetasjon og andre objekter +STR_0233_TOWN_GENERATION :{WHITE}By generering +STR_0234_NEW_TOWN :{BLACK}Ny by +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Grunnlegg en ny by +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Kan ikke grunnlegge by her... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...for nært kanten av kartet +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...for nært en annen by +STR_0239_SITE_UNSUITABLE :{WHITE}...området er usikket +STR_023A_TOO_MANY_TOWNS :{WHITE}...for mange byer +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Øk by størrelse +STR_023C_EXPAND :{BLACK}Utvid +STR_023D_RANDOM_TOWN :{BLACK}Lag tilfeldig by +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Grunnlegg by et tilfeldig sted +STR_023F_INDUSTRY_GENERATION :{WHITE}Industri generering +STR_0240_COAL_MINE :{BLACK}Kullgruve +STR_0241_POWER_STATION :{BLACK}Kraftstasjon +STR_0242_SAWMILL :{BLACK}Sagbruk +STR_0243_FOREST :{BLACK}Skog +STR_0244_OIL_REFINERY :{BLACK}Olje raffineri +STR_0245_OIL_RIG :{BLACK}Oljeplatform +STR_0246_FACTORY :{BLACK}Fabrikk +STR_0247_STEEL_MILL :{BLACK}Smelteverk +STR_0248_FARM :{BLACK}Gård +STR_0249_IRON_ORE_MINE :{BLACK}Jern gruve +STR_024A_OIL_WELLS :{BLACK}Oljebrønner +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Papirfabrikk +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Matforedlingsfabrikk +STR_024E_PRINTING_WORKS :{BLACK}Trykkeri +STR_024F_GOLD_MINE :{BLACK}Gullgruve +STR_0250_LUMBER_MILL :{BLACK}Sagbruk +STR_0251_FRUIT_PLANTATION :{BLACK}Frukt plantasje +STR_0252_RUBBER_PLANTATION :{BLACK}Gummi plantasje +STR_0253_WATER_SUPPLY :{BLACK}Vannreservoar +STR_0254_WATER_TOWER :{BLACK}Vanntårn +STR_0255_DIAMOND_MINE :{BLACK}Diamantgruve +STR_0256_COPPER_ORE_MINE :{BLACK}Kobbergruve +STR_0257_COTTON_CANDY_FOREST :{BLACK}Spunnet sukker skog +STR_0258_CANDY_FACTORY :{BLACK}Søtsakfabrikk +STR_0259_BATTERY_FARM :{BLACK}Batteri gård +STR_025A_COLA_WELLS :{BLACK}Cola brønner +STR_025B_TOY_SHOP :{BLACK}Leketøysbutikk +STR_025C_TOY_FACTORY :{BLACK}Leketøysfabrikk +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastikk fontener +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Mineralvannfabrikk +STR_025F_BUBBLE_GENERATOR :{BLACK}Boble generator +STR_0260_TOFFEE_QUARRY :{BLACK}Karamell brudd +STR_0261_SUGAR_MINE :{BLACK}Sukkergruve +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Bygg kullgruve +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Bygg kraftstasjon +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Bygg sagbruk +STR_0265_PLANT_FOREST :{BLACK}Plant skog +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Bygg oljeraffineri +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Bygg oljeplatform (Kan bare bygges nær kanten av kartet) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Bygg fabrikk +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Bygg smelteverk +STR_026A_CONSTRUCT_FARM :{BLACK}Bygg gård +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Bygg jerngruve +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Bygg oljebrønn +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bygg bank (Kan bare bygges i byer med flere enn 1200 innbyggere) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Bygg papir fabrikk +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Bygg matforedlingsfabrikk +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Bygg trykkeri +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Bygg gullgruve +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bygg bank (Kan bare bygges i byer) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Bygg sagbruk (fjerner reinskog og produserer tre) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plant frukt plantasje +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plant gummi plantasje +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Bygg vannreservoar +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Bygg vanntårn (Kan bare bygges i byer) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Bygg diamantgruve +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Bygg kobbergruve +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plant spunnet sukker skog +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Bygg søtsakfabrikk +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Bygg batterigård +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Bygg cola brønn +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Bygg leketøysbutikk +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Bygg leketøysfabrikk +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Bygg plastikk fontener +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Bygg mineralvannfabrikk +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Bygg boble generator +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Bygg karamell brudd +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Bygg sukkergruve +STR_0285_CAN_T_BUILD_HERE :{WHITE}Kan ikke bygge {STRING} here... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...må bygge en by først +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...bare en er tillatt per by +STR_0288_PLANT_TREES :{BLACK}Plant trær +STR_0289_PLACE_SIGN :{BLACK}Plassere skilt +STR_028A_RANDOM_TREES :{BLACK}Plant trær tilfeldig +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Plasser trær tilfeldig i landskapet +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Plasser steinete området i landskapet +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Plasser fyrlykt +STR_028E_PLACE_TRANSMITTER :{BLACK}Plasser radiosender +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definere ørken +STR_0290_DELETE :{BLACK}Slett +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Slett denne byen fullstendig +STR_0292_SAVE_SCENARIO :Lagre scenario +STR_0293_LOAD_SCENARIO :Last inn scenario +STR_0294_QUIT_EDITOR :Avslutt redigeringsprogram +STR_0295 : +STR_0296_QUIT :Avslutt openTTD +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Lagre scenario, laste inn scenario, forlate scenario redigeringsprogrammet, avslutte +STR_0298_LOAD_SCENARIO :{WHITE}Last inn scenario +STR_0299_SAVE_SCENARIO :{WHITE}Lagre scenario +STR_029A_PLAY_SCENARIO :{BLACK}Spill scenario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Er du sikker på du vil forlate dette scenarioet ? +STR_029C_QUIT_EDITOR :{WHITE}Avslutt redigeringsprogrammet +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bare bygges i byer med mer en 1200 innbyggere +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Flytt startdatoen tilbake ett år +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Flytt startdatoen frem ett år +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...broen sine ender må være på land +STR_02A1_SMALL :{BLACK}Liten +STR_02A2_MEDIUM :{BLACK}Middels +STR_02A3_LARGE :{BLACK}Stor +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Velg by størrelse +STR_02A5_TOWN_SIZE :{YELLOW}By størrelse: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Vis siste melding eller nyhetsrapport +STR_02B8_SUMMARY :{BLACK}Sammendrag +STR_02B9_FULL :{BLACK}Fullt +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :By oversikt +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Kjøretøy navn +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Standard +STR_02BF_CUSTOM :Egendefinert +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Lagre egendefinerte navn +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Velg kjøretøy navn +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Lagre egendefinerte kjøretøy navn + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Spill innstillinger +STR_02C4_GAME_OPTIONS :Spill innstillinger +STR_02C5_DIFFICULTY_SETTINGS :Vanskelighetsgrad +STR_02C6_DIFFICULTY_SETTINGS :Vanskelighetsgrad +STR_02C7_CONFIG_PATCHES :Konfigurer andre valg +STR_02C8_CONFIG_PATCHES :Konfigurer andre valg +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Vis bynavn +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Vis bynavn +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Vis stasjonsnavn +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Vis stasjonsnavn +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Vis skilt +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Vis skilt +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Vis kontrollpunkt +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Vis kontrollpunkt +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Fullstending animasjon +STR_02D0_FULL_ANIMATION :{SETX 12}Fullstending animasjon +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Maksimalt med detaljer +STR_02D2_FULL_DETAIL :{SETX 12}Maksimalt med detaljer +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Gjennomsiktige bygninger +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Gjennomsiktige bygninger +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Informasjon om tomt. +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Skjermdump (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Stor skjermdump (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Om 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}På +STR_02DB_OFF :{BLACK}Av +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Vis subsidier +STR_02DD_SUBSIDIES :Subsidier +STR_02DE_MAP_OF_WORLD :Verdenskart +STR_02DF_TOWN_DIRECTORY :By oversikt +STR_02E0_CURRENCY_UNITS :{BLACK}Valuta enhet +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Velg valuta enhet +STR_02E3_DISTANCE_UNITS :{BLACK}Enhet for avstand +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Velg enhet for avstand +STR_02E6_ROAD_VEHICLES :{BLACK}Veigående kjøretøy +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Velg kjøreretning +STR_02E9_DRIVE_ON_LEFT :Kjør på venstre +STR_02EA_DRIVE_ON_RIGHT :Kjør på høyre +STR_02EB_TOWN_NAMES :{BLACK}By navn +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Velg bynavn type + +STR_02F4_AUTOSAVE :{BLACK}Automatisk lagring +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Velg intervall for automatisk lagring +STR_02F7_OFF :Av +STR_02F8_EVERY_3_MONTHS :Hver 3. måned +STR_02F9_EVERY_6_MONTHS :Hver 6. måned +STR_02FA_EVERY_12_MONTHS :Hver 12. måned +STR_02FB_START_A_NEW_GAME :{BLACK}Start nytt spill +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Last inn et lagret spill +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Se demontrasjoner/veiledninger +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Spesial lag en spill verden eller et scenario +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Velg en spiller-modus +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Velg to spiller-modus +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Vis spillinnstillinger +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Vis vanskelighetsgrad +STR_0303_START_A_NEW_GAME_USING :{BLACK}Start et nytt spill som bruker et scenario +STR_0304_QUIT :{BLACK}Avslutt +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Forlat 'OpenTTD', og avslutt +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Se demonstrasjon/veiledning +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bare bygges i byer +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Velg temperert miljø +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Velg sub-artisk miljø +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Velg sub-tropisk miljø +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Velg leketøysland miljø +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Finansier byggingen av ny industri + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Finansier ny industri +STR_INDUSTRY_DIR :Industri oversikt +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Finansier ny industri +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bare bygges i byer +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...kan bare bygges i regnskog områder +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kan bare bygges i ørken områder +STR_0319_PAUSED :{YELLOW}* * PAUSE * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Skjærmdumpen ble lagret som '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Skjærmdump feilet! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Kjøp land for fremtidig bruk +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Kjøretøy service +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Jernbane service +STR_032C_3_AIR_SERVICE :{BLACK}3: Fly service +STR_032D_4_SHIP_SERVICE :{BLACK}4: Skip service +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Jernbane service (avansert) +STR_032F_AUTOSAVE :{RED}AUTOLAGRING +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Velg 'Ezy style music' program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Engelsk +STR_TOWNNAME_FRENCH :Fransk +STR_TOWNNAME_GERMAN :Tysk +STR_TOWNNAME_AMERICAN :Amerikansk +STR_TOWNNAME_LATIN_AMERICAN :Latin-Amerikansk +STR_TOWNNAME_SILLY :Tåpelige +STR_TOWNNAME_SWEDISH :Svensk +STR_TOWNNAME_DUTCH :Nederlandsk +STR_TOWNNAME_FINNISH :Finsk +STR_TOWNNAME_POLISH :Polsk +STR_TOWNNAME_SLOVAKISH :Slovak +STR_TOWNNAME_HUNGARIAN :Ungarsk +STR_TOWNNAME_AUSTRIAN :Østerriksk +############ end of townname region + +STR_CURR_POUNDS :Pund ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollar ($) +STR_CURR_FF :Franc (FF) +STR_CURR_DM :Tyskemark (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Pesetas (Pt) +STR_CURR_FT :Ungarsk Forint (Ft) +STR_CURR_ZL :Poliske Zloty (zl) +STR_CURR_ATS :Østeriske Shilling (ATS) +STR_CURR_BEF :Belgiske Franc (BEF) +STR_CURR_DKK :Dansk Krone (DKK) +STR_CURR_FIM :Finske Markka (FIM) +STR_CURR_GRD :Greske Drachma (GRD) +STR_CURR_CHF :Sveitsiske Franc (CHF) +STR_CURR_NLG :Hollandske Guilder (NLG) +STR_CURR_ITL :Italienske Lira (ITL) +STR_CURR_SEK :Svenske Krona (SEK) +STR_CURR_RUR :Russiske Rubel (rur) +STR_CURR_CZK :Tsjekkisk Koruna (CZK) +STR_CURR_ISK :Islandsk Krona (ISK) +STR_CURR_NOK :Norsk Krone (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Språk +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Velg språk som skal brukes + +STR_OPTIONS_RES :{BLACK}Skjerm oppløsning +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Velg skjerm oppløsningen som skal brukes + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Skjermdump format +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Velg hvilket skjermdump format som skal brukes + +STR_AUTOSAVE_1_MONTH :Hver måned +STR_AUTOSAVE_FAILED :{WHITE}Autolagring feilet + +STR_MONTH_JAN :Januar +STR_MONTH_FEB :Februar +STR_MONTH_MAR :Mars +STR_MONTH_APR :April +STR_MONTH_MAY :Mai +STR_MONTH_JUN :Juni +STR_MONTH_JUL :Juli +STR_MONTH_AUG :August +STR_MONTH_SEP :September +STR_MONTH_OCT :Oktober +STR_MONTH_NOV :November +STR_MONTH_DEC :Desember + +STR_HEADING_FOR_STATION :{LTBLUE}Er på vei mot {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Er på vei mot {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Ingen ordre +STR_NO_ORDERS_VEL :{LTBLUE}Ingen ordre, {VELOCITY} + +STR_PASSENGERS :passasjerer +STR_BAGS :bagger +STR_TONS :tonn +STR_LITERS :liter +STR_ITEMS :objekter +STR_CRATES :kasser +STR_RES_OTHER :annet +STR_NOTHING :ingenting + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Kan ikke dele ordre liste... +STR_CANT_COPY_ORDER_LIST :{WHITE}Kan ikke kopiere ordre liste... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Slutt på delte ordre - - + +STR_TRAIN_IS_LOST :{WHITE}Tog {COMMA16} har kjørt seg vill. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Tog {COMMA16} sitt overskudd sist år var {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Andre innstillinger +STR_CONFIG_PATCHES_TIP :{BLACK}Endre andre innstillinger +STR_CONFIG_PATCHES_CAPTION :{WHITE}Andre instillinger + +STR_CONFIG_PATCHES_OFF :Av +STR_CONFIG_PATCHES_ON :På +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Vis kjøretøyet sin hastighet på statuslinja: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Tillate bygging på skråninger og i vannkanten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Tillate riving av industri, mer vei, etc: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Tillate bygging av veldig lange tog : {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Realistisk tog akslerasjon: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Slå sammen stasjoner som blir bygget på siden av hverandre: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Forlat stasjonen når en type varevogn er full, hvis 'full last' er på: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Ingen automatisk tog service: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Lever varer til en stasjon bare når varen trengs: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Tillate bygging av veldig lange broer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Tillate gå til jernbanestall order: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Tillate bygging av råmaterial produserende anlegg: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Tillate flere like industrier i samme byen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Industrier av samme type kan bygges nær hverandre: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Alltid vis lang dato på statuslinja: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Vis jerbane signal lyker på samme side som kjøreretningen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Vis budsjett ved nyttår: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch kompatibel nonstop håndtering: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Kjøretøyskø (med kvantumseffekter): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Flytt på bildet vis pilen er nær ytterkantene i det vannrette planet: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Tillate bestikkelser av kommunestyret: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Ny togstall lokalisering: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Ikke ensartet stasjoner: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Ny algoritme for togs kjørerute: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Tillate bygging i pause modus: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Alltid tillate bygging av små flyplasser: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Et tog har kjørt seg vil vist de ikke har kommet lengre på ordrelisten etter:{ORANGE}{STRING} dager +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Advar hvis et tog går med større underskudd enn: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Bytt automatisk ut kjøretøy, når det blir gammelt: +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Varighet til feilmelding: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Snø høyde: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maks statsjon spredning: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Utfør service på helikopter automatisk på helikopterlandingsteder: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maks antall tog per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maks antall kjøretøy per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maks antall fly per spiller: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maks antall skip per spiller: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Hindre datamaskinen i å bygge tog: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Hindre datamaskinen i å bygge kjøretøy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Hindre datamaskinen i å bygge fly: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Hindre datamaskinen i å bygge skip: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Standard service intervall for tog: {ORANGE}{STRING} dager +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Standard service intervall for kjøretøy: {ORANGE}{STRING} dager +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Standard service intervall for fly: {ORANGE}{STRING} dager +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Standard service intervall for båter: {ORANGE}{STRING} dager + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Farge i avisen kommer i: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Start dato: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Jevn økonomi (Flere, mindre endringer) + +STR_CONFIG_PATCHES_GUI :{BLACK}Grensesnitt +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstruksjon +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Kjøretøy +STR_CONFIG_PATCHES_STATIONS :{BLACK}Statsjoner +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Økonomi + +STR_CONFIG_PATCHES_DISABLED :Slått av +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Endre innstillingsverdi + + +STR_CHEATS :{WHITE}Juks +STR_CHEATS_TIP :{BLACK}Avkryssningsbokser indikerer at du har brukt denne juksekoden tidligere. +STR_CHEATS_WARNING :{BLACK}Advarsel! Vær klar over at du er i ferd med å bedra dine motstandere og at straffen for slike handlinger er å brenne i helvete etter din død. +STR_CHEAT_MONEY :{LTBLUE}Øk pengebeholdningen med {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Spiller som spiller: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magisk bulldoser (fjern industrier, ufjernbare ting): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tuneller kan krysse hverandre: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Navn +STR_TOWNDIR_POPULATION :{BLACK}Innbyggere +STR_TOWNDIR_SORT_TIP :{BLACK}Velg sorterings metode + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Har kurs for {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Har kurs for {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Kjør via {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Kontrollpunkt {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Kontrollpunkt {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Kontrollpunkt + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Endre navnet til kontrollpunkt... + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Kan ikke endre navnet til kontrollpunktet... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Konverter jernbane til kontrollpunkt +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Kan ikke bygge kontrollpunkt for tog her... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Kan ikke fjerne kontrollpunktet... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Bygg jernbane ved hjelp av Autobane modusen + +STR_TREES_RANDOM_TYPE :{BLACK}Trær av tilfeldig type +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Plasser trær av tilfeldig type + +STR_CANT_BUILD_CANALS :{WHITE}Kan ikke bygge kanaler her... +STR_BUILD_CANALS_TIP :{BLACK}Bygg kanaler +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Kan ikke bygge sluser her... +STR_BUILD_LOCKS_TIP :{BLACK}Bygg sluser +STR_LANDINFO_LOCK :Sulse + +STR_LANDINFO_COORDS :{BLACK}Koordinater: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Kan ikke fjerne del av stasjonen... +STR_CANT_CONVERT_RAIL :{WHITE}Kan ikke konvertere jernbanetype her... +STR_CONVERT_RAIL_TIP :{BLACK}Konverter/oppgrader jernbanetypen + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Dra lokomotivet her for å selge hele toget. + +STR_DRAG_DROP :{BLACK}Dra og slipp +STR_STATION_DRAG_DROP :{BLACK}Bygg stasjon med dra og slipp + +STR_FAST_FORWARD :{BLACK}Hurtig tid +STR_MESSAGE_HISTORY :{WHITE}Tidligere meldinger + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Bygg kullgruve +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plant skog +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Bygg oljeplatform +STR_CONSTRUCT_FARM_TIP :{BLACK}Finansier gård +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Bygg kobbergruve +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Bygg oljebrønn +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Bygg gullgruve +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Bygg diamantgruve +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Bygg jerngruve +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Finansier frukt plantasje +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Finansier gummi plantasje +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Finansier vannreservoar +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plant spunnet sukker skog +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Finansier batteri gård +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Bygg colabrønn +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Finasier plastikk fontener +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Bygg boble generator +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Finansier karamell brudd +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Bygg sukkergruve + +STR_INDUSTRYDIR_NAME :{BLACK}Navn +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produksjon +STR_INDUSTRYDIR_TYPE :{BLACK}Type +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrier +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...For nært en annen industri + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Bygg om et lokomotiv til å ta en annen type last +STR_RAIL_REFIT :{WHITE}{STRING} (bygg om) +STR_RAIL_REFIT_VEHICLE :{BLACK}Bygg om lokomotivet +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Velg hvilken last lokomotivet skal ta +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Bygg om lokomotivet til å frakte den valgte varetypen +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Kan ikke bygge om lokomotiv... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Kostnad: {CURRENCY} +STR_0801_COST :{RED}Kostnad: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Inntekt: {CURRENCY} +STR_0803_INCOME :{GREEN}Inntekt: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Anslått kostnad: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Anslått kostand: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Anslått inntekt: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Anslått inntekt: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Kan ikke heve land her... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Kan ikke senke land her... +STR_080A_ROCKS :Steiner +STR_080B_ROUGH_LAND :Ulendt terreng +STR_080C_BARE_LAND :Bart land +STR_080D_GRASS :Gress +STR_080E_FIELDS :Jorde +STR_080F_SNOW_COVERED_LAND :Snødekket land +STR_0810_DESERT :Ørken + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Landet heller i feil retning +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Umulig spor kombinasjon +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Utgraving vil skade tunnel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Allerede på havnivå +STR_1004_TOO_HIGH :{WHITE}For høyt +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Upassende jernbanespor +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Tog inni togstallen +STR_1007_ALREADY_BUILT :{WHITE}...allerede bygget +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Må fjerne jernbane spor først +STR_1009_TOO_MANY_DEPOTS :{WHITE}For mange togstaller +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Bygg jernbane +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Bygg Monorail +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Bygg MagLev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Velg jernbanebrotype +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Kan ikke bygge togstall her... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Kan ikke bygge jernbanestasjon her +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Kan ikke bygge signallykter her... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Kan ikke bygge jernbanespor her... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Kan ikke fjerne jernbanespor herfra... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Kan ikke fjerne signallykter herfra... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Retning for togstall +STR_1015_RAILROAD_CONSTRUCTION :Bygg jernbane +STR_1016_MONORAIL_CONSTRUCTION :Bygg Monorail +STR_1017_MAGLEV_CONSTRUCTION :Bygg MagLev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Bygg jernbane spor +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Bygg togstall (trengs for bygging og service av tog) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Bygg jernbanestasjon +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Bygg signallykter +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Bygg jernbanebro +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Bygg jernbanetunnel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Velg mellom bygging/fjerning for jernbanespor og signallykter +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Bro valg - trykk på broen du har valg for å bygge den. +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Velg retning for togstall +STR_1021_RAILROAD_TRACK :Jernbanespor +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Jernbanespor med signallykter +STR_1023_RAILROAD_TRAIN_DEPOT :Togstall +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...område eies av et annet firma +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Jernbane spor med normale signaler +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Jernbane spor med for-signaler +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Jernbane spor med forlat-signaler +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Jernbane spor med kombinerte signaler + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Landområdet heller i feil vei for veibygging +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Må fjerne vei først +STR_1802_ROAD_CONSTRUCTION :{WHITE}Bygg vei +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Velg vei bro type +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Kan ikke bygge vei her +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Kan ikke fjerne vei herfra... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Retning for garasje +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan ikke bygge garasje her... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Kan ikke bygge busstatsjon... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kan ikke bygge lasteterminal... +STR_180A_ROAD_CONSTRUCTION :Bygg vei +STR_180B_BUILD_ROAD_SECTION :{BLACK}Bygg vei +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Bygg garasje (trengs for bygging og service av kjøretøy) +STR_180D_BUILD_BUS_STATION :{BLACK}Bygg bus stasjon +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Bygg lasteterminal +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Bygg veibro +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Bygg veitunnel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Velg mellom bygging/fjerning for vei bygging +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Bro valg - trykk på broen du har valgt for å bygge den. +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Velg retning for garasje +STR_1814_ROAD :Vei +STR_1815_ROAD_WITH_STREETLIGHTS :Vei med gatelykter +STR_1816_TREE_LINED_ROAD :Tre-linjet vei +STR_1817_ROAD_VEHICLE_DEPOT :Garasje +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Jernbane overgang + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Byer +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Byggningen må rives først +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Innbyggertall: {ORANGE}{COMMA32}{BLACK} Antall Hus: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Bytt navn +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Kan ikke bytte navn på byten... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} kommunen nekter deg å gjøre dette. +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}By navn - trykk på by navnet for å se på byen +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Sentrer bildet rundt byen +STR_200C_CHANGE_TOWN_NAME :{BLACK}Bytt by navn +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passasjerer forrige måned: {ORANGE}{COMMA16}{BLACK} maks: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Post sist måned: {ORANGE}{COMMA16}{BLACK} maks: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Høyhus +STR_2010_OFFICE_BLOCK :Kontorblokk +STR_2011_SMALL_BLOCK_OF_FLATS :Leilighetsblokk +STR_2012_CHURCH :Kirke +STR_2013_LARGE_OFFICE_BLOCK :Stor kontorblokk +STR_2014_TOWN_HOUSES :By hus +STR_2015_HOTEL :Hotell +STR_2016_STATUE :Statue +STR_2017_FOUNTAIN :Fontene +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kontorblokk +STR_201A_SHOPS_AND_OFFICES :Butikker og kontorer +STR_201B_MODERN_OFFICE_BUILDING :Moderne kontorblokk +STR_201C_WAREHOUSE :Varehus +STR_201D_OFFICE_BLOCK :Kontorblokk +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Gamle hus +STR_2020_LOCAL_AUTHORITY :{BLACK}Kommune +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Vis informasjon om kommunen +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} kommune +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Transport firma vurdering: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subsidier +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Subsidier som ingen firma har tatt:- +STR_2027_FROM_TO :{ORANGE}{STRING} fra {STRING} til {STRING} +STR_2028_BY :{YELLOW} (innen {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Ingen +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Tjenester som allerede er subsidiert:- +STR_202C_FROM_TO :{ORANGE}{STRING} fra {STATION} til {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, inntil {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Tilbud om subsidie har gått ut:{}{}{STRING} fra {STRING} til {STRING} vil ikke lenger være subsidiert. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subsidie trukket tilbake:{}{}{STRING} transport fra {STATION} til {STATION} er ikke lenger subsidiert. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Subsidie tilbud:{}{}Første {STRING} transport fra {STRING} til {STRING} vil være subsidiert i et år, av kommunen +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Tjeneste subsidie gitt til {STRING}!{}{}{STRING} transport fra {STATION} til {STATION} vil betale 50% mer i løpet av et år! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Tjeneste subsidie gitt til {STRING}!{}{}{STRING} transport fra {STATION} til {STATION} vil betale dobbelt så mye i løpet av et år! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Tjeneste subsidie gitt til {STRING}!{}{}{STRING} transport fra {STATION} til {STATION} vil betale tre ganger så mye i løpet av et år! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Tjeneste subsidie gitt til {STRING}!{}{}{STRING} transport fra {STATION} til {STATION} vil betale fire ganger så mye i løpet av et år! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} kommunen tillater ikke flere flyplasser i denne byen +STR_2036_COTTAGES :Hytter +STR_2037_HOUSES :Hus +STR_2038_FLATS :Leiligheter +STR_2039_TALL_OFFICE_BLOCK :Høyhus +STR_203A_SHOPS_AND_OFFICES :Butikker og kontorer +STR_203B_SHOPS_AND_OFFICES :Butikker og kontorer +STR_203C_THEATER :Theater +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Kontorer +STR_203F_HOUSES :Hus +STR_2040_CINEMA :Kino +STR_2041_SHOPPING_MALL :Kjøpesenter +STR_2042_DO_IT :{BLACK}Gjør det +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Liste med ting som kan gjøres for/i byen - trykk på valg for mer informasjon +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Utfør den gjeldene aksjonen valgt i listen over. +STR_2045_ACTIONS_AVAILABLE :{BLACK}Aksjoner tilgjengeligt: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Liten reklame kampanje +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Medium reklame kampanje +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Stor reklame kampanje +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Finansier lokal rekonstruksjon av vei nettet +STR_204A_BUILD_STATUE_OF_COMPANY :Bygg statue av firmaet sin grunnlegger +STR_204B_FUND_NEW_BUILDINGS :Finansier nye byggninger +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kjøp alle transportrettigheter +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Besikk kommunestyret +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en liten lokal reklame kampanje, for å tiltrekke deg flere passasjerer og mer varer til dine transport tjenester.{} Koster: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en medium lokal reklame kampanje, for å tiltrekke deg flere passasjerer og mer varer til dine transport tjenester.{} Koster: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Start en stor lokal reklame kampanje, for å tiltrekke deg flere passasjerer og mer varer til dine transport tjenester.{} Koster: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Finansier rekonstrusjon av det lokale veinettet. Fører til vei problemer i seks måneder.{} Koster: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Bygg en statue for å ære firmaet.{} Cost: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Finasier byggingen av nye kommersielle byggninger i byen .{} Koster: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Kjøp ekslusive transport rettigheter i kommunen. Kommunen vil bare tillate passasjerer og varer å bruke dine transport tjenester.{} Koster: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Bestikk kommunestyret til å forbedre firmaets vurdering, men du riskerer å bli bøtlagt hvis du blir oppdaget.{} Koster: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Kan ikke gjøre det... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Traffkk kaos i {TOWN}!{}{}Vei rekonstruksjonsprogram finasiert av {STRING}, fører med seg seks måneders vei problemer. +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (under bygging) +STR_2059_IGLOO :Iglo +STR_205A_TEPEES :Indianertelt +STR_205B_TEAPOT_HOUSE :Tekjelehus +STR_205C_PIGGY_BANK :Sparebøsse + +##id 0x2800 +STR_2800_PLANT_TREES :Plant trær +STR_2801_PLACE_SIGN :Plasser skilt +STR_2802_TREES :{WHITE}Tre +STR_2803_TREE_ALREADY_HERE :{WHITE}...tre finnes det allerede her +STR_2804_SITE_UNSUITABLE :{WHITE}...upassende område +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Kan ikke plante tre her... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...for mange skilt +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Kan ikke plassere skilt her... +STR_280A_SIGN :Skilt +STR_280B_EDIT_SIGN_TEXT :{WHITE}Endre teksten på skiltet +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Kan ikke endre teksten på skiltet... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Velg tre type som skal plantes +STR_280E_TREES :Trær +STR_280F_RAINFOREST :Regnskog +STR_2810_CACTUS_PLANTS :Kaktusplanter + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Velg jernbanestasjon type +STR_3001_AIRPORT_SELECTION :{WHITE}Velg flyplass type +STR_3002_ORIENTATION :{BLACK}Retning +STR_3003_NUMBER_OF_TRACKS :{BLACK}Antall spor +STR_3004_PLATFORM_LENGTH :{BLACK}Platform lengde +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}For nær en annen jernbanestasjon +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grenser til mer enn en eksiterende stasjon/lasteterminal +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}For mange stasjoner/lasteterminaler i byen +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}For mange stasjner/lasteterminaler +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}For nær en annen jerbanestasjon/lasteterminal +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Må rive eksiterende jernbanestasjon først +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}For nær en annen flyplass +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Må rive eksiterende flyplass først + +STR_3030_RENAME_STATION_LOADING :Endre navnet til stasjon/lasteterminal +STR_3031_CAN_T_RENAME_STATION :{WHITE}Kan ikke endre navnet til stasjonen... +STR_3032_RATINGS :{BLACK}Vurderinger +STR_3033_ACCEPTS :{BLACK}Aksepterer +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Lokal vurdering av transport tjenester: + +############ range for rating starts +STR_3035_APPALLING :Forferdelig +STR_3036_VERY_POOR :Veldig dårlig +STR_3037_POOR :Dårlig +STR_3038_MEDIOCRE :Medium +STR_3039_GOOD :God +STR_303A_VERY_GOOD :Veldig god +STR_303B_EXCELLENT :Utmerket +STR_303C_OUTSTANDING :Fremragende +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} akseptere ikke lenger {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} akseptere ikke lenger {STRING} eller {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} akseptere nå {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} akseptere nå {STRING} og {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Bussterminal retning +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Lasteterminal retning +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}For nærme en annen bussterminal +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}For nærme en annen lasteterminal +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Må rive bussterminal først +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Må rive lasteterminal først +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stasjoner +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Ingen - +STR_304B_SITE_UNSUITABLE :{WHITE}...upassende område +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}For nærme enn annen havn +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Må rive havn først +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Velg jerbanestasjon retning +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Velg antall spor stasjonen skal ha +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Velg hvor lang stasjonen skal være +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Velg bussterminal retning +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Velg lasteterminal retning +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Sentrer bildet på stasjonsområdet +STR_3054_SHOW_STATION_RATINGS :{BLACK}Vis stasjonsvurdering +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Endre navnet til stasjonen +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Vis liste over aksepterte varer +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Stasjonsnavn - Trykk på navnet for å sentrere bilder på stasjonområdet +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Velg størrelse/type flyplass +STR_3059_SMALL :{BLACK}Liten +STR_305A_LARGE :{BLACK}Stor +STR_305AA_LARGE :{BLACK}Nasjonal flyplass +STR_305AB_LARGE :{BLACK}Internasjonal flyplass +STR_305B_SIZE :{BLACK}Størrelse +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Jernbanestasjon +STR_305F_AIRCRAFT_HANGAR :Flyplass hangar +STR_3060_AIRPORT :Flyplass +STR_3061_TRUCK_LOADING_AREA :Lasteterminal +STR_3062_BUS_STATION :Bussterminal +STR_3063_SHIP_DOCK :Havn +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Dekningsområdet til den forslåtte plassering +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Ikke vis dekningsområdet til den forslåtte plassering +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Dekningsområdet +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Monorailstasjon valg. +STR_3068_DOCK :{WHITE}Havn +STR_3069_BUOY :Bøye +STR_306A_BUOY_IN_THE_WAY :{WHITE}...bøyen er i veien +STR_306B_HELIPORT :{BLACK}Helikopterlandingsplass +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stasjonen er spredd for mye + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Skipdepot retning +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...må bygges i sjøen +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Kan ikke bygge skipdepot her... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Velg skipdepot retning +STR_3804_WATER :Vann +STR_3805_COAST_OR_RIVERBANK :Kyst eller elvebredd +STR_3806_SHIP_DEPOT :Skipdepot +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Kan ikke bygge på vann + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Lagre spill +STR_4001_LOAD_GAME :{WHITE}Hent frem spill +STR_4002_SAVE :{BLACK}Lagre +STR_4003_DELETE :{BLACK}Slett +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabyte ledig +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Kan ikke lese fra disk +STR_4007_GAME_SAVE_FAILED :{WHITE}Lagring av spillet feilet +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Kan ikke slette fil +STR_4009_GAME_LOAD_FAILED :{WHITE}Frem henting av spill feilet +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Liste over disker, mapper og lagrede spill +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Gjeldende navn for valgt lagret spill +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Slett spillet som er valgt +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Lagre gjeldende spill ved å bruke navnet som er valgt +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Velg ny spill type +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Velg scenario (grønn), forhåndsatt spill (blått), eller nytt tilfeldig spill +STR_4010_GENERATE_RANDOM_NEW_GAME :Lag et tilfeldig spill + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} er i veien +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kullgruve +STR_4803_POWER_STATION :Kraftstasjon +STR_4804_SAWMILL :Sagbruk +STR_4805_FOREST :Skog +STR_4806_OIL_REFINERY :Oljeraffineri +STR_4807_OIL_RIG :Oljeplatform +STR_4808_FACTORY :Fabrikk +STR_4809_PRINTING_WORKS :Trykkeri +STR_480A_STEEL_MILL :Smelteverk +STR_480B_FARM :Gård +STR_480C_COPPER_ORE_MINE :Kobber gruve +STR_480D_OIL_WELLS :Olje brønn +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Matforedlingsfabrikk +STR_4810_PAPER_MILL :Papirfabrikk +STR_4811_GOLD_MINE :Gullgruve +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamantgruve +STR_4814_IRON_ORE_MINE :Jerngruve +STR_4815_FRUIT_PLANTATION :Frukt plantasje +STR_4816_RUBBER_PLANTATION :Gummi plantasje +STR_4817_WATER_SUPPLY :Vannreservoar +STR_4818_WATER_TOWER :Vanntårn +STR_4819_FACTORY :Fabrikk +STR_481A_FARM :Gård +STR_481B_LUMBER_MILL :Sagbruk +STR_481C_COTTON_CANDY_FOREST :Spunnet sukker skog +STR_481D_CANDY_FACTORY :Søtsakfabrikk +STR_481E_BATTERY_FARM :Batteri gård +STR_481F_COLA_WELLS :Cola brønner +STR_4820_TOY_SHOP :Leketøysbutikk +STR_4821_TOY_FACTORY :Leketøysfabrikk +STR_4822_PLASTIC_FOUNTAINS :Plastikk fontener +STR_4823_FIZZY_DRINK_FACTORY :Mineralvannfabrikk +STR_4824_BUBBLE_GENERATOR :Boble generator +STR_4825_TOFFEE_QUARRY :Karamell brudd +STR_4826_SUGAR_MINE :Sukkergruve + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Trenger: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Trenger: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Trenger: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produksjon sist måned: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transportert) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Sentrer bilde på industriområdet +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Ny {STRING} under bygging nær {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Ny {STRING} plantes i nærheten av {TOWN}! +STR_482F_COST :{BLACK}Koster: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Kan ikke bygge industri type her... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...skog kan bare plantes over snøgrensen +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} annonserer umiddelbar nedleggelse! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Leveringsproblemer forårsaker {TOWN} {STRING} til å annonsere umiddelbar nedleggelse! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Mangel på trær i nærheten får {TOWN} {STRING} til å annonsere umiddelbar nedleggelse! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} øker produksjonen! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Ny kullåre funnet i {TOWN} {STRING}!{}Produksjonen er forventet til å dobles! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nye oljereserver funnet i {TOWN} {STRING}!{}Produksjonen er forventet til å dobles! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Forbedring i gårdbruksmetoder på {TOWN} {STRING} er forventet til å doble produksjonen! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} sin produksjon har sunket med 50 % +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Insekt invasjon på {TOWN} {STRING}!{}Produksjonen synker med 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...kan bare plasseres i nærheten av kartkanten +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} produksjonen ved {TOWN}{STRING}øker med {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} produksjonen ved {TOWN}{STRING}synker med {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Tog i tunnelen +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Kjøretøy i tunnelen +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Annen tunnel i veien +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Kan ikke grave ut land til den andre tunnel utgangen +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Må rive tunnel først +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Må rive bro først +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan ikke starte og slutte på samme landområde +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Flatt land eller vann trengs under broa +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start og slutt må være på linje +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Området er upassende for tunnelinngang +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Hengebro, Stål +STR_500F_GIRDER_STEEL :Bjelker, Stål +STR_5010_CANTILEVER_STEEL :Frittbærende, Stål +STR_5011_SUSPENSION_CONCRETE :Hengebro, Betong +STR_5012_WOODEN :Tre +STR_5013_CONCRETE :Betong +STR_5014_TUBULAR_STEEL :Rørformet, Stål +STR_BRIDGE_TUBULAR_SILICON :Rørformet, Silikon +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Kan ikke bygge bro her... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan ikke bygge tunnel her... +STR_5017_RAILROAD_TUNNEL :Jernbane tunnel +STR_5018_ROAD_TUNNEL :Vei tunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Stål hengebro (jernbane) +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Stål bjelkebro (jernbane) +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Stål frittbærende bro (jernbane) +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Armert betong hengebro (jernbane) +STR_501F_WOODEN_RAIL_BRIDGE :Tre bro (jernbane) +STR_5020_CONCRETE_RAIL_BRIDGE :Betong bro (jernbane) +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Stål hengebro (vei) +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Stål bjelkebro (vei) +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Stpl frittbærende bro (vei) +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Armert betong hengebro (vei) +STR_5025_WOODEN_ROAD_BRIDGE :Tre bro (vei) +STR_5026_CONCRETE_ROAD_BRIDGE :Betong bro (vei) +STR_5027_TUBULAR_RAIL_BRIDGE :Rørformet bro (jernbane) +STR_5028_TUBULAR_ROAD_BRIDGE :Rørformet bro (vei) +STR_5029_STEEL :Stål + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Objekt er i veien +STR_5801_TRANSMITTER :Radiosender +STR_5802_LIGHTHOUSE :Fyrlykt +STR_5803_COMPANY_HEADQUARTERS :Firma hovedkontor +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...firma hovedkontor er i veien +STR_5805_COMPANY_OWNED_LAND :Firma eid land +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Kan ikke kjøpe dette land området +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...du eier det allerede + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Uten navn{SKIP} +STR_SV_TRAIN_NAME :Tog {COMMA16} +STR_SV_ROADVEH_NAME :Kjøretøy {COMMA16} +STR_SV_SHIP_NAME :Skip {COMMA16} +STR_SV_AIRCRAFT_NAME :Fly {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Nord +STR_SV_STNAME_SOUTH :{STRING} Sør +STR_SV_STNAME_EAST :{STRING} Øst +STR_SV_STNAME_WEST :{STRING} Vest +STR_SV_STNAME_CENTRAL :{STRING} Sentral +STR_SV_STNAME_TRANSFER :{STRING} Holdeplass +STR_SV_STNAME_HALT :{STRING} Stopp +STR_SV_STNAME_VALLEY :{STRING} Dal +STR_SV_STNAME_HEIGHTS :{STRING} Høyde +STR_SV_STNAME_WOODS :{STRING} Skog +STR_SV_STNAME_LAKESIDE :{STRING} Vann +STR_SV_STNAME_EXCHANGE :{STRING} Overgang +STR_SV_STNAME_AIRPORT :{STRING} Flyplass +STR_SV_STNAME_OILFIELD :{STRING} Oljefelt +STR_SV_STNAME_MINES :{STRING} Gruve +STR_SV_STNAME_DOCKS :{STRING} Havn +STR_SV_STNAME_BUOY_1 :{STRING} Bøye 1 +STR_SV_STNAME_BUOY_2 :{STRING} Bøye 2 +STR_SV_STNAME_BUOY_3 :{STRING} Bøye 3 +STR_SV_STNAME_BUOY_4 :{STRING} Bøye 4 +STR_SV_STNAME_BUOY_5 :{STRING} Bøye 5 +STR_SV_STNAME_BUOY_6 :{STRING} Bøye 6 +STR_SV_STNAME_BUOY_7 :{STRING} Bøye 7 +STR_SV_STNAME_BUOY_8 :{STRING} Bøye 8 +STR_SV_STNAME_BUOY_9 :{STRING} Bøye 9 +STR_SV_STNAME_ANNEXE :{STRING} Anneks +STR_SV_STNAME_SIDINGS :{STRING} Side +STR_SV_STNAME_BRANCH :{STRING} Gren +STR_SV_STNAME_UPPER :Øvre {STRING} +STR_SV_STNAME_LOWER :Nedre {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Skog + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Vanskelighetsgrad + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Lett +STR_6802_MEDIUM :{BLACK}Medium +STR_6803_HARD :{BLACK}Vanskelig +STR_6804_CUSTOM :{BLACK}Egendefinert +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maks. antall konkurrenter: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Konkurrentenes starttidspunkt: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Antall byer: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Antall industrier: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maksimal begynner lån: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Begynner rente: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Kjøretøy sine driftkostnader: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Kontruksjonshastighet hos konkurrenter: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Konkurrentene sin intelligens: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Kjøretøy havarier: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Subiside multiplikator: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Konstruksjonskosnader: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Terreng type: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Mengde med sjø/innsjøer: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Økonomi: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Tog reversering: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katastrofer: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Lite +STR_6817_NORMAL :Normal +STR_6818_HIGH :Høyt +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Veldig sent +STR_681C_SLOW :Sent +STR_681D_MEDIUM :Medium +STR_681E_FAST :Rask +STR_681F_VERY_FAST :Veldig rask +STR_VERY_LOW :Veldig lavt +STR_6820_LOW :Lavt +STR_6821_MEDIUM :Medium +STR_6822_HIGH :Høyt +STR_6823_NONE :Ingen +STR_6824_REDUCED :Redusert +STR_6825_NORMAL :Normalt +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Veldig flatt +STR_682B_FLAT :Flatt +STR_682C_HILLY :Åslendt +STR_682D_MOUNTAINOUS :Berglendt +STR_682E_STEADY :Stødig +STR_682F_FLUCTUATING :Flytende +STR_6830_IMMEDIATE :Øyeblikkelig +STR_6831_3_MONTHS_AFTER_PLAYER :3 måneder etter spiller +STR_6832_6_MONTHS_AFTER_PLAYER :6 måneder etter spiller +STR_6833_9_MONTHS_AFTER_PLAYER :9 måneder etter spiller +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Ved linje slutt og stasjoner +STR_6835_AT_END_OF_LINE_ONLY :Bare ved linje slutt +STR_6836_OFF :Av +STR_6837_ON :På +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Vis rekorder + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Spiller 1) +STR_7003_PLAYER_2 : (Spiller 2) +STR_7004_NEW_FACE :{BLACK}Nytt ansikt +STR_7005_COLOR_SCHEME :{BLACK}Firma farge +STR_7006_COLOR_SCHEME :{GOLD}Firma farge: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Ny firma farge +STR_7008_COMPANY_NAME :{BLACK}Firma navn +STR_7009_PRESIDENT_NAME :{BLACK}Leder navn +STR_700A_COMPANY_NAME :Firma navn +STR_700B_PRESIDENT_S_NAME :Leder sitt navn +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Kan ikke endre firma navn... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Kan ikke bytte leder navn... +STR_700E_FINANCES :{WHITE}{STRING} Finanser{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Utgifter/Inntekter +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Konstruksjon +STR_7012_NEW_VEHICLES :{GOLD}Nye kjøretøy +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Tog driftkostnader +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Kjøretøy driftkostnader +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Fly driftkostnader +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Skip driftkostnader +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Vedlikehold av eiendom +STR_7018_TRAIN_INCOME :{GOLD}Tog inntekter +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Kjøretøy inntekter +STR_701A_AIRCRAFT_INCOME :{GOLD}Fly inntekter +STR_701B_SHIP_INCOME :{GOLD}Skip inntekter +STR_701C_LOAN_INTEREST :{GOLD}Renter +STR_701D_OTHER :{GOLD}Annet +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Totalt: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Inntektsgraf +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Overskudd graf +STR_7026_BANK_BALANCE :{WHITE}Saldo +STR_7027_LOAN :{WHITE}Lån +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Låne mer ({SKIP}{SKIP}{SKIP}{CURRENCY}) +STR_702A_REPAY :{BLACK}Betale tilbake ({SKIP}{SKIP}{SKIP}{CURRENCY}) +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maksimalt lån er {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Kan ikke låne mer penger... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...lånet er allerede betalt tilbake +STR_702E_REQUIRED :{WHITE}...{CURRENCY} trengs +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Kan ikke betale tilbake lån... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Velg nytt utsende for firma lederen +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Endre firma farge +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Endre leder navn +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Endre firma navn +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Trykk på fargen du har valgt +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Øk størrelsen på lånet +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Betal tilbake en del av lånet +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Leder) +STR_7038_INAUGURATED :{GOLD}Grunnlagt: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Kjøretøy: +STR_703A_TRAIN :{WHITE}{COMMA16} tog +STR_703B_TRAINS :{WHITE}{COMMA16} tog +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} kjøretøy +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} kjøretøy +STR_703E_AIRCRAFT :{WHITE}{COMMA16} fly +STR_703F_AIRCRAFT :{WHITE}{COMMA16} fly +STR_7040_SHIP :{WHITE}{COMMA16} skip +STR_7041_SHIPS :{WHITE}{COMMA16} skip +STR_7042_NONE :{WHITE}Ingen +STR_7043_FACE_SELECTION :{WHITE}Velg utsende +STR_7044_MALE :{BLACK}Mann +STR_7045_FEMALE :{BLACK}Kvinne +STR_7046_NEW_FACE :{BLACK}Nytt ansikt +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Avbryt velg utstende +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Aksepter nytt utsende +STR_7049_SELECT_MALE_FACES :{BLACK}Velg mannlig utsende +STR_704A_SELECT_FEMALE_FACES :{BLACK}Velg kvinnelig utsende +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Lag tilfeldig nytt ansikt +STR_704C_KEY :{BLACK}Nøkkel +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Vis oversikt over grafvalg +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Vis oversikt over firmagraf valg +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Trykk her for å skru et firma sin graf av/på +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Antall varer levert +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Firma prestasjons vudering (maks poeng=1000) +STR_7052_COMPANY_VALUES :{WHITE}Firma verdi +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Firma rangering +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transport firma i problemer! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} vil bli solgt eller nedlagt, hvis ikke firmaets økonomi tar seg opp! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(President) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Transport firma fusjon! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} har blitt solgt til {STRING} for {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Vi ser etter ett firma som er villig til å overta oss.{}{}Vil du kjøpe {STRING} for {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Konkurs! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} har blitt stengt av kreditorer og alt av verdi har blitt solgt! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nytt transport firma startet! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} starter bygging i nærheten av {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Kan ikke kjøpe firma.., +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Vare betalingstakst +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Dager i transport +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Betaling for levering av ti enheter (eller 10,000 liter) over en distance på 20 ruter- +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Skru av/på graf for en bestemt varetype +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingeniør +STR_7067_TRAFFIC_MANAGER :Trafikk leder +STR_7068_TRANSPORT_COORDINATOR :Transport koordinator +STR_7069_ROUTE_SUPERVISOR :Rute oppsynsmann +STR_706A_DIRECTOR :Direktør +STR_706B_CHIEF_EXECUTIVE :Sjefsleder +STR_706C_CHAIRMAN :Formann +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Finansfyrste +STR_706F_BUILD_HQ :{BLACK}Bygg HK +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Bygg firmaets hovedkontor / se firmaets hovedkontor +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Kan ikke bygge hovedkontor... +STR_7072_VIEW_HQ :{BLACK}Se HK +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Verdenskrise!{}{}Økonomer frykter det værste når de går nedgangstider i møte. +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Verdenskrise over!{}{}Opptur i markedet gir tilbake selvsikkerheten til industrien. +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Bytte mellom stor/liten vindu størrelse +STR_7076_COMPANY_VALUE :{GOLD}Firma verdi: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Kjøp 25% av aksjene i firmaet +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Selg 25% av aksjene du eier +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kjøp 25% av aksjene i firmaet +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Selg 25% av aksjene du eier +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Kan ikke kjøpe 25% av aksjene... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Kan ikke selge 25% av aksjene... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% eies av {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% eies av {STRING}{} {COMMA16}% eies av {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} har blitt kjøpt opp av {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Damp) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Damp) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Damp) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Damp) +STR_800A_SH_8P_STEAM :SH '8P' (Damp) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektrisk) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektrisk) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektrisk) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektrisk) +STR_801B_PASSENGER_CAR :Passasjervogn +STR_801C_MAIL_VAN :Postvogn +STR_801D_COAL_CAR :Kullvogn +STR_801E_OIL_TANKER :Oljetankvogn +STR_801F_LIVESTOCK_VAN :Buskap vogn +STR_8020_GOODS_VAN :Godsvogn +STR_8021_GRAIN_HOPPER :Korn vogn +STR_8022_WOOD_TRUCK :Tømmervogn +STR_8023_IRON_ORE_HOPPER :Jernmalm vogn +STR_8024_STEEL_TRUCK :Stål vogn +STR_8025_ARMORED_VAN :Armert vogn +STR_8026_FOOD_VAN :Mat vogn +STR_8027_PAPER_TRUCK :Papir vogn +STR_8028_COPPER_ORE_HOPPER :Kobbermalm vogn +STR_8029_WATER_TANKER :Vanntank vogn +STR_802A_FRUIT_TRUCK :Frukt vogn +STR_802B_RUBBER_TRUCK :Gummi vogn +STR_802C_SUGAR_TRUCK :Sukker vogn +STR_802D_COTTON_CANDY_HOPPER :Spunnet sukker vogn +STR_802E_TOFFEE_HOPPER :Karamell vogn +STR_802F_BUBBLE_VAN :Boble vogn +STR_8030_COLA_TANKER :Cola tank vogn +STR_8031_CANDY_VAN :Søtsak vogn +STR_8032_TOY_VAN :Leketøy vogn +STR_8033_BATTERY_TRUCK :Batteri vogn +STR_8034_FIZZY_DRINK_TRUCK :Mineralvann vogn +STR_8035_PLASTIC_TRUCK :Plastikk vogn +STR_8036_X2001_ELECTRIC :'X2001' (Elektrisk) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektrisk) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Passasjervogn +STR_803A_MAIL_VAN :Postvogn +STR_803B_COAL_CAR :Kullvogn +STR_803C_OIL_TANKER :Oljetankvogn +STR_803D_LIVESTOCK_VAN :Buskap vogn +STR_803E_GOODS_VAN :Godsvogn +STR_803F_GRAIN_HOPPER :Korn vogn +STR_8040_WOOD_TRUCK :Tømmervogn +STR_8041_IRON_ORE_HOPPER :Jernmalm vogn +STR_8042_STEEL_TRUCK :Stål vogn +STR_8043_ARMORED_VAN :Armert vogn +STR_8044_FOOD_VAN :Mat vogn +STR_8045_PAPER_TRUCK :Papir vogn +STR_8046_COPPER_ORE_HOPPER :Kobbermalm vogn +STR_8047_WATER_TANKER :Vanntank vogn +STR_8048_FRUIT_TRUCK :Frukt vogn +STR_8049_RUBBER_TRUCK :Gummi vogn +STR_804A_SUGAR_TRUCK :Sukker vogn +STR_804B_COTTON_CANDY_HOPPER :Spunnet sukker vogn +STR_804C_TOFFEE_HOPPER :Karamell vogn +STR_804D_BUBBLE_VAN :Boble vogn +STR_804E_COLA_TANKER :Cola tank vogn +STR_804F_CANDY_VAN :Søtsak vogn +STR_8050_TOY_VAN :Leketøy vogn +STR_8051_BATTERY_TRUCK :Batteri vogn +STR_8052_FIZZY_DRINK_TRUCK :Mineralvann vogn +STR_8053_PLASTIC_TRUCK :Plastikk vogn +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektrisk) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektrisk) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektrisk) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektrisk) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Passasjervogn +STR_805A_MAIL_VAN :Postvogn +STR_805B_COAL_CAR :Kullvogn +STR_805C_OIL_TANKER :Oljetankvogn +STR_805D_LIVESTOCK_VAN :Buskap vogn +STR_805E_GOODS_VAN :Godsvogn +STR_805F_GRAIN_HOPPER :Korn vogn +STR_8060_WOOD_TRUCK :Tømmervogn +STR_8061_IRON_ORE_HOPPER :Jernmalm vogn +STR_8062_STEEL_TRUCK :Stål vogn +STR_8063_ARMORED_VAN :Armert vogn +STR_8064_FOOD_VAN :Mat vogn +STR_8065_PAPER_TRUCK :Papir vogn +STR_8066_COPPER_ORE_HOPPER :Kobbermalm vogn +STR_8067_WATER_TANKER :Vanntank vogn +STR_8068_FRUIT_TRUCK :Frukt vogn +STR_8069_RUBBER_TRUCK :Gummi vogn +STR_806A_SUGAR_TRUCK :Sukker vogn +STR_806B_COTTON_CANDY_HOPPER :Spunnet sukker vogn +STR_806C_TOFFEE_HOPPER :Karamell vogn +STR_806D_BUBBLE_VAN :Boble vogn +STR_806E_COLA_TANKER :Cola tank vogn +STR_806F_CANDY_VAN :Søtsak vogn +STR_8070_TOY_VAN :Leketøy vogn +STR_8071_BATTERY_TRUCK :Batteri vogn +STR_8072_FIZZY_DRINK_TRUCK :Mineralvann vogn +STR_8073_PLASTIC_TRUCK :Plastikk vogn +STR_8074_MPS_REGAL_BUS :MPS Regal buss +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard buss +STR_8076_FOSTER_BUS :Foster buss +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Super buss +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI buss +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII buss +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII buss +STR_807B_BALOGH_COAL_TRUCK :Balogh kull lastebil +STR_807C_UHL_COAL_TRUCK :Uhl kull lastebil +STR_807D_DW_COAL_TRUCK :DW kull lastebil +STR_807E_MPS_MAIL_TRUCK :MPS postbil +STR_807F_REYNARD_MAIL_TRUCK :Reynard postbil +STR_8080_PERRY_MAIL_TRUCK :Perry postbil +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover postbil +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught postbil +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow postbil +STR_8084_WITCOMBE_OIL_TANKER :Witcombe olje tankbil +STR_8085_FOSTER_OIL_TANKER :Foster olje tankbil +STR_8086_PERRY_OIL_TANKER :Perry olje tankbil +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott buskap lastebil +STR_8088_UHL_LIVESTOCK_VAN :Uhl buskap lastebil +STR_8089_FOSTER_LIVESTOCK_VAN :Foster buskap lastebil +STR_808A_BALOGH_GOODS_TRUCK :Balogh gods lastebil +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead gods lastebil +STR_808C_GOSS_GOODS_TRUCK :Goss gods lastebil +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford korn lastebil +STR_808E_THOMAS_GRAIN_TRUCK :Thomas korn lastebil +STR_808F_GOSS_GRAIN_TRUCK :Goss korn lastebil +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe tømmer lastebil +STR_8091_FOSTER_WOOD_TRUCK :Foster tømmer lastebil +STR_8092_MORELAND_WOOD_TRUCK :Moreland tømmer lastebil +STR_8093_MPS_IRON_ORE_TRUCK :MPS Jernmalm lastebil +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Jernmalm lastebil +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Jernmalm lastebil +STR_8096_BALOGH_STEEL_TRUCK :Balogh stål lastebil +STR_8097_UHL_STEEL_TRUCK :Uhl stål lastebil +STR_8098_KELLING_STEEL_TRUCK :Kelling stål lastebil +STR_8099_BALOGH_ARMORED_TRUCK :Balogh armert bil +STR_809A_UHL_ARMORED_TRUCK :Uhl armert bil +STR_809B_FOSTER_ARMORED_TRUCK :Foster armert bil +STR_809C_FOSTER_FOOD_VAN :Foster mat lastebil +STR_809D_PERRY_FOOD_VAN :Perry mat lastebil +STR_809E_CHIPPY_FOOD_VAN :Chippy mat lastebil +STR_809F_UHL_PAPER_TRUCK :Uhl papir lastebil +STR_80A0_BALOGH_PAPER_TRUCK :Balogh papir lastebil +STR_80A1_MPS_PAPER_TRUCK :MPS papir lastebil +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS kobbermalm lastebil +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl kobbermalm lastebil +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss kobbermalm lastebil +STR_80A5_UHL_WATER_TANKER :Uhl vanntank bil +STR_80A6_BALOGH_WATER_TANKER :Balogh vanntank bil +STR_80A7_MPS_WATER_TANKER :MPS vanntank bil +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh frukt lastebil +STR_80A9_UHL_FRUIT_TRUCK :Uhl frukt lastebil +STR_80AA_KELLING_FRUIT_TRUCK :Kelling frukt lastebil +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh gummi lastebil +STR_80AC_UHL_RUBBER_TRUCK :Uhl gummi lastebil +STR_80AD_RMT_RUBBER_TRUCK :RMT gummi lastebil +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover sukker lastebil +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught sukker lastebil +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow sukker lastebil +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Cola lastebil +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Cola lastebil +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Cola lastebil +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Spunnet sukker lastebil +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Spunnet sukker lastebil +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Spunnet sukker lastebil +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover karamell lastebil +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught karamell lastebil +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow karamell lastebil +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover leketøy lastebil +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught leketøy lastebil +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow leketøy lastebil +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover søtsak lastebil +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught søtsak lastebil +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow søtsak lastebil +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover batteri lastebil +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught batteri lastebil +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow batteri lastebil +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover mineralvann lastebil +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught mineralvann lastebil +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow mineralvann lastebil +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover plastikk lastebil +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught plastikk lastebil +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow plastikk lastebil +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover boble lastebil +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught boble lastebil +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow boble lastebil +STR_80CC_MPS_OIL_TANKER :MPS olje tankskip +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. olje tankskip +STR_80CE_MPS_PASSENGER_FERRY :MPS passasjer ferje +STR_80CF_FFP_PASSENGER_FERRY :FFP passasjer ferje +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 luftpute båt +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug passasjer ferje +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake passasjer ferje +STR_80D3_YATE_CARGO_SHIP :Yate konteinerskip +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell konteinerskip +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover konteinerskip +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut konteinerskip +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helikopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helikopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helikopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Melding fra kjøretøysprodusent +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Vi har nettopp designet nytt {STRING} - er du interessert i ett år esklusivt bruk av dette, slik vi kan se hvordan det virker før det blir allment tilgjengelig +STR_8102_RAILROAD_LOCOMOTIVE :jernbane tog +STR_8103_ROAD_VEHICLE :kjøretøy +STR_8104_AIRCRAFT :fly +STR_8105_SHIP :skip +STR_8106_MONORAIL_LOCOMOTIVE :monorail tog +STR_8107_MAGLEV_LOCOMOTIVE :maglev tog + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Togstall +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Innbyggerne jubler . . .{}Første tog ankommer {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Detaljer) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Tog i veien +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Kjør til {STATION} +STR_8807_GO_TO_UNLOAD :Kjør til {STATION} (Last av) +STR_8808_GO_TO_LOAD :Kjør til {STATION} (Last fullt) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Kjør uten å stoppe til {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Kjør uten å stoppe til {STATION} (Last av) +STR_880C_GO_NON_STOP_TO_LOAD :Kjør uten å stoppe til {STATION} (Last fullt) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Kjør til {TOWN} togstall +STR_SERVICE_AT_TRAIN_DEPOT :Service ved {TOWN} togstall +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Kjør uten å stoppe til {TOWN} togstall +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Service (uten å stoppe) ved {TOWN} togstall + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Er på vei til {TOWN} togstall +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Er på vei til {TOWN} togstall, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Tom +STR_8813_FROM :{LTBLUE}{CARGO} fra {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Tog {COMMA16} venter i togstallen +STR_8815_NEW_VEHICLES :{BLACK}Nye tog/vogner +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Koster: {GOLD}{CURRENCY}{BLACK} Vekt: {GOLD}{COMMA16}t{}{BLACK}Fart: {GOLD}{VELOCITY}{BLACK} Kraft: {GOLD}{COMMA16}hk{}{BLACK}Driftkostnader: {GOLD}{CURRENCY}/år{}{BLACK}Kapasitet: {GOLD}{STRING}{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Levetid: {GOLD}{COMMA16} år{}{BLACK}Maks. pålitelighet: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informasjon +STR_8819_TRAIN_TOO_LONG :{WHITE}Toget er for langt +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Tog kan bare endres når det står stille inni togstallen +STR_881B_TRAINS :{WHITE}{STRING} - Tog +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nye jernbane tog/vogner +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nye Monorail tog/vogner +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nye Maglev tog/vogner +STR_881F_BUILD_VEHICLE :{BLACK}Kjøp tog/vogn +STR_8820_RENAME :{BLACK}Endre navn +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Koster: {GOLD}{CURRENCY}{}{BLACK}Vekt: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapasitet: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Hopp over +STR_8824_DELETE :{BLACK}Slett +STR_8825_NON_STOP :{BLACK}Uten-stopp +STR_8826_GO_TO :{BLACK}Kjør til +STR_8827_FULL_LOAD :{BLACK}Last fullt +STR_8828_UNLOAD :{BLACK}Last av +STR_8829_ORDERS :{WHITE}{STRING} (Ordre) +STR_882A_END_OF_ORDERS :{SETX 10}- - Slutt på ordre - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Service +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Kan ikke bygge jernbane kjøretøy... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Verdi: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Verdi: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Laster på/av +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Kan ikke sende tog til togstall... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ikke mer plass til ordre +STR_8832_TOO_MANY_ORDERS :{WHITE}For mange ordre +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Kan ikke sette inn ny ordre... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Kan ikke slette denne ordren... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Kan ikke endre denne ordren... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Må bygge togstall først +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Kan ikke flytte kjøretøy... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Kan ikke selge jernbane kjøretøy... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Kan ikke finne en togstall i nærheten +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Kan ikke stoppe/starte tog... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Service interval: {LTBLUE}{COMMA16}dager{BLACK} Siste service: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tog - trykk på tog for mer informasjon +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Bygg nye tog (trenger en togstall) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tog - trykk på tog for mer info. Dra vogn for å legge til/fjerne fra tog +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Bygg nytt tog(vogn) +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Dra tog (vogn) her for å selge +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Vis stedet togstallen ligger på +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Tog/vogn liste - trykk på tog/vogn for mer informasjon +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Bygg den valgte enheten +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Endre navnet til den valgte enheten +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Gjeldende tog status - trykk her for å stoppe/starte tog +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Vis toget sine ordre +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Vis toget sin gjeldene posisjon +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Send toget til en togstall +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Tving toget til å kjøre på rødt lys +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Bytt kjøreretning +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Vis tog detaljer +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Øk service interval +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Reduser service interval +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Vis detaljer angående innholdet i vognene +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Vis detaljer om tog/vogner +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Vis kapasitet til vognene +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Vis en total kapasitet på togene oppdelt etter godstype +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Ordre liste - trykk på en ordre for å velge den +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Hopper over gjeldende ordre, og forsett på neste +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Slett den valgte ordren +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gjør den valgte ordren om til en "Uten å stoppe" ordre +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Sett inn en ordre før den valgte ordren, eller i slutten av listen. +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gjør den valgte ordren om til en vent til full last ordre +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gjør den valgte ordren om til en bare last av ordre +STR_SERVICE_HINT :{BLACK}Hopp over ordren ved mindre service trengs. +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt {STRING} er nå tilgjengelig! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Koster: {CURRENCY} Vekt: {COMMA16}t{}Fart: {VELOCITY} Kraft: {COMMA16}hk{}Driftkostnader: {CURRENCY}/år{}Kapasitet: {STRING} +STR_885C_BROKEN_DOWN :{RED}Havarert +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Driftkostnad: {LTBLUE}{CURRENCY}/år +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Vekt: {LTBLUE}{COMMA16}t {BLACK}Kraft: {LTBLUE}{COMMA32}hk{BLACK} Maks. fart: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Inntekt i år: {LTBLUE}{CURRENCY} (sist år: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Pålitelighet: {LTBLUE}{COMMA8}% {BLACK}Havarier siden sist service: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Stoppet +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan ikke tvinge tog til å kjøre på rødt lyse ved fare... +STR_8863_CRASHED :{RED}Krasjet + +STR_8865_NAME_TRAIN :{WHITE}Navngi tog +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Kan ikke navngi tog... +STR_8867_NAME_TRAIN :{BLACK}Navngi tog +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Tog krasj!{}{COMMA16} dør i kollisjonen +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Kan ikke snu toget... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Gi tog/vogn nytt navn +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Kan ikke gi tog/vogn nytt navn... + +STR_TRAIN_STOPPING :{RED}Stopper +STR_TRAIN_STOPPING_VEL :{RED}Stopper, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Kjøretøy i veien +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Kjøretøy +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Garasje +STR_9004_NEW_VEHICLES :{BLACK}Nye kjøretøy +STR_9005_INFORMATION :{BLACK}Informasjon +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nye kjøretøy +STR_9007_BUILD_VEHICLE :{BLACK}Kjøp kjøretøy +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Koster: {GOLD}{CURRENCY}{BLACK} Fart: {GOLD}{VELOCITY}{}{BLACK}Driftkostnader: {GOLD}{CURRENCY}/år{}{BLACK}Kapasitet: {GOLD}{STRING}{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Levetid: {GOLD}{COMMA16} år{}{BLACK}Maks.pålitelighet: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan ikke kjøpe kjøretøy... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Må bygge garasje først +STR_900B_ORDERS :{WHITE}{STRING} (Ordre) +STR_900C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Driftkostnader: {LTBLUE}{CURRENCY}/år +STR_900E_MAX_SPEED :{BLACK}Maks. fart: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Inntekt i år: {LTBLUE}{CURRENCY} (sist år: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Pålitelighet: {LTBLUE}{COMMA8}% {BLACK}Havarier siden sist service: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Verdi: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapasitet: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}må være stoppet inni en garasje +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Kan ikke selge kjøretøy... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Kan ikke starte/stoppe kjøretøy... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Kjøretøy {COMMA16} er i garasjen +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Er på vei til {TOWN} garasje +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Er på vei til {TOWN} garasje, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kan ikke sende kjøretøy til garasje... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finne en garasje i nærheten +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Kjøretøy - trykk på kjøretøy for informasjon +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Bygg nye kjøretøy (krever en garasje) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Gjeldende kjøretøy status - trykk her for å stoppe/starte kjøretøy +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Vis kjøretøyet sin ordreliste +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Vis kjøretøyet sin gjeldende posisjon +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Send kjøretøy til en garasje +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Bytt kjøreretning +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Vis kjøretøy detaljer +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Kjøretøy liste - trykk på kjøretøy for mer informasjon +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Bygg nytt kjøretøy +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Dra kjøretøy her for å selge det +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Vis stedet garasjen ligger på +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Kjøretøy liste - trykk på kjøretøy for mer informasjon +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Bygg det valgte kjøretøyet +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt kjøretøy er nå tilgjengelig! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Koster: {CURRENCY}{}Fart: {VELOCITY}{}Driftkostnader: {CURRENCY}/år{}Kapasitet: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Navngi kjøretøy +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Kan ikke navngi kjøretøy... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Navngi kjøretøy +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Innbyggerne jubler . . .{}Første buss ankommer {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Innbyggerne jubler . . .{}Første lastebil ankommer {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Kollisjon!{}Sjåfør dør etter kollisjon med tog +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Kollisjon!{}{COMMA16} dør etter kollisjon med tog +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Kan ikke bytte kjøreretning... +STR_9034_RENAME :{BLACK}Endre navn +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Endre navnet til kjøretøytypen +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Endre navnet til kjøretøytypen +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Kan ikke endre navnet til kjøretøytypen... +STR_9038_GO_TO_ROADVEH_DEPOT :Kjør til {TOWN} garasje +STR_SERVICE_AT_ROADVEH_DEPOT :Service ved {TOWN} garasje + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Bygg havn +STR_9801_DOCK_CONSTRUCTION :{WHITE}Bygg havn +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Kan ikke bygge havn her... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Skipdepot +STR_9804_NEW_SHIPS :{BLACK}Nye skip +STR_9805_SHIPS :{WHITE}{STRING} - Skip +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Kan ikke bygge skip... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Må rive skipdepot først +STR_9808_NEW_SHIPS :{WHITE}Nye skip +STR_9809_BUILD_SHIP :{BLACK}Bygg skip +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Koster: {GOLD}{CURRENCY}{BLACK} Fart: {GOLD}{VELOCITY}{}{BLACK}Kapasitet: {GOLD}{STRING} {STRING}{}{BLACK}Driftkostnader: {GOLD}{CURRENCY}/år{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Levetid: {GOLD}{COMMA16} år{}{BLACK}Maks. Pålitelighet: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Må være stoppet inni i depotet +STR_980C_CAN_T_SELL_SHIP :{WHITE}Kan ikke selge skip... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Kan ikke bygge skip... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Det er et skip i veien +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Ordre) +STR_9811_DETAILS :{WHITE}{STRING} (Detaljer) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Driftkostnader: {LTBLUE}{CURRENCY}/år +STR_9813_MAX_SPEED :{BLACK}Maks. fart: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Inntekt i år: {LTBLUE}{CURRENCY} (sist år: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Pålitelighet: {LTBLUE}{COMMA8}% {BLACK}Havarier siden sist service: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Verdi: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapasitet: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Kan ikke starte/stoppe skip... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Kan ikke sende skip til depotet... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan ikke finne et depot i nærheten +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Er på vei mot {TOWN} skipdepot +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Er på vei mot {TOWN} skipdepot, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Skip {COMMA16} venter i depotet +STR_981D_BUILD_SHIP_DOCK :{BLACK}Bygg havn +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Bygg skipdepot (trengs for bygging og service av skip) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skip - trykk på skip for mer informasjon +STR_9820_BUILD_NEW_SHIP :{BLACK}Bygg nytt skip +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Dra skip her for å selge det +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Vis stedet depotet ligger på +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skip - trykk på skip for mer informasjon +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Bygg nytt skip (trenger et skipdepot) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Skip liste - trykk på skip for mer informasjon +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Bygg det valgte skipet +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Gjeldende skip status - trykk her for å stoppe/starte skip +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Vis skipet sine ordre +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Vis skipet sin gjeldende posisjon +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Send skipet til depotet +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Vis skip detaljer +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt skip er nå tilgjengelig! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Koster: {CURRENCY} Maks. fart: {VELOCITY}{}Kapasitet: {STRING}{}Driftkostnader: {CURRENCY}/år +STR_982F_NAME_SHIP :{BLACK}Navngi skip + +STR_9831_NAME_SHIP :{WHITE}Navngi skip +STR_9832_CAN_T_NAME_SHIP :{WHITE}Kan ikke navngi skip... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Innbyggerne jubler . . .{}Første skip ankommer {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Plasser bøye, kan brukes til å danne kontrollpunkter +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Kan ikke plassere bøye her... +STR_9836_RENAME :{BLACK}Endre navn +STR_9837_RENAME_SHIP_TYPE :{BLACK}Endre navnet til skiptypen +STR_9838_RENAME_SHIP_TYPE :{WHITE}Endre navnet til skiptypen +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Kan ikke endre navnet til skiptypen... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Bygg om et konteiner skip til å ta en annen type last +STR_983B_REFIT :{WHITE}{STRING} (Bygg om) +STR_983C_REFIT_SHIP :{BLACK}Bygg om skip +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Velg hvilken last skipet skal ta +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Bygg om skip til å frakte den valgte varetypen +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Velg varetype:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapasitet: {GOLD}{STRING}{}{BLACK}Kostnad for ombygging: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Kan ikke bygge om skip... +STR_9842_REFITTABLE :(ombyggbart) +STR_GO_TO_SHIP_DEPOT :Seil til {TOWN} skipdepot +SERVICE_AT_SHIP_DEPOT :Service ved {TOWN} skipdepot + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Bygg flyplass +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Kan ikke bygge flyplass her... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Hangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nytt fly +STR_A004_INFORMATION :{BLACK}Informasjon +STR_A005_NEW_AIRCRAFT :{WHITE}Nytt fly +STR_A006_BUILD_AIRCRAFT :{BLACK}Bygg fly +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Koster: {GOLD}{CURRENCY}{BLACK} Fart: {GOLD}{VELOCITY}{}{BLACK}Kapasitet: {GOLD}{COMMA16} passasjerer, {COMMA16} sekker post{}{BLACK}Driftkostnader: {GOLD}{CURRENCY}/år{}{BLACK}Designet: {GOLD}{NUMU16}{BLACK} Levetid: {GOLD}{COMMA16} år{}{BLACK}Maks. Pålitelighet: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Kan ikke bygge fly... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Fly +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Ordre) +STR_A00C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Alder: {LTBLUE}{STRING}{BLACK} Driftkostnader: {LTBLUE}{CURRENCY}/år +STR_A00E_MAX_SPEED :{BLACK}Maks. fart: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Inntekt i år: {LTBLUE}{CURRENCY} (sist år: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Pålitelighet: {LTBLUE}{COMMA8}% {BLACK}Havarier siden sist service: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Bygget: {LTBLUE}{NUMU16}{BLACK} Verdi: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Kan ikke sende fly til hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}Er på vei til {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Er på vei til {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Fly {COMMA16} venter i hangaren +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Det er et fly i veien +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Kan ikke stoppe/starte fly... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Flyet er i lufta +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Må bygge flyplass først +STR_A019_CAPACITY :{BLACK}Kapasitet: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapasitet: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Må være stoppet inni en hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Kan ikke selge fly... +STR_A01D_AIRPORT_CONSTRUCTION :Bygg flyplass +STR_A01E_BUILD_AIRPORT :{BLACK}Bygg flyplass +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Fly - trykk på fly for mer informasjon +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Bygg nytt fly (krever flyplass med hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Fly - trykk på fly for mer informasjon +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Bygg nytt fly +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Dra fly her for å selge +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Vis stedet hangaren ligger +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Fly liste - trykk på fly for mer informasjon +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Bygg det valge flyet +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Gjeldende fly status - trykk her for å stoppe/starte fly +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Vis flyet sine ordre +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Vis flyet sin gjeldende posisjon +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Send fly til hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Vis fly detaljer +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt fly er nå tilgjengelig +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Koster: {CURRENCY} Maks. fart: {VELOCITY}{}Kapasitet: {COMMA16} passasjerer, {COMMA16} sekker post {}Driftkostnader: {CURRENCY}/år + +STR_A030_NAME_AIRCRAFT :{WHITE}Navngi fly +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kan ikke navngi fly... +STR_A032_NAME_AIRCRAFT :{BLACK}Navngi fly +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Innbyggerne jubler . . .{}Første fly ankommer {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Fly krasj!{}{COMMA16} dør ved {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Stoppested: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Endre navn +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Endre navn til fly type +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Endre navn til fly type +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Kan ikke endre navn... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Bygg om et fly til å ta en annen type last +STR_A03C_REFIT :{WHITE}{STRING} (Refit) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Bygg om fly +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Velg hvilken last skipet skal ta +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Bygg om skip til å frakte den valgte varetypen +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Velg varetype:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapasitet: {GOLD}{STRING}{}{BLACK}Kostnad for ombygging: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Kan ikke bygge om fly... +STR_A043_REFITTABLE :(ombyggbart) +STR_GO_TO_AIRPORT_HANGAR :Fly til {STATION} hangar +SERVICE_AT_AIRPORT_HANGAR :Service ved {STATION} hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin ulykke på {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Kjøretøy ødelagt i 'UFO' kollisjon! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Eksplosjon på olje raffineri nær {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabrikk ødelagt på mistenkeligvis nær {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' lander nær {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Gruvegang kollaps danner et spor av ødeleggelser nær {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Ditt forsøk på bestikkelser +STR_BRIBE_FAILED_2 :{WHITE}har blitt oppdaget av en regional inspektør. diff --git a/lang/polish.txt b/lang/polish.txt new file mode 100644 --- /dev/null +++ b/lang/polish.txt @@ -0,0 +1,2450 @@ +##name Polish +##ownname Polski +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Poza krawedzia mapy +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Zbyt blisko krawedzi mapy +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Za malo pieniedzy - wymagane {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Wymagany plaski teren +STR_0008_WAITING :{BLACK}Czeka: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (w drodze z +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Akceptuje: {WHITE} +STR_000D_ACCEPTS :{BLACK}Akceptuje: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Pasazerowie +STR_0010_COAL :Wegiel +STR_0011_MAIL :Poczta +STR_0012_OIL :Ropa +STR_0013_LIVESTOCK :Zywiec +STR_0014_GOODS :Towary +STR_0015_GRAIN :Zboze +STR_0016_WOOD :Drewno +STR_0017_IRON_ORE :Ruda zelaza +STR_0018_STEEL :Stal +STR_0019_VALUABLES :Kosztownosci +STR_001A_COPPER_ORE :Ruda miedzi +STR_001B_MAIZE :Kukurydza +STR_001C_FRUIT :Owoce +STR_001D_DIAMONDS :Diamenty +STR_001E_FOOD :Zywnosc +STR_001F_PAPER :Papier +STR_0020_GOLD :Zloto +STR_0021_WATER :Woda +STR_0022_WHEAT :Pszenica +STR_0023_RUBBER :Guma +STR_0024_SUGAR :Cukier +STR_0025_TOYS :Zabawki +STR_0026_CANDY :Slodycze +STR_0027_COLA :Cola +STR_0028_COTTON_CANDY :Wata cukrowa +STR_0029_BUBBLES :Babelki +STR_002A_TOFFEE :Tofi +STR_002B_BATTERIES :Baterie +STR_002C_PLASTIC :Plastik +STR_002D_FIZZY_DRINKS :Napoje gazowane +STR_002E : +STR_002F_PASSENGER :Pasazerowie +STR_0030_COAL :Wegiel +STR_0031_MAIL :Poczta +STR_0032_OIL :Ropa +STR_0033_LIVESTOCK :Zywiec +STR_0034_GOODS :Towary +STR_0035_GRAIN :Zboze +STR_0036_WOOD :Drewno +STR_0037_IRON_ORE :Ruda zelaza +STR_0038_STEEL :Stal +STR_0039_VALUABLES :Kosztownosci +STR_003A_COPPER_ORE :Ruda miedzi +STR_003B_MAIZE :Kukurydza +STR_003C_FRUIT :Owoce +STR_003D_DIAMOND :Diamenty +STR_003E_FOOD :Zywnosc +STR_003F_PAPER :Papier +STR_0040_GOLD :Zloto +STR_0041_WATER :Woda +STR_0042_WHEAT :Pszenica +STR_0043_RUBBER :Guma +STR_0044_SUGAR :Cukier +STR_0045_TOY :Zabawki +STR_0046_CANDY :Slodycze +STR_0047_COLA :Cola +STR_0048_COTTON_CANDY :Wata cukrowa +STR_0049_BUBBLE :Babelki +STR_004A_TOFFEE :Tofi +STR_004B_BATTERY :Baterie +STR_004C_PLASTIC :Plastik +STR_004D_FIZZY_DRINK :Napoje gazowane +STR_004E : +STR_004F_PASSENGER :{COMMA16} pasazerow +STR_0050_TON_OF_COAL :{COMMA16} ton wegla +STR_0051_BAG_OF_MAIL :{COMMA16} paczek poczty +STR_0052_OF_OIL :{VOLUME} ropy +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} sztuk zywca +STR_0054_CRATE_OF_GOODS :{COMMA16} towarow +STR_0055_TON_OF_GRAIN :{COMMA16} ton zboza +STR_0056_TON_OF_WOOD :{COMMA16} ton drewna +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton rudy zelaza +STR_0058_TON_OF_STEEL :{COMMA16} ton stali +STR_0059_BAG_OF_VALUABLES :{COMMA16} kosztownosci +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton rudy miedzi +STR_005B_TON_OF_MAIZE :{COMMA16} ton kukurydzy +STR_005C_TON_OF_FRUIT :{COMMA16} ton owocow +STR_005D_BAG_OF_DIAMONDS :{COMMA16} paczek diamentow +STR_005E_TON_OF_FOOD :{COMMA16} ton zywnosci +STR_005F_TON_OF_PAPER :{COMMA16} ton papieru +STR_0060_BAG_OF_GOLD :{COMMA16} zlota +STR_0061_OF_WATER :{VOLUME} wody +STR_0062_TON_OF_WHEAT :{COMMA16} ton pszenicy +STR_0063_OF_RUBBER :{VOLUME} gumy +STR_0064_TON_OF_SUGAR :{COMMA16} ton cukru +STR_0065_TOY :{COMMA16} zabawek +STR_0066_BAG_OF_CANDY :{COMMA16} paczek slodyczy +STR_0067_OF_COLA :{VOLUME} coli +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton waty cukrowej +STR_0069_BUBBLE :{COMMA16} babelkow +STR_006A_TON_OF_TOFFEE :{COMMA16} ton tofi +STR_006B_BATTERY :{COMMA16} baterii +STR_006C_OF_PLASTIC :{VOLUME} plastiku +STR_006D_FIZZY_DRINK :{COMMA16} napoju gazowanego +STR_006E : +STR_006F_PASSENGERS :{COMMA16} pasazerow +STR_0070_TONS_OF_COAL :{COMMA16} ton wegla +STR_0071_BAGS_OF_MAIL :{COMMA16} paczek z poczta +STR_0072_OF_OIL :{VOLUME} ropy +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} sztuk zywca +STR_0074_CRATES_OF_GOODS :{COMMA16} towarow +STR_0075_TONS_OF_GRAIN :{COMMA16} ton zboza +STR_0076_TONS_OF_WOOD :{COMMA16} ton drewna +STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton rudy zelaza +STR_0078_TONS_OF_STEEL :{COMMA16} ton stali +STR_0079_BAGS_OF_VALUABLES :{COMMA16} kosztownosci +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton rudy miedzi +STR_007B_TONS_OF_MAIZE :{COMMA16} ton kukurydzy +STR_007C_TONS_OF_FRUIT :{COMMA16} ton owocow +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} diamentow +STR_007E_TONS_OF_FOOD :{COMMA16} ton zywnosci +STR_007F_TONS_OF_PAPER :{COMMA16} ton papieru +STR_0080_BAGS_OF_GOLD :{COMMA16} zlota +STR_0081_OF_WATER :{VOLUME} wody +STR_0082_TONS_OF_WHEAT :{COMMA16} ton pszenicy +STR_0083_OF_RUBBER :{VOLUME} gumy +STR_0084_TONS_OF_SUGAR :{COMMA16} ton cukru +STR_0085_TOYS :{COMMA16} zabawek +STR_0086_BAGS_OF_CANDY :{COMMA16} slodyczy +STR_0087_OF_COLA :{VOLUME} coli +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton waty cukrowej +STR_0089_BUBBLES :{COMMA16} babelkow +STR_008A_TONS_OF_TOFFEE :{COMMA16} ton tofi +STR_008B_BATTERIES :{COMMA16} baterii +STR_008C_OF_PLASTIC :{VOLUME} plastiku +STR_008D_FIZZY_DRINKS :{COMMA16} napojow gazowanych +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}CL +STR_0091_ML :{TINYFONT}ML +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}LV +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}GR +STR_0096_WD :{TINYFONT}WD +STR_0097_OR :{TINYFONT}OR +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VL +STR_009A_CO :{TINYFONT}CO +STR_009B_MZ :{TINYFONT}MZ +STR_009C_FT :{TINYFONT}FT +STR_009D_DM :{TINYFONT}DM +STR_009E_FD :{TINYFONT}FD +STR_009F_PR :{TINYFONT}PR +STR_00A0_GD :{TINYFONT}GD +STR_00A1_WR :{TINYFONT}WR +STR_00A2_WH :{TINYFONT}WH +STR_00A3_RB :{TINYFONT}RB +STR_00A4_SG :{TINYFONT}SG +STR_00A5_TY :{TINYFONT}TY +STR_00A6_SW :{TINYFONT}SW +STR_00A7_CL :{TINYFONT}CL +STR_00A8_CF :{TINYFONT}CF +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}TF +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}FZ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Mapa - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Opcje gry +STR_00B2_MESSAGE :{YELLOW}Wiadomosc +STR_00B3_MESSAGE_FROM :{YELLOW}Wiadomosc od {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Niemozna tego zrobic.... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Nie mozna wyczyscic terenu.... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, All rights reserved +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}Wersja OpenTTD {REV}: Language Pack by Tom and PolPot and Spooqy +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Designed & Programmed by Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Graphics by Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Wyjscie +STR_00C8_YES :{BLACK}Tak +STR_00C9_NO :{BLACK}Nie +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jestes pewny ze chcesz zakonczyc ta gre i wrocic do {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nic +STR_00D1_DARK_BLUE :Ciemno niebieski +STR_00D2_PALE_GREEN :Blado zielony +STR_00D3_PINK :Rozowy +STR_00D4_YELLOW :Zolty +STR_00D5_RED :Czerowny +STR_00D6_LIGHT_BLUE :Jasno niebieski +STR_00D7_GREEN :Zielony +STR_00D8_DARK_GREEN :Ciemno zielony +STR_00D9_BLUE :Niebieski +STR_00DA_CREAM :Kremowy +STR_00DB_MAUVE :Fiolkoworozowy +STR_00DC_PURPLE :Purpurowy +STR_00DD_ORANGE :Pomaranczowy +STR_00DE_BROWN :Brazowy +STR_00DF_GREY :Szary +STR_00E0_WHITE :Bialy +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Za duzo pojazdow w grze +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Lokalizacja +STR_00E5_CONTOURS :Uksztaltowanie +STR_00E6_VEHICLES :Pojazdy +STR_00E7_INDUSTRIES :Fabryki +STR_00E8_ROUTES :Drogi i koleje +STR_00E9_VEGETATION :Roslinnosc +STR_00EA_OWNERS :Wlasciciele +STR_00EB_ROADS :{BLACK}{TINYFONT}Drogi +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Koleje +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stacje/Lotniska/Doki +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Budynki/Fabryki +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Pojazdy +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Pociagi +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Samochody +STR_00F7_SHIPS :{BLACK}{TINYFONT}Statki +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Samoloty +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Trasy transportowe +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kopalnia wegla +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Elektrownia +STR_00FC_FOREST :{BLACK}{TINYFONT}Las +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Tartak +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Rafineria +STR_00FF_FARM :{BLACK}{TINYFONT}Farm +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabryka +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Drukarnia +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Pole naftowe +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Kopalnia rudy zelaza +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Huta +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Zaklady papiernicze +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Kopalnia zlota +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Przetwornia jedzenia +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Kopalnia diamentow +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Kopalnia rudy miedzi +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Sad +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Plantacja gumy +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Ujecie wody +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Wieza cisnien +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Tartak +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Las waty cukrowej +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Zaklad cukierniczy +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Farma baterii +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Studnie coli +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Zklep z zabawkami +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Fabryka zabawek +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Fontanny palstiku +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Fabryka napojow gazowanych +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Generator babelkow +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Kopalnia Tofi +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Kopalnia cukru +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Stacja kolejowa +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Zaladunek ciezarowek +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Przystanek +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Lotnisko +STR_011F_DOCK :{BLACK}{TINYFONT}Port +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Wyboista ziemia +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Trawa +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Odslonieta ziemia +STR_0123_FIELDS :{BLACK}{TINYFONT}Pola +STR_0124_TREES :{BLACK}{TINYFONT}Drzewa +STR_0125_ROCKS :{BLACK}{TINYFONT}Skaly +STR_0126_WATER :{BLACK}{TINYFONT}Woda +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Brak wlasciciela +STR_0128_TOWNS :{BLACK}{TINYFONT}Miasta +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Fabryki +STR_012A_DESERT :{BLACK}{TINYFONT}Pustynia +STR_012B_SNOW :{BLACK}{TINYFONT}Snieg +STR_012C_MESSAGE :{WHITE}Wiadomosc +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Anuluj +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Zmien nazwe +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Za duzo zdefiniowanych nazw +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Nazwa jest juz uzywana + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Brytyjski (mile) +STR_013A_METRIC_KILOMETERS :Metryczny (kilometry) +STR_013B_OWNED_BY :{WHITE}...w posiadaniu {STRING} +STR_013C_CARGO :{BLACK}Ladunek +STR_013D_INFORMATION :{BLACK}Informacja +STR_013E_CAPACITIES :{BLACK}Pojemnosc +STR_013E_TOTAL_CARGO :{BLACK}Calkowity ladunek +STR_013F_CAPACITY :{BLACK}Pojemnosc: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Calkowita pojemnosc tego pociagu: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nowa gra +STR_0141_LOAD_GAME :{BLACK}Zaladuj gre +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Wprowadzenie/Demo +STR_SINGLE_PLAYER :{BLACK}Single player +STR_MULTIPLAYER :{BLACK}Multiplayer + +STR_0148_GAME_OPTIONS :{BLACK}Opcje gry + +STR_0150_SOMEONE :ktos{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Mapa swiata +STR_0152_TOWN_DIRECTORY :Lista miast +STR_0153_SUBSIDIES :Subsydia + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Wykres obrotu +STR_0155_INCOME_GRAPH :Wykres przychodow +STR_0156_DELIVERED_CARGO_GRAPH :Wykres przewozonego ladunku +STR_0157_PERFORMANCE_HISTORY_GRAPH :Historia dokonan +STR_0158_COMPANY_VALUE_GRAPH :Wykres wartosci firmy +STR_0159_CARGO_PAYMENT_RATES :Stawki za ladunek +STR_015A_COMPANY_LEAGUE_TABLE :Wykres Ligi Firm +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Zapisz gre +STR_015D_LOAD_GAME :Wczytaj gre +STR_015E_QUIT_GAME :Opusc gre +STR_015F_QUIT :Wyjscie +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jestes pewny ze chesz skonczyc gre? +STR_0161_QUIT_GAME :{WHITE}Wyjscie + +############ range for months starts +STR_0162_JAN :Sty +STR_0163_FEB :Lut +STR_0164_MAR :Mar +STR_0165_APR :Kwi +STR_0166_MAY :Maj +STR_0167_JUN :Cze +STR_0168_JUL :Lip +STR_0169_AUG :Sie +STR_016A_SEP :Wrz +STR_016B_OCT :Paz +STR_016C_NOV :Lis +STR_016D_DEC :Gru +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pauza +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Zapis gry, opuszczenie gry, wyjscie +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Wyswietl liste stacji firmy +STR_0174_DISPLAY_MAP :{BLACK}Wyswietl mape +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Wyswietl mape, liste miast +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Wyswietl liste miast +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Wyswietl informacje finansowe firmy +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Wyswietl informacje ogolne firmy +STR_0179_DISPLAY_GRAPHS :{BLACK}Wyswietl wykresy +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Wyswietl tabele firm +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Wyswietl liste pociagow firmy +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Wyswietl liste samochodow firmy +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Wyswietl liste statkow firmy +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Wyswietl liste samolotow firmy +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Przyblizenie +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Oddalenie +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Budowa torow kolejowych +STR_0182_BUILD_ROADS :{BLACK}Budowa drog +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Budowa portow +STR_0184_BUILD_AIRPORTS :{BLACK}Budowa lotnisk +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Roslinnosc, znaki komunikacyjne itp +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Informacje o terenie +STR_0187_OPTIONS :{BLACK}Opcje +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Nie mozna zmienic okresu miedzy serwisowaniem... +STR_018B_CLOSE_WINDOW :{BLACK}Zamkniecie okna +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Tytul okienka - przeciagnij to by ruszyc oknem +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Niszczenie budynkow itp w danym kwadracie terenu +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Nizszy naroznik terenu +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Wyzszy naroznik terenu +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Pazsek przesuwu - przesuwa liste gora/dol +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Pokaz zarysy ladu na mapie +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Pokaz pojazdy na mapie +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Pokaz przedsiebiorstwa na mapie +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Pokaz drogi na mapie +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Pokaz roslinnosc na mapie +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Pokaz teren majacy wlasciciela +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Przelacz wyswietlanie nazw miast na mapie +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Zysk w tym roku: {CURRENCY} (ostatni rok: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} rok ({COMMA16}) +STR_019A_YEARS :{COMMA16} lata ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} lata ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Samochod +STR_019D_AIRCRAFT :Samolot +STR_019E_SHIP :Statek +STR_019F_TRAIN :Pociag +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} jest stary +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} jest bardzo stary +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} jest bardzo stary i natychmiast wymaga wymiany +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacja o terenie +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Koszt czyszczenia: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Koszt czyszczenia: {LTBLUE}{CURRENCY} +STR_01A6_N_A :Brak +STR_01A7_OWNER :{BLACK}Wlasciciel: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Lokalne wladze: {LTBLUE}{STRING} +STR_01A9_NONE :Brak +STR_01AA_NAME :{BLACK}Nazwa +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1szy +STR_01AD_2ND :2gi +STR_01AE_3RD :3ci +STR_01AF_4TH :4ty +STR_01B0_5TH :5ty +STR_01B1_6TH :6ty +STR_01B2_7TH :7my +STR_01B3_8TH :8my +STR_01B4_9TH :9ty +STR_01B5_10TH :10ty +STR_01B6_11TH :11ty +STR_01B7_12TH :12ty +STR_01B8_13TH :13ty +STR_01B9_14TH :14ty +STR_01BA_15TH :15ty +STR_01BB_16TH :16ty +STR_01BC_17TH :17ty +STR_01BD_18TH :18ty +STR_01BE_19TH :19ty +STR_01BF_20TH :20ty +STR_01C0_21ST :21szy +STR_01C1_22ND :22gi +STR_01C2_23RD :23ci +STR_01C3_24TH :24ty +STR_01C4_25TH :25ty +STR_01C5_26TH :26ty +STR_01C6_27TH :27my +STR_01C7_28TH :28my +STR_01C8_29TH :29ty +STR_01C9_30TH :30ty +STR_01CA_31ST :31szy +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Przelaczanie miedzy duza/mala mapa +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Wybierz Wprowadzenie/Demo + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Akceptowany ladunek: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Akceptowany ladunek: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Akceptowany ladunek: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Dzwiek/muzyka +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Pokaz okno dzwiek/muzyka +STR_01D5_ALL :{TINYFONT}Wszystko +STR_01D6_OLD_STYLE :{TINYFONT}Stary styl +STR_01D7_NEW_STYLE :{TINYFONT}Nowy styl +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Wlasny 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Wlasny 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Glosnosc muzyki +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Glosnosc efektow dzwiekowych +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Przejdz do nastepnej sciezki +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Przejdz do nastepnej sciezki +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Zatrzymaj muzyke +STR_01E1_START_PLAYING_MUSIC :{BLACK}Odgrywaj muzyke +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Przesun suwaki zeby ustawic glosnosc dzwiekow i muzyki +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Sciezka{SETX 88}Tytul +STR_01E9_SHUFFLE :{TINYFONT}Przypadkowo +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Wybor Programu +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Wykaz sciezek +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Programuj - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Wyczysc +STR_01F1_SAVE :{TINYFONT}{BLACK}Zapisz +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Obecny program sciezek +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Wybierz program 'Wszystko' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Wybierz program 'Stary styl' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Wybierz program 'Nowy styl' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Wybierz program 'Wlasny 1' (definiowany) +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Wybierz program 'Custom 2' (definiowany) +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Wyczysc obecny program (tylko Wlasny1 lub Wlasny2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Zapisz ustawienia na dysk +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klik na sciezce aby dodac do obecnego programu (Wlasny1 i Wlasny2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Przelacz przypandkowo on/off +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Pokaz okno wyboru sciezek +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klik na usludze zeby wysrodkowac widok na Fabryke/Miasto +STR_01FE_DIFFICULTY :{BLACK}Trudnosc ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Ostatnia wiadomosc/ogloszenie +STR_0201_MESSAGE_SETTINGS :Ustawienia wiadomosci +STR_MESSAGE_HISTORY_MENU :Poprzednie wiadomosci +STR_0202_SEND_MESSAGE :Wyslij wiadomosc +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Pokaz ostatnia wiadomosc/ogloszenie, pokaz ustawienia wiadomosci +STR_0204_MESSAGE_OPTIONS :{WHITE}Opcje wiadomosci +STR_0205_MESSAGE_TYPES :{BLACK}Typy wiadomosci:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Przybyl pierwszy pojazd do stacji gracza +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Przybyl pierwszy pojazd do stacji przeciwnika +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Wypadki / kleski +STR_0209_COMPANY_INFORMATION :{YELLOW}Informacja firmy +STR_020A_ECONOMY_CHANGES :{YELLOW}Zmiany ekonomiczne +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Porady / informacje o pojazdach gracza +STR_020C_NEW_VEHICLES :{YELLOW}Nowe pojazdy +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Zamiany w akceptowaniu ladunku +STR_020E_SUBSIDIES :{YELLOW}Subsydia +STR_020F_GENERAL_INFORMATION :{YELLOW}Ogolne informacje +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...zbyt daleko od poprzedniego celu +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Pierwsza firma ktora osiagnie 2050{}({STRING} Poziom) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Biznesmen +STR_0214_ENTREPRENEUR :Przedsiebiorca +STR_0215_INDUSTRIALIST :Przemyslowiec +STR_0216_CAPITALIST :Kapitalista +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon Stulecia +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} osiaga status: '{STRING}'! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} {STRING} osiaga status: '{STRING}'! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Tworzenie scenariusza +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Edytor scenariusza +STR_0223_LAND_GENERATION :{WHITE}Generowanie ladu +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Przypadkowy lad +STR_0227_RESET_LAND :{BLACK}Kasowanie ladu +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Zwieksz powierzchnie do podwyzszenia/obnizenia +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Zmniejsz powierzchnie do podwyzszenia/obnizenia +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Geneowanie przypadkowego ladu +STR_022B_RESET_LANDSCAPE :{BLACK}Resetuj krajobraz +STR_022C_RESET_LANDSCAPE :{WHITE}Resetuj krajobraz +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Jestes pewien ze chcesz zrestetowac krajobraz? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Generacja krajobrazu +STR_022F_TOWN_GENERATION :{BLACK}Generacja miast +STR_0230_INDUSTRY_GENERATION :{BLACK}Generacja fabryk +STR_0231_ROAD_CONSTRUCTION :{BLACK}Konstrukcja drog +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Roslinnosc i inne obiekty +STR_0233_TOWN_GENERATION :{WHITE}Generacja miast +STR_0234_NEW_TOWN :{BLACK}Nowe miasto +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Zbuduj nowe miasto +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Nie mozna tutaj zbudowac miasta... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...zbyt blisko krawedzi mapy +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...zbyt bliko innego miasta +STR_0239_SITE_UNSUITABLE :{WHITE}...niewlasciwa parcela +STR_023A_TOO_MANY_TOWNS :{WHITE}...zbyt wiele miast +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Zwieksz rozmar miasta +STR_023C_EXPAND :{BLACK}Rozszerz +STR_023D_RANDOM_TOWN :{BLACK}Dowolne miasto +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Budowanie miasta w przyadkowym miejsu +STR_023F_INDUSTRY_GENERATION :{WHITE}Generacja Fabryk +STR_0240_COAL_MINE :{BLACK}Kopalnia wegla +STR_0241_POWER_STATION :{BLACK}Elektrownia +STR_0242_SAWMILL :{BLACK}Tartak +STR_0243_FOREST :{BLACK}Las +STR_0244_OIL_REFINERY :{BLACK}Refineria +STR_0245_OIL_RIG :{BLACK}Platforma wiertnicza +STR_0246_FACTORY :{BLACK}Fabryka +STR_0247_STEEL_MILL :{BLACK}Huta +STR_0248_FARM :{BLACK}Farma +STR_0249_IRON_ORE_MINE :{BLACK}Kopalnia rudy zelaza +STR_024A_OIL_WELLS :{BLACK}Pole naftowe +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Zaklady papiernicze +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Przetwornia jedzenia +STR_024E_PRINTING_WORKS :{BLACK}Drukarnia +STR_024F_GOLD_MINE :{BLACK}Kopalnia zlota +STR_0250_LUMBER_MILL :{BLACK}Tartak +STR_0251_FRUIT_PLANTATION :{BLACK}Sad +STR_0252_RUBBER_PLANTATION :{BLACK}Plantatacja gumy +STR_0253_WATER_SUPPLY :{BLACK}Zbiornik wody +STR_0254_WATER_TOWER :{BLACK}Wieza wody +STR_0255_DIAMOND_MINE :{BLACK}Kopalnia diamentow +STR_0256_COPPER_ORE_MINE :{BLACK}Kopalnia rudy miedzi +STR_0257_COTTON_CANDY_FOREST :{BLACK}Las waty cukrowej +STR_0258_CANDY_FACTORY :{BLACK}Zaklady +STR_0259_BATTERY_FARM :{BLACK}Farma Baterii +STR_025A_COLA_WELLS :{BLACK}Studnie Coli +STR_025B_TOY_SHOP :{BLACK}Sklep z zabawkami +STR_025C_TOY_FACTORY :{BLACK}Fabryka zabawek +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Fontanny plastiku +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Fabryka napojow gazowanych +STR_025F_BUBBLE_GENERATOR :{BLACK}Generator babelkow +STR_0260_TOFFEE_QUARRY :{BLACK}Kopalnia tofi +STR_0261_SUGAR_MINE :{BLACK}Kopalnia cukru +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Zbuduj Kopalnie wegla +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Zbuduj Elektrownie +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Zbuduj Tartak +STR_0265_PLANT_FOREST :{BLACK}Posadz Las +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Zbuduj Rafinerie +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Zbuduj Platforme wiernicza (Mozna zbudowac tylko przy krawedzi mapy) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Zbuduj Fabryke +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Zbuduj Hutel +STR_026A_CONSTRUCT_FARM :{BLACK}Zbuduj Farme +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Zbuduj Kopalnie rudy zelaza +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Zbuduj Pole naftowe +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Zbuduj Bank (Mozna zbudowac tylko w miastach z populacja wieksza niz 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Zbuduj Zaklady Papiernicze +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Zbuduj Przetwornie jedzenia +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Zbuduj Drukarnie +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Zbuduj Kopalnie zlota +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Zbuduj Bank (Mozna zbudowac tylko w miastach) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Zbuduj Tartak (aby wyczyscic las deszczowy i wyprodukowac drewno) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Posadz Plantacje owocow +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Posadz Plantacje gumy +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Zbuduj Ujecie wody +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Zbuduj Wieze cisnien (Mozna zbudowac tylko w miastach) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Zbuduj Kopalnie diamentow +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Zbuduj Kopalnie rudy miedzi +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Posadz Las waty cukrowej +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Zbuduj Cukiernie +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Zbuduj Farme Baterii +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Zbuduj Studnie Coli +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Zbuduj Sklep z zabawkami +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Zbuduj Fabryke zabawek +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Zbuduj Fontanny plastiku +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Zbuduj Fabryke napojow gazowanych +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Zbuduj Generator babelkow +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Zbuduj Kopalnie tofi +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Zbuduj Kopalnie cukru +STR_0285_CAN_T_BUILD_HERE :{WHITE}Nie mozna wybudowac tutaj: {STRING}... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...najpierw trzeba wybudowac miasto +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...dozwolone jedno na miasto +STR_0288_PLANT_TREES :{BLACK}Posadz drzewa +STR_0289_PLACE_SIGN :{BLACK}Umiesc napis +STR_028A_RANDOM_TREES :{BLACK}Dowolne drzewa +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Zasadz drzewa dowolnie +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Umiesc kamieniste tereny +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Umiesc Latarnie morska +STR_028E_PLACE_TRANSMITTER :{BLACK}Umiesc Antene +STR_028F_DEFINE_DESERT_AREA :{BLACK}Zdefiniuj teren pustyni +STR_0290_DELETE :{BLACK}Skasuj +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Skasuj to miasto calkowicie +STR_0292_SAVE_SCENARIO :Zapisz scenariusz +STR_0293_LOAD_SCENARIO :Wczytaj scenariusz +STR_0294_QUIT_EDITOR :Wyjdz z edytora +STR_0295 : +STR_0296_QUIT :Wyjscie +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Zapis scenariusza, wczytnie scenariusza, wyjscie z edytora, wyjscie +STR_0298_LOAD_SCENARIO :{WHITE}Wczytaj scenariusz +STR_0299_SAVE_SCENARIO :{WHITE}Zapisz scenariusz +STR_029A_PLAY_SCENARIO :{BLACK}Zagraj scenariusz +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Jestes pewny ze chcesz opuscic scenariusz? +STR_029C_QUIT_EDITOR :{WHITE}Wyjscie z edytora +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...mozna zbudowac jedynie w miastach o populacji przynajmniej 1200 +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Zmien date poczatkawa w tyl o 1 rok +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Zmien date poczatkawa do przodu o 1 rok +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...konce mostu musza znajdowac sie na ladzie +STR_02A1_SMALL :{BLACK}Male +STR_02A2_MEDIUM :{BLACK}Srednie +STR_02A3_LARGE :{BLACK}Duze +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Wybierz wielkosc miasta +STR_02A5_TOWN_SIZE :{YELLOW}Wielkosc miasta: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Pokaz ostatnia wiadomosc lub ogloszenie +STR_02B8_SUMMARY :{BLACK}Sumarycznie +STR_02B9_FULL :{BLACK}Pelne +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Lista miast +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Nazwy pojazdow +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Domyslne +STR_02BF_CUSTOM :Wlasne +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Zapisz wlasne nazwy na dysk +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Wybor nazw pojazdow +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Zapisz niestandardowe nazwy pojazdow na dysk + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Opcje gry +STR_02C4_GAME_OPTIONS :Opcje gry +STR_02C5_DIFFICULTY_SETTINGS :Ustawienia trudnosci +STR_02C6_DIFFICULTY_SETTINGS :Ustawienia trudnosci +STR_02C7_CONFIG_PATCHES :Konfiguracja patcha +STR_02C8_CONFIG_PATCHES :Konfiguracja patcha +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Wyswietlanie nazw miast +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Wyswietlanie nazw miast +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Wyswietlanie nazw stacji +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Wyswietlanie nazw stacji +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Wyswietlanie znakow +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Wyswietlanie znakow +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Wyswietlanie punktow kontrolnych +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Wyswietlanie punktow kontrolnych +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Pelna animacja +STR_02D0_FULL_ANIMATION :{SETX 12}Pelna animacja +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Wszystkie detale +STR_02D2_FULL_DETAIL :{SETX 12}Wszystkie detale +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Przezroczyste budynki +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Przezroczyste budynki +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Info o terenie. +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Zrzut ekranu (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Gigantyczny zrzut(Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Info o 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}Wla. +STR_02DB_OFF :{BLACK}Wyl. +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Wyswietl subsydia +STR_02DD_SUBSIDIES :Subsydia +STR_02DE_MAP_OF_WORLD :Mapa swiata +STR_02DF_TOWN_DIRECTORY :Lista miast +STR_02E0_CURRENCY_UNITS :{BLACK}Waluta +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Wybor waluty +STR_02E3_DISTANCE_UNITS :{BLACK}Jednostki miary +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Wybor jednostek odleglosci +STR_02E6_ROAD_VEHICLES :{BLACK}Pojazdy drogowe +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Wybierz strone po ktorej maja jezdzic samochody +STR_02E9_DRIVE_ON_LEFT :Jazda po lewej +STR_02EA_DRIVE_ON_RIGHT :Jazda po prawej +STR_02EB_TOWN_NAMES :{BLACK}Nazwy miast +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Wybierz styl nazw miast + +STR_02F4_AUTOSAVE :{BLACK}Autozapis +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Wybierz przerwy pomiedzy autozapisami +STR_02F7_OFF :Wyl +STR_02F8_EVERY_3_MONTHS :Co 3 miesiace +STR_02F9_EVERY_6_MONTHS :Co 6 miesiecy +STR_02FA_EVERY_12_MONTHS :Co 12 miesiecy +STR_02FB_START_A_NEW_GAME :{BLACK}Rozpocznij nowa gre +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Wczytanie i zapis gry na dysk +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Zobacz demo/tutorial +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Stworz wlasny swiat/scenariusz +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Wybor jednego gracza +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Wybor dwoch graczy +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Wyswietl opcje gry +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Wyswietl opcje trudnosci +STR_0303_START_A_NEW_GAME_USING :{BLACK}Rozpocznij gre uzywajac wlasnego scenariusza +STR_0304_QUIT :{BLACK}Wyjscie +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Opusc 'OpenTTD', i wyjdz +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Zobacz demo/wprowadzenie +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...moze byc wybudowane tylko w miescie +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Wybierz krajobraz 'Umiarkowany' +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Wybierz krajobraz 'Arktyczny' +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Wybierz krajobraz 'Tropicalny' +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Wybierz krajobraz 'Zabawkowy' +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Ufunduj budowe nowego przedsieb. + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Ufunduj nowe przedsieb. +STR_INDUSTRY_DIR :Katalog fabryk +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Ufundowanie nowego przedsieb. +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...moze byc wybudowane tylko w miescie +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...moze byc wybudowane tylko w lasach deszczowych +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...moze byc wybudowane tylko na pustyni +STR_0319_PAUSED :{YELLOW}* * PAUZA * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Zrzut ekranu zapisany na dysk z powodzeniem {STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Blad zrzutu ekranu! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}nabyj teren do przyszlego uzycia +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Serwis samochodow +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Serwis pociagow +STR_032C_3_AIR_SERVICE :{BLACK}3: Serwis samolotow +STR_032D_4_SHIP_SERVICE :{BLACK}4: Serwis statkow +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Serwis pociagow (zaawansowany) +STR_032F_AUTOSAVE :{RED}AUTOZAPIS +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Wybierz program 'Ezy Street' + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Angielskie +STR_TOWNNAME_FRENCH :Francuskie +STR_TOWNNAME_GERMAN :Niemieckie +STR_TOWNNAME_AMERICAN :Amerykanskie +STR_TOWNNAME_LATIN_AMERICAN :Poludniowoamerykanskie +STR_TOWNNAME_SILLY :Glupie +STR_TOWNNAME_SWEDISH :Szwedzkie +STR_TOWNNAME_DUTCH :Holenderskie +STR_TOWNNAME_FINNISH :Finskie +STR_TOWNNAME_POLISH :Polskie +STR_TOWNNAME_SLOVAKISH :Slowackie +STR_TOWNNAME_HUNGARIAN :Wegierskie +STR_TOWNNAME_AUSTRIAN :Austriackie +############ end of townname region + +STR_CURR_POUNDS :Funty ({POUNDSIGN}) +STR_CURR_DOLLARS :Dolary ($) +STR_CURR_FF :Franki (FF) +STR_CURR_DM :Marki (DM) +STR_CURR_YEN :Jeny ({YENSIGN}) +STR_CURR_PT :Pesety (Pt) +STR_CURR_FT :Forinty (Ft) +STR_CURR_ZL :Zloty (zl) +STR_CURR_ATS :Szylingi (ATS) +STR_CURR_BEF :Franki belgijskie (BEF) +STR_CURR_DKK :Korony dunskie (DKK) +STR_CURR_FIM :Marki finskie (FIM) +STR_CURR_GRD :Drachmy (GRD) +STR_CURR_CHF :Franki szwajcarskie (CHF) +STR_CURR_NLG :Guldeny (NLG) +STR_CURR_ITL :Liry (ITL) +STR_CURR_SEK :Korony szweckie (SEK) +STR_CURR_RUR :Ruble (rur) +STR_CURR_CZK :Korony czeskie (CZK) +STR_CURR_ISK :Korony islandzckie (ISK) +STR_CURR_NOK :Korony norweskie (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Jezyk +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Wybierz jezyk interfejsu + +STR_OPTIONS_RES :{BLACK}Rozdzielczosc ekranu +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Wybierz rozdzielczosc ekranu + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Format zrzutu ekranu +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Wybierz format zrzutu ekranu + +STR_AUTOSAVE_1_MONTH :Kazdego miesiaca +STR_AUTOSAVE_FAILED :{WHITE}Blad autozapisu + +STR_MONTH_JAN :Styczen +STR_MONTH_FEB :Luty +STR_MONTH_MAR :Marzec +STR_MONTH_APR :Kwiecien +STR_MONTH_MAY :Maj +STR_MONTH_JUN :Czerwiec +STR_MONTH_JUL :Lipiec +STR_MONTH_AUG :Sierpien +STR_MONTH_SEP :Wrzesien +STR_MONTH_OCT :Pazdziernik +STR_MONTH_NOV :Listopad +STR_MONTH_DEC :grudzien + +STR_HEADING_FOR_STATION :{LTBLUE}Zmierza do {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Zmierza do {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Bez polecen +STR_NO_ORDERS_VEL :{LTBLUE}Bez polecen, {VELOCITY} + +STR_PASSENGERS :pasazerow +STR_BAGS :workow +STR_TONS :ton +STR_LITERS :litrow +STR_ITEMS :sztuk +STR_CRATES :skrzyn +STR_RES_OTHER :inne +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Nie mozna wspoldzielic polecen... +STR_CANT_COPY_ORDER_LIST :{WHITE}Nie mozna skopiowac listy polecen... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Koniec wspoldz. polecen - - + +STR_TRAIN_IS_LOST :{WHITE}Pociag {COMMA16} zabladzil. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Pociag {COMMA16} zarobil w zeszlym roku {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Konfiguracja Patcha +STR_CONFIG_PATCHES_TIP :{BLACK}Konfiguracja Patcha +STR_CONFIG_PATCHES_CAPTION :{WHITE}Konfiguracja Patcha + +STR_CONFIG_PATCHES_OFF :Wyl +STR_CONFIG_PATCHES_ON :Wla +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Pokazuj predkosc pojazdow w pasku statusu: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Pozwol budowac na pochylosciach i wybrzezach: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Pozwol usuwac wiecej drog, mostow, tuneli etc. nalezacych do miasta: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Pozwol budowac bardzo dlugie pociagi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Realistyczne przyspieszenie pociagow: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Polacz stacje budowane jedna obok drugiej: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Wyjazd ze stacji gdy jakis towar jest pelny, gdy 'Zaladunek': {ORANGE}{STRING} +STR_CONFIG_PATCHES_INFLATION :{LTBLUE}Inflacja: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Bez auomatycznego servisowania pociagow: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Dostarcz ladunek do stacji tylko jesli jest zapotrzebowanie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Pozwol budowac bardzo dlugie mosty: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Allow goto depot orders: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Pozwol budowac obiekty produkujace surowce: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Pozwol na wiele podobnych przedsiebiorstw w miescie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Przedsiebiorstwa jednego typu moga byc bud. obok siebie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Zawsze pokazuj date w dlugim formacie w pasku statusu: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Pokazuj semafory po stronie jazdy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Pokazuj okno finansow na koniec roku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch compatible nonstop handling: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Kolejki samochodow (with quantum effects): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Przesun okno kiedy kursor jest przy krawedzi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Pozwol dawac lapowki lok. wladzom: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Szukanie nowych zajezdni: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Niejednolite stacje: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Nowy algorytm szukania drogi dla pociagow: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Budowanie w czasie pauzy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Zawsze zezwalaj budowac male lotniska: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Pociag zagubil sie jesli nie porusza sie przez: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Ostrzegaj jesli pociag przynosi straty: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES:{LTBLUE}Pojazdy nigdy nie starzeja sie: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Automatycznie odnow pojazd kiedy sa stare +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Czas trwania komunikatu o bledzie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Wysokosc granicy wiecznych sniegow: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maks wielkosc stacji: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Serwisuj helikoptery na lotniskach automatycznie: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maks liczba pociagow na gracza: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maks liczba samochodow na gracza: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maks liczba samolotow na gracza: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maks liczba statkow na gracza: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Pociagi niedostepne dla komputera: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Samochody niedostepne dla komputera: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Samoloty niedostepne dla komputera: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Statki niedostepne dla komputera: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Domyslny okres miedzy serwis. dla pociagow: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Domyslny okres miedzy serwis. dla samochodow: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Domyslny okres miedzy serwis. dla samolotow: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Domyslny okres miedzy serwis. dla statkow: {ORANGE}{STRING} dni + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Pojawianie sie kolorowych wiadomosci w: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Data rozpoczecia: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Pozwol na lagodna ekonomie (male zmiany) + +STR_CONFIG_PATCHES_GUI :{BLACK}Interfejs +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstrukcje +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Pojazdy +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stacje +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Ekonomia + +STR_CONFIG_PATCHES_DISABLED :niedostepne +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Zmiana wartosci + + +STR_CHEATS :{WHITE}Tricki +STR_CHEATS_TIP :{BLACK}Checkboxy pokazuja czy uzywano juz tego tricku +STR_CHEATS_WARNING :{BLACK}Uwaga! Wlasnie chcesz zdradzic swoich wspolnikow. Zwaz, ze zostanie to zapamietane na wieki! +STR_CHEAT_MONEY :{LTBLUE}Zwieksz ilosc pieniedzy o {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Gra jako gracz: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magiczny buldozer (usuwanie przedsiebiorstw etc.): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunele moga sie krzyzowac: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Nazwa +STR_TOWNDIR_POPULATION :{BLACK}Populacja +STR_TOWNDIR_SORT_TIP :{BLACK}Wybierz porzadek sortowania + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Zmierza do {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Zmierza do {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Idz przez {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Pkt. kontrolny {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Pkt. kontrolny {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Pkt. kontrolny + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Edytuj nazwe pkt. kontrolnego + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Nie mozna zmienic nazwy pkt. kontrolnego... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Zmiana torow na pkt. kontrolny +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Nie mozna zbudowac pkt. kontolnego tutaj... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Nie mozna usunac pkt. kontolnego z tego miejsca... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Budowanie torow uzywajac trybu Autorail + +STR_NO_TOWN_IN_SCENARIO :{WHITE}...niema zadnego miasta w scenariuszu + +STR_GENERATE_RANDOM_LANDSCAPE :{WHITE}Jestes pewny ze chcesz stworzyc przypadkowy krajobraz? +STR_MANY_RANDOM_TOWNS :{BLACK}Wiele przypadkowych miast +STR_RANDOM_TOWNS_TIP :{BLACK}Pokryj mape przypadkowo polozonymi miastami +STR_MANY_RANDOM_INDUSTRIES :{BLACK}Wiele przypadkowych obiek. przyemyslowych +STR_RANDOM_INDUSTRIES_TIP :{BLACK}Pokryj mape przypadkowo polozonymi przesiebiorstwami +STR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nie mozna wygenerowac przesiebiorstw... + +STR_LANDSCAPING_TOOLBAR :{WHITE}Krajobraz +STR_LEVEL_LAND_TOOLTIP :{BLACK}Poziom ladu + + +STR_TREES_RANDOM_TYPE :{BLACK}Drzewa roznych rodzajow +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Sadzenie drzew roznych rodzajow + +STR_CANT_BUILD_CANALS :{WHITE}Nie mozna tutaj wybudowac kanalu... +STR_BUILD_CANALS_TIP :{BLACK}Buduj kanaly +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Nie mozna tutaj wybudowac sluzy... +STR_BUILD_LOCKS_TIP :{BLACK}Buduj sluzy +STR_LANDINFO_LOCK :Sluza + +STR_LANDINFO_COORDS :{BLACK}Pozycja: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Nie mozna usunac czesci stacji... +STR_CANT_CONVERT_RAIL :{WHITE}Nie mozna zmienic typu torow w tym miejscu... +STR_CONVERT_RAIL_TIP :{BLACK}Zamiana/Unowoczesnienie typu torow + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Przeciagnij tutaj lokomotywe by sprzedac caly pociag + +STR_DRAG_DROP :{BLACK}Przeciagnij i upusc +STR_STATION_DRAG_DROP :{BLACK}Budowanie stacji uzywajac przeciagnij i upusc + +STR_FAST_FORWARD :{BLACK}Szybkie przewijanie w grze +STR_MESSAGE_HISTORY :{WHITE}Poprzednie wiadomosci +STR_MESSAGE_HISTORY_TIP :{BLACK}List ostatnich wiadomosci +STR_MESSAGES_DISABLE_ALL :{BLACK}Wylacz wszystko +STR_MESSAGES_ENABLE_ALL :{BLACK}Wlacz wszystko + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Wybuduj kopalnie wegla +STR_CONSTRUCT_FOREST_TIP :{BLACK}Posadz las +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Zbuduj platforme wiertnicza +STR_CONSTRUCT_FARM_TIP :{BLACK}Wybuduj farme +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Wybuduj kopalnie rudy miedzi +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Odwiert do ropy +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Wybuduj kopalnie zlota +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Wybuduj kopalnie diamentow +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Wybuduj kopalnie rudy zelaza +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Posadz plantacje owocow +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Posadz plantacje gumy +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Zbuduj ujecie wody +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Posadz las waty cukrowej +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Zbuduj farme baterii +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Odwiert do coli +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Zbuduj fontanny plastiku +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Zbuduj generator babelkow +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Zbuduj kopalnie toffi +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Wybuduj kopalnie cukru + +STR_INDUSTRYDIR_NAME :{BLACK}Nazwa +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produkcja +STR_INDUSTRYDIR_TYPE :{BLACK}Typ +STR_INDUSTRYDIR_TRANSPORTED :{BLACK}Transported +STR_INDUSTRYDIR_CAPTION :{WHITE}Przemysl +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_TWO :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}/{STRING}){YELLOW} ({COMMA16}%/{COMMA16}% transported) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...zbyt blisko innego przedsiebiorstwa + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Przebudowa pociagu do przewozu innego ladunku +STR_RAIL_REFIT :{WHITE}{STRING} (Przebudowa) +STR_RAIL_REFIT_VEHICLE :{BLACK}Przebudowa pociagu +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wybierz typ ladunku jaki ma przewozic pociag +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Przebudowa pociagu do przewozu podswietlonych towarow +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Nie mozna przebudowac pociagu... + + +############ network gui strings + +TEMP_STRING_NO_NETWORK :{WHITE}Interface sieciowy nie jest jeszcze zrobiony! + +STR_NETWORK_MULTIPLAYER :{WHITE}Gra wieloosobowa + +STR_NETWORK_FIND_SERVER :{BLACK}Szukanie serwera +STR_NETWORK_FIND_SERVER_TIP :{BLACK}Przeszukuje siec w poszukiwaniu serwera +STR_NETWORK_DIRECT_CONNECT :{BLACK}Polaczenie bezposrednie +STR_NETWORK_ENTER_IP :{BLACK}Wpisz adres IP serwera +STR_NETWORK_DIRECT_CONNECT_TIP :{BLACK}Laczenie sie ze znanym IP +STR_NETWORK_START_SERVER :{BLACK}Uruchomienie serwera +STR_NETWORK_START_SERVER_TIP :{BLACK}Uruchomienie wlasnego serwera + +STR_NETWORK_PLAYER_NAME :{BLACK}Nazwa gracza: +STR_NETWORK_ENTER_NAME_TIP :{BLACK}To jest nazwa pod ktora beda Cie widziec inni gracze + +STR_NETWORK_SELECT_CONNECTION :{BLACK}Wybierz typ polaczenia: +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Wybor miedzy gra w internecie a siecia lokalna +STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} +STR_NETWORK_LAN :{BLACK}LAN +STR_NETWORK_INTERNET :{BLACK}Internet + +STR_NETWORK_GAME_NAME :{BLACK}Nazwa +STR_NETWORK_GAME_NAME_TIP :{BLACK}Nazwa gry +STR_NETWORK_PLAYERS :{BLACK}#/# +STR_NETWORK_PLAYERS_TIP :{BLACK}Osoby obecne w grze / Maksymalna ilosc graczy +STR_NETWORK_MAP_SIZE :{BLACK}Rozmiar +STR_NETWORK_MAP_SIZE_TIP :{BLACK}Rozmiar mapy +STR_NETWORK_INFO_ICONS_TIP :{BLACK}Jezyk, wersja serwera, itp. +STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Klinknij na grze z listy by ja wybrac + +STR_NETWORK_JOIN_GAME :{BLACK}Przylacz sie do gry + + +STR_NETWORK_START_GAME_WINDOW :{WHITE}Rozpocznij nowa gre + +STR_NETWORK_NEW_GAME_NAME :{BLACK}Nazwa gry: +STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}Nazwa gry bedzie wyswietlana u innych graczy w menu gry wieloosobowej +STR_NETWORK_PASSWORD :{BLACK}Haslo: +STR_NETWORK_PASSWORD_TIP :{BLACK}Zabezpiecz gre haslem jesli nei chcesz by ktos przlaczyl sie do gry +STR_NETWORK_SELECT_MAP :{BLACK}Wybierz mape: +STR_NETWORK_SELECT_MAP_TIP :{BLACK}Wybierz mape na ktorej chcesz grac +STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Ilosc graczy: +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Okresl maksymalna ilosc graczy. Nie wszystkie pola musza byc wypelnione. +STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_NETWORK_2_PLAYERS :{BLACK}2 graczy +STR_NETWORK_3_PLAYERS :{BLACK}3 graczy +STR_NETWORK_4_PLAYERS :{BLACK}4 graczy +STR_NETWORK_5_PLAYERS :{BLACK}5 graczy +STR_NETWORK_6_PLAYERS :{BLACK}6 graczy +STR_NETWORK_7_PLAYERS :{BLACK}7 graczy +STR_NETWORK_8_PLAYERS :{BLACK}8 graczy +STR_NETWORK_START_GAME :{BLACK}Rozpocznij gre + + +STR_NETWORK_GAME_LOBBY :{WHITE}Lobby gry wieloosobowej + +STR_NETWORK_SEND :{BLACK}Wyslij +STR_NETWORK_SEND_TIP :{BLACK}Wyslij wiadomosc do innych graczy +STR_NETWORK_COMPANY_NAME :{BLACK}Nazwa firmy: +STR_NETWORK_COMPANY_NAME_TIP :{BLACK}Zmien nazwe swojej firmy. Wcisnij Enter by zaakceptowac zmiany +STR_NETWORK_SPECTATE_GAME :{BLACK}Spectate game +STR_NETWORK_SPECTATE_GAME_TIP :{BLACK}Ogladaj gre jako widz +STR_NETWORK_NEW_COMPANY :{BLACK}Nowa firma +STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Rozpoczecie dzialanosci nowej firmy +STR_NETWORK_READY :{BLACK}Zrobione + + +############ end network gui strings + + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Koszt: {CURRENCY} +STR_0801_COST :{RED}Koszt: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Przychod: {CURRENCY} +STR_0803_INCOME :{GREEN}Przychod: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Przypuszczalny koszt: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Przypuszczalny koszt: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Przypuszczalny przychod: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Przypuszczalny przychod: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Nie mozna wzniesc ladu tutaj... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Nie mozna obnizyc ladu tutaj... +STR_080A_ROCKS :Skaly +STR_080B_ROUGH_LAND :Pagorkowaty teren +STR_080C_BARE_LAND :Odkryty teren +STR_080D_GRASS :Trawa +STR_080E_FIELDS :Pola +STR_080F_SNOW_COVERED_LAND :Zasniezony teren +STR_0810_DESERT :Pustynia + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren pochylony w zlym kierunku +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Niemozliwa kombinaca torow +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Wykop zniszczylby tunel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Juz na poziome morza +STR_1004_TOO_HIGH :{WHITE}Zbyt wysoko +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Nie ma odpowiedniego rodz. torow +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Pociag w zajezdni +STR_1007_ALREADY_BUILT :{WHITE}...juz zbudowano +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Najpierw trzeba usunac tory +STR_1009_TOO_MANY_DEPOTS :{WHITE}Zbyt wiele zajezdni +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Konstrukcja torowiska +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Konstrukcja szyny trak. +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Konstrukcja szyny MagLev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Wybierz rodzaj mostu kolejowego +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Nie mozna tutaj wybudowac zajezdni... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Nie mozna tutaj wybudowac stacji... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Nie mona postawic tutaj znakow... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Nie mozna tutaj ulozyc torow... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Nie mozna stad usunac torow... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Nie mozna stad usunac znakow... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Orientacja zajezdni +STR_1015_RAILROAD_CONSTRUCTION :Konstrukcja torowiska +STR_1016_MONORAIL_CONSTRUCTION :Konstrukcja szyny trak. +STR_1017_MAGLEV_CONSTRUCTION :Konstrukcja szyny MagLev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Budowa torow +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Budowa zajezdni (w celu budowy i serwisowania pociagow) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Budowa stacji kolejowej +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Budowa znakow kolejowych +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Budowa mostu kolejowego +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Budowa tunelu kolejowego +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Przelacz buduj/usun dla torow i semaforow +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Wybor mostu - klik na wybranym moscie aby go zbudowac +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Wybierz orientacje zajezdni kolejowej +STR_1021_RAILROAD_TRACK :Tory +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Tory wraz z sygnalizacja +STR_1023_RAILROAD_TRAIN_DEPOT :Zajezdnia kolejowa +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...teren jest wlasnoscia innej firmy +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Tory ze zwykla sygnalizacja +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Tory z pre-sygnalami +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Tory z sygnalizacja wyjsciowa +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Tory z sygnalizacja combo + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren pochylony w zla strone +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Trzeba usunac najpierw droge +STR_1802_ROAD_CONSTRUCTION :{WHITE}Tworzenie drog +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Wybierz most drogowy +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Nie mozna zbudowac tutaj drogi... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Nie mozna usunac drogi z tego miejsca... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientacja zajezdni samochodowej +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nie mozna tutaj zbudowac zajezdni... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Nie mozna zbudowac przystanku... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nie mozna zbudowac stacji ciezarowek... +STR_180A_ROAD_CONSTRUCTION :Budowa drogi +STR_180B_BUILD_ROAD_SECTION :{BLACK}Sekcja budowy drog +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Wybuduj zajezdnie samochodowa(do budowania i serwisowania pojazdow) +STR_180D_BUILD_BUS_STATION :{BLACK}Budowa przystanku +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Wybuduj zat. ladowania ciezarowek +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Budowa mostu drogowego +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Budowa tunelu drogowego +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Przelacz buduj/usun dla konstrukcji drog +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Wybor mostow - klik na wybranym moscie aby go wybudowac +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Wybiesz umiejscowienie zajezdni samochod. +STR_1814_ROAD :Droga +STR_1815_ROAD_WITH_STREETLIGHTS :Droga z oswietleniem ulicznym +STR_1816_TREE_LINED_ROAD :Droga z drzewami +STR_1817_ROAD_VEHICLE_DEPOT :Zajezdnia samochodowa +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Poziom przecinania sie drog/torow + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Miasta +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Budynek musi byc najpierw zburzony +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Populacja: {ORANGE}{COMMA32}{BLACK} Domow: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Zmien nazwe miasta +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Nie mozna zmienic nazwy miasta... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} Lokalne wladze nie pozwalaja na to +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Nazwy miast - klik na nazwie aby wycentrowac widok na miescie +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Wycentruj glowny widok na miescie +STR_200C_CHANGE_TOWN_NAME :{BLACK}Zmien nazwe miasta +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Pasazerowie w ostatnim miesiacu: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Poczta w ostatnim miesiacu: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Wysoki biurowiec +STR_2010_OFFICE_BLOCK :Biurowiec +STR_2011_SMALL_BLOCK_OF_FLATS :Maly blok mieszkalny +STR_2012_CHURCH :Kosciol +STR_2013_LARGE_OFFICE_BLOCK :Duzy biurowiec +STR_2014_TOWN_HOUSES :Domki miejskie +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Pomnik +STR_2017_FOUNTAIN :Fontanna +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Biurowiec +STR_201A_SHOPS_AND_OFFICES :Sklepy i biura +STR_201B_MODERN_OFFICE_BUILDING :Nowoczesny biurowiec +STR_201C_WAREHOUSE :Magazyny +STR_201D_OFFICE_BLOCK :Biurowiec +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Stare domy +STR_2020_LOCAL_AUTHORITY :{BLACK}Lokalne wladze +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Pokaz informacje o lokalnych wladzach +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} lokalne wladze +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Ocena transportu firmy: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subsydia +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Oferta subsydiow dla uslugi przewozu:- +STR_2027_FROM_TO :{ORANGE}{STRING} z {STRING} do {STRING} +STR_2028_BY :{YELLOW} (do {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Zadne +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Uslugi juz subsydiowane:- +STR_202C_FROM_TO :{ORANGE}{STRING} z {STATION} do {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, do {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Subsydiowanie wygaslo:{}{}{STRING} z {STRING} do {STRING} juz nie bedzie dotowane. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Koniec dotacji:{}{}{STRING} usluga z {STATION} do {STATION} juz nie jest subsydiowana +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Oferta uslugi dotowanej:{}{}Pierwszy przewoz {STRING} z {STRING} do {STRING} bedzie dotowane przez rok przez lokalne wladze! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Przyznano subsydia dla {STRING}!{}{}Przewoz {STRING} z {STATION} do {STATION} bedzie placony 50% wiecej przez nastepny rok! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Przyznano subsydia dla {STRING}!{}{}Przewoz {STRING} z {STATION} do {STATION} bedzie placony podwojnie przez nastepny rok! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Przyznano subsydia dla {STRING}!{}{}Przewoz {STRING} z {STATION} do {STATION} bedzie placony potrojnie przez nastepny rok! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Przyznano subsydia dla {STRING}!{}{}Przewoz {STRING} z {STATION} do {STATION} bedzie placony poczwornie przez nastepny rok! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} lokalne wladze nie pozwalaja na budowe nastepnego lotniska w tym miescie +STR_2036_COTTAGES :Domki +STR_2037_HOUSES :Domy +STR_2038_FLATS :Mieszkania +STR_2039_TALL_OFFICE_BLOCK :Wysoki biurowiec +STR_203A_SHOPS_AND_OFFICES :Sklepy i biura +STR_203B_SHOPS_AND_OFFICES :Sklepy i biura +STR_203C_THEATER :Teatr +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Biura +STR_203F_HOUSES :Domy +STR_2040_CINEMA :Kino +STR_2041_SHOPPING_MALL :Centrum handlowe +STR_2042_DO_IT :{BLACK}Wykonaj +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Lista rzeczy do zrobienia w tym miescie - klik dla wiecej detali +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Wykonaj podswietlana dzialalnosc z listy ponizej +STR_2045_ACTIONS_AVAILABLE :{BLACK}Mozliwe dzialanie: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Mala kampania reklamowa +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Srednia kampania reklamowa +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Duza kampania reklamowa +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Ufunduj rekonstrukcje drog +STR_204A_BUILD_STATUE_OF_COMPANY :Wybuduj statue wlasciciela +STR_204B_FUND_NEW_BUILDINGS :Ufunduj nowe budynki +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Kup wylacznasc na uslugi +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Daj lapowke lokalnym wladzom +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Rozpocznij mala kampanie reklamowa, aby zachecic pasazerow i fabryki do twoich uslug.{} Koszt: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Rozpocznij srednia kampanie reklamowa, aby zachecic wiecej pasazerow i fabryk do twoich uslug transportowych.{} Koszt: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Rozpocznij duza kampanie reklamowa, aby zachecic wiecej pasazerow i fabryk do twoich uslug transportowych.{} Koszt: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Ufunduj remont sieci drog. Powoduje zaklocenia w ruchu ulicznym do 6 miesiecy.{} Koszt: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Wybuduj statue dla uczczenia swojej firmy.{} Koszt: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Ufundowanie nowych budynkow handlowych w miescie.{} Koszt: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Kup roczna wylacznosc na prawa transportowe w miescie. Lokalne wladze pozwala kozystac tylko ze stacji twojej firmy.{} Koszt: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Daj lapowke lokanym wladzom, powieksz swoja ocene, ryzykujac powazne kary w razie zlapania.{} Koszt: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Nie mozna wykonac... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Chaos na drogach w {TOWN}!{}{}Program przebudowy drog ufundowany przez {STRING} prowadzi do 6 miesiecy meki dla kierowcow! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (w budowie) +STR_2059_IGLOO :Iglo +STR_205A_TEPEES :Tipi +STR_205B_TEAPOT_HOUSE :Dom-Czajniczek +STR_205C_PIGGY_BANK :Swinka-skarbonka + +##id 0x2800 +STR_LANDSCAPING :Krajobraz +STR_2800_PLANT_TREES :Zasadz drzewa +STR_2801_PLACE_SIGN :Postaw napis +STR_2802_TREES :{WHITE}Drzewa +STR_2803_TREE_ALREADY_HERE :{WHITE}...drzewo juz tu jest +STR_2804_SITE_UNSUITABLE :{WHITE}...niewlasciwe miejsce +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Nie mozna posadzic drzewa... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...zbyt wiele napisow +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Nie mozna umiescic napisu... +STR_280A_SIGN :Napis +STR_280B_EDIT_SIGN_TEXT :{WHITE}Edycja tekstu napisu +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nie mozesz zmienic nazwy napisu... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Wybierz typ drzew do sadzenia +STR_280E_TREES :Drzewa +STR_280F_RAINFOREST :Las deszczowy +STR_2810_CACTUS_PLANTS :Pole kaktusow + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Wybor stacji +STR_3001_AIRPORT_SELECTION :{WHITE}Wybor lotiska +STR_3002_ORIENTATION :{BLACK}Orientacja +STR_3003_NUMBER_OF_TRACKS :{BLACK}Ilosc peronow +STR_3004_PLATFORM_LENGTH :{BLACK}Dlugosc peronu +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Zbyt blisko innej stacji +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Przylega do wiecej niz jednej stacji/miejsca zalad. +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Za duzo stacji/miejsc zalad. w tym miescie +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Za duzo stacji/miejsc zaladunk. +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Zbyt blisko innej stacji/miejsca zladunk. +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Musisz najpierw zniszczyc stacje +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Zbyt blisko innego lotniska +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Musisz najpierw zniszczyc lotnisko + +STR_3030_RENAME_STATION_LOADING :Zmien nazwe stacji/miejsca zalad. +STR_3031_CAN_T_RENAME_STATION :{WHITE}Nie mozna zmienic nazwy. +STR_3032_RATINGS :{BLACK}Oceny +STR_3033_ACCEPTS :{BLACK}Przyjmuje +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Lokalna ocena uslug transportowych: + +############ range for rating starts +STR_3035_APPALLING :Beznadziejne +STR_3036_VERY_POOR :Bardzo slabe +STR_3037_POOR :Slabe +STR_3038_MEDIOCRE :Srednie +STR_3039_GOOD :Dobre +STR_303A_VERY_GOOD :Bardzo dobre +STR_303B_EXCELLENT :Wysmienite +STR_303C_OUTSTANDING :Bezkonkurencyjne +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} dluzej nie akceptuje {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} dluzej nie akceptuje {STRING} lub {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} akceptuje {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} akceptuje {STRING} i {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Orientacja przystanku +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Orientacja st.s.ciez. +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Zbyt blisko innego przystanku +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Zbyt blisko innego przystanku ciez. +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Musisz zniszczyc najpierw przystanek +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Musisz najpierw zniszczyc przystanek. +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stacje +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Nic - +STR_304B_SITE_UNSUITABLE :{WHITE}...niewlasciwe miejsce +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Zbyt blisko innego portu +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Najpierw musisz zniszczyc port +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Wybierz orientacje stacji +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Wybierz ilosc peronow na stacji +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Wybierz dlugosc stacji +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Wybierz orientacje przystanku +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Orientacja zajezdni ladowania ciezarowek +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centruj widok na stacji +STR_3054_SHOW_STATION_RATINGS :{BLACK}Pokaz ocene stacji +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Zmien nazwe stacji/przystanku +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Pokaz liste akceptowanych towarow +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Nazwa stacji - kliknij na nazwie aby scentrowac glowny widok na stacji +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Wybierz wielkosc/typ lotniska +STR_3059_SMALL :{BLACK}Male +STR_305A_LARGE :{BLACK}Duze +STR_305AA_LARGE :{BLACK}lotnisko metropoli +STR_305AB_LARGE :{BLACK}Lotnisko miedzynarodowe +STR_305B_SIZE :{BLACK}Rozmiar +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Stacja kolejowa +STR_305F_AIRCRAFT_HANGAR :Hangar +STR_3060_AIRPORT :Lotnisko +STR_3061_TRUCK_LOADING_AREA :Miejsce zaladunku +STR_3062_BUS_STATION :Przystanek +STR_3063_SHIP_DOCK :Port +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Highlight coverage area of proposed site +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Don't highlight coverage area of proposed site +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Pokryj zaznaczony teren +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Wybierz stacje jednoszynowa. +STR_3068_DOCK :{WHITE}Port +STR_3069_BUOY :Boja +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boja na drodze +STR_306B_HELIPORT :{BLACK}Lotnisko +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stacja zbyt rozlegla + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Orientacja stoczni +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...musi byc wybudowane na wodzie +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Nie mozna tutaj wybudowac stoczni... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}wybierz orientacje stoczni +STR_3804_WATER :Woda +STR_3805_COAST_OR_RIVERBANK :Wybrzeze lub brzeg rzeki +STR_3806_SHIP_DEPOT :Stocznia +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Nie mozna wybudowac na wodzie + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Zapisz gre +STR_4001_LOAD_GAME :{WHITE}Zaladuj gre +STR_4002_SAVE :{BLACK}Zapisz +STR_4003_DELETE :{BLACK}Usun +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} MB wolnego +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Nie mozna odczytac napedu +STR_4007_GAME_SAVE_FAILED :{WHITE}Nie mozna zapisac gry +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Nie mozna usunac pliku +STR_4009_GAME_LOAD_FAILED :{WHITE}Nie mozna wczytac gry +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Lista napedow, katalogow i zapisanych plikow gry +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Obecnie zaznaczona nazwa dla zapisanej gry +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Skasuj zaznaczona zapisana gre +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Zapisz bierzaca gre uzywajac wybranej nazwy +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Wybierz nowy typ gry +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Wybierz scenariusz (zielony), ustawiona gre (niebieski), lub przypadkowa dowolna +STR_4010_GENERATE_RANDOM_NEW_GAME :generacja przypadkowej nowej gry + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} na drodze +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kopalnia wegla +STR_4803_POWER_STATION :Elektrownia +STR_4804_SAWMILL :Tartak +STR_4805_FOREST :Las +STR_4806_OIL_REFINERY :Rafineria +STR_4807_OIL_RIG :Platforma wiertnicza +STR_4808_FACTORY :Fabryka +STR_4809_PRINTING_WORKS :Drukarnia +STR_480A_STEEL_MILL :Huta +STR_480B_FARM :Farma +STR_480C_COPPER_ORE_MINE :Kopalnia rudy miedzi +STR_480D_OIL_WELLS :Pole naftowe +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Przetwornia jedzenia +STR_4810_PAPER_MILL :Zaklad papierniczy +STR_4811_GOLD_MINE :Kopalnia zlota +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Kopalnia diamentow +STR_4814_IRON_ORE_MINE :Kopalnia rudy zelaza +STR_4815_FRUIT_PLANTATION :Sad +STR_4816_RUBBER_PLANTATION :Plantacja gumy +STR_4817_WATER_SUPPLY :Ujecie wody +STR_4818_WATER_TOWER :Wieza cisnien +STR_4819_FACTORY :Fabryka +STR_481A_FARM :Farma +STR_481B_LUMBER_MILL :Tartak +STR_481C_COTTON_CANDY_FOREST :Las waty cukrowej +STR_481D_CANDY_FACTORY :Zaklad cukierniczy +STR_481E_BATTERY_FARM :Battery Farm +STR_481F_COLA_WELLS :Studnia Coli +STR_4820_TOY_SHOP :Sklep z zabawkami +STR_4821_TOY_FACTORY :Fabryka zabawek +STR_4822_PLASTIC_FOUNTAINS :Fontanny plastiku +STR_4823_FIZZY_DRINK_FACTORY :Fabryka napojow gazowanych +STR_4824_BUBBLE_GENERATOR :Generator babelkow +STR_4825_TOFFEE_QUARRY :Kopalnia tofi +STR_4826_SUGAR_MINE :Kopalnia cukru + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Wymagania: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Wymagania: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Wymagania: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Wyprodukowano w ostatnim miesiacu: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% przetransportowano) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centruj glowny widok na przedsiebiorstwie +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Rozpoczeto budowe nowego {STRING} blisko {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Nowa {STRING} zostala obsadzona blisko {TOWN}! +STR_482F_COST :{BLACK}Koszt: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nie mozna tutaj wybudowac tego przedsiebiorstwa... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...las moze byc posadzony tylko ponizej lini wiecznego lodu +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} oglasza bliskie zamkniecie! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Problemy z zaopatrz. w {TOWN} {STRING} oglosza bliskie zamkniecie! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Niedobor drzew w {TOWN} {STRING} oglosza bliskie zamkniecie! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} zwieksza produkcje! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Odkryty nowy poklad wegla {TOWN} {STRING}!{} Podwojenie produkcji! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Odkryte nowe rezerwy ropy {TOWN} {STRING}!{} Podwojenie produkcji! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Unowoczesniono prod. rolna w {TOWN} {STRING} Podwojenie produkcji! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} produkcja zmniejszona o 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Plaga insektow w {TOWN} {STRING}!{}Produkcja spadla o 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...moze byc usytuowane tylko blisko krawedzi mapy +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} produkcja w {TOWN} {STRING} zwiekszona o {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} produkcja w {TOWN} {STRING} zmniejszona o {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Pociag w tunelu +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Samochod w tunelu +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Inny tunel na drodze +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Brak odpwiedniego ladu dla drugiego konca tunelu +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Trzeba najpierw zniszczyc tunel +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Trzeba najpierw zniszczyc most +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nie mozna zaczynac i konczyc w tym samym miejscu +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Rowny lad lub woda wymagana pod mostem +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Poczatek i koniec musza byc w jednej linii +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Nieodpowiednie miejsce na wejscie tunelu +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Podwieszany, Stalowy +STR_500F_GIRDER_STEEL :Dzwigarowy, Stalowy +STR_5010_CANTILEVER_STEEL :Wspornikowy, Stalowy +STR_5011_SUSPENSION_CONCRETE :Podwieszany, Betonowy +STR_5012_WOODEN :Drewniany +STR_5013_CONCRETE :Betonowy +STR_5014_TUBULAR_STEEL :Cylindryczny, Stalowy +STR_BRIDGE_TUBULAR_SILICON :Cylindryczny, Krzemowy +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Nie mozna tutaj wybudowac mostu... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nie mozna tutaj wybudowac tunelu... +STR_5017_RAILROAD_TUNNEL :Tunel kolejowy +STR_5018_ROAD_TUNNEL :Tunel samochodowy +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Stalowy most kolejowy podwieszany +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Stalowy dzwigarowy most kolejowy +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Stalowy wspornikowy most kolejowy +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Wzmocniony betonem podwieszany most kolejowy +STR_501F_WOODEN_RAIL_BRIDGE :Drewniany most kolejowy +STR_5020_CONCRETE_RAIL_BRIDGE :Betonowy most kolejowy +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Stalowy most drogowy podwieszany +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Stalowy dzwigarowy most drogowy +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Stalowy wspornikowy most drogowy +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Wzmocniony betonem podwieszany most drogowy +STR_5025_WOODEN_ROAD_BRIDGE :Drewniany most drogowy +STR_5026_CONCRETE_ROAD_BRIDGE :Betonowy most drogowy +STR_5027_TUBULAR_RAIL_BRIDGE :Cylindryczny most kolejowy +STR_5028_TUBULAR_ROAD_BRIDGE :Cylindryczny most drogowy +STR_5029_STEEL :Stalowy + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Obiekt na drodze +STR_5801_TRANSMITTER :Antena +STR_5802_LIGHTHOUSE :Latarnia +STR_5803_COMPANY_HEADQUARTERS :Glowna siedziba firmy +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...glowna siedziba firmy na drodze +STR_5805_COMPANY_OWNED_LAND :Teren w posiadaniu firmy +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Nie mozesz nabyc tego terenu... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...to juz jest Twoje! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Bez nazwy{SKIP} +STR_SV_TRAIN_NAME :Pociag {COMMA16} +STR_SV_ROADVEH_NAME :Samochod {COMMA16} +STR_SV_SHIP_NAME :Statek {COMMA16} +STR_SV_AIRCRAFT_NAME :Samolot {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Polnoc +STR_SV_STNAME_SOUTH :{STRING} Poludnie +STR_SV_STNAME_EAST :{STRING} Wschod +STR_SV_STNAME_WEST :{STRING} Zachod +STR_SV_STNAME_CENTRAL :{STRING} Centrum +STR_SV_STNAME_TRANSFER :{STRING} Transfer +STR_SV_STNAME_HALT :{STRING} Stop +STR_SV_STNAME_VALLEY :{STRING} Dolina +STR_SV_STNAME_HEIGHTS :{STRING} Wzgorza +STR_SV_STNAME_WOODS :{STRING} Tartak +STR_SV_STNAME_LAKESIDE :{STRING} Jezioro +STR_SV_STNAME_EXCHANGE :{STRING} Gielda +STR_SV_STNAME_AIRPORT :{STRING} Lotnisko +STR_SV_STNAME_OILFIELD :{STRING} Nafta +STR_SV_STNAME_MINES :{STRING} Kopalnia +STR_SV_STNAME_DOCKS :{STRING} Port +STR_SV_STNAME_BUOY_1 :{STRING} Boja 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boja 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boja 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boja 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boja 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boja 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boja 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boja 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boja 9 +STR_SV_STNAME_ANNEXE :{STRING} Pawilon +STR_SV_STNAME_SIDINGS :{STRING} Bocznica +STR_SV_STNAME_BRANCH :{STRING} Rozjazd +STR_SV_STNAME_UPPER :{STRING} Gorny +STR_SV_STNAME_LOWER :{STRING} Dolny +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Las + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Poziom trudnosci + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Latwy +STR_6802_MEDIUM :{BLACK}Sredni +STR_6803_HARD :{BLACK}Trudny +STR_6804_CUSTOM :{BLACK}Wlasny +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Maksymalna ilosc przeciwnikow: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Przeciwnik zaczyna od: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Ilosc miast: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Ilosc przedsiebiorstw: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maksymalna poczatkowa pozyczka: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Poczatkowy wspolczynnik wzrostu: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Utrzymanie pojazdow: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Szybkosc budowania przeciwnikow: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Poziom inteligencji przeciwnikow: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Uszkodzenia pojazdow: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Wspolczynnik subsydiow: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Koszt konstrukcji: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Typ terenu: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Ilosc morz/jezior: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Ekonomia: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Zawracanie pociagow: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Kleski zywiolowe: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Malo +STR_6817_NORMAL :Srednio +STR_6818_HIGH :Duzo +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Bardzo wolno +STR_681C_SLOW :Wolno +STR_681D_MEDIUM :Srednio +STR_681E_FAST :Szybko +STR_681F_VERY_FAST :Bardzo szybko +STR_VERY_LOW :Bardzo niski +STR_6820_LOW :Niski +STR_6821_MEDIUM :Sredni +STR_6822_HIGH :Wysoki +STR_6823_NONE :Brak +STR_6824_REDUCED :Zredukowany +STR_6825_NORMAL :Normaly +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Bardzo szybko +STR_682B_FLAT :Plaski +STR_682C_HILLY :Pagorkowaty +STR_682D_MOUNTAINOUS :Gorski +STR_682E_STEADY :Stabilna +STR_682F_FLUCTUATING :Zmienna +STR_6830_IMMEDIATE :Natychmiast +STR_6831_3_MONTHS_AFTER_PLAYER :3 miesiace po graczu +STR_6832_6_MONTHS_AFTER_PLAYER :6 miesiacy po graczu +STR_6833_9_MONTHS_AFTER_PLAYER :9 miesiacy po graczu +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Na koncu trasy i na stacjach +STR_6835_AT_END_OF_LINE_ONLY :Na koncu trasy +STR_6836_OFF :Wylaczone +STR_6837_ON :Wlaczone +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Pokaz liste hi-score + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Gracz 1) +STR_7003_PLAYER_2 : (Gracz 2) +STR_7004_NEW_FACE :{BLACK}nowa twarz +STR_7005_COLOR_SCHEME :{BLACK}Schemat koloru +STR_7006_COLOR_SCHEME :{GOLD}Schemat koloru: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nowy schemat koloru +STR_7008_COMPANY_NAME :{BLACK}Nazwa firmy +STR_7009_PRESIDENT_NAME :{BLACK}Prezes +STR_700A_COMPANY_NAME :Nazwa firmy +STR_700B_PRESIDENT_S_NAME :Prezesa +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Nie mozna zmienic nazwy firmy... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Nie mozna zmienic nazwiska prezesa... +STR_700E_FINANCES :{WHITE}{STRING} Finanse{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Wychody/Przychody +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Konstrukcje +STR_7012_NEW_VEHICLES :{GOLD}Nowe pojazdy +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Utrzymanie pociagow +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Utrzymanie samocodow +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Utrzymanie samolotow +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Utrzymanie statkow +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Utrzymywanie wlasnosci +STR_7018_TRAIN_INCOME :{GOLD}Przychod z pociagow +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Przychod z samochodow +STR_701A_AIRCRAFT_INCOME :{GOLD}Przychod z samolotow +STR_701B_SHIP_INCOME :{GOLD}Przychod ze statkow +STR_701C_LOAN_INTEREST :{GOLD}Obsluga pozyczki +STR_701D_OTHER :{GOLD}Inne +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Calkowicie: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Wykres przychodow +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Wykres obrotow +STR_7026_BANK_BALANCE :{WHITE}Bilans bankowy +STR_7027_LOAN :{WHITE}Pozyczka +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Pozyczka {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Zwrot {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maksymalna dozwolona pozyczka wynosi {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nie mozna pozyczyc wiecej pieniedzy... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...pozyczka juz splacona +STR_702E_REQUIRED :{WHITE}...{CURRENCY} wymagane +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Nie mozna zwrocic pozyczki... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Wybierz nowa twarz prezesa +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Zmien dostawce pojazdow dla firmy +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Zmien imie prezesa +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Zmien nazwe firmy +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Kliknij na nowym schemacie kolorow +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Zwieksz wielkosc pozyczki +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Zwroc czesc pozyczki +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Prezes) +STR_7038_INAUGURATED :{GOLD}Inauguracja: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Pojazdy: +STR_703A_TRAIN :{WHITE}{COMMA16} pociag +STR_703B_TRAINS :{WHITE}{COMMA16} pociagi(ow) +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} samochod +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} samochody(ow) +STR_703E_AIRCRAFT :{WHITE}{COMMA16} samolot +STR_703F_AIRCRAFT :{WHITE}{COMMA16} samoloty(ow) +STR_7040_SHIP :{WHITE}{COMMA16} statek +STR_7041_SHIPS :{WHITE}{COMMA16} statki(ow) +STR_7042_NONE :{WHITE}Brak +STR_7043_FACE_SELECTION :{WHITE}Wybor twarzy +STR_7044_MALE :{BLACK}Mezczyzna +STR_7045_FEMALE :{BLACK}Kobieta +STR_7046_NEW_FACE :{BLACK}Nowa twarz +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Anuluj wybor nowej twarzy +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Zatwierdz wybor nowej twarzy +STR_7049_SELECT_MALE_FACES :{BLACK}Wybierz meska twarz +STR_704A_SELECT_FEMALE_FACES :{BLACK}Wybierz kobieca twarz +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Generuj przypadkowa twarz +STR_704C_KEY :{BLACK}Legenda +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Pokaz legende na wykresie +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Legenda do wykresow firm +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Kliknij tutaj aby przelaczyc wyswietlanie firmy na wykresie wla/wyl +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Dostarczonych jednostek ladunku +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Ocena dzialalnosci firmy (max. ocena=1000) +STR_7052_COMPANY_VALUES :{WHITE}Wartowsc firmy +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Tabela Ligi Firm +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Firma ma problemy! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} bedzie odsprzedane lub oglosi bankructwo jezeli zysk firmy nie wzrosnie! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Prezes) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Polaczenie firm transportowych! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} zostal sprzedany {STRING} za {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Szukamy firmy transportowej zeby przejela nasza firme{}{}Czy chcesz kupic {STRING} za {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrut! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} zostaje zamkniety przez wierzycieli i wszystkie udzialy zostaja sprzedane! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nowa firma zaczela dzialalnosc! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} zaczyna budowe niedaleko {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Nie mozna kupic firmy... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Oplaty za przewoz +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Dni w transporcie +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Oplata za przewoz 20 jednostek (lub 10,000 litrow) towaru na odleglosc 20 kwadratow +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Przelacznik wykresu ladunku wla/wyl +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Inzynier +STR_7067_TRAFFIC_MANAGER :Zarzadca ruchu +STR_7068_TRANSPORT_COORDINATOR :Koordynator transportu +STR_7069_ROUTE_SUPERVISOR :Kierownik drog +STR_706A_DIRECTOR :Dyrektor +STR_706B_CHIEF_EXECUTIVE :Chief Executive +STR_706C_CHAIRMAN :Chairman +STR_706D_PRESIDENT :Prezes +STR_706E_TYCOON :Magnat +STR_706F_BUILD_HQ :{BLACK}Budowa siedziby gl. +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Buduj siedzibe glowna / zobacz siedzibe glowna +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Nie mozna zbudowac siedziby glownej... +STR_7072_VIEW_HQ :{BLACK}Zobacz SG +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Swiatowa recesja!{}{}Eksperci finansowi obawiaja sie najgorszego z powodu zastoju! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Koniec recesji!{}{}Zmiana w wymianach daje pewnosc umocnienia fabryk i ekonomii! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Przelacz duze/male okienko +STR_7076_COMPANY_VALUE :{GOLD}Wartosc firmy: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Kup 25% udzialow w firmie +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Sprzedaj 25% udzialow w firmie +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kup 25% udzialow w tej firmie +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Sprzedaj 25% udzialow w tej firmie +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nie mozna kupic 25% udzialow w tej firmie... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}nie mozna sprzedac 25% udzialow w tej firmie... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% w posiadaniu przez {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% w posiadaniu przez {STRING}{} {COMMA16}% w posiadaniu przez {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} zostalo przejete przez {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Parowoz) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Parowoz) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Parowoz) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Parowoz) +STR_800A_SH_8P_STEAM :SH '8P' (Parowoz) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektrowoz) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektrowoz) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektrowoz) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektrowoz) +STR_801B_PASSENGER_CAR :Wagon pasazerski +STR_801C_MAIL_VAN :Wagon pocztowy +STR_801D_COAL_CAR :Wagon na wegiel +STR_801E_OIL_TANKER :Cysterna +STR_801F_LIVESTOCK_VAN :Wagon na zywiec +STR_8020_GOODS_VAN :Wagon towarowy +STR_8021_GRAIN_HOPPER :Wagon na zboze +STR_8022_WOOD_TRUCK :Wagon na drewno +STR_8023_IRON_ORE_HOPPER :Wagon na rude zelaza +STR_8024_STEEL_TRUCK :Wagon na stal +STR_8025_ARMORED_VAN :Opancerzony wagon +STR_8026_FOOD_VAN :Wagon na zywnosc +STR_8027_PAPER_TRUCK :Wagon na papier +STR_8028_COPPER_ORE_HOPPER :Wagon na rude miedzi +STR_8029_WATER_TANKER :Wagon na wode +STR_802A_FRUIT_TRUCK :Wagon na owoce +STR_802B_RUBBER_TRUCK :Wagon na gume +STR_802C_SUGAR_TRUCK :Wagon na cukier +STR_802D_COTTON_CANDY_HOPPER :Wagon na wate cukrowa +STR_802E_TOFFEE_HOPPER :Wagon na tofi +STR_802F_BUBBLE_VAN :Wagon na gume do zucia +STR_8030_COLA_TANKER :Cysterna na cole +STR_8031_CANDY_VAN :Wagon na cukierki +STR_8032_TOY_VAN :Wagon na zabawki +STR_8033_BATTERY_TRUCK :Wagon na baterie +STR_8034_FIZZY_DRINK_TRUCK :Wagon na napoje gazowane +STR_8035_PLASTIC_TRUCK :Wagon na plastik +STR_8036_X2001_ELECTRIC :'X2001' (Electric) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektrowoz) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Autobus +STR_803A_MAIL_VAN :Pocztowy +STR_803B_COAL_CAR :do wegiel +STR_803C_OIL_TANKER :do rope +STR_803D_LIVESTOCK_VAN :do zywca +STR_803E_GOODS_VAN :do towarow +STR_803F_GRAIN_HOPPER :do zboza +STR_8040_WOOD_TRUCK :do drewna +STR_8041_IRON_ORE_HOPPER :do rudy zelaza +STR_8042_STEEL_TRUCK :do stali +STR_8043_ARMORED_VAN :opancerzony +STR_8044_FOOD_VAN :do zywnosci +STR_8045_PAPER_TRUCK :do papieru +STR_8046_COPPER_ORE_HOPPER :do rudy miedzi +STR_8047_WATER_TANKER :do wody +STR_8048_FRUIT_TRUCK :do owocow +STR_8049_RUBBER_TRUCK :do gumy +STR_804A_SUGAR_TRUCK :do cukru +STR_804B_COTTON_CANDY_HOPPER :Wagon na wate cukrowa +STR_804C_TOFFEE_HOPPER :Wagon na toffi +STR_804D_BUBBLE_VAN :Wagon na gume do zucia +STR_804E_COLA_TANKER :Cysterna na Cole +STR_804F_CANDY_VAN :Wagon na cukierki +STR_8050_TOY_VAN :Wagon na zabawki +STR_8051_BATTERY_TRUCK :Wagon na baterie +STR_8052_FIZZY_DRINK_TRUCK :Wagon na napoje gazowane +STR_8053_PLASTIC_TRUCK :Wagon na plastik +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektrowoz) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektrowoz) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektrowoz) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektrowoz) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Wagon pasazerski +STR_805A_MAIL_VAN :Wagon pocztowy +STR_805B_COAL_CAR :Wagon na wegiel +STR_805C_OIL_TANKER :Wagon na rope +STR_805D_LIVESTOCK_VAN :Wagon na zywiec +STR_805E_GOODS_VAN :Wagon towarowy +STR_805F_GRAIN_HOPPER :Wagon na zboze +STR_8060_WOOD_TRUCK :Wagon na drewno +STR_8061_IRON_ORE_HOPPER :Wagon na rude zelaza +STR_8062_STEEL_TRUCK :Wagon na stal +STR_8063_ARMORED_VAN :Wagon opancerzony +STR_8064_FOOD_VAN :Wagon na zywnosc +STR_8065_PAPER_TRUCK :Wagon na papier +STR_8066_COPPER_ORE_HOPPER :Wagon na rude miedzi +STR_8067_WATER_TANKER :Wagon na wode +STR_8068_FRUIT_TRUCK :Wagon na owoce +STR_8069_RUBBER_TRUCK :Wagon na gume +STR_806A_SUGAR_TRUCK :Wagon na cukier +STR_806B_COTTON_CANDY_HOPPER :Wagon na wate cukrowa +STR_806C_TOFFEE_HOPPER :Wagon na toffi +STR_806D_BUBBLE_VAN :Wagon na fume do zucia +STR_806E_COLA_TANKER :Cysterna na Cole +STR_806F_CANDY_VAN :Wagon na cukierki +STR_8070_TOY_VAN :Wagon na zabawki +STR_8071_BATTERY_TRUCK :Wagon na baterie +STR_8072_FIZZY_DRINK_TRUCK :Wagon na napoje gazowane +STR_8073_PLASTIC_TRUCK :Wagon na plastik +STR_8074_MPS_REGAL_BUS :Autobus MPS Regal +STR_8075_HEREFORD_LEOPARD_BUS :Autobus Hereford Leopard +STR_8076_FOSTER_BUS :Autobus Foster +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Superbus +STR_8078_PLODDYPHUT_MKI_BUS :Autobus Ploddyphut MkI +STR_8079_PLODDYPHUT_MKII_BUS :Autobus Ploddyphut MkII +STR_807A_PLODDYPHUT_MKIII_BUS :Autobus Ploddyphut MkIII +STR_807B_BALOGH_COAL_TRUCK :Ciezarowka na wegiel Balogh +STR_807C_UHL_COAL_TRUCK :Ciezarowka na wegiel Uhl +STR_807D_DW_COAL_TRUCK :Ciezarowka na wegiel DW +STR_807E_MPS_MAIL_TRUCK :Ciezarowka na poczteMPS +STR_807F_REYNARD_MAIL_TRUCK :Ciezarowka na Reynard +STR_8080_PERRY_MAIL_TRUCK :Ciezarowka na Perry +STR_8081_MIGHTYMOVER_MAIL_TRUCK :Ciezarowka na MightyMover +STR_8082_POWERNAUGHT_MAIL_TRUCK :Ciezarowka na Powernaught +STR_8083_WIZZOWOW_MAIL_TRUCK :Ciezarowka na Wizzowow +STR_8084_WITCOMBE_OIL_TANKER :Cysterna do ropy Witcombe +STR_8085_FOSTER_OIL_TANKER :Cysterna do ropy Foster +STR_8086_PERRY_OIL_TANKER :Cysterna do ropy Perry +STR_8087_TALBOTT_LIVESTOCK_VAN :Samochod do zywca Talbott +STR_8088_UHL_LIVESTOCK_VAN :Samochod do zywca Uhl +STR_8089_FOSTER_LIVESTOCK_VAN :Samochod do zywca Foster +STR_808A_BALOGH_GOODS_TRUCK :Samochod towarowy Balogh +STR_808B_CRAIGHEAD_GOODS_TRUCK :Samochod towarowy Craighead +STR_808C_GOSS_GOODS_TRUCK :Samochod towarowy Goss +STR_808D_HEREFORD_GRAIN_TRUCK :Samochod do zboza Hereford +STR_808E_THOMAS_GRAIN_TRUCK :Samochod do zboza Thomas +STR_808F_GOSS_GRAIN_TRUCK :Samochod do zboza Goss +STR_8090_WITCOMBE_WOOD_TRUCK :Samochod do drewna Witcombe +STR_8091_FOSTER_WOOD_TRUCK :Samochod do drewna Foster +STR_8092_MORELAND_WOOD_TRUCK :Samochod do drewna Moreland +STR_8093_MPS_IRON_ORE_TRUCK :Samochod do rudy zelaza MPS +STR_8094_UHL_IRON_ORE_TRUCK :Samochod do rudy zelaza Uhl +STR_8095_CHIPPY_IRON_ORE_TRUCK :Samochod do rudy zelaza Chippy +STR_8096_BALOGH_STEEL_TRUCK :Samochod do stali Balogh +STR_8097_UHL_STEEL_TRUCK :Samochod do stali Uhl +STR_8098_KELLING_STEEL_TRUCK :Samochod do stali Kelling +STR_8099_BALOGH_ARMORED_TRUCK :Samochod opancerzony Balogh +STR_809A_UHL_ARMORED_TRUCK :Samochod opancerzony Uhl +STR_809B_FOSTER_ARMORED_TRUCK :Samochod opancerzony Foster +STR_809C_FOSTER_FOOD_VAN :Samochod do zywnosci Foster +STR_809D_PERRY_FOOD_VAN :Samochod do zywnosci Perry +STR_809E_CHIPPY_FOOD_VAN :Samochod do zywnosci Chippy +STR_809F_UHL_PAPER_TRUCK :Samochod do papieru Uhl +STR_80A0_BALOGH_PAPER_TRUCK :Samochod do papieru Balogh +STR_80A1_MPS_PAPER_TRUCK :Samochod do papieru MPS +STR_80A2_MPS_COPPER_ORE_TRUCK :Samochod do rudy miedzi MPS +STR_80A3_UHL_COPPER_ORE_TRUCK :Samochod do rudy miedzi Uhl +STR_80A4_GOSS_COPPER_ORE_TRUCK :Samochod do rudy miedzi Goss +STR_80A5_UHL_WATER_TANKER :Cysterna do wody Uhl +STR_80A6_BALOGH_WATER_TANKER :Cysterna do wody Balogh +STR_80A7_MPS_WATER_TANKER :Cysterna do wody MPS +STR_80A8_BALOGH_FRUIT_TRUCK :Samochod do owocow Balogh +STR_80A9_UHL_FRUIT_TRUCK :Samochod do owocow Uhl +STR_80AA_KELLING_FRUIT_TRUCK :Samochod do owocow Kelling +STR_80AB_BALOGH_RUBBER_TRUCK :Samochod do gumy Balogh +STR_80AC_UHL_RUBBER_TRUCK :Samochod do gumy Uhl +STR_80AD_RMT_RUBBER_TRUCK :Samochod do gumy RMT +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :Samochod do cukier MightyMover +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Samochod do cukier Powernaught +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Samochod do cukier Wizzowow +STR_80B1_MIGHTYMOVER_COLA_TRUCK :Cysterna na Cole MightyMover +STR_80B2_POWERNAUGHT_COLA_TRUCK :Cysterna na ColePowernaught +STR_80B3_WIZZOWOW_COLA_TRUCK :Cysterna na ColeWizzowow +STR_80B4_MIGHTYMOVER_COTTON_CANDY :Samochod do waty cukrowa MightyMover +STR_80B5_POWERNAUGHT_COTTON_CANDY :Samochod do waty cukrowa Powernaught +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Samochod do waty cukrowa Wizzowow +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :Samochod do toffi MightyMover +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Samochod do toffi Powernaught +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Samochod do toffi Wizzowow +STR_80BA_MIGHTYMOVER_TOY_VAN :Samochod do zabawek MightyMover +STR_80BB_POWERNAUGHT_TOY_VAN :Samochod do zabawek Powernaught +STR_80BC_WIZZOWOW_TOY_VAN :Samochod do zabawek Wizzowow +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :Samochod do cukierkow MightyMover +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Samochod do cukierkow Powernaught +STR_80BF_WIZZOWOW_CANDY_TRUCK :Samochod do cukierkow Wizzowow +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :Samochod do baterii MightyMover +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Samochod do baterii Powernaught +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Samochod do baterii Wizzowow +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :Cysterna na napoje gazowane MightyMover +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Cysterna na napoje gazowane Powernaught +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Cysterna na napoje gazowane izzowow +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :Samochod do plastiku MightyMover +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Samochod do plastiku Powernaught +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Samochod do plastiku Wizzowow +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :Samochod do gumy do zucia MightyMover +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Samochod do gumy do zucia Powernaught +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Samochod do gumy do zucia Wizzowow +STR_80CC_MPS_OIL_TANKER :Wagon na rope MPS +STR_80CD_CS_INC_OIL_TANKER :Wagon na rope CS-Inc. +STR_80CE_MPS_PASSENGER_FERRY :Prom pasazerski MPS +STR_80CF_FFP_PASSENGER_FERRY :Prom pasazerski FFP +STR_80D0_BAKEWELL_300_HOVERCRAFT :Poduszkowiec Bakewell 300 +STR_80D1_CHUGGER_CHUG_PASSENGER :Prom pasazerski Chugger-Chug +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Prom pasazerski Shivershake +STR_80D3_YATE_CARGO_SHIP :Statek towarowy Yate +STR_80D4_BAKEWELL_CARGO_SHIP :Statek towarowy Bakewell +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Statek towarowy Mightymover +STR_80D6_POWERNAUT_CARGO_SHIP :Statek towarowy Powernaut +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Cotswald LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Cotswald LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Cotswald LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Cotswald LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Cotswald LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Helikopter Tricario +STR_80FE_GURU_X2_HELICOPTER :Helikopter Guru X2 +STR_80FF_POWERNAUT_HELICOPTER :Helikopter Powernaut +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Wiadomosc od producentow pojazdow +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Wlasnie zaprojektowalismy {STRING} - czy jestes zainteresowany w rocznej wylacznosci na uzycie tego pojazdu, zebysmy mogli zobaczyc jak sie sprawuje przed wypuszczeniem na rynek? +STR_8102_RAILROAD_LOCOMOTIVE :Lokomotywa +STR_8103_ROAD_VEHICLE :Samochod +STR_8104_AIRCRAFT :Samolot +STR_8105_SHIP :Statek +STR_8106_MONORAIL_LOCOMOTIVE :Lokomotywa jednoszynowa +STR_8107_MAGLEV_LOCOMOTIVE :Lokomotywa na poduszce magnetyczej + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Zajezdnia +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mieszkancy swietuja . . .{}Pierwszy pociag przybyl do {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Szczegoly) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Pociag na drodze +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Idz do {STATION} +STR_8807_GO_TO_UNLOAD :Idz do {STATION} (Rozladunek) +STR_8808_GO_TO_LOAD :Idz do {STATION} (Zaladunek) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Idz bez przystankow do {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Idz bez przystankow do {STATION} (Rozladunek) +STR_880C_GO_NON_STOP_TO_LOAD :Idz bez przystankow do {STATION} (Zaladunek) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Idz do {TOWN} zajezdni +STR_SERVICE_AT_TRAIN_DEPOT :Serwisuj w {TOWN} zajezdni +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Idz bez przystankow do {TOWN} zajezdni +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Idz bez przystankow do serwisu w {TOWN} zajezdni + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Zmierza do {TOWN} zajezdni +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Zmierza do {TOWN} zajezdni, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Pusto +STR_8813_FROM :{LTBLUE}{CARGO} z {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Pociag {COMMA16} czeka w zajezdni +STR_8815_NEW_VEHICLES :{BLACK}Nowe pojazdy +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Koszt: {GOLD}{CURRENCY}{BLACK} Waga: {GOLD}{COMMA16}t{}{BLACK}Predkosc: {GOLD}{VELOCITY}{BLACK} Moc: {GOLD}{COMMA16}hp{}{BLACK}Utrzymanie: {GOLD}{CURRENCY}/rok{}{BLACK}Pojemnosc: {GOLD}{STRING}{}{BLACK}Zaprojektowany: {GOLD}{NUMU16}{BLACK} Trwalosc: {GOLD}{COMMA16} lat{}{BLACK}Max. Niezawodnosc: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informacje +STR_8819_TRAIN_TOO_LONG :{WHITE}Pociag zbyt dlugi +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Pociag moze byc modyfikowany tylko jak jest zatrzymany w zajezdni +STR_881B_TRAINS :{WHITE}{STRING} - Pociagi +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nowe pociagi +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nowe pociagi jednoszynowe +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nowe pociagi Maglev +STR_881F_BUILD_VEHICLE :{BLACK}Buduj pojazd +STR_8820_RENAME :{BLACK}Zmien nazwe +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Koszt: {GOLD}{CURRENCY}{}{BLACK}Waga: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Pojemnosc: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Pomin +STR_8824_DELETE :{BLACK}Usun +STR_8825_NON_STOP :{BLACK}Non-Stop +STR_8826_GO_TO :{BLACK}Idz do +STR_8827_FULL_LOAD :{BLACK}Zaladunek +STR_8828_UNLOAD :{BLACK}Rozladunek +STR_8829_ORDERS :{WHITE}{STRING} (Kolejnosc) +STR_882A_END_OF_ORDERS :{SETX 10}- - Koniec polecen - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Serwis +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Nie mozna wybudowac lokomotywy... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Budowa: {LTBLUE}{NUMU16}{BLACK} Wartosc: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Wartosc: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Zaladunek / Rozladowanie +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Nie mozna wyslac pociagu do zajezdni... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Brak miejsca na polecenia +STR_8832_TOO_MANY_ORDERS :{WHITE}Zbyt wiele polecen +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Nie mozna wstawic polecenia... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Nie mozna usunac tego polecenia... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Nie mozna zmodyfikowac tego polecenia... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Trzeba najpierw wybudowac zajezdnie +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Nie mozna ruszyc pojazdem... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Nie mozna sprzedac lokomotywy... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Nie mozna znalezc drogi do zajezdni. +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Nie mozna zatrzymac/ruszyc pociagiem... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Okres miedzy serwisowaniem: {LTBLUE}{COMMA16}dni{BLACK} Ostatni serwis: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Pociagi - klik na pojezdzie aby uzyskac inforamcje +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Budowa nowych pociagow (wymaga zajezdni) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Pociagi - klik na pociagu po info, przeciagnij pojazd/wagon aby dodac +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Buduj nowy pociag +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Przeciagnij tutaj pociag aby go sprzedac +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrowanie glownego okna na pozycji zajezdni +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Lista wyboru pociagow - klik na pojezdzie aby uzyskac inforamcje +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Budowa zaznaczonego pojazdu +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Zmiana nazwy typu pociagu +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Obecny stan pociagu - klik tutaj aby zatrzymac ruszyc pociag +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Pokaz polecenia dla pociagu +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrowanie glownego okna na pozycji pociagu +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Wyslij pociag do zajezdni +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Wymuszony wyjazd pociagu bez czekania na sygnal +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Odwroc kierunek jazdy pociagu +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Pokaz szczegoly pociagu +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Zwieksz okres miedzy serwisowaniem +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Zmniejsz okres miedzy serwisowaniem +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Pokaz szczegoly przewozonych towarow +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Pokaz szczegoly pociagu +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Pokaz pojemnosc kazdego wagonu +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Pokaz calkowita pojemnosc pociagu, wedlug typu ladunku +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Lista polecen - klik na poleceniu aby zaznaczyc +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Pomin obecne polecenie i zacznij nastepne +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Usun podswietlone polecenie +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Zrob z tego polecenia, polecenie 'non-stop' +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Wstaw nowe polecenie przed zaznaczonym poleceniem, lub dodaj na koncu +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Spraw aby zaznaczone polecenie zmusilo pojazd do czekania na pelny zaladunek +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Spraw aby zaznaczone polecenie zmusilo pojazd do wyladunku +STR_SERVICE_HINT :{BLACK}Pomin to polecenie jesli jest wymagany serwis +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nowy {STRING} juz dostepny! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Koszt: {CURRENCY} Waga: {COMMA16}t{}Predkosc: {VELOCITY} Moc: {COMMA16}KM{}Utrzymanie: {CURRENCY}/rok{}Pojemnosc: {STRING} +STR_885C_BROKEN_DOWN :{RED}Awaria +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Wiek: {LTBLUE}{STRING}{BLACK} Utrzymanie: {LTBLUE}{CURRENCY}/rok +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Waga: {LTBLUE}{COMMA16}t {BLACK}Moc: {LTBLUE}{COMMA32}KM{BLACK} Max. predkosc: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zysk w tym roku: {LTBLUE}{CURRENCY} (w ostatnim roku: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Niezawodnosc: {LTBLUE}{COMMA8}% {BLACK}Awarie od ostatniego serwisowania: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Zatrzymany +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nie mozna przepuscic pociagu za sygnal, niebezpieczenstwo... +STR_8863_CRASHED :{RED}Wypadek! + +STR_8865_NAME_TRAIN :{WHITE}Nazwa pociagu +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Nie mozna zmienic nazwy pociagu... +STR_8867_NAME_TRAIN :{BLACK}Nazwa pociagu +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Wypadek kolejowy!{}{COMMA16} ofiar w kolizji +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Nie mozna odwrocic kierunku jazdy pociagu... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Zmiana nazwy typu pociagu +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Nie mozna zmienic nazwy typu pojazdu... + +STR_TRAIN_STOPPING :{RED}Hamowanie +STR_TRAIN_STOPPING_VEL :{RED}Hamowanie, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Samochod na drodze +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Samochody +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Zajezdnia samochodowa +STR_9004_NEW_VEHICLES :{BLACK}Nowe pojazdy +STR_9005_INFORMATION :{BLACK}Informacje +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nowy Samochod +STR_9007_BUILD_VEHICLE :{BLACK}Zbuduj pojazd +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Koszt: {GOLD}{CURRENCY}{BLACK} Predkosc: {GOLD}{VELOCITY}{}{BLACK}Utrzymanie: {GOLD}{CURRENCY}/rok{}{BLACK}Pojemnosc: {GOLD}{STRING}{}{BLACK}Zaprojektowany: {GOLD}{NUMU16}{BLACK} Trwalosc: {GOLD}{COMMA16} lat{}{BLACK}Max. Niezawodnosc: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nie mozna zbudowac samochodu... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Musisz najpierw zbudowac zajezdnie samochodowa +STR_900B_ORDERS :{WHITE}{STRING} (Polecenia) +STR_900C_DETAILS :{WHITE}{STRING} (Szczegoly) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Wiek: {LTBLUE}{STRING}{BLACK} Utrzymanie: {LTBLUE}{CURRENCY}/rok +STR_900E_MAX_SPEED :{BLACK}Max. predkkosc: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zysk w tym roku: {LTBLUE}{CURRENCY} (ostatni rok: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Niezawodnosc: {LTBLUE}{COMMA8}% {BLACK}Awarie od ostatniego serwisowania: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zbudowany: {LTBLUE}{NUMU16}{BLACK} Wartosc: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Pojemnosc: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...musi byc zatrzymany w zajezdni samochodowej +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Nie mozna sprzedac samochodu... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Nie mozna zatrzymac/ruszyc samochodu... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Samochod {COMMA16} czeka w zjezdni +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Zmierza do {TOWN} zajezdni sam. +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}Zmierza do {TOWN} zajezdni sam., {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Nie mozna wyslac samochodu do zajezdni sam... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nie mozna znalezc zajezdni +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Samochody - klik na pojezdzie po wiecej info +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Zbuduj nowe samochody (wymaga zajezdni sam.) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Obecny stan pojazdu - klik tutaj aby zatrzymac/ruszyc pojazd +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Pokaz polecenia pojazdu +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centruj widok na lokacji pojazdu +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Wyslij pojazd do zajezdni +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Zmus pojazd do zawrocenia +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Pokaz detale samochodu +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Pojazdy - klik na pojezdzie po wiecej info +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Zbuduj nowy samochod +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Przecianij samochod tutaj aby go sprzedac +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centruj widok na lokacji zajezdni samochodowej +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Lista wyboru samochodow - klik na pojezdzie po wiecej info +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Zbuduj wybrany samochod +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Dostepny jest nowy samochod! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Koszt: {CURRENCY}{}Predkosc: {VELOCITY}{}Utrzymanie: {CURRENCY}/rok{}Pojemnosc: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Nazwij samochod +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Nie mozna nazwac samochodu... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Nazwij samochod +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mieszkancy swietuja . . .{}Pierwszy autobus przybyl do {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mieszkancy swietuja . . .{}Pierwsza ciezarowka przybyla do {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Wypadek samochodowy!{}Kierowca zginal po zderzeniu z pociagiem +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Wypadek samochodowy!{}{COMMA16} ofiar po zderzeniu z pociagiem +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Nie mozna zawrocic samochodu... +STR_9034_RENAME :{BLACK}Zmien nazwe +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Zmien nazwe typu samochodu +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Zmien nazwe typu samochodu +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Nie mozna zmienic nazwy typu samochodu... +STR_9038_GO_TO_ROADVEH_DEPOT :Jedz do {TOWN} zajednia sam. +STR_SERVICE_AT_ROADVEH_DEPOT :Serwisuj w {TOWN} zajezdni sam. + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Konstrukcje morskie +STR_9801_DOCK_CONSTRUCTION :{WHITE}Konstrukcje portowe +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Nie mozna tutaj wybudowac portu... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Stocznia +STR_9804_NEW_SHIPS :{BLACK}Nowe statki +STR_9805_SHIPS :{WHITE}{STRING} - Statki +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Nie mozna zbudowac statku... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Trzeba najpierw zbudowac stocznie +STR_9808_NEW_SHIPS :{WHITE}Nowe statki +STR_9809_BUILD_SHIP :{BLACK}Budowa statku +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Koszt: {GOLD}{CURRENCY}{BLACK} Predkosc: {GOLD}{VELOCITY}{}{BLACK}Pojemnosc: {GOLD}{STRING} {STRING}{}{BLACK}Utrzymanie: {GOLD}{CURRENCY}/rok{}{BLACK}Zaprojektowany: {GOLD}{NUMU16}{BLACK} Trwalosc: {GOLD}{COMMA16} lat{}{BLACK}Max. niezawodnosc: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Statek musi byc zatrzymany w stoczni +STR_980C_CAN_T_SELL_SHIP :{WHITE}Nie mozna sprzedac statku... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Nie mozna wybudowac statku... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Statek na drodze +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Polecenia) +STR_9811_DETAILS :{WHITE}{STRING} (Szczegoly) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Wiek: {LTBLUE}{STRING}{BLACK} Utrzymanie: {LTBLUE}{CURRENCY}/rok +STR_9813_MAX_SPEED :{BLACK}Max. predkosc: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zysk w tym roku: {LTBLUE}{CURRENCY} (w ostatnim roku: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Niezawodnosc: {LTBLUE}{COMMA8}% {BLACK}Awarie od ostatniego serwisowania: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Wybudowany: {LTBLUE}{NUMU16}{BLACK} Wartosc: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Pojemnosc: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Nie mozna zatrzymac/ruszyc statku... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Nie mozna wyslac statku do stoczni... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nie mozna znalezc zajezdni +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Zmierza do stoczni w {TOWN} +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Zmierza do stoczni w {TOWN}, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Statek {COMMA16} czeka w stoczni +STR_981D_BUILD_SHIP_DOCK :{BLACK}Budowa portu +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Budowa stoczni (do budowy i serwisowania statkow) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Statki - klik aby uzyskac informacje o statku +STR_9820_BUILD_NEW_SHIP :{BLACK}Budowa nowego statku +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Przeciagnij tu statek aby go sprzedac +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centruj glowne okno na pozycji stoczni +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Kliknij na statku aby uzyskac inforamcje +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Budowa nowych statkow (wymaga stoczni) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Lista wyboru statkow - klik na statku aby uzyskac informacje +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Budowa zaznaczonego statku +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Stan obecnego statku - klik aby zatrzymac/ruszyc statek +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Pokaz liste polecen dla statku +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centruj glowne okno na pozycji statku +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Wyslij statek do stoczni +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Pokaz szczegoly statku +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Dostepny nowy statek! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Koszt: {CURRENCY} Max. Predkosc: {VELOCITY}{}Pojemnosc: {STRING}{}Utrzymanie: {CURRENCY}/rok +STR_982F_NAME_SHIP :{BLACK}Nazwa statku + +STR_9831_NAME_SHIP :{WHITE}Nazwa statku +STR_9832_CAN_T_NAME_SHIP :{WHITE}Nie mozna zmienic nazwy statku... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mieszkancy swietuja . . .{}Pierwszy statek przybyl do {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Ustaw boje, ktora moze byc uzyta jako dodatkowy pkt. drogi +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Nie mzna ustawic tutaj boji... +STR_9836_RENAME :{BLACK}Zmien nazwe +STR_9837_RENAME_SHIP_TYPE :{BLACK}Zmien nazwe typu statku +STR_9838_RENAME_SHIP_TYPE :{WHITE}Zmien nazwe typu statku +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Nie mozna zmienic nazwy typu statku... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Przebuduj statek aby przwozil inny rodzaj towaru +STR_983B_REFIT :{WHITE}{STRING} (Przebudowa) +STR_983C_REFIT_SHIP :{BLACK}Przebudowa statku +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wybierz typ ladunku jaki ma przwozic statek +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Zmien statek zeby mogl przewozic zaznaczony typ ladunku +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Wybierz typ ladunku do przewozu:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nowa pojemnosc: {GOLD}{STRING}{}{BLACK}Koszt przebudowy: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Nie mozna przebudowac statku... +STR_9842_REFITTABLE :(zm. typu lad.) +STR_GO_TO_SHIP_DEPOT :Idz do stoczni w {TOWN} +SERVICE_AT_SHIP_DEPOT :Serwisuj w stoczni w {TOWN} + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Konstrukcje lotnicze. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Nie mozna tu wybudowac lotniska... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Hangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nowy samolot +STR_A004_INFORMATION :{BLACK}Informacje +STR_A005_NEW_AIRCRAFT :{WHITE}Nowy samolot +STR_A006_BUILD_AIRCRAFT :{BLACK}Budowa samolotu +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Koszt: {GOLD}{CURRENCY}{BLACK} Predkosc: {GOLD}{VELOCITY}{}{BLACK}Pojemnosc: {GOLD}{COMMA16} pasazerow, {COMMA16} paczek poczty{}{BLACK}Utrzymanie: {GOLD}{CURRENCY}/rok{}{BLACK}Zaprojektowany: {GOLD}{NUMU16}{BLACK} Trwalosc: {GOLD}{COMMA16} lat{}{BLACK}Max. niezawodnosc: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Nie mozna zbudowac samolotu... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Samolot +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Polecenia) +STR_A00C_DETAILS :{WHITE}{STRING} (Szczegoly) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Wiek: {LTBLUE}{STRING}{BLACK} Utrzymanie: {LTBLUE}{CURRENCY}/rok +STR_A00E_MAX_SPEED :{BLACK}Max. predkosc: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zysk w tym roku: {LTBLUE}{CURRENCY} (w ostatnim roku: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Niezawodnosc: {LTBLUE}{COMMA8}% {BLACK}Awarie od ostatniego serwisowania: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Zbudowany: {LTBLUE}{NUMU16}{BLACK} Wartosc: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Nie mozna wyslac samolotu do hangaru... +STR_HEADING_FOR_HANGAR :{LTBLUE}Zmierza do hangaru w {STATION} +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Zmierza do hangaru w {STATION}, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Samolot {COMMA16} czeka w hangarze +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Samolot jest w drodze +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Nie mozna zatrzymac/ruszyc samolotu +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Samolot wlasnie leci +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Trzeba najpierw zbudowac lotnisko +STR_A019_CAPACITY :{BLACK}Pojemnosc: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Pojemnosc: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Samolot musi byc zatrzymany w hangarze +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Nie mozna sprzedac samolotu... +STR_A01D_AIRPORT_CONSTRUCTION :Konstrukcje lotnicze +STR_A01E_BUILD_AIRPORT :{BLACK}Budowa lotniska +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Samolot - klik na samolocie aby uzyskac informacje +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Budowa samolotu (wymaga lotniska z hangarem) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Samolot - klik na samolocie aby uzyskac informacje +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Budowa nowego samolotu +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Przeciagnij tutaj samolot aby go sprzedac +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centruj glowne okno na pozycji hangaru +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Lista wyboru samolotow - klik na samolocie aby uzyskac informacje +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Zbudowa zaznaczonych samolotow +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Stan obecnego samolotu - klik aby zatrzymac/ruszyc samolot +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Pokaz polecenia dla samolotu +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centruj glowne okno na pozycji samolotu +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Wyslij samolot do hangaru +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Pokaz szczegoly samolotu +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Dostepny nowy typ samolotu! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Koszt: {CURRENCY} Max. Predkosc: {VELOCITY}{}Pojemnosc: {COMMA16} pasazerow, {COMMA16} paczek poczty{}Utrzymanie: {CURRENCY}/rok + +STR_A030_NAME_AIRCRAFT :{WHITE}Nazwa samolotu +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Nie mozna zmienic nazwy samolotu... +STR_A032_NAME_AIRCRAFT :{BLACK}Nazwa samolotu +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mieszkancy swietuja . . .{}pierwszy samolot przylecial do {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Katastrofa lotnicza!{}{COMMA16} ofiar na {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Cele: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Zmien nazwe +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Zmien nazwe typu samolotu +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Zmien nazwe typu samolotu +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Nie mozna zmienic nazwy typu samolotu... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Przebudowa samolotu do przewozu innego towaru +STR_A03C_REFIT :{WHITE}{STRING} (Przebudowa) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Przebudowa samolotu +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Wybierz typ towaru jaki ma przenosic samolot +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Przebudowa samolotu do przewozu podswietlonych towarow +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Wybierz typ towaru do przewozu:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nowa pojemnosc: {GOLD}{STRING}{}{BLACK}Koszt przebudowy: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Nie mozna przebudowac samolotu... +STR_A043_REFITTABLE :(zm. typ lad.) +STR_GO_TO_AIRPORT_HANGAR :Idz do hangaru na {STATION} +SERVICE_AT_AIRPORT_HANGAR :Serwisuj w hangarze na {STATION} + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Katastrofa Zeppelina przy {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Samochod zniszczony po kolizji z 'UFO'! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Eksplozja rafineri blisko {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabryka zniszczona w niewyjasnionych okolicznosciach w poblizu {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' wyladowalo blisko {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Tapniecie w kopalni zniszczylo tory w poblizu {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Twoja lapowka zostala +STR_BRIBE_FAILED_2 :{WHITE}wykryta przez lokalne wladze. diff --git a/lang/slovak.txt b/lang/slovak.txt new file mode 100644 --- /dev/null +++ b/lang/slovak.txt @@ -0,0 +1,2356 @@ +##name Slovak +##ownname Slovensky + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Za okrajom mapy +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Prilis blizko okraju mapy +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Mala hotovost - potrebna {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Potrebny rovny teren +STR_0008_WAITING :{BLACK}Caka: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (na ceste z +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Prijma: {WHITE} +STR_000D_ACCEPTS :{BLACK}Prijma: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Cestujucich +STR_0010_COAL :Uhlie +STR_0011_MAIL :Postu +STR_0012_OIL :Ropu +STR_0013_LIVESTOCK :Dobytok +STR_0014_GOODS :Tovar +STR_0015_GRAIN :Obilie +STR_0016_WOOD :Drevo +STR_0017_IRON_ORE :Zeleznu rudu +STR_0018_STEEL :Ocel +STR_0019_VALUABLES :Cennosti +STR_001A_COPPER_ORE :Medenna ruda +STR_001B_MAIZE :Kukuricu +STR_001C_FRUIT :Ovocie +STR_001D_DIAMONDS :Diamanty +STR_001E_FOOD :Jedlo +STR_001F_PAPER :Papier +STR_0020_GOLD :Zlato +STR_0021_WATER :Vodu +STR_0022_WHEAT :Psenicu +STR_0023_RUBBER :Kaucuk +STR_0024_SUGAR :Cukor +STR_0025_TOYS :Hracky +STR_0026_CANDY :Cukriky +STR_0027_COLA :Kofolu +STR_0028_COTTON_CANDY :Cukrovu vatu +STR_0029_BUBBLES :Bublin +STR_002A_TOFFEE :Karamelky +STR_002B_BATTERIES :Baterie +STR_002C_PLASTIC :Zuvaciek +STR_002D_FIZZY_DRINKS :Sumienku +STR_002E : +STR_002F_PASSENGER :Cestujuci +STR_0030_COAL :Uhlie +STR_0031_MAIL :Posta +STR_0032_OIL :Ropa +STR_0033_LIVESTOCK :Dobytok +STR_0034_GOODS :Tovar +STR_0035_GRAIN :Obilie +STR_0036_WOOD :Drevo +STR_0037_IRON_ORE :Zelezna ruda +STR_0038_STEEL :Ocel +STR_0039_VALUABLES :Cennosti +STR_003A_COPPER_ORE :Medenna ruda +STR_003B_MAIZE :Kukurica +STR_003C_FRUIT :Ovocie +STR_003D_DIAMOND :Diamant +STR_003E_FOOD :Jedlo +STR_003F_PAPER :Papier +STR_0040_GOLD :Zlato +STR_0041_WATER :Voda +STR_0042_WHEAT :Psenica +STR_0043_RUBBER :Kaucuk +STR_0044_SUGAR :Cukor +STR_0045_TOY :Hracky +STR_0046_CANDY :Cukriky +STR_0047_COLA :Kofola +STR_0048_COTTON_CANDY :Cukrova vata +STR_0049_BUBBLE :Bubliny +STR_004A_TOFFEE :Karamel +STR_004B_BATTERY :Baterie +STR_004C_PLASTIC :Zuvacky +STR_004D_FIZZY_DRINK :Sumienka +STR_004E : +STR_004F_PASSENGER :{COMMA16} cestujuci +STR_0050_TON_OF_COAL :{COMMA16} tona uhlia +STR_0051_BAG_OF_MAIL :{COMMA16} balik posty +STR_0052_OF_OIL :{VOLUME} ropy +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} kus dobytka +STR_0054_CRATE_OF_GOODS :{COMMA16} debna tovaru +STR_0055_TON_OF_GRAIN :{COMMA16} tona obilia +STR_0056_TON_OF_WOOD :{COMMA16} tona dreva +STR_0057_TON_OF_IRON_ORE :{COMMA16} tona zeleznej rudy +STR_0058_TON_OF_STEEL :{COMMA16} tona ocele +STR_0059_BAG_OF_VALUABLES :{COMMA16} vreco cennosti +STR_005A_TON_OF_COPPER_ORE :{COMMA16} tona medennej rudy +STR_005B_TON_OF_MAIZE :{COMMA16} tona kukurice +STR_005C_TON_OF_FRUIT :{COMMA16} tona ovocia +STR_005D_BAG_OF_DIAMONDS :{COMMA16} debna diamantov +STR_005E_TON_OF_FOOD :{COMMA16} tona jedla +STR_005F_TON_OF_PAPER :{COMMA16} tona papiera +STR_0060_BAG_OF_GOLD :{COMMA16} debna zlata +STR_0061_OF_WATER :{VOLUME} voda +STR_0062_TON_OF_WHEAT :{COMMA16} tona psenice +STR_0063_OF_RUBBER :{VOLUME} kaucuk +STR_0064_TON_OF_SUGAR :{COMMA16} tona cukru +STR_0065_TOY :{COMMA16} hracka +STR_0066_BAG_OF_CANDY :{COMMA16} debna cukrikov +STR_0067_OF_COLA :{VOLUME} kofola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tona cukrovej vaty +STR_0069_BUBBLE :{COMMA16} bublina +STR_006A_TON_OF_TOFFEE :{COMMA16} tona karamelu +STR_006B_BATTERY :{COMMA16} bateria +STR_006C_OF_PLASTIC :{VOLUME} zuvacka +STR_006D_FIZZY_DRINK :{COMMA16} sumienka +STR_006E : +STR_006F_PASSENGERS :{COMMA16} cestujucich +STR_0070_TONS_OF_COAL :{COMMA16} ton uhlia +STR_0071_BAGS_OF_MAIL :{COMMA16} balikov posty +STR_0072_OF_OIL :{VOLUME} ropy +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} kusov dobytka +STR_0074_CRATES_OF_GOODS :{COMMA16} debien tovaru +STR_0075_TONS_OF_GRAIN :{COMMA16} ton obilia +STR_0076_TONS_OF_WOOD :{COMMA16} ton dreva +STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton zeleznej rudy +STR_0078_TONS_OF_STEEL :{COMMA16} ton ocele +STR_0079_BAGS_OF_VALUABLES :{COMMA16} vriec cennosti +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton medennej rudy +STR_007B_TONS_OF_MAIZE :{COMMA16} ton kukurice +STR_007C_TONS_OF_FRUIT :{COMMA16} ton ovocia +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} debien diamantov +STR_007E_TONS_OF_FOOD :{COMMA16} ton jedla +STR_007F_TONS_OF_PAPER :{COMMA16} ton papiera +STR_0080_BAGS_OF_GOLD :{COMMA16} debien zlata +STR_0081_OF_WATER :{VOLUME} vody +STR_0082_TONS_OF_WHEAT :{COMMA16} ton psenice +STR_0083_OF_RUBBER :{VOLUME} kaucuku +STR_0084_TONS_OF_SUGAR :{COMMA16} ton cukru +STR_0085_TOYS :{COMMA16} hraciek +STR_0086_BAGS_OF_CANDY :{COMMA16} debien cukrikov +STR_0087_OF_COLA :{VOLUME} kofoly +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton cukrovej vaty +STR_0089_BUBBLES :{COMMA16} bublin +STR_008A_TONS_OF_TOFFEE :{COMMA16} ton karamelu +STR_008B_BATTERIES :{COMMA16} baterii +STR_008C_OF_PLASTIC :{VOLUME} zuvaciek +STR_008D_FIZZY_DRINKS :{COMMA16} sumienky +STR_008E : +STR_008F_PS :{TINYFONT}CE +STR_0090_CL :{TINYFONT}UH +STR_0091_ML :{TINYFONT}PO +STR_0092_OL :{TINYFONT}RO +STR_0093_LV :{TINYFONT}DO +STR_0094_GD :{TINYFONT}TO +STR_0095_GR :{TINYFONT}OB +STR_0096_WD :{TINYFONT}DR +STR_0097_OR :{TINYFONT}ZR +STR_0098_ST :{TINYFONT}OC +STR_0099_VL :{TINYFONT}CE +STR_009A_CO :{TINYFONT}MR +STR_009B_MZ :{TINYFONT}KU +STR_009C_FT :{TINYFONT}OV +STR_009D_DM :{TINYFONT}DI +STR_009E_FD :{TINYFONT}JE +STR_009F_PR :{TINYFONT}PA +STR_00A0_GD :{TINYFONT}ZL +STR_00A1_WR :{TINYFONT}VO +STR_00A2_WH :{TINYFONT}PS +STR_00A3_RB :{TINYFONT}KA +STR_00A4_SG :{TINYFONT}CU +STR_00A5_TY :{TINYFONT}HR +STR_00A6_SW :{TINYFONT}CK +STR_00A7_CL :{TINYFONT}KO +STR_00A8_CF :{TINYFONT}CV +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}KR +STR_00AB_BA :{TINYFONT}BT +STR_00AC_PL :{TINYFONT}ZU +STR_00AD_FZ :{TINYFONT}SU +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Mapa - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Nastavenia Hry +STR_00B2_MESSAGE :{YELLOW}Sprava +STR_00B3_MESSAGE_FROM :{YELLOW}Sprava od {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Takto sa to neda... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Oblast sa neda vycistit... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Original copyright {COPYRIGHT} 1995 Chris Sawyer, All rights reserved +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Original design by Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Graphics by Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 The OpenTTD team + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Koniec +STR_00C8_YES :{BLACK}Ano +STR_00C9_NO :{BLACK}Nie +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Si si isty ze chces ukoncit hru a vratit sa do {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Nie je +STR_00D1_DARK_BLUE :Tmavomodra +STR_00D2_PALE_GREEN :Svetlozelena +STR_00D3_PINK :Ruzova +STR_00D4_YELLOW :Zlta +STR_00D5_RED :Cervena +STR_00D6_LIGHT_BLUE :Svetlomodra +STR_00D7_GREEN :Zelena +STR_00D8_DARK_GREEN :Tmavozelena +STR_00D9_BLUE :Modra +STR_00DA_CREAM :Kremova +STR_00DB_MAUVE :Ruzova +STR_00DC_PURPLE :Fialova +STR_00DD_ORANGE :Oranzova +STR_00DE_BROWN :Hneda +STR_00DF_GREY :Seda +STR_00E0_WHITE :Biela +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}V hre je prilis vela dopravnych prostriedkov +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Pozicia +STR_00E5_CONTOURS :Vrstevnice +STR_00E6_VEHICLES :Dopravne Prostriedky +STR_00E7_INDUSTRIES :Priemysel +STR_00E8_ROUTES :Trasy +STR_00E9_VEGETATION :Vegetacia +STR_00EA_OWNERS :Vlastnici +STR_00EB_ROADS :{BLACK}{TINYFONT}Cesty +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Zeleznicne drahy +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stanice/Letiska/Pristavy +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Budovy/Tovarne +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Dopravne Prostriedky +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Vlaky +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Auta +STR_00F7_SHIPS :{BLACK}{TINYFONT}Lode +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Lietadla +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Dopravne Trasy +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Uholna bana +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Elektraren +STR_00FC_FOREST :{BLACK}{TINYFONT}Les +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Pila +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Ropna rafineria +STR_00FF_FARM :{BLACK}{TINYFONT}Farma +STR_0100_FACTORY :{BLACK}{TINYFONT}Tovaren +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Tlaciaren +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Ropny vrt +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Zelezna bana +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Oceliaren +STR_0105_BANK :{BLACK}{TINYFONT}Banka +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Vyroba papiera +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Zlata bana +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Vyroba potravin +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamantova bana +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Medenna bana +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Ovocny sad +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Kaucukova plantaz +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Zasobaren vody +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vodojem +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Pila +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Les cukrovej vaty +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Cukrovar +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Vyroba baterii +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Vyroba kofoly +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Hrackarstvo +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Vyroba hraciek +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Zuvackova fontana +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Vyroba sumienky +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Bublifuk +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Karamelovy lom +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Cukrova bana +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Zeleznicna stanica +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Nakladacia rampa +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Autobusova zastavka +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Letisko +STR_011F_DOCK :{BLACK}{TINYFONT}Pristav +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Hruby teren +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Travnaty teren +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Holy teren +STR_0123_FIELDS :{BLACK}{TINYFONT}Polia +STR_0124_TREES :{BLACK}{TINYFONT}Lesy +STR_0125_ROCKS :{BLACK}{TINYFONT}Skaly +STR_0126_WATER :{BLACK}{TINYFONT}Voda +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Bez vlastnika +STR_0128_TOWNS :{BLACK}{TINYFONT}Mesta +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Priemysel +STR_012A_DESERT :{BLACK}{TINYFONT}Pust +STR_012B_SNOW :{BLACK}{TINYFONT}Sneh +STR_012C_MESSAGE :{WHITE}Sprava +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Zrusit +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Premenovat +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}Pouzitych prilis vela mien +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Vybrane meno je uz pouzite + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Imperial (mile) +STR_013A_METRIC_KILOMETERS :Metric (kilometre) +STR_013B_OWNED_BY :{WHITE}...vlastnik {STRING} +STR_013C_CARGO :{BLACK}Naklad +STR_013D_INFORMATION :{BLACK}Informacia +STR_013E_CAPACITIES :{BLACK}Kapacita +STR_013E_TOTAL_CARGO :{BLACK}Celkovy Naklad +STR_013F_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT :{BLACK}Celkovy naklad (kapacita) tohoto vlaku: +STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nova Hra +STR_0141_LOAD_GAME :{BLACK}Nahrat Hru +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Nacvik / Ukazka +STR_0143_1_PLAYER :{BLACK}1 Hrac +STR_0144_2_PLAYERS :{BLACK}2 Hraci + +STR_0148_GAME_OPTIONS :{BLACK}Nastavenia Hry + +STR_0150_SOMEONE :niekto{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Mapa sveta +STR_0152_TOWN_DIRECTORY :Zoznam miest +STR_0153_SUBSIDIES :Dotacie + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Graf prevadzkoveho zisku +STR_0155_INCOME_GRAPH :Graf trzieb +STR_0156_DELIVERED_CARGO_GRAPH :Graf prepraveneho nakladu +STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf hodnotenia vykonu +STR_0158_COMPANY_VALUE_GRAPH :Graf hodnoty spolocnosti +STR_0159_CARGO_PAYMENT_RATES :Ceny Prepravy +STR_015A_COMPANY_LEAGUE_TABLE :Hodnotenie spolocnosti +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Ulozit hru +STR_015D_LOAD_GAME :Nahrat hru +STR_015E_QUIT_GAME :Koniec hry +STR_015F_QUIT :Ukoncit program +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Si si isty ze chces ukoncit tuto hru ? +STR_0161_QUIT_GAME :{WHITE}Koniec hry + +############ range for months starts +STR_0162_JAN :Jan +STR_0163_FEB :Feb +STR_0164_MAR :Mar +STR_0165_APR :Apr +STR_0166_MAY :Maj +STR_0167_JUN :Jun +STR_0168_JUL :Jul +STR_0169_AUG :Aug +STR_016A_SEP :Sep +STR_016B_OCT :Okt +STR_016C_NOV :Nov +STR_016D_DEC :Dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pauza +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Ulozit hru, opustit hru, ukoncit program +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Zoznam stanic spolocnosti +STR_0174_DISPLAY_MAP :{BLACK}Zobrazit mapu +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Zobrazit mapu, zoznam miest +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Zobrazit zoznam miest +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Financne informacie o spolocnosti +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Informacie o spolocnosti +STR_0179_DISPLAY_GRAPHS :{BLACK}Grafy +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Hodnotenie spolocnosti +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Zoznam vlakov +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Zoznam automobilov +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Zoznam lodi +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Zoznam Lietadiel +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Priblizit +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Oddialit +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Vystavba zeleznice +STR_0182_BUILD_ROADS :{BLACK}Vystavba ciest +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Vystavba pristavov +STR_0184_BUILD_AIRPORTS :{BLACK}Vystavba letisk +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Sadit stromy, rezervacia pozemku +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Informacie o pozemku +STR_0187_OPTIONS :{BLACK}Nastavenia +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Nieje mozne zmenit servisny interval... +STR_018B_CLOSE_WINDOW :{BLACK}Zavriet okno +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Nadpis okna - potiahni pre posun okna +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Zburanie budov, cistenie terenu +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Znizit roh terenu +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Zvysit roh terenu +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Posuvacia lista +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Zobrazit vrstevnice na mape +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Zobrazit dopravne prostriedky na mape +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Zobrazit priemysel na mape +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Zobrazit dopravne trasy na mape +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Zobrazit vegetaciu na mape +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Zobrazit vlastnikov pozemkov na mape +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Zapnut / Vypnut nazvy miest na mape +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Zisk tento rok: {CURRENCY} (posledny rok: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} rok ({COMMA16}) +STR_019A_YEARS :{COMMA16} rokov ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} rokov ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Automobil +STR_019D_AIRCRAFT :Lietadlo +STR_019E_SHIP :Lod +STR_019F_TRAIN :Vlak +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} je stary +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} je velmi stary +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} je velmi stary a potrebuje vymenit +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Informacie o pozemku +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Cena za zburanie: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Cena za zburanie: {LTBLUE}{CURRENCY} +STR_01A6_N_A :Nezname +STR_01A7_OWNER :{BLACK}Vlastnik: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Miestna sprava: {LTBLUE}{STRING} +STR_01A9_NONE :Nezname +STR_01AA_NAME :{BLACK}Meno +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1 +STR_01AD_2ND :2 +STR_01AE_3RD :3 +STR_01AF_4TH :4 +STR_01B0_5TH :5 +STR_01B1_6TH :6 +STR_01B2_7TH :7 +STR_01B3_8TH :8 +STR_01B4_9TH :9 +STR_01B5_10TH :10 +STR_01B6_11TH :11 +STR_01B7_12TH :12 +STR_01B8_13TH :13 +STR_01B9_14TH :14 +STR_01BA_15TH :15 +STR_01BB_16TH :16 +STR_01BC_17TH :17 +STR_01BD_18TH :18 +STR_01BE_19TH :19 +STR_01BF_20TH :20 +STR_01C0_21ST :21 +STR_01C1_22ND :22 +STR_01C2_23RD :23 +STR_01C3_24TH :24 +STR_01C4_25TH :25 +STR_01C5_26TH :26 +STR_01C6_27TH :27 +STR_01C7_28TH :28 +STR_01C8_29TH :29 +STR_01C9_30TH :30 +STR_01CA_31ST :31 +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Prepnut malu / velku mapu +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Vybrat Nacvik / Ukazku + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Prijma naklad: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Prijma naklad: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Prijma naklad: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Gramofon +STR_01D3_SOUND_MUSIC :Zvuk/Hydba +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Zobraz zvukove/hudobne okno +STR_01D5_ALL :{TINYFONT}Vsetko +STR_01D6_OLD_STYLE :{TINYFONT}Stary styl +STR_01D7_NEW_STYLE :{TINYFONT}Novy styl +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Vlastne 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Vlastne 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Hlasitost hudby +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}hlasitost zvuk. efektov +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Predchadzajuca stopa +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Nasledujuca stopa +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Zastavit prehravanie hudby +STR_01E1_START_PLAYING_MUSIC :{BLACK}Spustit prehravanie hudby +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Tahat posuvace pre zmenu hlasitosti +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Stopa{SETX 88}Title +STR_01E9_SHUFFLE :{TINYFONT}Nahodne +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Vyber hudobneho programu +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Cislo stopy +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Zmazat +STR_01F1_SAVE :{TINYFONT}{BLACK}Ulozit +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Aktualny program +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Vybrat 'Vsetko' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Vybrat 'Stary styl' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Vybrat 'Novy styl' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Vybrat 'Vlastny 1' (uzivatelom definovany) program +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Vybrat 'Vlastny 2' (uzivatelom definovany) program +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Vymazat aktualny program (len Vlastny 1 a Vlastny 2 program) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Ulozit nastavenia hudby na disk +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Kliknut na stopu pre ulozenie (len Vlastny 1 a Vlastny 2 program) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Zapnut / Vypnut nahodny vyber +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Zobrazit okno pre vyber hudobnych stop +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Kliknut na trasu pre centrovanie pohladu na tovaren/mesto +STR_01FE_DIFFICULTY :{BLACK}Obtiaznost ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Zobrazit poslednu spravu/novinku +STR_0201_MESSAGE_SETTINGS :Nastavenia sprav +STR_MESSAGE_HISTORY_MENU :Historia Sprav +STR_0202_SEND_MESSAGE :Poslat spravu +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Zobrazit poslednu spravu/novinku, nastavenia sprav +STR_0204_MESSAGE_OPTIONS :{WHITE}Nastavenia sprav +STR_0205_MESSAGE_TYPES :{BLACK}Typ sprav:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prijazd prveho vozidla do stanice hraca +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Prijazd prveho vozidla do stanice konkurencie +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Havarie / Katastrofy +STR_0209_COMPANY_INFORMATION :{YELLOW}Informacie o spolocnosti +STR_020A_ECONOMY_CHANGES :{YELLOW}Zmeny ekonomiky +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Oznamenia / Informacia o vozidlach hraca +STR_020C_NEW_VEHICLES :{YELLOW}Nove vozidla +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Zmeny prijmu nakladu +STR_020E_SUBSIDIES :{YELLOW}Dotacie +STR_020F_GENERAL_INFORMATION :{YELLOW}Hlavne informacie +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...prilis daleko z predchadzajuceho ciela +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Najlepsie spolocnosti ktore dosiahli rok 2050{}({STRING} Uroven) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Obchodnik +STR_0214_ENTREPRENEUR :Podnikatel +STR_0215_INDUSTRIALIST :Priemyselnik +STR_0216_CAPITALIST :Kapitalista +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Tycoon +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} dosiahol '{STRING}' stav! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} dosiahnuti {STRING} '{STRING}' stavu! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Vytvorit Scenar +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Editor scenarov +STR_0223_LAND_GENERATION :{WHITE}Generovanie uzemia +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Nahodne uzemie +STR_0227_RESET_LAND :{BLACK}Zresetovat uzemie +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Pre zvysenie/znizenie oblasti je potrebne zvacsit uzemie +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Pre zvysenie/znizenie oblasti je potrebne zmensit uzemie +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Vygenerovat nahodne uzemie +STR_022B_RESET_LANDSCAPE :{BLACK}Zresetovat uzemie +STR_022C_RESET_LANDSCAPE :{WHITE}Zresetovat Uzemie +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Si si isty ze chces zresetovat uzemie ? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Vytvorenie uzemia +STR_022F_TOWN_GENERATION :{BLACK}Vytvorenie mesta +STR_0230_INDUSTRY_GENERATION :{BLACK}Vytvorenie priemyslu +STR_0231_ROAD_CONSTRUCTION :{BLACK}Stavba cesty +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetacia a ine objekty +STR_0233_TOWN_GENERATION :{WHITE}Vytvorenie mesta +STR_0234_NEW_TOWN :{BLACK}Nove mesto +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Stavat nove mesto +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Tu sa mesto neda postavit... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...prilis blizko kraja mapy +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...prilis blizko ineho mesta +STR_0239_SITE_UNSUITABLE :{WHITE}...miesto je nepouzitelne +STR_023A_TOO_MANY_TOWNS :{WHITE}...prilis vela miest +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Zvacsit velkost mesta +STR_023C_EXPAND :{BLACK}Rozsirit +STR_023D_RANDOM_TOWN :{BLACK}Nahodne mesto +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Postavit mesto na nahodnej pozicii +STR_023F_INDUSTRY_GENERATION :{WHITE}Vytvorenie priemyslu +STR_0240_COAL_MINE :{BLACK}Uholna bana +STR_0241_POWER_STATION :{BLACK}Elektraren +STR_0242_SAWMILL :{BLACK}Pila +STR_0243_FOREST :{BLACK}Les +STR_0244_OIL_REFINERY :{BLACK}Ropna rafineria +STR_0245_OIL_RIG :{BLACK}Vrtna plosina +STR_0246_FACTORY :{BLACK}Tovaren +STR_0247_STEEL_MILL :{BLACK}Oceliaren +STR_0248_FARM :{BLACK}Farma +STR_0249_IRON_ORE_MINE :{BLACK}Bana na zeleznu rudu +STR_024A_OIL_WELLS :{BLACK}Vrtna veza +STR_024B_BANK :{BLACK}Banka +STR_024C_PAPER_MILL :{BLACK}Vyroba papiera +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Vyroba jedla +STR_024E_PRINTING_WORKS :{BLACK}Tlaciaren +STR_024F_GOLD_MINE :{BLACK}Zlata bana +STR_0250_LUMBER_MILL :{BLACK}Pila +STR_0251_FRUIT_PLANTATION :{BLACK}Ovocny sad +STR_0252_RUBBER_PLANTATION :{BLACK}Kaucukova plantaz +STR_0253_WATER_SUPPLY :{BLACK}Zasobaren vody +STR_0254_WATER_TOWER :{BLACK}Vodojem +STR_0255_DIAMOND_MINE :{BLACK}Diamantova bana +STR_0256_COPPER_ORE_MINE :{BLACK}Medenna bana +STR_0257_COTTON_CANDY_FOREST :{BLACK}Les cukrovej vaty +STR_0258_CANDY_FACTORY :{BLACK}Cukrovar +STR_0259_BATTERY_FARM :{BLACK}Vyroba baterii +STR_025A_COLA_WELLS :{BLACK}Vyroba kofoly +STR_025B_TOY_SHOP :{BLACK}Hrackarstvo +STR_025C_TOY_FACTORY :{BLACK}Vyroba hraciek +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Zuvackova fontana +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Vyroba sumienky +STR_025F_BUBBLE_GENERATOR :{BLACK}Bublifuk +STR_0260_TOFFEE_QUARRY :{BLACK}Karamelovy lom +STR_0261_SUGAR_MINE :{BLACK}Cukrova bana +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Postavit uholnu banu +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Postavit elektraren +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Postavit pilu +STR_0265_PLANT_FOREST :{BLACK}Zasadit les +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Postavit ropnu rafineriu +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Postavit vrtnu plosiny (da sa postavit len blizko kraja mapy) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Postavit tovaren +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Postavit oceliaren +STR_026A_CONSTRUCT_FARM :{BLACK}Postavit farmu +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Postavit banu na zeleznu rudu +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Postavit ropny vrt +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Postavit banku (len v mestach kde je populacia vacsia ako 1200) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Postavit vyrobu papiera +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Postavit vyrobu jedla +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Postavit tlaciaren +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Postavit zlatu banu +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Postavit banku (len v mestach) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Postavit pilu (na cistenie dazdoveho pralesa a produkciu dreva) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Postavit ovocny sad +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Postavit kaucukovu plantaz +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Postavit zasobaren vody +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Postavit vodojem (len v mestach) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Postavit diamantovu banu +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Postavit medennu banu +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Postavit les cukrovej vaty +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Postavit cukrovar +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Postavit vyrobu baterii +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Postavit vyrobu kofoly +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Postavit hrackarstvo +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Postavit vyrobu hraciek +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Postavit zuvackovu fontanu +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Postavit vyrobu sumienky +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Postavit bublifuk +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Postavit karamelovy lom +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Postavit cukrovu banu +STR_0285_CAN_T_BUILD_HERE :{WHITE}{STRING} sa tu neda postavit... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...najskor treba postavit mesto... +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...povolene len jedno pre mesto... +STR_0288_PLANT_TREES :{BLACK}Zasadit stromy +STR_0289_PLACE_SIGN :{BLACK}Umiestnit popis +STR_028A_RANDOM_TREES :{BLACK}Nahodne stromy +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Zasadit nahodne stromy +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Umiestnit nahodne skaly +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Umiestnit majak +STR_028E_PLACE_TRANSMITTER :{BLACK}Umiestnit vysielac +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definovat oblast puste +STR_0290_DELETE :{BLACK}Vymazat +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Vymazat kompletne toto mesto +STR_0292_SAVE_SCENARIO :Ulozit scenar +STR_0293_LOAD_SCENARIO :Nahrat scenar +STR_0294_QUIT_EDITOR :Ukoncit editor +STR_0295 : +STR_0296_QUIT :Ukoncit program +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Ulozit scenar, nahrat scenar, ukoncit editor scenara, ukoncit program +STR_0298_LOAD_SCENARIO :{WHITE}Nahrat Scenar +STR_0299_SAVE_SCENARIO :{WHITE}Ulozit Scenar +STR_029A_PLAY_SCENARIO :{BLACK}Spustit/Hrat scenar +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Si si isty ze chces ukoncit tento scenar ? +STR_029C_QUIT_EDITOR :{WHITE}Ukoncit Editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...Moze byt postavene v mestach z populaciou vacsou ako 1200 +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Posunut zaciatok o rok dozadu +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Posunut zaciatok o rok dopredu +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...konce mostu musia byt na pevnine +STR_02A1_SMALL :{BLACK}Male +STR_02A2_MEDIUM :{BLACK}Stredne +STR_02A3_LARGE :{BLACK}Velke +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Vyber velkost mesta +STR_02A5_TOWN_SIZE :{YELLOW}Velkost mesta: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Zobraz poslednu spravu alebo novinku +STR_02B8_SUMMARY :{BLACK}Obsah +STR_02B9_FULL :{BLACK}Plne +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Zoznam miest +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Nazvy vozidiel +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Vychodzie +STR_02BF_CUSTOM :Vlastne +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Ulozit vlastne nazvy vozidiel na disk +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Vyber nazvu vozidiel +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Ulozit vlastne nazvy vozidiel na disk + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Nastavenia hry +STR_02C4_GAME_OPTIONS :Nastavenia hry +STR_02C5_DIFFICULTY_SETTINGS :Nastavenia obtiaznosti +STR_02C6_DIFFICULTY_SETTINGS :Nastavenia obtiaznosti +STR_02C7_CONFIG_PATCHES :Konfigurovat zaplaty +STR_02C8_CONFIG_PATCHES :Konfigurovat zaplaty +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazit nazvy miest +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Zobrazit nazvy miest +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazit nazvy stanic +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Zobrazit nazvy stanic +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazit popisy +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Zobrazit popisy +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Zobrazit navigacne body +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Zobrazit navigacne body +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Plna animacia +STR_02D0_FULL_ANIMATION :{SETX 12}Plna animacia +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Plne detaily +STR_02D2_FULL_DETAIL :{SETX 12}Plne detaily +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Priesvitne budovy +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Priesvitne budovy +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Informacie o uzemi. +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :ScreenShot (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Velky ScreenShot (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :O hre 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}Zap. +STR_02DB_OFF :{BLACK}Vyp. +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Zobrazit Dotacie +STR_02DD_SUBSIDIES :Dotacie +STR_02DE_MAP_OF_WORLD :Mapa sveta +STR_02DF_TOWN_DIRECTORY :Zoznam miest +STR_02E0_CURRENCY_UNITS :{BLACK}Mena +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Vyber meny +STR_02E3_DISTANCE_UNITS :{BLACK}Jednotky vzdialenosti +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Vyber jednotky vzdialenosti +STR_02E6_ROAD_VEHICLES :{BLACK}Cestne vozidla +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Na ktorej strane jazdia cestne vozidla +STR_02E9_DRIVE_ON_LEFT :Jazdia na lavej strane +STR_02EA_DRIVE_ON_RIGHT :Jazdia na pravej strane +STR_02EB_TOWN_NAMES :{BLACK}Nazvy miest +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Vyber styl nazvov miest + +STR_02F4_AUTOSAVE :{BLACK}Automaticke ukladanie +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Vyber interval automatickeho ukladania +STR_02F7_OFF :Vypnute +STR_02F8_EVERY_3_MONTHS :Kazde 3 mesiace +STR_02F9_EVERY_6_MONTHS :Kazdych 6 mesiacov +STR_02FA_EVERY_12_MONTHS :Kazdych 6 mesiacov +STR_02FB_START_A_NEW_GAME :{BLACK}Spustit novu hru +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Nahrat / ulozit hru z disku +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}Pozriet Vyucbu/ukazky +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Vytvorit vlastny svet / scenar +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Vyber jednouzivatelskej hry +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Vyber viacuzivatelskej hry +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Zobraz nastavenia hry +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Zobraz nastavenia obtiaznosti +STR_0303_START_A_NEW_GAME_USING :{BLACK}Spustit novu hru z pouzitim vlastneho scenara +STR_0304_QUIT :{BLACK}Ukoncit program +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Ukoncit 'OpenTTD' +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Pozriet Vyucbu/ukazky +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} + +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...moze byt postavene len v meste +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Vyber styl uzemia +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Vyber 'arkticky' styl uzemia +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Vyber 'tropicky' styl uzemia +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Vyber 'detsky' styl uzemia +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Financovat vystavbu noveho priemyslu + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Financovat novy priemysel +STR_INDUSTRY_DIR :Zoznam priemyslu +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Financovat novy priemysel +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...moze byt postavene len v meste +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}...moze byt postavene len v dazdovom pralese +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...moze byt postavene len v pusti +STR_0319_PAUSED :{YELLOW}* * ZASTAVENE * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Screenshot bol ulozeny na disk ako '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Screenshot zlyhal! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Zakupit uzemie pre buduce pouzitie +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Automobilove sluzby +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Zeleznicne sluzby +STR_032C_3_AIR_SERVICE :{BLACK}3: Letecke sluzby +STR_032D_4_SHIP_SERVICE :{BLACK}4: Lodne sluzby +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Automobilove sluzby (rozsirene) +STR_032F_AUTOSAVE :{RED}AUTOULOZENIE +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Vyber 'Ezy Street style music' program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Anglicke +STR_TOWNNAME_FRENCH :Francuzke +STR_TOWNNAME_GERMAN :Nemecke +STR_TOWNNAME_AMERICAN :Americke +STR_TOWNNAME_LATIN_AMERICAN :Latinsko-Americke +STR_TOWNNAME_SILLY :Hlupe (anglicky) +STR_TOWNNAME_SWEDISH :Svedske +STR_TOWNNAME_DUTCH :Holandske +STR_TOWNNAME_FINNISH :Finske +STR_TOWNNAME_POLISH :Polske +STR_TOWNNAME_SLOVAKISH :Slovenske +STR_TOWNNAME_HUNGARIAN :Madarske +STR_TOWNNAME_AUSTRIAN :Rakuske +############ end of townname region + +STR_CURR_POUNDS :Libry ({POUNDSIGN}) +STR_CURR_DOLLARS :Dolare ($) +STR_CURR_FF :Franky (FF) +STR_CURR_DM :Nemecke Marky (DM) +STR_CURR_YEN :Jeny ({YENSIGN}) +STR_CURR_PT :Pesos (Pt) +STR_CURR_FT :Madarske Forinty (Ft) +STR_CURR_ZL :Polske Zlote (zl) +STR_CURR_ATS :Rakuske Silingy (ATS) +STR_CURR_BEF :Belgicke Franky (BEF) +STR_CURR_DKK :Danske Koruny (DKK) +STR_CURR_FIM :Finske Marky (FIM) +STR_CURR_GRD :Grecke Drachny (GRD) +STR_CURR_CHF :Svajciarske Franky (CHF) +STR_CURR_NLG :Danske Guldeny (NLG) +STR_CURR_ITL :Talianske Liry (ITL) +STR_CURR_SEK :Svedske Koruny (SEK) +STR_CURR_RUR :Rusle Ruble (rur) +STR_CURR_CZK :Ceske Koruny (CZK) +STR_CURR_ISK :Islandske Koruny (ISK) +STR_CURR_NOK :Norske Koruny (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Jazyk +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Vyber jazyka rozhrania + +STR_OPTIONS_RES :{BLACK}Rozlisenie obrazovky +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Vyber rozlisenia obrazovky + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Format screenshotov +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Vyber format screenshotov + +STR_AUTOSAVE_1_MONTH :Kazdy mesiac +STR_AUTOSAVE_FAILED :{WHITE}Autoulozenie zlyhalo + +STR_MONTH_JAN :Januar +STR_MONTH_FEB :Februar +STR_MONTH_MAR :Marec +STR_MONTH_APR :April +STR_MONTH_MAY :Maj +STR_MONTH_JUN :Jun +STR_MONTH_JUL :Jul +STR_MONTH_AUG :August +STR_MONTH_SEP :September +STR_MONTH_OCT :Oktober +STR_MONTH_NOV :November +STR_MONTH_DEC :December + +STR_HEADING_FOR_STATION :{LTBLUE}Smeruje do {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}Smeruje do {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Bez urcenia +STR_NO_ORDERS_VEL :{LTBLUE}Bez urcenia, {VELOCITY} + +STR_PASSENGERS :cestujucich +STR_BAGS :vriec +STR_TONS :ton +STR_LITERS :litrov +STR_ITEMS :kusov +STR_CRATES :debien +STR_RES_OTHER :ine +STR_NOTHING : + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Nemoze zdielat zoznam smerov... +STR_CANT_COPY_ORDER_LIST :{WHITE}Nemoze kopirovat zoznam smerov... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Koniec zdielanych smerov - - + +STR_TRAIN_IS_LOST :{WHITE}Vlak {COMMA16} sa stratil. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Zisk vlaku {COMMA16} za posledny rok bol {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Konfigurovat Zaplaty +STR_CONFIG_PATCHES_TIP :{BLACK}Konfigurovat Zaplaty +STR_CONFIG_PATCHES_CAPTION :{WHITE}Konfigurovat Zaplaty + +STR_CONFIG_PATCHES_OFF :Vyp. +STR_CONFIG_PATCHES_ON :Zap. +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Zobraz rychlost vozidla v stavovej liste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Umoznit vystavbu na sikmine a pobrezi: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Umoznit odstranenie viacerych mestskych ciest, mostov, tunelov, etc: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Umoznit stavbu dlhych vlakov: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Zapnut realnu akceleraciu vlakov: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Umoznit spajat stanice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Opustit stanicu ked jeden z nakladov je plny, pri 'plne naloz': {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Vypnut automaticke opravy vlakov: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Vykladat tovar v stanici len ked je dopyt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Umoznit stavbu dlhych mostov: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Umoznit prikaz chod do depa: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Umoznit vystavbu priemyslu produkujuceho suroviny: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Umoznit rozne priemysly v meste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Ten isty priemysel moze byt stavany blizko seba: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Ukazuj dlhy format datumu v stavovej liste: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Zobrazuj signaly na strane cesty: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Ukaz rozpocet na konci roku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch kompaktibilne nonstop ovladanie: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Radenie cestnych vozidiel (podla mnozstva tovaru): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Posuvanie okna ked je mys na kraji: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Umoznit podplacanie miestnej spravy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Nove vyhladavanie depa: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Roznorode stanice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Novy algoritmus pre hladanie smeru: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Umoznit vystavbu v pauze: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Vzdy povolit male letiska: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Vlak sa strati pokial nic nedosiahne za: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Upozornit na stratu vlaku: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Automaticka obnova dopravnych prostriedkov, ked su stare +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Dlzka zobrazenia chybovej spravy: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Uroven ciary snehu: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Maximalne pokrytie stanice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Automaticke opravy vrtulnikov v heliporte: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Maximalny pocet vlakov hraca: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Maximalny pocet automobilov hraca: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Maximalny pocet lietadiel hraca: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Maximalny pocet lodi hraca: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Zakazat vlaky pre pocitac: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Zakazat automobily pre pocitac: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Zakazat lietadla pre pocitac: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Zakazat lode pre pocitac: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Vychodzi servisny interval pre vlaky: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Vychodzi servisny interval pre automobily: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Vychodzi servisny interval pre lietadla: {ORANGE}{STRING} dni +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Vychodzi servisny interval pre lode: {ORANGE}{STRING} dni + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Farebne novinky sa objavia v roku: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Datum zaciatku hry: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Mierne zmeny ekonomiky (viac mensich zmien) + +STR_CONFIG_PATCHES_GUI :{BLACK}Rozhranie +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Vystavba +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Vozidla +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stanice +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Ekonomika + +STR_CONFIG_PATCHES_DISABLED :zakazane +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Zmenit hodnotu nastavenia + + +STR_CHEATS :{WHITE}Cheaty +STR_CHEATS_TIP :{BLACK}Checkbox indikuje opakovane pouzite cheatu +STR_CHEATS_WARNING :{BLACK}Varovanie! Chcete podviest vasich protihracov. Tento podvod sa navzdy zapameta. +STR_CHEAT_MONEY :{LTBLUE}Zvysit hotovost o {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Hrat ako hrac: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magicky buldozer (odstrani priemysel, budovy): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunely sa mozu navzajom krizit: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Meno +STR_TOWNDIR_POPULATION :{BLACK}Populacia +STR_TOWNDIR_SORT_TIP :{BLACK}Vyber smer zoradenia + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}Smeruje do {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}Smeruje do {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Chod cez {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Smerovy bod {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Smerovy bod {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Smerovy bod + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Upravit nazvy smerovych bodov + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Meno smeroveho bodu sa neda zmenit... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Konvertovat zeleznicu na smerove body +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Tu nie je mozne postavit zeleznicny smerovy bod... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Tu nie je mozne odstranit zeleznicny smerovy bod... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Automaticka stavba zeleznicnych kolaji + +STR_TREES_RANDOM_TYPE :{BLACK}Nahodne stromy +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Umiestnit nahodne stromy + +STR_CANT_BUILD_CANALS :{WHITE}Tu sa neda postavit prieplav... +STR_BUILD_CANALS_TIP :{BLACK}Postavit prieplavy +STR_LANDINFO_CANAL :Prieplav + +STR_CANT_BUILD_LOCKS :{WHITE}Tu sa neda postavit stavidlo... +STR_BUILD_LOCKS_TIP :{BLACK}Postavit stavidla... +STR_LANDINFO_LOCK :Stavidlo + +STR_LANDINFO_COORDS :{BLACK}Suradnice: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Nemozno odstranit cast stanice... +STR_CANT_CONVERT_RAIL :{WHITE}Tu nemozno zkonvertovat typ zeleznice... +STR_CONVERT_RAIL_TIP :{BLACK}Konvertovat/vylepsit typ zeleznice + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Prenes lokomotivu sem, pre predaj celeho vlaku + +STR_DRAG_DROP :{BLACK}Automaticky +STR_STATION_DRAG_DROP :{BLACK}Automaticky postavit stanicu podla oznaceneho bloku terenu + +STR_FAST_FORWARD :{BLACK}Rychle posunutie hry do predu +STR_MESSAGE_HISTORY :{WHITE}Historia Sprav + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Postavit uholnu banu +STR_CONSTRUCT_FOREST_TIP :{BLACK}Vysadit les +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Postavit vrtnu plosinu +STR_CONSTRUCT_FARM_TIP :{BLACK}Financovat farmu +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Postavit medennu banu +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Postavit ropny vrt +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Postavit zlatu banu +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Postavit diamantovu banu +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Postavit banu na zeleznu rudu +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Financovat ovocnu plantaz +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Financovat kaucukovu plantaz +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Financovat zasobaren vody +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Vysadit les na cukrovu vatu +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Postavit vyrobu baterii +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Postavit vyrobu kofoly +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Financovat zuvackovu fontanu +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Postavit bublifuk +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Postavit karamelovy lom +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Postavit cukrovu banu + +STR_INDUSTRYDIR_NAME :{BLACK}Meno +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produkcia +STR_INDUSTRYDIR_TYPE :{BLACK}Typ +STR_INDUSTRYDIR_CAPTION :{WHITE}Priemysel +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}...prilis blizko ineho priemyslu + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Prerobit vlak na prepravu ineho nakladu +STR_RAIL_REFIT :{WHITE}{STRING} (Prerobit) +STR_RAIL_REFIT_VEHICLE :{BLACK}Prerobit vlak +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vybrat typ prepravovaneho nakladu +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Prerobit vlak na prepravu vybraneho nakladu +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Nemozno prerobit vlak... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Cena: {CURRENCY} +STR_0801_COST :{RED}Cena: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Zisk: {CURRENCY} +STR_0803_INCOME :{GREEN}Zisk: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Priblizna cena: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Priblizna Cena: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Priblizny Zisk: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Priblizny Zisk: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Tu nemozno zdvihnut teren... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Tu nemozno znizit teren... +STR_080A_ROCKS :Skaly +STR_080B_ROUGH_LAND :Nerovny teren +STR_080C_BARE_LAND :Holy teren +STR_080D_GRASS :Travnaty teren +STR_080E_FIELDS :Polia +STR_080F_SNOW_COVERED_LAND :Zasnezeny teren +STR_0810_DESERT :Pust + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren ma nevhodny sklon +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nemozna kombinacia trate +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Vyhlbenie moze poskodit tunel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Na urovni mora +STR_1004_TOO_HIGH :{WHITE}Prilis vysoko +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Ziadne pouzitelne zeleznicne kolaje +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}V depe je vlak +STR_1007_ALREADY_BUILT :{WHITE}...uz bolo vytvorene +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Najskor treba odstranit zeleznicne kolaje +STR_1009_TOO_MANY_DEPOTS :{WHITE}Prilis velky pocet dep +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Vystavba zeleznice +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Vystavba jednokolajky +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Vystavba magnetickej drahy +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Vyber zeleznicny most +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Tu nemoze byt postavene depo... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Tu nemoze byt postavena zeleznicna stanica... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Tu sa nedaju stavat semafory... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Tu sa nedaju stavat zeleznicne kolaje... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Tu nemozno odstranit zeleznicne kolaje... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Tu nemozno odstranit semafory... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Otocenie depa +STR_1015_RAILROAD_CONSTRUCTION :Vystavba zeleznice +STR_1016_MONORAIL_CONSTRUCTION :Vystavba jednokolajky +STR_1017_MAGLEV_CONSTRUCTION :Vystavba magnetickej drahy +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Postavit zeleznicne kolaje +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Postavit zeleznicne depo (pre vyrobu a opravu vlakov) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Postavit zeleznicnu stanicu +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Postavit zeleznicne semafory +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Postavit zeleznicny most +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Postavit zeleznicny tunel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Zapnut postavit/odstranit zeleznicne kolaje a semafory +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Vyber mostu - kliknut na vybrany most +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO :{BLACK}Vyber otocenie depa +STR_1021_RAILROAD_TRACK :Zeleznicne kolaje +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Zeleznicne kolaje so semaforom +STR_1023_RAILROAD_TRAIN_DEPOT :Zeleznicne depo +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...oblast vlastni ina spolocnost +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Zeleznicne kolaje zo standartnym semaforom +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Zeleznicne kolaje z pre-signami +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Zeleznicne kolaje z exit-signalmi +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Zeleznicne kolaje z combo-signalmi + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren ma nevhodny sklon pre stavbu cesty +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Cesta musi byt najskor odstranena +STR_1802_ROAD_CONSTRUCTION :{WHITE}Vystavba cesty +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Vyber cestny most +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Tu sa neda postavit cesta... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Tu sa neda odstranit cesta... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Orientacia garaze +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}tu sa neda postavit garaz... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Nemozno postavit autobusovu zastavku... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Nemozno postavit vykladku... +STR_180A_ROAD_CONSTRUCTION :Vystavba cesty +STR_180B_BUILD_ROAD_SECTION :{BLACK}Postavit cast cesty +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Postavit garaz (na vyroby a opravy automobilov) +STR_180D_BUILD_BUS_STATION :{BLACK}Postavit autobusovu zastavku +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Postavit vykladku +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Postavit cestny most +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Postavit cestny tunel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Zapnut postavit/odstranit cestu +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Vyber mostu - kliknut na vybrany most +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Vybrat otocenie garaze +STR_1814_ROAD :Cesta +STR_1815_ROAD_WITH_STREETLIGHTS :Cesta s lampami +STR_1816_TREE_LINED_ROAD :Cesta v aleji +STR_1817_ROAD_VEHICLE_DEPOT :Garaz +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Zeleznicny prejazd + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Mesta +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Budova sa musi zburat +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Obyvatelstvo: {ORANGE}{COMMA32}{BLACK} Domov: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Premenovat mesto +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Mesto nemoze byt odstranene... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} miestna sprava to nedovoli +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Nazvy miest - kliknut na meno pre pohlad na stred mesta +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Pohlad na stred mesta +STR_200C_CHANGE_TOWN_NAME :{BLACK}Zmenit nazov mesta +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Cestujuci za posledny mesiac: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Posta za posledny mesiac: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Administrativa +STR_2010_OFFICE_BLOCK :Kancelaria +STR_2011_SMALL_BLOCK_OF_FLATS :Male byty +STR_2012_CHURCH :Kostol +STR_2013_LARGE_OFFICE_BLOCK :Ministerstvo +STR_2014_TOWN_HOUSES :Mestske domy +STR_2015_HOTEL :Hotel +STR_2016_STATUE :Socha +STR_2017_FOUNTAIN :Fontana +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kancelaria +STR_201A_SHOPS_AND_OFFICES :Obchody a kancelarie +STR_201B_MODERN_OFFICE_BUILDING :Moderna administrativna budova +STR_201C_WAREHOUSE :Sklad +STR_201D_OFFICE_BLOCK :Kancelaria +STR_201E_STADIUM :Stadion +STR_201F_OLD_HOUSES :Stare domy +STR_2020_LOCAL_AUTHORITY :{BLACK}Miestna sprava +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Zobrazit informacie o miestnej sprave +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} Miestna sprava +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Hodnotenie dopravnych spolocnosti: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Dotacie +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Ponuknute dotacie:- +STR_2027_FROM_TO :{ORANGE}{STRING} z {STRING} do {STRING} +STR_2028_BY :{YELLOW} ({DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Nie je +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Uz dotovane:- +STR_202C_FROM_TO :{ORANGE}{STRING} z {STATION} do {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, do {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Dotacia skoncila:{}{}Preprava {STRING} z {STRING} do {STRING} uz nebude dotovana. +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Vyska dotacie:{}{}Preprava {STRING} z {STATION} do {STATION} uz nieje dotovana. +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Ponuka dotacie:{}{}Prva preprava {STRING} z {STRING} do {STRING} bude dotovana miestnou spravou! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotacia udelena spolocnosti {STRING}!{}{}Preprava {STRING} z {STATION} do {STATION} bude buduci rok o 50% vynosnejsia! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotacia udelena spolocnosti {STRING}!{}{}Preprava {STRING} z {STATION} to {STATION} bude buduci rok 2x vynosejnsia! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotacia udelena spolocnosti {STRING}!{}{}Preprava {STRING} z {STATION} do {STATION} bude buduci rok 3x vynosnejsia! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Dotacia udelena spolocnosti {STRING}!{}{}Preprava {STRING} z {STATION} do {STATION} bude buduci rok 4x vynosnejsia! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} miestna sprava odmietla stavbu letiska v tomto meste +STR_2036_COTTAGES :Chaty +STR_2037_HOUSES :Domy +STR_2038_FLATS :Byty +STR_2039_TALL_OFFICE_BLOCK :Administrativa +STR_203A_SHOPS_AND_OFFICES :Obchody a kancelarie +STR_203B_SHOPS_AND_OFFICES :Obchody a kancelarie +STR_203C_THEATER :Divadlo +STR_203D_STADIUM :Stadion +STR_203E_OFFICES :Kancelarie +STR_203F_HOUSES :Domy +STR_2040_CINEMA :Kino +STR_2041_SHOPPING_MALL :Obchodny dom +STR_2042_DO_IT :{BLACK}Vykonaj +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Co sa da urobit v tomto meste - kliknut na polozku pre detaily +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Vykonat vybranu cinnost +STR_2045_ACTIONS_AVAILABLE :{BLACK}Dostupne cinnosti: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Mala reklamna kampan +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Stredna reklamna kampan +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Velka reklamna kampan +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Financovat rekonstrukciu ciest +STR_204A_BUILD_STATUE_OF_COMPANY :Postavit sochu majitela spolocnosti +STR_204B_FUND_NEW_BUILDINGS :Financovat vystavbu budov +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Zakupit exkluzivne dopravne prava +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Podplatit miestnu spravu +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Spustit malu reklamnu kampan vasich dopravnych sluzieb.{} Cena: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Spustit strednu reklamnu kampan vasich dopravnych sluzieb.{} Cena: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Spustit velku reklamnu kampan vasich dopravnych sluzieb.{} Cena: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Financovat rekonstrukciu a vystavbu cesty. Sposobi dopravny chaos a zapchy trvajuce dalsich 6 mesiacov.{} Cena: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Postavit sochu na oslavu vasej spolocnosti.{} Cena: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Financovat vystavbu administrativnych a obchodnych budov.{} Cena: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Na 1 rok kupit exkluzivne dopravne prava pre vasu spolocnost. Miestna sprava vam zaruci vyuzivanie dopravnych sluzieb len vasej spolocnosti.{} Cena: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Podplatit miestnu spravu pre zvysenie hodnotenia vasej spolocnosti, s rizikom tazkeho postihu ked sa to prevali!{} Cost: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}To sa neda urobit... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING :{BIGFONT}{BLACK}V meste {TOWN} zavladol dopravny chaos!{}{}Rekonstrukcia ciest financovana {STRING} prinesie 6 mesiacov utrpenia pre motoristov! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (v rekonstrukcii) +STR_2059_IGLOO :Iglu +STR_205A_TEPEES :Vigvam +STR_205B_TEAPOT_HOUSE :Kaviaren +STR_205C_PIGGY_BANK :Mala Banka + +##id 0x2800 +STR_2800_PLANT_TREES :Sadit stromy +STR_2801_PLACE_SIGN :Vlozit popis +STR_2802_TREES :{WHITE}Stromy +STR_2803_TREE_ALREADY_HERE :{WHITE}...strom tu uz je +STR_2804_SITE_UNSUITABLE :{WHITE}...nevhodne miesto +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Tu sa strom neda zasadit... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...prilis vela popisov +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Tu sa neda dat popis... +STR_280A_SIGN :Popis +STR_280B_EDIT_SIGN_TEXT :{WHITE}Upravit text popisu +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Nemozno zmenit text popisu... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Vybrat typ stromu pre sadenie +STR_280E_TREES :Stromy +STR_280F_RAINFOREST :Dazdovy prales +STR_2810_CACTUS_PLANTS :Kaktusy + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Vyber zeleznicnej stanice +STR_3001_AIRPORT_SELECTION :{WHITE}Vyber letiska +STR_3002_ORIENTATION :{BLACK}Otocenie +STR_3003_NUMBER_OF_TRACKS :{BLACK}Pocet kolaji +STR_3004_PLATFORM_LENGTH :{BLACK}Dlzka nastupista +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}Prilis blizko inej zeleznicnej stanice +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Susedi z viacerymi stanicami/vykladkami +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}Prilis vela stanic/vykladok v tomto meste +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}Prilis vela stanic/vykladok +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Prilis blizko inej stanice/vykladky +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Zeleznicna stanica sa musi naskor zburat +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Prilis blizko ineho letiska +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Letisko sa musi najskor zburat + +STR_3030_RENAME_STATION_LOADING :Premenovat stanicu/vykladku +STR_3031_CAN_T_RENAME_STATION :{WHITE}Stanica sa neda premenovat... +STR_3032_RATINGS :{BLACK}Hodnotenie +STR_3033_ACCEPTS :{BLACK}Prijma +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Hodnotenie prepravy: + +############ range for rating starts +STR_3035_APPALLING :Hrozne +STR_3036_VERY_POOR :Velmi zle +STR_3037_POOR :Zle +STR_3038_MEDIOCRE :Priemerne +STR_3039_GOOD :Dobre +STR_303A_VERY_GOOD :Velmi dobre +STR_303B_EXCELLENT :Vyborne +STR_303C_OUTSTANDING :Perfektne +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} uz neprijma {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} uz neprijma {STRING} or {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} teraz prijma {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} teraz prijma {STRING} and {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Otocenie zastavky +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Otocenie vykladky +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}Prilis blizko inej zastavky +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}Prilis blizko inej vykladky +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Zastavka musi byt najskor zburana +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Vykladka musi byt najskor zburana +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stanice +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Nie je - +STR_304B_SITE_UNSUITABLE :{WHITE}...miesto je nepouzitelne +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Priliz blizko ineho pristavu +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Pristav musi byt najskor zburany +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Vybrat otocenie zeleznicnej stanice +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Pocet kolaji zeleznicnej stanice +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Dlzka zeleznicnej stanice +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Vybrat otocenie zastavky +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Vybrat otocenie vykladky +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Vycentrovat pohlad na poziciu stanice +STR_3054_SHOW_STATION_RATINGS :{BLACK}Zobrazit hodnotenie stanice +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Zmenit nazov stanice +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Zobrazit zoznam prijmaneho nakladu +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Nazvy stanic - kliknut pre vycentrovanie pohladu na poziciu stanice +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Vybrat velkost/typ letiska +STR_3059_SMALL :{BLACK}Male +STR_305A_LARGE :{BLACK}Velke +STR_305AA_LARGE :{BLACK}Metropolitan airport +STR_305AB_LARGE :{BLACK}Medzinarodne letisko +STR_305B_SIZE :{BLACK}Velkost +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Zeleznicna stanica +STR_305F_AIRCRAFT_HANGAR :Letecky hangar +STR_3060_AIRPORT :Letisko +STR_3061_TRUCK_LOADING_AREA :Vykladka +STR_3062_BUS_STATION :Zastavka +STR_3063_SHIP_DOCK :Pristav +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Zobrazit oblast pokrytia stavanej plochy +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Nezobrazit oblast pokrytia stavanej plochy +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Ukazat oblast pokrytia +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Vyber jednokolajovej stanice. +STR_3068_DOCK :{WHITE}Molo +STR_3069_BUOY :Boja +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boja v ceste +STR_306B_HELIPORT :{BLACK}Heliport +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...stanica je prilis velka + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Otocenie lodenice +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...musi byt postavene na vode +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Lodenica sa tu neda postavit +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Vyber otocenie pristavu +STR_3804_WATER :Voda +STR_3805_COAST_OR_RIVERBANK :Pobrezie alebo nabrezie +STR_3806_SHIP_DEPOT :Lodenica +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...nemoze byt postavene na vode + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Ulozit Hru +STR_4001_LOAD_GAME :{WHITE}Nahrat Hru +STR_4002_SAVE :{BLACK}Ulozit +STR_4003_DELETE :{BLACK}Vymazat +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} volnych megabajtov +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Zariadenie je necitatelne +STR_4007_GAME_SAVE_FAILED :{WHITE}Ulozenie hry zlyhalo +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Subor sa neda vymazat +STR_4009_GAME_LOAD_FAILED :{WHITE}Nahratie hry zlyhalo +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Zoznam diskov, adresare a subory ulozenych hier +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Vybrane meno pre ulozenie hry +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Vymazat vybranu ulozenu hru +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Ulozit aktualnu hru s pouzitim vybraneho mena +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Vyber novy typ hry +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Vyber scenar (zeleny), prednastavena hra (modra), alebo nahodnu hru +STR_4010_GENERATE_RANDOM_NEW_GAME :Vygenerovat nahodnu novu hru + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} v ceste +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Uholna bana +STR_4803_POWER_STATION :Elektraren +STR_4804_SAWMILL :Pila +STR_4805_FOREST :Les +STR_4806_OIL_REFINERY :Ropna rafineria +STR_4807_OIL_RIG :Ropny vrt +STR_4808_FACTORY :Tovaren +STR_4809_PRINTING_WORKS :Tlaciaren +STR_480A_STEEL_MILL :Oceliaren +STR_480B_FARM :Farma +STR_480C_COPPER_ORE_MINE :Medenna bana +STR_480D_OIL_WELLS :Ropna plosina +STR_480E_BANK :Banka +STR_480F_FOOD_PROCESSING_PLANT :Vyroba jedla +STR_4810_PAPER_MILL :Vyroba papiera +STR_4811_GOLD_MINE :Zlata bana +STR_4812_BANK :Banka +STR_4813_DIAMOND_MINE :Diamantova bana +STR_4814_IRON_ORE_MINE :Bana na zeleznu rudu +STR_4815_FRUIT_PLANTATION :Ovocny sad +STR_4816_RUBBER_PLANTATION :Kaucukova plantaz +STR_4817_WATER_SUPPLY :Zasobaren vody +STR_4818_WATER_TOWER :Vodojem +STR_4819_FACTORY :Tovaren +STR_481A_FARM :Farma +STR_481B_LUMBER_MILL :Pila +STR_481C_COTTON_CANDY_FOREST :Les cukrovej vaty +STR_481D_CANDY_FACTORY :Cukrovar +STR_481E_BATTERY_FARM :Vyroba baterii +STR_481F_COLA_WELLS :Vyroba kofoly +STR_4820_TOY_SHOP :Hrackarstvo +STR_4821_TOY_FACTORY :Vyroba hraciek +STR_4822_PLASTIC_FOUNTAINS :Zuvackova fontana +STR_4823_FIZZY_DRINK_FACTORY :Vyroba sumienky +STR_4824_BUBBLE_GENERATOR :Bublifuk +STR_4825_TOFFEE_QUARRY :Karamelovy lom +STR_4826_SUGAR_MINE :Cukrova bana + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Potrebuje: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Potrebuje: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Potrebuje: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produkcia za posledny mesiac: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% prepravene) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Vycentrovanie pohladu na poziciu tovarne +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}{STRING} sa zacina stavat nedaleko {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}{STRING} sa vysadza nedaleko {TOWN}! +STR_482F_COST :{BLACK}Cena: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Tento typ priemyslu sa tu neda postavit... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...les sa moze sadit len pod ciarou snehu +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} oznamuje skore uzavretie! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Zasobovacie problemy donutili {TOWN} {STRING} oznamit skore uzavretie! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Nedostupnost blizkeho lesa donutil {TOWN} {STRING} oznamit skore uzavretie! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} zvysuje produkciu! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nove nalezisko uhlia sa objavilo pri {TOWN} {STRING}!{}Ocakava sa zdvojnasobenie produkcie! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nove nalezisko ropy sa objavilo pri {TOWN} {STRING}!{}Ocakava sa zdvojnasobenie produkcie! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Na {TOWN} {STRING} objavili nove metody!Ocakava sa zdvojnasobenie produkcie! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}{TOWN} {STRING} znizuje produkciu o 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Premnozenie skodcov sposobilo znicenie urody pri {TOWN} {STRING}!{}Produkcia sa znizila o 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...moze byt umiestnene len pri okraji mapy +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} produkcia v {TOWN} {STRING} sa zvysuje o {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} produkcia v {TOWN} {STRING} sa znizuje o {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Vlak v tuneli +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Automobil v tuneli +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Iny tunel v ceste +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Nemozno zarovnat teren na druhej strane tunela +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Tunel musi byt najskor zburany +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Most musi byt najskor zburany +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Nemozno zacat a skoncit na tom istom mieste +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Pod mostom je potrebna voda alebo udolie +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Zaciatok a koniec musi byt v rovine +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}To miesto je nepouzitelne ako vstup do tunela +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Zavesny ocelovy +STR_500F_GIRDER_STEEL :Pilierovy ocelovy +STR_5010_CANTILEVER_STEEL :Visuty ocelovy +STR_5011_SUSPENSION_CONCRETE :Zavesny betonovy +STR_5012_WOODEN :Drevenny +STR_5013_CONCRETE :Betonovy +STR_5014_TUBULAR_STEEL :Kryty ocelovy +STR_BRIDGE_TUBULAR_SILICON :Kryty plastovy +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Tu sa neda postavit most... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tu sa neda postavit tunel... +STR_5017_RAILROAD_TUNNEL :Zeleznicny tunel +STR_5018_ROAD_TUNNEL :Cestny tunel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Ocelovy zavesny zeleznicny most +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Ocelovy pilierovy zeleznicny most +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Ocelovy visuty zeleznicny most +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Vystuzeny zavesny betonovy zeleznicny most +STR_501F_WOODEN_RAIL_BRIDGE :Drevenny zeleznicny most +STR_5020_CONCRETE_RAIL_BRIDGE :Betonovy zeleznicny most +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Ocelovy zavesny cestny most +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Ocelovy pilierovy cestny most +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Ocelovy visuty cestny most +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Vystuzeny zavesny betonovy cestny most +STR_5025_WOODEN_ROAD_BRIDGE :Drevenny cestny most +STR_5026_CONCRETE_ROAD_BRIDGE :Betonovy cestny most +STR_5027_TUBULAR_RAIL_BRIDGE :Kryty zeleznicny most +STR_5028_TUBULAR_ROAD_BRIDGE :Kryty cestny most +STR_5029_STEEL :Ocel + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Nieco je v ceste +STR_5801_TRANSMITTER :Vysielac +STR_5802_LIGHTHOUSE :Majak +STR_5803_COMPANY_HEADQUARTERS :Sidlo firmy +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...sidlo firmy v ceste +STR_5805_COMPANY_OWNED_LAND :Spolocnostou vlastnene uzemie +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}To uzemie sa neda kupit... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...uz to vlastnis! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Bez mena{SKIP} +STR_SV_TRAIN_NAME :Vlak {COMMA16} +STR_SV_ROADVEH_NAME :Automobil {COMMA16} +STR_SV_SHIP_NAME :Lod {COMMA16} +STR_SV_AIRCRAFT_NAME :Lietadlo {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} Sever +STR_SV_STNAME_SOUTH :{STRING} Juh +STR_SV_STNAME_EAST :{STRING} Vychod +STR_SV_STNAME_WEST :{STRING} Zapad +STR_SV_STNAME_CENTRAL :{STRING} Stred +STR_SV_STNAME_TRANSFER :{STRING} Razcestie +STR_SV_STNAME_HALT :{STRING} Za horou +STR_SV_STNAME_VALLEY :{STRING} Udolie +STR_SV_STNAME_HEIGHTS :{STRING} Na kopci +STR_SV_STNAME_WOODS :{STRING} Lesy +STR_SV_STNAME_LAKESIDE :{STRING} Jazera +STR_SV_STNAME_EXCHANGE :{STRING} Predmestie +STR_SV_STNAME_AIRPORT :{STRING} Letisko +STR_SV_STNAME_OILFIELD :{STRING} Vrtna plosina +STR_SV_STNAME_MINES :{STRING} Bane +STR_SV_STNAME_DOCKS :{STRING} Bristav +STR_SV_STNAME_BUOY_1 :{STRING} Boja 1 +STR_SV_STNAME_BUOY_2 :{STRING} Boja 2 +STR_SV_STNAME_BUOY_3 :{STRING} Boja 3 +STR_SV_STNAME_BUOY_4 :{STRING} Boja 4 +STR_SV_STNAME_BUOY_5 :{STRING} Boja 5 +STR_SV_STNAME_BUOY_6 :{STRING} Boja 6 +STR_SV_STNAME_BUOY_7 :{STRING} Boja 7 +STR_SV_STNAME_BUOY_8 :{STRING} Boja 8 +STR_SV_STNAME_BUOY_9 :{STRING} Boja 9 +STR_SV_STNAME_ANNEXE :{STRING} Zatavka +STR_SV_STNAME_SIDINGS :{STRING} Sihot +STR_SV_STNAME_BRANCH :{STRING} Za rohom +STR_SV_STNAME_UPPER :Horny {STRING} +STR_SV_STNAME_LOWER :Dolny {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Heliport +STR_SV_STNAME_FOREST :{STRING} Les + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Uroven obtiaznosti +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Lahka +STR_6802_MEDIUM :{BLACK}Stredna +STR_6803_HARD :{BLACK}Tazka +STR_6804_CUSTOM :{BLACK}Vlastna +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Pocet konkurentov: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Zaciatok konkurencie: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Pocet miest: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Pocet priemyslu: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maximalna prvotna pozicka: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Pociatocny urok: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Cena prevadzky vozidiel: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR :{LTBLUE}Rychlost konkurencie: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Inteligencia konkurencie: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Poruchy vozidiel: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Nasobok dotacii: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Cena vystavby: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Typ terenu: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Rozsah oceanov/jazier: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Ekonomika: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Otacanie vlakov: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Havarie: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Nizke +STR_6817_NORMAL :Normalne +STR_6818_HIGH :Vysoke +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Velmi Pomale +STR_681C_SLOW :Pomale +STR_681D_MEDIUM :Stredne +STR_681E_FAST :Rychle +STR_681F_VERY_FAST :Velmi rychle +STR_VERY_LOW :Velmi nizke +STR_6820_LOW :Nizke +STR_6821_MEDIUM :Stredne +STR_6822_HIGH :Vysoke +STR_6823_NONE :Ziadne +STR_6824_REDUCED :Znizene +STR_6825_NORMAL :Normalne +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Velmi rovne +STR_682B_FLAT :Rovne +STR_682C_HILLY :Kopcovite +STR_682D_MOUNTAINOUS :Hory +STR_682E_STEADY :Stabilna +STR_682F_FLUCTUATING :Kolisava +STR_6830_IMMEDIATE :Ihned +STR_6831_3_MONTHS_AFTER_PLAYER :3 mesiace po hracovi +STR_6832_6_MONTHS_AFTER_PLAYER :6 mesiace po hracovi +STR_6833_9_MONTHS_AFTER_PLAYER :9 mesiace po hracovi +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Na konci trasy a v stanicach +STR_6835_AT_END_OF_LINE_ONLY :Len na konci trasy +STR_6836_OFF :Vyp. +STR_6837_ON :Zap. +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Zobrazit tabulku najlepsich + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Hrac 1) +STR_7003_PLAYER_2 : (Hrac 2) +STR_7004_NEW_FACE :{BLACK}Nova tvar +STR_7005_COLOR_SCHEME :{BLACK}Farebna schema +STR_7006_COLOR_SCHEME :{GOLD}Farebna schema: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nova farebna schema +STR_7008_COMPANY_NAME :{BLACK}Nazov spolocnosti +STR_7009_PRESIDENT_NAME :{BLACK}Meno prezidenta +STR_700A_COMPANY_NAME :Nazov spolocnosti +STR_700B_PRESIDENT_S_NAME :Meno prezidenta +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Nazov spolocnosti sa neda zmenit... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Meno prezidenta sa neda zmenit... +STR_700E_FINANCES :{WHITE}{STRING} Financie{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Vydaje/Prijmy +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Vystavba +STR_7012_NEW_VEHICLES :{GOLD}Nove vozidla +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Cena prevadzky vlakov +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Cena prevadzky automobilov +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Cena prevadzky lietadiel +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Cena prevadzky lodi +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Udrzba majetku +STR_7018_TRAIN_INCOME :{GOLD}Zisk vlakov +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Zisk automobilov +STR_701A_AIRCRAFT_INCOME :{GOLD}Zisk lietadiel +STR_701B_SHIP_INCOME :{GOLD}Zisk lodi +STR_701C_LOAN_INTEREST :{GOLD}Uroky +STR_701D_OTHER :{GOLD}Ine +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Spolu: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Graf zisku +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graf prevadzkoveho zisku +STR_7026_BANK_BALANCE :{WHITE}Zostatok v banke +STR_7027_LOAN :{WHITE}Pozicka +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Pozicat {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Vratit {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maximalna vyska pozicky je {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemozno pozicat viac penazi... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...pozicka uz bola splatena +STR_702E_REQUIRED :{WHITE}...{CURRENCY} potrebne +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Pozicka sa neda vratit... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Vybrat novu tvar prezidenta +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Zmenit vzhlad spolocnosti +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Zmenit meno prezidenta +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Zmenit nazov spolocnosti +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Kliknut pre vyber novej farby +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Zvysit velkost pozicky +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Vratit cast pozicky +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(Prezident) +STR_7038_INAUGURATED :{GOLD}Zvoleny: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Strojov: +STR_703A_TRAIN :{WHITE}{COMMA16} vlak +STR_703B_TRAINS :{WHITE}{COMMA16} vlakov +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} automobil +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} automobilov +STR_703E_AIRCRAFT :{WHITE}{COMMA16} lietadlo +STR_703F_AIRCRAFT :{WHITE}{COMMA16} lietadiel +STR_7040_SHIP :{WHITE}{COMMA16} lod +STR_7041_SHIPS :{WHITE}{COMMA16} lodi +STR_7042_NONE :{WHITE}Ziadne +STR_7043_FACE_SELECTION :{WHITE}Vyber tvare +STR_7044_MALE :{BLACK}Muz +STR_7045_FEMALE :{BLACK}Zena +STR_7046_NEW_FACE :{BLACK}Nova tvar +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Zrusit vyber novej tvare +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Potvrdit vyber tvare +STR_7049_SELECT_MALE_FACES :{BLACK}Vyber muzskych tvari +STR_704A_SELECT_FEMALE_FACES :{BLACK}Vyber zenskych tvari +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Nahodna nova tvar +STR_704C_KEY :{BLACK}Vyb. +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Vybrat polozky na grafe +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Vyber poloziek na grafe +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Kliknut pre zobrazenie tejto polozky na grafe +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Dopravenych jednotiek nakladu +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Hodnotenie produktivity spolocnosti (maximalna produktivita je 1000) +STR_7052_COMPANY_VALUES :{WHITE}Hodnota spolocnosti +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Hodnotenie spolocnosti +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Dopravna spolocnost ma problemy! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} bude predana alebo vyhlasi bankrot pokial coskoro nezvysi produktivitu! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(Prezident) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Dopravne spolocnosti sa zlucili! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} bola predana {STRING} za {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Hladame zaujemcu na kupu nasej spolocnosti{}{}Chcete kupit nasu spolocnost {STRING} za {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrot! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} bola zavreta veritelmi a cely majetok bol rozpredany! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Zalozena nova dopravna spolocnost! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} zacina stavat nedaleko {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Spolocnost sa neda kupit... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Ceny prepravy +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Pocet dni transportu +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Cena za prepravenie 10 jednotiek (alebo 10,000 litrov) nakladu cez 20 stvorcov terenu +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Prepinac typu nakladu zap./vyp. +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Inzinier +STR_7067_TRAFFIC_MANAGER :Manazer dopravy +STR_7068_TRANSPORT_COORDINATOR :Koordinator dopravy +STR_7069_ROUTE_SUPERVISOR :Cestny inspektor +STR_706A_DIRECTOR :Riaditel +STR_706B_CHIEF_EXECUTIVE :Vykonny riaditel +STR_706C_CHAIRMAN :Predseda +STR_706D_PRESIDENT :Prezident +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Postavit sidlo +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Postavit sidlo spolocnosti / pozriet na sidlo spolocnosti +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS: {WHITE}Sidlo spolocnosti sa neda postavit... +STR_7072_VIEW_HQ :{BLACK}Pozriet sidlo +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Svetova kriza!{}{}Financni experti maju obavy z prepadu ekonomiky! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Koniec krizy!{}{}Ocakava sa vzostup predaja a posilnenie ekonomiky! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Prepinac velkosti okna +STR_7076_COMPANY_VALUE :{GOLD}Hodnota spolocnosti: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Kupit 25% podiel v spolocnosti +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Predat 25% podiel v spolocnosti +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Kupit 25% podiel v tejto spolocnosti +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Predat 25% podiel v tejto spolocnosti +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}25% podiel v tejto spolocnosti sa neda kupit... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}25% podiel v tejto spolocnosti sa neda predat... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% vlastnene {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% vlastnene {STRING}{} {COMMA16}% vlastnene {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} bola kupena spolocnostou {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Parny) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Parny) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Parny) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Parny) +STR_800A_SH_8P_STEAM :SH '8P' (Parny) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektricky) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektricky) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektricky) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektricky) +STR_801B_PASSENGER_CAR :Vagon pre cestujucich +STR_801C_MAIL_VAN :Postovy vagon +STR_801D_COAL_CAR :Vagon na uhlie +STR_801E_OIL_TANKER :Vagon na ropu +STR_801F_LIVESTOCK_VAN :Vagon na dobytok +STR_8020_GOODS_VAN :Vagon na tovar +STR_8021_GRAIN_HOPPER :Vagon na obilie +STR_8022_WOOD_TRUCK :Vagon na drevo +STR_8023_IRON_ORE_HOPPER :Vagon na zeleznu rudu +STR_8024_STEEL_TRUCK :Vagon na ocel +STR_8025_ARMORED_VAN :Obrneny vagon +STR_8026_FOOD_VAN :Vagon na jedlo +STR_8027_PAPER_TRUCK :Vagon na papier +STR_8028_COPPER_ORE_HOPPER :Vagon na medennu rudu +STR_8029_WATER_TANKER :Vagon na vodu +STR_802A_FRUIT_TRUCK :Vagon na ovocie +STR_802B_RUBBER_TRUCK :Vagon na kaucuk +STR_802C_SUGAR_TRUCK :Vagon na cukor +STR_802D_COTTON_CANDY_HOPPER :Vagon na cukrovu vatu +STR_802E_TOFFEE_HOPPER :Vagon na karamel +STR_802F_BUBBLE_VAN :Vagon na bubliny +STR_8030_COLA_TANKER :Vagon na kofolu +STR_8031_CANDY_VAN :Vagon na cukriky +STR_8032_TOY_VAN :Vagon na hracky +STR_8033_BATTERY_TRUCK :Vagon na baterie +STR_8034_FIZZY_DRINK_TRUCK :Vagon na sumienku +STR_8035_PLASTIC_TRUCK :Vagon na zuvacky +STR_8036_X2001_ELECTRIC :'X2001' (Elektricky) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektricky) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Vagon pre cestujucich +STR_803A_MAIL_VAN :Postovy vagon +STR_803B_COAL_CAR :Vagon na uhlie +STR_803C_OIL_TANKER :Vagon na ropu +STR_803D_LIVESTOCK_VAN :Vagon na dobytok +STR_803E_GOODS_VAN :Vagon na tovar +STR_803F_GRAIN_HOPPER :Vagon na obilie +STR_8040_WOOD_TRUCK :Vagon na drevo +STR_8041_IRON_ORE_HOPPER :Vagon na zeleznu rudu +STR_8042_STEEL_TRUCK :Vagon na ocel +STR_8043_ARMORED_VAN :Obrneny vagon +STR_8044_FOOD_VAN :Vagon na jedlo +STR_8045_PAPER_TRUCK :Vagon na papier +STR_8046_COPPER_ORE_HOPPER :Vagon na medennu rudu +STR_8047_WATER_TANKER :Vagon na vodu +STR_8048_FRUIT_TRUCK :Vagon na ovocie +STR_8049_RUBBER_TRUCK :Vagon na kaucuk +STR_804A_SUGAR_TRUCK :Vagon na cukor +STR_804B_COTTON_CANDY_HOPPER :Vagon na cukrovu vatu +STR_804C_TOFFEE_HOPPER :Vagon na karamel +STR_804D_BUBBLE_VAN :Vagon na bubliny +STR_804E_COLA_TANKER :Vagon na kofolu +STR_804F_CANDY_VAN :Vagon na cukriky +STR_8050_TOY_VAN :Vagon na hracky +STR_8051_BATTERY_TRUCK :Vagon na baterie +STR_8052_FIZZY_DRINK_TRUCK :Vagon na sumienku +STR_8053_PLASTIC_TRUCK :Vagon na zuvacky +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektricky) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektricky) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektricky) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektricky) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Vagon pre cestujucich +STR_805A_MAIL_VAN :Postovy vagon +STR_805B_COAL_CAR :Vagon na uhlie +STR_805C_OIL_TANKER :Vagon na ropu +STR_805D_LIVESTOCK_VAN :Vagon na dobytok +STR_805E_GOODS_VAN :Vagon na tovar +STR_805F_GRAIN_HOPPER :Vagon na obilie +STR_8060_WOOD_TRUCK :Vagon na drevo +STR_8061_IRON_ORE_HOPPER :Vagon na zeleznu rudu +STR_8062_STEEL_TRUCK :Vagon na ocel +STR_8063_ARMORED_VAN :Obrneny vagon +STR_8064_FOOD_VAN :Vagon na jedlo +STR_8065_PAPER_TRUCK :Vagon na papier +STR_8066_COPPER_ORE_HOPPER :Vagon na medennu rudu +STR_8067_WATER_TANKER :Vagon na vodu +STR_8068_FRUIT_TRUCK :Vagon na ovocie +STR_8069_RUBBER_TRUCK :Vagon na kaucuk +STR_806A_SUGAR_TRUCK :Vagon na cukor +STR_806B_COTTON_CANDY_HOPPER :Vagon na cukrovu vatu +STR_806C_TOFFEE_HOPPER :Vagon na karamel +STR_806D_BUBBLE_VAN :Vagon na bubliny +STR_806E_COLA_TANKER :Vagon na kofolu +STR_806F_CANDY_VAN :Vagon na cukriky +STR_8070_TOY_VAN :Vagon na hracky +STR_8071_BATTERY_TRUCK :Vagon na baterie +STR_8072_FIZZY_DRINK_TRUCK :Vagon na sumienku +STR_8073_PLASTIC_TRUCK :Vagon na zuvacky +STR_8074_MPS_REGAL_BUS :MPS Regal Autobus +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Autobus +STR_8076_FOSTER_BUS :Foster Autobus +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Autobus +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Autobus +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Autobus +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Autobus +STR_807B_BALOGH_COAL_TRUCK :Balogh - Uhlie +STR_807C_UHL_COAL_TRUCK :Uhl - Uhlie +STR_807D_DW_COAL_TRUCK :DW - Uhlie +STR_807E_MPS_MAIL_TRUCK :MPS - Posta +STR_807F_REYNARD_MAIL_TRUCK :Reynard - Posta +STR_8080_PERRY_MAIL_TRUCK :Perry - Posta +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover - Posta +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught - Posta +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow - Posta +STR_8084_WITCOMBE_OIL_TANKER :Witcombe - Ropa +STR_8085_FOSTER_OIL_TANKER :Foster - Ropa +STR_8086_PERRY_OIL_TANKER :Perry - Ropa +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott - Dobytok +STR_8088_UHL_LIVESTOCK_VAN :Uhl - Dobytok +STR_8089_FOSTER_LIVESTOCK_VAN :Foster - Dobytok +STR_808A_BALOGH_GOODS_TRUCK :Balogh - Tovar +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead - Tovar +STR_808C_GOSS_GOODS_TRUCK :Goss - Tovar +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford - Obilie +STR_808E_THOMAS_GRAIN_TRUCK :Thomas - Obilie +STR_808F_GOSS_GRAIN_TRUCK :Goss - Obilie +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe - Drevo +STR_8091_FOSTER_WOOD_TRUCK :Foster - Drevo +STR_8092_MORELAND_WOOD_TRUCK :Moreland - Drevo +STR_8093_MPS_IRON_ORE_TRUCK :MPS - Zelezna ruda +STR_8094_UHL_IRON_ORE_TRUCK :Uhl - Zelezna ruda +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy - Zelezna ruda +STR_8096_BALOGH_STEEL_TRUCK :Balogh - Ocel +STR_8097_UHL_STEEL_TRUCK :Uhl - Ocel +STR_8098_KELLING_STEEL_TRUCK :Kelling - Ocel +STR_8099_BALOGH_ARMORED_TRUCK :Balogh - Obrnene vozidlo +STR_809A_UHL_ARMORED_TRUCK :Uhl - Obrnene vozidlo +STR_809B_FOSTER_ARMORED_TRUCK :Foster - Obrnene vozidlo +STR_809C_FOSTER_FOOD_VAN :Foster - Jedlo +STR_809D_PERRY_FOOD_VAN :Perry - Jedlo +STR_809E_CHIPPY_FOOD_VAN :Chippy - Jedlo +STR_809F_UHL_PAPER_TRUCK :Uhl - Papier +STR_80A0_BALOGH_PAPER_TRUCK :Balogh - Papier +STR_80A1_MPS_PAPER_TRUCK :MPS - Papier +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS - Medenna ruda +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl - Medenna ruda +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss - Medenna ruda +STR_80A5_UHL_WATER_TANKER :Uhl - Voda +STR_80A6_BALOGH_WATER_TANKER :Balogh - Voda +STR_80A7_MPS_WATER_TANKER :MPS - Voda +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh - Ovocie +STR_80A9_UHL_FRUIT_TRUCK :Uhl - Ovocie +STR_80AA_KELLING_FRUIT_TRUCK :Kelling - Ovocie +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh - Kaucuk +STR_80AC_UHL_RUBBER_TRUCK :Uhl - Kaucuk +STR_80AD_RMT_RUBBER_TRUCK :RMT - Kaucuk +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover - Cukor +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught - Cukor +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow - Cukor +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover - Kofola +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught - Kofola +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow - Kofola +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover - Cukrova vata +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught - Cukrova vata +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow - Cukrova vata +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover - Karamel +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught - Karamel +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow - Karamel +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover - Hracky +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught - Hracky +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow - Hracky +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover - Cukriky +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught - Cukriky +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow - Cukriky +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover - Baterie +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught - Baterie +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow - Baterie +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover - Sumienka +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught - Sumienka +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow - Sumienka +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover - Zuvacky +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught - Zuvacky +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow - Zuvacky +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover - Bubliny +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught - Bubliny +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow - Bubliny +STR_80CC_MPS_OIL_TANKER :MPS - Ropa +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. - Ropa +STR_80CE_MPS_PASSENGER_FERRY :MPS Prievoz +STR_80CF_FFP_PASSENGER_FERRY :FFP Prievoz +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Vznasadlo +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Prievoz +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Prievoz +STR_80D3_YATE_CARGO_SHIP :Yate Nakladna lod +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Nakladna lod +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Nakladna lod +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Nakladna lod +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helicopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helicopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helicopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Sprava od vyrobcu dopravnych prostriedkov +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Prave sme vyrobili {STRING} - mate zaujem o rok exkluzivneho pouzivania? Chceme vyskusat funkcnost pred tym ako to uvedieme na verejny trh. +STR_8102_RAILROAD_LOCOMOTIVE :zeleznicna lokomotiva +STR_8103_ROAD_VEHICLE :automobil +STR_8104_AIRCRAFT :lietadlo +STR_8105_SHIP :lod +STR_8106_MONORAIL_LOCOMOTIVE :jednokolajova lokomotiva +STR_8107_MAGLEV_LOCOMOTIVE :magneticka lokomotiva + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} Depo +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mesto oslavuje . . .{}Prvy vlak dorazil do stanice {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Detaily) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Vlak v ceste +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Chod do {STATION} +STR_8807_GO_TO_UNLOAD :Chod do {STATION} (Vylozit) +STR_8808_GO_TO_LOAD :Chod do {STATION} (Nalozit) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Chod non-stop do {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Chod non-stop do {STATION} (Vylozit) +STR_880C_GO_NON_STOP_TO_LOAD :Chod non-stop do {STATION} (Nalozit) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Chod do {TOWN} depa +STR_SERVICE_AT_TRAIN_DEPOT :Opravit v {TOWN} Vlakovom Depe +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Chod non-stop do {TOWN} depa +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Opravovat non-stop v {TOWN} Vlakovom Depe + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}Smeruje do {TOWN} depa +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}Smeruje do {TOWN} depa, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Prazdny +STR_8813_FROM :{LTBLUE}{CARGO} z {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Vlak {COMMA16} caka v depe +STR_8815_NEW_VEHICLES :{BLACK}Nove vozidla +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Nosnost: {GOLD}{COMMA16}t{}{BLACK}Rychlost: {GOLD}{VELOCITY}{BLACK} Vykon: {GOLD}{COMMA16}hp{}{BLACK}Cena prevadzky: {GOLD}{CURRENCY}/rok{}{BLACK}Kapacita: {GOLD}{STRING}{}{BLACK}Navrnute: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} rokov{}{BLACK}Spolahlivost: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Informacie +STR_8819_TRAIN_TOO_LONG :{WHITE}Vlak je prilis dlhy +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Vlaky sa daju prerobit len v depe +STR_881B_TRAINS :{WHITE}{STRING} - Vlaky +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nove vlaky +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nove jednokolajove vlaky +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nove magneticke vlaky +STR_881F_BUILD_VEHICLE :{BLACK}Vyrobit Vozidlo +STR_8820_RENAME :{BLACK}Premenovat +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Cena: {GOLD}{CURRENCY}{}{BLACK}Nosnost: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapacita: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Preskocit +STR_8824_DELETE :{BLACK}Vynechat +STR_8825_NON_STOP :{BLACK}Non-Stop +STR_8826_GO_TO :{BLACK}Chod do +STR_8827_FULL_LOAD :{BLACK}Plne naloz +STR_8828_UNLOAD :{BLACK}Vylozit +STR_8829_ORDERS :{WHITE}{STRING} (Prikazy) +STR_882A_END_OF_ORDERS :{SETX 10}- - Koniec prikazov - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Oprava +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Nemozno vyrobit vlak... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vyrobene: {LTBLUE}{NUMU16}{BLACK} cena: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Cena: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Naklada/Vyklada +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Vlak sa neda poslat do depa... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Nemozno zadat dalsie prikazy +STR_8832_TOO_MANY_ORDERS :{WHITE}Prilis vela prikazov +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Nemozno vlozit novy prikaz... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Nemozno vymazat tebnto prikaz... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Nemozno zmenit tento prikaz... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Najskor treba postavat depo +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}nemozno posuvat vozdlo... +STR_8838_N_A :Nie je{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Nemozno predat automobil... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Nemoze najst cestu do depa +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Nemozno zastavit/spustit vlak... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Servisny interval: {LTBLUE}{COMMA16}dni{BLACK} Posledny servis: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaky - kliknut na vlak pre informacie +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Vyrobit nove vlaky (potrebne depo) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Vlaky - kliknut na vlak pre informacie, potiahni pre zmenu pozicie +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Vyrobit novy vlak +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Potiahni vlak tu, na predaj +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Vycentrovat pohlad na poziciu depa +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Vyber vlakov - kliknut na vlak pre informacie +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Vyrobit vybrany vlak +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Premenovat vlak +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Aktualna cinnost vlaku - kliknut pre zastavenie/spustenie +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Zobrazit cestovne prikazy vlakov +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Vycentrovat pohlad na poziciu vlaku +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Poslat vlak do depa +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Poslat vlak na cervenu +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Obratit vlak +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Zobrazit detaily o vlaku +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Predlzit servisny interval +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Skratit servisny interval +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Zobrazit detaily o prevezenom naklade +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Zobrazit detaily o vlaku +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Zobrazit kapacitu kazdeho vozidla +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Zobrazit celkovu kapacitu vlaku, rozdelenu podla tovaru +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Zoznam prikazov - kliknut na prikaz pre zobrazenie +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Vynechat aktualny prikaz - preskocit na dalsi +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Vymazat oznaceny prikaz +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Oznaceny prikaz bude prevadzkovany non-stop +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Vlozit novy prikaz pred oznaceny prikaz, alebo na koniec zoznamu +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Na oznacenom prikaze bude vozidlo cakat na plne nalozenie +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Na oznacenom prikaze bude vozidlo uplne vylozene +STR_SERVICE_HINT :{BLACK}Vynechat tento prikaz pokial nieje potrebna oprava +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nove {STRING} je uz dostupne! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Cena: {CURRENCY} Nosnost: {COMMA16}t{}Rychlost: {VELOCITY} Vykon: {COMMA16}hp{}Cena prevadzky: {CURRENCY}/rok{}Kapacita: {STRING} +STR_885C_BROKEN_DOWN :{RED}Pokazene +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena prevadzky: {LTBLUE}{CURRENCY}/rok +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Nosnost: {LTBLUE}{COMMA16}t {BLACK}Vykon: {LTBLUE}{COMMA32}hp{BLACK} Max. Rychlost: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zisk tento rok: {LTBLUE}{CURRENCY} (predchadzajuci rok: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Spolahlivost: {LTBLUE}{COMMA8}% {BLACK}Pokazene od posledneho servisu: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Zastavene +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Nemozno pustit vlak na cervenu ked hrozi nebezpecenstvo... +STR_8863_CRASHED :{RED}Havaroval! + +STR_8865_NAME_TRAIN :{WHITE}Pomenovat vlak +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Vlak nemozno pomenovat... +STR_8867_NAME_TRAIN :{BLACK}Pomenovat vlak +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Vlak havaroval!{}{COMMA16} mrtvych pri poziari po kolizii +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Nemozno zmenit smer vlaku... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Premenovat typ vlaku +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Typ vlaku nemoze byt premenovany... + +STR_TRAIN_STOPPING :{RED}Zastavuje +STR_TRAIN_STOPPING_VEL :{RED}Zastavuje, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Automobil v ceste +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Automobily +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Garaz +STR_9004_NEW_VEHICLES :{BLACK}Nove vozidla +STR_9005_INFORMATION :{BLACK}Informacia +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nove automobily +STR_9007_BUILD_VEHICLE :{BLACK}Vyrobit vozidlo +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Cena prevadzky: {GOLD}{CURRENCY}/rok{}{BLACK}Kapacita: {GOLD}{STRING}{}{BLACK}Navrhnute: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} rokov{}{BLACK}Max. Spolahlivost: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Nemozno vyrobit automobil... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Najskor musi byt postavena garaz +STR_900B_ORDERS :{WHITE}{STRING} (Prikazy) +STR_900C_DETAILS :{WHITE}{STRING} (Detaily) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena prevadzky: {LTBLUE}{CURRENCY}/rok +STR_900E_MAX_SPEED :{BLACK}Max. Rychlost: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zisk tento rok: {LTBLUE}{CURRENCY} (posledny rok: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Spolahlivost: {LTBLUE}{COMMA8}% {BLACK}Pokazene od posledneho servisu: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vyrobene: {LTBLUE}{NUMU16}{BLACK} Cena: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...musi byt zastaveny v garazi +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Nemozno predat automobil... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Nemozno zastavit/spustit automobil... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Automobil {COMMA16} caka v garazi +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}Smeruje do {TOWN} garaze +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}smeruje do {TOWN} garaze, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Nemozno poslat automobil do garaze... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nemozno najst miestnu garaz +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Automobily - kliknut pre detaily +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Vyrobit novy automobil (potrebna garaz) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Aktualna cinnost vozidla - kliknut pre zastavenie/spustenie +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Zobrazit cestovne prikazy +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Vycentrovat pohlad na vozidlo +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Poslat vozidlo do depa +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Otocit vozidlo +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Zobrazit detaily o automobile +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Vozidla - kliknut pre detaily +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Vyrobit novy automobil +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Potiahni sem pre predaj automobilu +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centrovat pohlad na poziciu garaze +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Vyber vozidiel - kliknut pre detaily +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Vyrobit vybrany automobil +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Novy automobil dostupny! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Cena: {CURRENCY}{}Rychlost: {VELOCITY}{}Cena prevadzky: {CURRENCY}/rok{}Kapacita: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Pomenovat automobil +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Nemozno pomenovat automobil... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}pomenovat automobil +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mesto oslavuje . . .{}Prvy autobus dorazil do {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mesto oslavuje . . .{}Prvy automobil dorazil do {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Automobilova havaria!{}Vodic zomrel po kolozii s vlakom +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Automobilova havaria!{}{COMMA16} zomrel po kolozii s vlakom +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Nemozno otocit vozidlo... +STR_9034_RENAME :{BLACK}Premenovat +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Premenovat typ automobilu +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Premenovat typ automobilu +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Nemozno premenovat typ automobilu... +STR_9038_GO_TO_ROADVEH_DEPOT :Chod do {TOWN} garaze +STR_SERVICE_AT_ROADVEH_DEPOT :Opravit v {TOWN} garazi + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Stavba doku +STR_9801_DOCK_CONSTRUCTION :{WHITE}Stavba doku +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Tu nemozno postavit dok... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Lodenica +STR_9804_NEW_SHIPS :{BLACK}Nove lode +STR_9805_SHIPS :{WHITE}{STRING} - Lode +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Nemozno vyrobit lode... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Najskor musi byt postavena lodenica +STR_9808_NEW_SHIPS :{WHITE}Nove lode +STR_9809_BUILD_SHIP :{BLACK}Vyrobit lod +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Kapacita: {GOLD}{STRING} {STRING}{}{BLACK}Cena prevadzky: {GOLD}{CURRENCY}/rok{}{BLACK}Navrhnute: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} rokov{}{BLACK}Max. spolahlivost: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}lob musi byt zastavena v lodenici +STR_980C_CAN_T_SELL_SHIP :{WHITE}Nemozno predat lod... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}nemozno vyrobit lod... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Lod na ceste +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Prikazy) +STR_9811_DETAILS :{WHITE}{STRING} (Detaily) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena prevadzky: {LTBLUE}{CURRENCY}/rok +STR_9813_MAX_SPEED :{BLACK}Max. rychlost: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zisk tento rok: {LTBLUE}{CURRENCY} (posledny rok: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Spolahlivost: {LTBLUE}{COMMA8}% {BLACK}Pokazene od posledneho servisu: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vyrobene: {LTBLUE}{NUMU16}{BLACK} Hodnota: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Nemozno zastavit/spustit lod... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Nemozno poslat lod do lodenice... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Nemozno najst miestnu lodenicu +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}Smeruje do {TOWN} lodenice +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}Smeruje do {TOWN} lodenice, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Lod {COMMA16} caka v lodenici +STR_981D_BUILD_SHIP_DOCK :{BLACK}Postavit lodenicu +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Postavit lodenicu (pre vyrobu a opravy lodi) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Lode - kliknut pre informacie +STR_9820_BUILD_NEW_SHIP :{BLACK}Postavit novu lod +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Potiahnut lod sem, na predaj +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Vycentrovat pohlad na lodenicu +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Lode - kliknut pre informacie +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Vyrabat nove lode (poterna lodenica) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Vyber lodi - kliknut pre informacie +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Vyrobit vybranu lod +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Atualna cinnost lode - klini pre zastavenie/spustenie +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}ZObrazit cestovne prikazy lodi +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Vycentrovat pohlad na lod +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Poslat lod do lodenice +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Zobrazit detaily o lodi +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nova lod je dostupna! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. rychlost: {VELOCITY}{}Kapacita: {STRING}{}Cena prevadzky: {CURRENCY}/rok +STR_982F_NAME_SHIP :{BLACK}Pomenovat lod + +STR_9831_NAME_SHIP :{WHITE}Pomenovat lod +STR_9832_CAN_T_NAME_SHIP :{WHITE}Nemozno pomenovat lod... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}mesto oslavuje . . .{}Prva lod dorazila do {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Postavit boju, moze byt pouzita pre vytycenie smeru +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Tu nemozno postavit boju... +STR_9836_RENAME :{BLACK}Premenovat +STR_9837_RENAME_SHIP_TYPE :{BLACK}Premenovat typ lode +STR_9838_RENAME_SHIP_TYPE :{WHITE}Premenovat typ lode +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Nemozno premenovat typ lode... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Prerobit lod na iny typ nakladu +STR_983B_REFIT :{WHITE}{STRING} (Prerobit) +STR_983C_REFIT_SHIP :{BLACK}Prerobit lod +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vybrat typ nakladu pre lod +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Prerobit lod na vybrany typ nakladu +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Vyber typ nakladu:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Nova kapacita: {GOLD}{STRING}{}{BLACK}Cena prerabky: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Nemozno prerobit lod... +STR_9842_REFITTABLE :(prerobitelna) +STR_GO_TO_SHIP_DEPOT :Chod do {TOWN} Lodenice +SERVICE_AT_SHIP_DEPOT :Opravit v {TOWN} Lodenici + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Vystavba letiska. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Tu sa letisko neda postavit... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Hangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nove Lietadlo +STR_A004_INFORMATION :{BLACK}Informacie +STR_A005_NEW_AIRCRAFT :{WHITE}Nove Lietadlo +STR_A006_BUILD_AIRCRAFT :{BLACK}Vyrobit lietadlo +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Cena: {GOLD}{CURRENCY}{BLACK} Rychlost: {GOLD}{VELOCITY}{}{BLACK}Kapacita: {GOLD}{COMMA16} cestujucich, {COMMA16} balikov posty{}{BLACK}Cena prevadzky: {GOLD}{CURRENCY}/rok{}{BLACK}Navrhnute: {GOLD}{NUMU16}{BLACK} Zivotnost: {GOLD}{COMMA16} rokov{}{BLACK}Spolahlivost: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Nemozno vyrobit lietadlo... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Lietadlo +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Prikazy) +STR_A00C_DETAILS :{WHITE}{STRING} (Detaily) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Vek: {LTBLUE}{STRING}{BLACK} Cena prevadzky: {LTBLUE}{CURRENCY}/rok +STR_A00E_MAX_SPEED :{BLACK}Max. Rychlost: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Zisk tento rok: {LTBLUE}{CURRENCY} (posledny rok: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Spolahlivost: {LTBLUE}{COMMA8}% {BLACK}Pokazene od posledneho servisu: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Vyrobene: {LTBLUE}{NUMU16}{BLACK} Hodnota: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Nemozno poslat lietadlo do hangaru... +STR_HEADING_FOR_HANGAR :{LTBLUE}Smeruje do {STATION} hangaru +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}Smeruje do {STATION} hangaru, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Lietadlo {COMMA16} caka v hangare +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Lietadlo na ceste +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Nemozno zastavit/spustit lietadlo +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Lietadlo leti +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Najskor treba postavit letisko +STR_A019_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapacita: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Letadlo sa musi zastavit v hangari +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Nemozno predat lietadlo... +STR_A01D_AIRPORT_CONSTRUCTION :Vystavba letiska +STR_A01E_BUILD_AIRPORT :{BLACK}Postavit letisko +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Lietadlo - kliknut pre informacie +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Vyrobit nove lietadlo (potrebne letisko z hangarom) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Lietadlo - kliknut pre informacie +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Vyrobit nove lietadlo +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Potiahni lietadlo sem pre predaj +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Vycentrovat pohlad na hangar +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Vyber lietadiel - kliknut pre vyber +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Vyrobit vybrane lietadlo +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Aktualna cinnost lietadla - klini pre zastavenie/spustenie +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Zobrazit cestovne prikazy lietadla +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Vycentrovat pohlad na lietadlo +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Poslat lietadlo do hangaru +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Zobrazit detaily o lietadle +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nove lietadlo dostupne! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Cena: {CURRENCY} Max. rychlost: {VELOCITY}{}Kapacita: {COMMA16} cestujucich, {COMMA16} balikov posty{}Cena prevadzky: {CURRENCY}/rok + +STR_A030_NAME_AIRCRAFT :{WHITE}Pomenovat lietadlo +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Nemozno pomenovat lietadlo... +STR_A032_NAME_AIRCRAFT :{BLACK}Pomenovat lietadlo +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Mesto oslavuje . . .{}Prve lietadlo pristalo na {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Letecka havaria!{}{COMMA16} mrtvych pri poziari na {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Ciele: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Premenovat +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Premenovat typ lietadla +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Premenovat typ lietadla +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Nemozno premenovat typ lietadla... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Prerobit lietadlo na iny typ nakladu +STR_A03C_REFIT :{WHITE}{STRING} (Prerobit) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Prerobit lietadlo +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Vyber novy typ nakladu +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Prerobit lietadlo na novy typ nakladu +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Vybrat typ noveho nakladu:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}nova kapacita: {GOLD}{STRING}{}{BLACK}cena prerobenia: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Nemozno prerobit na novy typ nakladu... +STR_A043_REFITTABLE :(prerobitelne) +STR_GO_TO_AIRPORT_HANGAR :Chod do {STATION} Hangaru +SERVICE_AT_AIRPORT_HANGAR :Opravit v {STATION} Hangare + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin katastrova v {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Automobil bol zniceny pri kolizii s 'UFO' +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Ropna rafineria explodovala nedaleko {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Za nejasnych okolnost bola znicena tovaren nedaleko {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' pristalo nedaleko {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Zaval v uholnej bani nedaleko {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Vas pokus o uplatok bol odhaleny +STR_BRIBE_FAILED_2 :{WHITE}miestnym vysetrovatelom. \ No newline at end of file diff --git a/lang/swedish.txt b/lang/swedish.txt new file mode 100644 --- /dev/null +++ b/lang/swedish.txt @@ -0,0 +1,2357 @@ +##name Swedish +##ownname Svenska + +##id 0x0000 +STR_NULL : +STR_0001_OFF_EDGE_OF_MAP :{WHITE}Utanför kanten +STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}För nära kanten +STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Inte tillräckligt med pengar - kräver {CURRENCY} +STR_0004 :{WHITE}{CURRENCY64} +STR_0005 :{RED}{CURRENCY64} +STR_EMPTY : +STR_0007_FLAT_LAND_REQUIRED :{WHITE}Platt mark krävs +STR_0008_WAITING :{BLACK}Väntar: {WHITE}{STRING} +STR_0009 :{WHITE}{STRING} +STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (på väg från +STR_000B :{YELLOW}{STATION}) +STR_000C_ACCEPTS :{BLACK}Accepterar: {WHITE} +STR_000D_ACCEPTS :{BLACK}Accepterar: {GOLD} +STR_000E : +STR_000F_PASSENGERS :Passagerare +STR_0010_COAL :Kol +STR_0011_MAIL :Post +STR_0012_OIL :Olja +STR_0013_LIVESTOCK :Boskap +STR_0014_GOODS :Gods +STR_0015_GRAIN :Spannmål +STR_0016_WOOD :Timmer +STR_0017_IRON_ORE :Järnmalm +STR_0018_STEEL :Stål +STR_0019_VALUABLES :Värdesaker +STR_001A_COPPER_ORE :Kopparmalm +STR_001B_MAIZE :Majs +STR_001C_FRUIT :Frukt +STR_001D_DIAMONDS :Diamanter +STR_001E_FOOD :Mat +STR_001F_PAPER :Papper +STR_0020_GOLD :Guld +STR_0021_WATER :Vatten +STR_0022_WHEAT :Vete +STR_0023_RUBBER :Gummi +STR_0024_SUGAR :Socker +STR_0025_TOYS :Leksaker +STR_0026_CANDY :Godis +STR_0027_COLA :Kola +STR_0028_COTTON_CANDY :Spunnet socker +STR_0029_BUBBLES :Bubblor +STR_002A_TOFFEE :Knäck +STR_002B_BATTERIES :Batterier +STR_002C_PLASTIC :Plast +STR_002D_FIZZY_DRINKS :Läsk +STR_002E : +STR_002F_PASSENGER :Passagerare +STR_0030_COAL :Kol +STR_0031_MAIL :Post +STR_0032_OIL :Olja +STR_0033_LIVESTOCK :Boskap +STR_0034_GOODS :Gods +STR_0035_GRAIN :Spannmål +STR_0036_WOOD :Timmer +STR_0037_IRON_ORE :Järnmalm +STR_0038_STEEL :Stål +STR_0039_VALUABLES :Värdesaker +STR_003A_COPPER_ORE :Kopparmalm +STR_003B_MAIZE :Majs +STR_003C_FRUIT :Frukt +STR_003D_DIAMOND :Diamanter +STR_003E_FOOD :Mat +STR_003F_PAPER :Papper +STR_0040_GOLD :Guld +STR_0041_WATER :Vatten +STR_0042_WHEAT :Vete +STR_0043_RUBBER :Gummi +STR_0044_SUGAR :Socker +STR_0045_TOY :Leksaker +STR_0046_CANDY :Godis +STR_0047_COLA :Kola +STR_0048_COTTON_CANDY :Spunnet socker +STR_0049_BUBBLE :Bubblor +STR_004A_TOFFEE :Knäck +STR_004B_BATTERY :Batterier +STR_004C_PLASTIC :Plast +STR_004D_FIZZY_DRINK :läsk +STR_004E : +STR_004F_PASSENGER :{COMMA16} passagerare +STR_0050_TON_OF_COAL :{COMMA16} ton kol +STR_0051_BAG_OF_MAIL :{COMMA16} postsäck +STR_0052_OF_OIL :{VOLUME} olja +STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} boskap +STR_0054_CRATE_OF_GOODS :{COMMA16} låda gods +STR_0055_TON_OF_GRAIN :{COMMA16} ton spannmål +STR_0056_TON_OF_WOOD :{COMMA16} ton timmer +STR_0057_TON_OF_IRON_ORE :{COMMA16} ton järnmalm +STR_0058_TON_OF_STEEL :{COMMA16} ton stål +STR_0059_BAG_OF_VALUABLES :{COMMA16} värdesäck +STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton kopparmalm +STR_005B_TON_OF_MAIZE :{COMMA16} ton majs +STR_005C_TON_OF_FRUIT :{COMMA16} ton frukt +STR_005D_BAG_OF_DIAMONDS :{COMMA16} diamantsäck +STR_005E_TON_OF_FOOD :{COMMA16} ton mat +STR_005F_TON_OF_PAPER :{COMMA16} ton papper +STR_0060_BAG_OF_GOLD :{COMMA16} guldsäck +STR_0061_OF_WATER :{VOLUME} vatten +STR_0062_TON_OF_WHEAT :{COMMA16} ton vete +STR_0063_OF_RUBBER :{VOLUME} gummi +STR_0064_TON_OF_SUGAR :{COMMA16} ton socker +STR_0065_TOY :{COMMA16} leksak +STR_0066_BAG_OF_CANDY :{COMMA16} godispåse +STR_0067_OF_COLA :{VOLUME} kola +STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton spunnet socker +STR_0069_BUBBLE :{COMMA16} bubbla +STR_006A_TON_OF_TOFFEE :{COMMA16} ton knäck +STR_006B_BATTERY :{COMMA16} batteri +STR_006C_OF_PLASTIC :{VOLUME} plast +STR_006D_FIZZY_DRINK :{COMMA16} läsk +STR_006E : +STR_006F_PASSENGERS :{COMMA16} passagerare +STR_0070_TONS_OF_COAL :{COMMA16} ton kol +STR_0071_BAGS_OF_MAIL :{COMMA16} postsäckar +STR_0072_OF_OIL :{VOLUME} olja +STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} stycken boskap +STR_0074_CRATES_OF_GOODS :{COMMA16} lådor gods +STR_0075_TONS_OF_GRAIN :{COMMA16} ton spannmål +STR_0076_TONS_OF_WOOD :{COMMA16} ton timmer +STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton järnmalm +STR_0078_TONS_OF_STEEL :{COMMA16} ton stål +STR_0079_BAGS_OF_VALUABLES :{COMMA16} värdesäckar +STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton kopparmalm +STR_007B_TONS_OF_MAIZE :{COMMA16} ton majs +STR_007C_TONS_OF_FRUIT :{COMMA16} ton frukt +STR_007D_BAGS_OF_DIAMONDS :{COMMA16} diamantsäckar +STR_007E_TONS_OF_FOOD :{COMMA16} ton mat +STR_007F_TONS_OF_PAPER :{COMMA16} ton papper +STR_0080_BAGS_OF_GOLD :{COMMA16} guldsäckar +STR_0081_OF_WATER :{VOLUME} vatten +STR_0082_TONS_OF_WHEAT :{COMMA16} ton vete +STR_0083_OF_RUBBER :{VOLUME} gummi +STR_0084_TONS_OF_SUGAR :{COMMA16} ton socker +STR_0085_TOYS :{COMMA16} leksaker +STR_0086_BAGS_OF_CANDY :{COMMA16} godispåsar +STR_0087_OF_COLA :{VOLUME} kola +STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton spunnet socker +STR_0089_BUBBLES :{COMMA16} bubblor +STR_008A_TONS_OF_TOFFEE :{COMMA16} ton knäck +STR_008B_BATTERIES :{COMMA16} batterier +STR_008C_OF_PLASTIC :{VOLUME} plast +STR_008D_FIZZY_DRINKS :{COMMA16} läsk +STR_008E : +STR_008F_PS :{TINYFONT}PS +STR_0090_CL :{TINYFONT}KL +STR_0091_ML :{TINYFONT}PO +STR_0092_OL :{TINYFONT}OL +STR_0093_LV :{TINYFONT}BO +STR_0094_GD :{TINYFONT}GD +STR_0095_GR :{TINYFONT}SP +STR_0096_WD :{TINYFONT}TI +STR_0097_OR :{TINYFONT}JÄ +STR_0098_ST :{TINYFONT}ST +STR_0099_VL :{TINYFONT}VÄ +STR_009A_CO :{TINYFONT}KO +STR_009B_MZ :{TINYFONT}MA +STR_009C_FT :{TINYFONT}FR +STR_009D_DM :{TINYFONT}DI +STR_009E_FD :{TINYFONT}MT +STR_009F_PR :{TINYFONT}PA +STR_00A0_GD :{TINYFONT}GL +STR_00A1_WR :{TINYFONT}VA +STR_00A2_WH :{TINYFONT}VE +STR_00A3_RB :{TINYFONT}GU +STR_00A4_SG :{TINYFONT}SO +STR_00A5_TY :{TINYFONT}LE +STR_00A6_SW :{TINYFONT}GO +STR_00A7_CL :{TINYFONT}KA +STR_00A8_CF :{TINYFONT}SS +STR_00A9_BU :{TINYFONT}BU +STR_00AA_TF :{TINYFONT}KN +STR_00AB_BA :{TINYFONT}BA +STR_00AC_PL :{TINYFONT}PL +STR_00AD_FZ :{TINYFONT}LÄ +STR_00AE :{WHITE}{DATE_SHORT} +STR_00AF :{WHITE}{DATE_LONG} +STR_00B0_MAP :{WHITE}Karta - {STRING} +STR_00B1_GAME_OPTIONS :{WHITE}Spelinställningar +STR_00B2_MESSAGE :{YELLOW}Meddelande +STR_00B3_MESSAGE_FROM :{YELLOW}Meddelande från {STRING} +STR_00B4_CAN_T_DO_THIS :{WHITE}Kan inte utföra detta... +STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Kan inte röja området... +STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER :{BLACK}Ursprunglig äganderätt {COPYRIGHT} 1995 Chris Sawyer, Alla rättigheter reserverade +STR_00B7_VERSION_3_02_011_11TH_OCTOBER :{BLACK}OpenTTD version {REV} +STR_00B8_DESIGNED_PROGRAMMED_BY :{BLACK}Ursprungligen designat av Chris Sawyer +STR_00B9_GRAPHICS_BY_SIMON_FOSTER :{BLACK}Grafik av Simon Foster +STR_00BA_WINDOWS_95_CONVERSION_BY :{BLACK}OpenTTD {COPYRIGHT}2002-2004 OpenTTD-teamet + +STR_00C5 :{BLACK}{CROSS} +STR_00C6 :{SILVER}{CROSS} +STR_00C7_QUIT :{WHITE}Avsluta +STR_00C8_YES :{BLACK}Ja +STR_00C9_NO :{BLACK}Nej +STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vill du verkligen avsluta spelet och återvända till {STRING}? +STR_00CB_1 :{BLACK}1 +STR_00CC_2 :{BLACK}2 +STR_00CD_3 :{BLACK}3 +STR_00CE_4 :{BLACK}4 +STR_00CF_5 :{BLACK}5 +STR_00D0_NOTHING :Inget +STR_00D1_DARK_BLUE :Mörkgrön +STR_00D2_PALE_GREEN :Mattgrön +STR_00D3_PINK :Rosa +STR_00D4_YELLOW :Gul +STR_00D5_RED :Röd +STR_00D6_LIGHT_BLUE :Ljusblå +STR_00D7_GREEN :Grön +STR_00D8_DARK_GREEN :Mörkgrön +STR_00D9_BLUE :Blå +STR_00DA_CREAM :Gräddvit +STR_00DB_MAUVE :Lila +STR_00DC_PURPLE :Purpur +STR_00DD_ORANGE :Orange +STR_00DE_BROWN :Brun +STR_00DF_GREY :Grå +STR_00E0_WHITE :Vit +STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}För många fordon i spelet +STR_00E2 :{BLACK}{COMMA16} +STR_00E3 :{RED}{COMMA16} +STR_00E4_LOCATION :{BLACK}Plats +STR_00E5_CONTOURS :Konturer +STR_00E6_VEHICLES :Fordon +STR_00E7_INDUSTRIES :Industrier +STR_00E8_ROUTES :Rutter +STR_00E9_VEGETATION :Vegetation +STR_00EA_OWNERS :Ägare +STR_00EB_ROADS :{BLACK}{TINYFONT}Vägar +STR_00EC_RAILROADS :{BLACK}{TINYFONT}Järnvägar +STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Stationer/Flygplatser/Hamnar +STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Byggnader/Industrier +STR_00EF_VEHICLES :{BLACK}{TINYFONT}Fordon +STR_00F0_100M :{BLACK}{TINYFONT}100m +STR_00F1_200M :{BLACK}{TINYFONT}200m +STR_00F2_300M :{BLACK}{TINYFONT}300m +STR_00F3_400M :{BLACK}{TINYFONT}400m +STR_00F4_500M :{BLACK}{TINYFONT}500m +STR_00F5_TRAINS :{BLACK}{TINYFONT}Tåg +STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Vägfordon +STR_00F7_SHIPS :{BLACK}{TINYFONT}Skepp +STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Flygplan +STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Transportrutter +STR_00FA_COAL_MINE :{BLACK}{TINYFONT}Kolgruva +STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Kraftstation +STR_00FC_FOREST :{BLACK}{TINYFONT}Skog +STR_00FD_SAWMILL :{BLACK}{TINYFONT}Sågverk +STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Oljeraffinaderi +STR_00FF_FARM :{BLACK}{TINYFONT}Bondgård +STR_0100_FACTORY :{BLACK}{TINYFONT}Fabrik +STR_0101_PRINTING_WORKS :{BLACK}{TINYFONT}Tryckeri +STR_0102_OIL_WELLS :{BLACK}{TINYFONT}Oljekälla +STR_0103_IRON_ORE_MINE :{BLACK}{TINYFONT}Järnmalmsgruva +STR_0104_STEEL_MILL :{BLACK}{TINYFONT}Stålverk +STR_0105_BANK :{BLACK}{TINYFONT}Bank +STR_0106_PAPER_MILL :{BLACK}{TINYFONT}Pappersbruk +STR_0107_GOLD_MINE :{BLACK}{TINYFONT}Guldgruva +STR_0108_FOOD_PROCESSING_PLANT :{BLACK}{TINYFONT}Livsmedelsfabrik +STR_0109_DIAMOND_MINE :{BLACK}{TINYFONT}Diamantgruva +STR_010A_COPPER_ORE_MINE :{BLACK}{TINYFONT}Koppargruva +STR_010B_FRUIT_PLANTATION :{BLACK}{TINYFONT}Fruktplantage +STR_010C_RUBBER_PLANTATION :{BLACK}{TINYFONT}Gummiplantage +STR_010D_WATER_SUPPLY :{BLACK}{TINYFONT}Vattentillgång +STR_010E_WATER_TOWER :{BLACK}{TINYFONT}Vattentorn +STR_010F_LUMBER_MILL :{BLACK}{TINYFONT}Sågverk +STR_0110_COTTON_CANDY_FOREST :{BLACK}{TINYFONT}Spunnet socker-skog +STR_0111_CANDY_FACTORY :{BLACK}{TINYFONT}Godisfabrik +STR_0112_BATTERY_FARM :{BLACK}{TINYFONT}Batteribondgård +STR_0113_COLA_WELLS :{BLACK}{TINYFONT}Kolakälla +STR_0114_TOY_SHOP :{BLACK}{TINYFONT}Leksaksaffär +STR_0115_TOY_FACTORY :{BLACK}{TINYFONT}Leksaksfabrik +STR_0116_PLASTIC_FOUNTAINS :{BLACK}{TINYFONT}Plastfontäner +STR_0117_FIZZY_DRINK_FACTORY :{BLACK}{TINYFONT}Läskfabrik +STR_0118_BUBBLE_GENERATOR :{BLACK}{TINYFONT}Bubbelgenerator +STR_0119_TOFFEE_QUARRY :{BLACK}{TINYFONT}Knäckbrott +STR_011A_SUGAR_MINE :{BLACK}{TINYFONT}Sockergruva +STR_011B_RAILROAD_STATION :{BLACK}{TINYFONT}Järnvägsstation +STR_011C_TRUCK_LOADING_BAY :{BLACK}{TINYFONT}Lastbilsbrygga +STR_011D_BUS_STATION :{BLACK}{TINYFONT}Busshållplats +STR_011E_AIRPORT_HELIPORT :{BLACK}{TINYFONT}Flygplats/Helikopterplats +STR_011F_DOCK :{BLACK}{TINYFONT}Hamn +STR_0120_ROUGH_LAND :{BLACK}{TINYFONT}Obearbetad mark +STR_0121_GRASS_LAND :{BLACK}{TINYFONT}Gräsmark +STR_0122_BARE_LAND :{BLACK}{TINYFONT}Barmark +STR_0123_FIELDS :{BLACK}{TINYFONT}Fält +STR_0124_TREES :{BLACK}{TINYFONT}Träd +STR_0125_ROCKS :{BLACK}{TINYFONT}Stenar +STR_0126_WATER :{BLACK}{TINYFONT}Vatten +STR_0127_NO_OWNER :{BLACK}{TINYFONT}Ingen ägare +STR_0128_TOWNS :{BLACK}{TINYFONT}Städer +STR_0129_INDUSTRIES :{BLACK}{TINYFONT}Industrier +STR_012A_DESERT :{BLACK}{TINYFONT}Öken +STR_012B_SNOW :{BLACK}{TINYFONT}Snö +STR_012C_MESSAGE :{WHITE}Meddelande +STR_012D :{WHITE}{STRING} +STR_012E_CANCEL :{BLACK}Avbryt +STR_012F_OK :{BLACK}OK +STR_0130_RENAME :{BLACK}Byt namn +STR_0131_TOO_MANY_NAMES_DEFINED :{WHITE}För många namn definerade +STR_0132_CHOSEN_NAME_IN_USE_ALREADY :{WHITE}Namnet används redan + +STR_0133_WINDOWS :Windows +STR_0134_UNIX :Unix +STR_0135_OSX :OSX +STR_OSNAME_BEOS :BeOS +STR_OSNAME_MORPHOS :MorphOS + +STR_0139_IMPERIAL_MILES :Engelsk mil (miles) +STR_013A_METRIC_KILOMETERS :Metrisk (kilometer) +STR_013B_OWNED_BY :{WHITE}...ägs av {STRING} +STR_013C_CARGO :{BLACK}Gods +STR_013D_INFORMATION :{BLACK}Information +STR_013E_CAPACITIES :{BLACK}Kapaciteter +STR_013E_TOTAL_CARGO :{BLACK}Gods Totalt +STR_013F_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_013F_TOTAL_CAPACITY_TEXT:{BLACK}Tågets totala kapacitet: +STR_013F_TOTAL_CAPACITY :{LTBLUE}{CARGO} ({SHORTCARGO}) +STR_0140_NEW_GAME :{BLACK}Nytt spel +STR_0141_LOAD_GAME :{BLACK}Ladda spel +STR_0142_TUTORIAL_DEMONSTRATION :{BLACK}Tutorial / Demonstration +STR_0143_1_PLAYER :{BLACK}1 spelare +STR_0144_2_PLAYERS :{BLACK}2 spelare + +STR_0148_GAME_OPTIONS :{BLACK}Spelinställningar + +STR_0150_SOMEONE :någon{SKIP}{SKIP} +STR_0151_MAP_OF_WORLD :Världskarta +STR_0152_TOWN_DIRECTORY :Lista av städer +STR_0153_SUBSIDIES :Subventioner + +############ range for menu starts +STR_0154_OPERATING_PROFIT_GRAPH :Graf över gångbar inkomst +STR_0155_INCOME_GRAPH :Graf över inkomster +STR_0156_DELIVERED_CARGO_GRAPH :Graf över levererat gods +STR_0157_PERFORMANCE_HISTORY_GRAPH :Graf över prestationshistorik +STR_0158_COMPANY_VALUE_GRAPH :Graf över företagets värde +STR_0159_CARGO_PAYMENT_RATES :Fraktförtjänster +STR_015A_COMPANY_LEAGUE_TABLE :Tabell över ledande företag +############ range for menu ends + +STR_015B_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD +STR_015C_SAVE_GAME :Spara spelet +STR_015D_LOAD_GAME :Ladda ett spel +STR_015E_QUIT_GAME :Avsluta spelet +STR_015F_QUIT :Avsluta +STR_0160_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vill du verkligen avsluta spelet? +STR_0161_QUIT_GAME :{WHITE}Avsluta spelet + +############ range for months starts +STR_0162_JAN :jan +STR_0163_FEB :feb +STR_0164_MAR :mar +STR_0165_APR :apr +STR_0166_MAY :maj +STR_0167_JUN :jun +STR_0168_JUL :jul +STR_0169_AUG :aug +STR_016A_SEP :sep +STR_016B_OCT :okt +STR_016C_NOV :nov +STR_016D_DEC :dec +############ range for months ends + +STR_016E :{TINYFONT}{STRING}{} {STRING} +STR_016F :{TINYFONT}{STRING}{} {STRING}{}{NUMU16} +STR_0170 :{TINYFONT}{STRING}- +STR_0171_PAUSE_GAME :{BLACK}Pausa spelet +STR_0172_SAVE_GAME_ABANDON_GAME :{BLACK}Spara spelet, avbryt spelet, avsluta spelet +STR_0173_DISPLAY_LIST_OF_COMPANY :{BLACK}Visa lista över företagets stationer +STR_0174_DISPLAY_MAP :{BLACK}Visa karta +STR_0175_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Visa karta, lista av städer +STR_0176_DISPLAY_TOWN_DIRECTORY :{BLACK}Visa lista av städer +STR_0177_DISPLAY_COMPANY_FINANCES :{BLACK}Visa finansinformation för företaget +STR_0178_DISPLAY_COMPANY_GENERAL :{BLACK}Visa allmän företagsinformation +STR_0179_DISPLAY_GRAPHS :{BLACK}Visa grafer +STR_017A_DISPLAY_COMPANY_LEAGUE :{BLACK}Visa ledande företag +STR_017B_DISPLAY_LIST_OF_COMPANY :{BLACK}Visa lista av företags tåg +STR_017C_DISPLAY_LIST_OF_COMPANY :{BLACK}Visa lista av företags vägfordon +STR_017D_DISPLAY_LIST_OF_COMPANY :{BLACK}Visa lista av företags skepp +STR_017E_DISPLAY_LIST_OF_COMPANY :{BLACK}Visa lista av företags flygplan +STR_017F_ZOOM_THE_VIEW_IN :{BLACK}Zooma in +STR_0180_ZOOM_THE_VIEW_OUT :{BLACK}Zooma ut +STR_0181_BUILD_RAILROAD_TRACK :{BLACK}Bygg järnväg +STR_0182_BUILD_ROADS :{BLACK}Bygg vägar +STR_0183_BUILD_SHIP_DOCKS :{BLACK}Bygg hamnar +STR_0184_BUILD_AIRPORTS :{BLACK}Bygg flygplatser +STR_0185_PLANT_TREES_PLACE_SIGNS :{BLACK}Plantera träd, placera skyltar etc. +STR_0186_LAND_BLOCK_INFORMATION :{BLACK}Markinformation +STR_0187_OPTIONS :{BLACK}Inställningar +STR_0188 :{BLACK}{SMALLUPARROW} +STR_0189 :{BLACK}{SMALLDOWNARROW} +STR_018A_CAN_T_CHANGE_SERVICING :{WHITE}Kan inte ändra service-intervall... +STR_018B_CLOSE_WINDOW :{BLACK}Stäng fönster +STR_018C_WINDOW_TITLE_DRAG_THIS :{BLACK}Fönstertitel - dra för att flytta fönstret +STR_018D_DEMOLISH_BUILDINGS_ETC :{BLACK}Riv ned byggnader etc. på en ruta mark +STR_018E_LOWER_A_CORNER_OF_LAND :{BLACK}Sänk ett hörn av marken +STR_018F_RAISE_A_CORNER_OF_LAND :{BLACK}Höj upp ett hörn av marken +STR_0190_SCROLL_BAR_SCROLLS_LIST :{BLACK}Scrollbar - scrolla listan upp/ned +STR_0191_SHOW_LAND_CONTOURS_ON_MAP :{BLACK}Visa markkonturer på kartan +STR_0192_SHOW_VEHICLES_ON_MAP :{BLACK}Visa fordon på kartan +STR_0193_SHOW_INDUSTRIES_ON_MAP :{BLACK}Visa industrier på kartan +STR_0194_SHOW_TRANSPORT_ROUTES_ON :{BLACK}Visa transportrutter på kartan +STR_0195_SHOW_VEGETATION_ON_MAP :{BLACK}Visa vegetation på kartan +STR_0196_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Visa markägare på kartan +STR_0197_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Växla stadsnamn av/på på kartan +STR_0198_PROFIT_THIS_YEAR_LAST_YEAR :{TINYFONT}{BLACK}Vinst detta år: {CURRENCY} (förra året: {CURRENCY}) + +############ range for service numbers starts +STR_0199_YEAR :{COMMA16} år ({COMMA16}) +STR_019A_YEARS :{COMMA16} år ({COMMA16}) +STR_019B_YEARS :{RED}{COMMA16} år ({COMMA16}) +############ range for service numbers ends + +STR_019C_ROAD_VEHICLE :Vägfordon +STR_019D_AIRCRAFT :Flygplan +STR_019E_SHIP :Skepp +STR_019F_TRAIN :Tåg +STR_01A0_IS_GETTING_OLD :{WHITE}{STRING} {COMMA16} börjar bli gammal +STR_01A1_IS_GETTING_VERY_OLD :{WHITE}{STRING} {COMMA16} börjar bli väldigt gammal +STR_01A2_IS_GETTING_VERY_OLD_AND :{WHITE}{STRING} {COMMA16} börjar bli väldigt gammal och måste bytas ut +STR_01A3_LAND_AREA_INFORMATION :{WHITE}Markinformation +STR_01A4_COST_TO_CLEAR_N_A :{BLACK}Kostnad att röja: {LTBLUE}N/A +STR_01A5_COST_TO_CLEAR :{BLACK}Kostnad att röja: {LTBLUE}{CURRENCY} +STR_01A6_N_A :N/A +STR_01A7_OWNER :{BLACK}Ägare: {LTBLUE}{STRING} +STR_01A8_LOCAL_AUTHORITY :{BLACK}Kommun: {LTBLUE}{STRING} +STR_01A9_NONE :Ingen +STR_01AA_NAME :{BLACK}Namn +STR_01AB :{BLACK}{TINYFONT}{STRING} + +############ range for days starts +STR_01AC_1ST :1 +STR_01AD_2ND :2 +STR_01AE_3RD :3 +STR_01AF_4TH :4 +STR_01B0_5TH :5 +STR_01B1_6TH :6 +STR_01B2_7TH :7 +STR_01B3_8TH :8 +STR_01B4_9TH :9 +STR_01B5_10TH :10 +STR_01B6_11TH :11 +STR_01B7_12TH :12 +STR_01B8_13TH :13 +STR_01B9_14TH :14 +STR_01BA_15TH :15 +STR_01BB_16TH :16 +STR_01BC_17TH :17 +STR_01BD_18TH :18 +STR_01BE_19TH :19 +STR_01BF_20TH :20 +STR_01C0_21ST :21 +STR_01C1_22ND :22 +STR_01C2_23RD :23 +STR_01C3_24TH :24 +STR_01C4_25TH :25 +STR_01C5_26TH :26 +STR_01C6_27TH :27 +STR_01C7_28TH :28 +STR_01C8_29TH :29 +STR_01C9_30TH :30 +STR_01CA_31ST :31 +############ range for days ends + +STR_01CB :{TINYFONT}{COMMA16} +STR_01CC_TOGGLE_LARGE_SMALL_MAP :{BLACK}Växla stor/liten kartstorlek +STR_01CD_SELECT_TUTORIAL_DEMONSTRATION :{WHITE}Välj Tutorial/Demonstration + +############ range for cargo acecpted starts +STR_01CE_CARGO_ACCEPTED :{BLACK}Accepterat gods: {LTBLUE}{STRING} +STR_01CF_CARGO_ACCEPTED :{BLACK}Accepterat gods: {LTBLUE}{STRING}, {STRING} +STR_01D0_CARGO_ACCEPTED :{BLACK}Accepterat gods: {LTBLUE}{STRING}, {STRING}, {STRING} +############ range for cargo acecpted ends + +STR_01D1_8 :({COMMA8}/8 {STRING}) +STR_01D2_JAZZ_JUKEBOX :{WHITE}Jazz Jukebox +STR_01D3_SOUND_MUSIC :Ljud/musik +STR_01D4_SHOW_SOUND_MUSIC_WINDOW :{BLACK}Visa ljud-/musikfönster +STR_01D5_ALL :{TINYFONT}Alla +STR_01D6_OLD_STYLE :{TINYFONT}Gammaldags +STR_01D7_NEW_STYLE :{TINYFONT}Modern +STR_01D8_EZY_STREET :{TINYFONT}Ezy Street +STR_01D9_CUSTOM_1 :{TINYFONT}Egen 1 +STR_01DA_CUSTOM_2 :{TINYFONT}Egen 2 +STR_01DB_MUSIC_VOLUME :{BLACK}{TINYFONT}Musikvolym +STR_01DC_EFFECTS_VOLUME :{BLACK}{TINYFONT}Effektvolym +STR_01DD_MIN_MAX :{BLACK}{TINYFONT}MIN ' ' ' ' ' ' MAX +STR_01DE_SKIP_TO_PREVIOUS_TRACK :{BLACK}Byt till föregående spår +STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION:{BLACK}Byt till nästa spår +STR_01E0_STOP_PLAYING_MUSIC :{BLACK}Sluta spela musik +STR_01E1_START_PLAYING_MUSIC :{BLACK}Börja spela musik +STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC :{BLACK}Dra för att ändra musik- och ljudvolym +STR_01E3 :{DKGREEN}{TINYFONT}-- +STR_01E4_0 :{DKGREEN}{TINYFONT}0{COMMA8} +STR_01E5 :{DKGREEN}{TINYFONT}{COMMA8} +STR_01E6 :{DKGREEN}{TINYFONT}------ +STR_01E7 :{DKGREEN}{TINYFONT}"{STRING}" +STR_01E8_TRACK_XTITLE :{BLACK}{TINYFONT}Spår{SETX 88}Titel +STR_01E9_SHUFFLE :{TINYFONT}Slumpa +STR_01EA_PROGRAM :{TINYFONT}{BLACK}Program +STR_01EB_MUSIC_PROGRAM_SELECTION :{WHITE}Musikprogram +STR_01EC_0 :{TINYFONT}{LTBLUE}0{COMMA16} "{STRING}" +STR_01ED :{TINYFONT}{LTBLUE}{COMMA16} "{STRING}" +STR_01EE_TRACK_INDEX :{TINYFONT}{BLACK}Spårindex +STR_01EF_PROGRAM :{TINYFONT}{BLACK}Program - '{STRING}' +STR_01F0_CLEAR :{TINYFONT}{BLACK}Töm +STR_01F1_SAVE :{TINYFONT}{BLACK}Spara +STR_01F2_CURRENT_PROGRAM_OF_MUSIC :{BLACK}Nuvarande program av musik +STR_01F3_SELECT_ALL_TRACKS_PROGRAM :{BLACK}Välj spellistan 'alla' +STR_01F4_SELECT_OLD_STYLE_MUSIC :{BLACK}Välj spellistan 'gammaldags' +STR_01F5_SELECT_NEW_STYLE_MUSIC :{BLACK}Välj spellistan 'modern' +STR_01F6_SELECT_CUSTOM_1_USER_DEFINED :{BLACK}Välj spellistan 'Egen 1' (användardefinerad) +STR_01F7_SELECT_CUSTOM_2_USER_DEFINED :{BLACK}Välj spellistan 'Egen 2' (användardefinerad) +STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Töm aktuellt program (Enbart Egen1 eller Egen2) +STR_01F9_SAVE_MUSIC_SETTINGS_TO :{BLACK}Spara musikinställningarna +STR_01FA_CLICK_ON_MUSIC_TRACK_TO :{BLACK}Klicka på ett spår för att lägga till den till spellistan (Enbart Egen1 eller Egen2) +STR_01FB_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Växla slumpning av/på +STR_01FC_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Visa fönstret för val av musikspår +STR_01FD_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klicka för att centrera vyn ovanför industrin/staden +STR_01FE_DIFFICULTY :{BLACK}Svårighetsgrad ({STRING}) +STR_01FF :{TINYFONT}{BLACK}{DATE_LONG} +STR_0200_LAST_MESSAGE_NEWS_REPORT :Senaste meddelandet/nyheten +STR_0201_MESSAGE_SETTINGS :Meddelandeinställningar +STR_MESSAGE_HISTORY_MENU :Meddelandehistorik +STR_0202_SEND_MESSAGE :Skicka meddelande +STR_0203_SHOW_LAST_MESSAGE_NEWS :{BLACK}Visa senaste meddelandet/nyheten, visa meddelandeinställningar +STR_0204_MESSAGE_OPTIONS :{WHITE}Meddelandeinställningar +STR_0205_MESSAGE_TYPES :{BLACK}Meddelandetyper:- +STR_0206_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankomst av första fordonet vid spelarens stn. +STR_0207_ARRIVAL_OF_FIRST_VEHICLE :{YELLOW}Ankomst av första fordonet vid konkurrenternas stn. +STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Olyckor / katastrofer +STR_0209_COMPANY_INFORMATION :{YELLOW}Företagsinformation +STR_020A_ECONOMY_CHANGES :{YELLOW}Förändringar av ekonomin +STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Råd / information om spelarens fordon +STR_020C_NEW_VEHICLES :{YELLOW}Nya fordon +STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Ändringar i godsacceptans +STR_020E_SUBSIDIES :{YELLOW}Subventioner +STR_020F_GENERAL_INFORMATION :{YELLOW}Generell information +STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO:{WHITE}...för långt från föregående destination +STR_0211_TOP_COMPANIES_WHO_REACHED :{BIGFONT}{BLACK}Bästa företag som nått år 2050{}({STRING} Level) +STR_0212 :{BIGFONT}{COMMA16}. +STR_0213_BUSINESSMAN :Affärsman +STR_0214_ENTREPRENEUR :Entreprenör +STR_0215_INDUSTRIALIST :Industrialist +STR_0216_CAPITALIST :Kapitalist +STR_0217_MAGNATE :Magnat +STR_0218_MOGUL :Mogul +STR_0219_TYCOON_OF_THE_CENTURY :Århundradets Tycoon +STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} uppnår '{STRING}' status! +STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} av {STRING} uppnår '{STRING}' status! +STR_021D :{BLACK} +STR_021E :{WHITE} +STR_021F :{BLUE}{COMMA16} +STR_0220_CREATE_SCENARIO :{BLACK}Nytt scenario +STR_0221_TRANSPORT_TYCOON :{YELLOW}OpenTTD +STR_0222_SCENARIO_EDITOR :{YELLOW}Scenario-editor +STR_0223_LAND_GENERATION :{WHITE}Skapa mark +STR_0224 :{BLACK}{UPARROW} +STR_0225 :{BLACK}{DOWNARROW} +STR_0226_RANDOM_LAND :{BLACK}Slumpmässig mark +STR_0227_RESET_LAND :{BLACK}Återställ mark +STR_0228_INCREASE_SIZE_OF_LAND_AREA :{BLACK}Öka storlek av yta att höja/sänka +STR_0229_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Minska storlek av yta att höja/sänka +STR_022A_GENERATE_RANDOM_LAND :{BLACK}Gör slumpmässig mark +STR_022B_RESET_LANDSCAPE :{BLACK}Återställ landskapet +STR_022C_RESET_LANDSCAPE :{WHITE}Återställ landskapet +STR_022D_ARE_YOU_SURE_YOU_WANT_TO :{WHITE}Vill du verkligen återställa landskapet? +STR_022E_LANDSCAPE_GENERATION :{BLACK}Skapa landskap +STR_022F_TOWN_GENERATION :{BLACK}Bygg städer +STR_0230_INDUSTRY_GENERATION :{BLACK}Bygg industrier +STR_0231_ROAD_CONSTRUCTION :{BLACK}Bygg vägar +STR_0232_VEGETATION_AND_OTHER_OBJECTS :{BLACK}Vegetation och andra objekt +STR_0233_TOWN_GENERATION :{WHITE}Skapa städer +STR_0234_NEW_TOWN :{BLACK}Ny stad +STR_0235_CONSTRUCT_NEW_TOWN :{BLACK}Bygg ny stad +STR_0236_CAN_T_BUILD_TOWN_HERE :{WHITE}Kan inte bygga stad här... +STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}...för nära kartans kant +STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...för nära en annan stad +STR_0239_SITE_UNSUITABLE :{WHITE}...platsen passar inte +STR_023A_TOO_MANY_TOWNS :{WHITE}...för många städer +STR_023B_INCREASE_SIZE_OF_TOWN :{BLACK}Öka stadens storlek +STR_023C_EXPAND :{BLACK}Utöka +STR_023D_RANDOM_TOWN :{BLACK}Slumpmässig stad +STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION :{BLACK}Bygg stad på slumpmässig plats +STR_023F_INDUSTRY_GENERATION :{WHITE}Bygg industrier +STR_0240_COAL_MINE :{BLACK}Kolgruva +STR_0241_POWER_STATION :{BLACK}Kraftstation +STR_0242_SAWMILL :{BLACK}Sågverk +STR_0243_FOREST :{BLACK}Skog +STR_0244_OIL_REFINERY :{BLACK}Oljeraffinaderi +STR_0245_OIL_RIG :{BLACK}Oljerigg +STR_0246_FACTORY :{BLACK}Fabrik +STR_0247_STEEL_MILL :{BLACK}Stålverk +STR_0248_FARM :{BLACK}Bondgård +STR_0249_IRON_ORE_MINE :{BLACK}Järnmalmsgruva +STR_024A_OIL_WELLS :{BLACK}Oljekälla +STR_024B_BANK :{BLACK}Bank +STR_024C_PAPER_MILL :{BLACK}Pappersbruk +STR_024D_FOOD_PROCESSING_PLANT :{BLACK}Livsmedelsfabrik +STR_024E_PRINTING_WORKS :{BLACK}Tryckeri +STR_024F_GOLD_MINE :{BLACK}Guldgruva +STR_0250_LUMBER_MILL :{BLACK}Sågverk +STR_0251_FRUIT_PLANTATION :{BLACK}Fruktplantage +STR_0252_RUBBER_PLANTATION :{BLACK}Gummiplantage +STR_0253_WATER_SUPPLY :{BLACK}Vattentillgång +STR_0254_WATER_TOWER :{BLACK}Vattentorn +STR_0255_DIAMOND_MINE :{BLACK}Diamantgruva +STR_0256_COPPER_ORE_MINE :{BLACK}Koppargruva +STR_0257_COTTON_CANDY_FOREST :{BLACK}Spunnet socker-skog +STR_0258_CANDY_FACTORY :{BLACK}Godisfabrik +STR_0259_BATTERY_FARM :{BLACK}Batteribondgård +STR_025A_COLA_WELLS :{BLACK}Kolakälla +STR_025B_TOY_SHOP :{BLACK}Leksaksaffär +STR_025C_TOY_FACTORY :{BLACK}Leksaksfabrik +STR_025D_PLASTIC_FOUNTAINS :{BLACK}Plastfontäner +STR_025E_FIZZY_DRINK_FACTORY :{BLACK}Läskfabrik +STR_025F_BUBBLE_GENERATOR :{BLACK}Bubbelgenerator +STR_0260_TOFFEE_QUARRY :{BLACK}Knäckbrott +STR_0261_SUGAR_MINE :{BLACK}Sockergruva +STR_0262_CONSTRUCT_COAL_MINE :{BLACK}Bygg kolgruva +STR_0263_CONSTRUCT_POWER_STATION :{BLACK}Bygg kraftstation +STR_0264_CONSTRUCT_SAWMILL :{BLACK}Bygg sågverk +STR_0265_PLANT_FOREST :{BLACK}Plantera skog +STR_0266_CONSTRUCT_OIL_REFINERY :{BLACK}Bygg oljeraffinaderi +STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY :{BLACK}Bygg oljerigg (Kan bara byggas nära kartans kant) +STR_0268_CONSTRUCT_FACTORY :{BLACK}Bygg fabrik +STR_0269_CONSTRUCT_STEEL_MILL :{BLACK}Bygg stålverk +STR_026A_CONSTRUCT_FARM :{BLACK}Bygg bondgård +STR_026B_CONSTRUCT_IRON_ORE_MINE :{BLACK}Bygg järnmalmsgruva +STR_026C_CONSTRUCT_OIL_WELLS :{BLACK}Bygg oljekälla +STR_026D_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bygg bank (Kan bara byggas i städer med fler än 1200 invånare) +STR_026E_CONSTRUCT_PAPER_MILL :{BLACK}Bygg pappersbruk +STR_026F_CONSTRUCT_FOOD_PROCESSING :{BLACK}Bygg livsmedelsfabrik +STR_0270_CONSTRUCT_PRINTING_WORKS :{BLACK}Bygg tryckeri +STR_0271_CONSTRUCT_GOLD_MINE :{BLACK}Bygg guldgruva +STR_0272_CONSTRUCT_BANK_CAN_ONLY :{BLACK}Bygg bank (Kan bara byggas i städer) +STR_0273_CONSTRUCT_LUMBER_MILL_TO :{BLACK}Bygg sågverk (För att hugga ned skog och producera timmer) +STR_0274_PLANT_FRUIT_PLANTATION :{BLACK}Plantera fruktplantage +STR_0275_PLANT_RUBBER_PLANTATION :{BLACK}Plantera gummiplantage +STR_0276_CONSTRUCT_WATER_SUPPLY :{BLACK}Bygg vattentillgång +STR_0277_CONSTRUCT_WATER_TOWER_CAN :{BLACK}Bygg vattentorn (Kan bara byggas i städer) +STR_0278_CONSTRUCT_DIAMOND_MINE :{BLACK}Bygg diamantgruva +STR_0279_CONSTRUCT_COPPER_ORE_MINE :{BLACK}Bygg koppargruva +STR_027A_PLANT_COTTON_CANDY_FOREST :{BLACK}Plantera Spunnet socker-skog +STR_027B_CONSTRUCT_CANDY_FACTORY :{BLACK}Bygg godisfabrik +STR_027C_CONSTRUCT_BATTERY_FARM :{BLACK}Bygg batteribondgård +STR_027D_CONSTRUCT_COLA_WELLS :{BLACK}Bygg kolakälla +STR_027E_CONSTRUCT_TOY_SHOP :{BLACK}Bygg leksaksaffär +STR_027F_CONSTRUCT_TOY_FACTORY :{BLACK}Bygg leksaksfabrik +STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS :{BLACK}Bygg plastfontäner +STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY :{BLACK}Bygg läskfabrik +STR_0282_CONSTRUCT_BUBBLE_GENERATOR :{BLACK}Bygg bubbelgenerator +STR_0283_CONSTRUCT_TOFFEE_QUARRY :{BLACK}Bygg knäckbrott +STR_0284_CONSTRUCT_SUGAR_MINE :{BLACK}Bygg sockergruva +STR_0285_CAN_T_BUILD_HERE :{WHITE}Kan inte bygga {STRING} här... +STR_0286_MUST_BUILD_TOWN_FIRST :{WHITE}...måste bygga stad först +STR_0287_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}...endast en per stad +STR_0288_PLANT_TREES :{BLACK}Plantera träd +STR_0289_PLACE_SIGN :{BLACK}Placera skylt +STR_028A_RANDOM_TREES :{BLACK}Slumpmässigt träd +STR_028B_PLANT_TREES_RANDOMLY_OVER :{BLACK}Plantera träd slumpmässigt över landskapet +STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE :{BLACK}Placera stenar i landskapet +STR_028D_PLACE_LIGHTHOUSE :{BLACK}Placera fyrtorn +STR_028E_PLACE_TRANSMITTER :{BLACK}Placera radiosändare +STR_028F_DEFINE_DESERT_AREA :{BLACK}Definiera öken +STR_0290_DELETE :{BLACK}Ta bort +STR_0291_DELETE_THIS_TOWN_COMPLETELY :{BLACK}Ta bort staden helt och hållet +STR_0292_SAVE_SCENARIO :Spara scenario +STR_0293_LOAD_SCENARIO :Öppna scenario +STR_0294_QUIT_EDITOR :Avsluta editor +STR_0295 : +STR_0296_QUIT :Avsluta +STR_0297_SAVE_SCENARIO_LOAD_SCENARIO :{BLACK}Spara scenario, öppna scenario, avbryt scenarioeditor, avsluta +STR_0298_LOAD_SCENARIO :{WHITE}Öppna scenario +STR_0299_SAVE_SCENARIO :{WHITE}Spara scenario +STR_029A_PLAY_SCENARIO :{BLACK}Spela scenario +STR_029B_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vill du verkligen avsluta detta scenario? +STR_029C_QUIT_EDITOR :{WHITE}Avsluta editor +STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bara byggas i städer med minst 1200 invånare +STR_029E_MOVE_THE_STARTING_DATE :{BLACK}Flytta bak startdatumet 1 år +STR_029F_MOVE_THE_STARTING_DATE :{BLACK}Flytta fram startdatumet 1 år +STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...brons ändar måste båda vara på land +STR_02A1_SMALL :{BLACK}Liten +STR_02A2_MEDIUM :{BLACK}Mellan +STR_02A3_LARGE :{BLACK}Stor +STR_02A4_SELECT_TOWN_SIZE :{BLACK}Välj stadsstorlek +STR_02A5_TOWN_SIZE :{YELLOW}Stadsstorlek: + +STR_02B6 :{STRING} - {STRING} +STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS :{BLACK}Visa senaste meddelande eller nyhet +STR_02B8_SUMMARY :{BLACK}Summering +STR_02B9_FULL :{BLACK}Full +STR_02BA :{SILVER}- - {STRING} - - +STR_02BB_TOWN_DIRECTORY :Lista av städer +STR_02BC_VEHICLE_DESIGN_NAMES :{BLACK}Fordonens modellnamn +STR_02BD :{BLACK}{STRING} +STR_02BE_DEFAULT :Original +STR_02BF_CUSTOM :Egna +STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK :{BLACK}Spara egna namn till disk +STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION :{BLACK}Fordonens modellnamnssortiment +STR_02C2_SAVE_CUSTOMIZED_VEHICLE :{BLACK}Spara egna modellnamn för fordon till disk + +############ range for menu starts +STR_02C3_GAME_OPTIONS :Spelinställningar +STR_02C4_GAME_OPTIONS :Spelinställningar +STR_02C5_DIFFICULTY_SETTINGS :Svårighetsgrad +STR_02C6_DIFFICULTY_SETTINGS :Svårighetsgrad +STR_02C7_CONFIG_PATCHES :Konfigurera patchar +STR_02C8_CONFIG_PATCHES :Konfigurera patchar +STR_GAMEOPTMENU_0A : +STR_GAMEOPTMENU_0B : +STR_02C9_TOWN_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Stadsnamn visas +STR_02CA_TOWN_NAMES_DISPLAYED :{SETX 12}Stadsnamn visas +STR_02CB_STATION_NAMES_DISPLAYED :{CHECKMARK}{SETX 12}Stationsnamn visas +STR_02CC_STATION_NAMES_DISPLAYED :{SETX 12}Stationsnamn visas +STR_02CD_SIGNS_DISPLAYED :{CHECKMARK}{SETX 12}Skyltar visas +STR_02CE_SIGNS_DISPLAYED :{SETX 12}Skyltar visas +STR_CHECKPOINTS_DISPLAYED :{CHECKMARK}{SETX 12}Kontrollstationer visas +STR_CHECKPOINTS_DISPLAYED2 :{SETX 12}Kontrollstationer visas +STR_02CF_FULL_ANIMATION :{CHECKMARK}{SETX 12}Full animation +STR_02D0_FULL_ANIMATION :{SETX 12}Full animation +STR_02D1_FULL_DETAIL :{CHECKMARK}{SETX 12}Full detaljnivå +STR_02D2_FULL_DETAIL :{SETX 12}Full detaljnivå +STR_02D3_TRANSPARENT_BUILDINGS :{CHECKMARK}{SETX 12}Transparenta byggnader +STR_02D4_TRANSPARENT_BUILDINGS :{SETX 12}Transparenta byggnader +############ range ends here + +############ range for menu starts +STR_02D5_LAND_BLOCK_INFO :Information om mark +STR_02D6 : +STR_02D7_SCREENSHOT_CTRL_S :Skärmdump (Ctrl-S) +STR_02D8_GIANT_SCREENSHOT_CTRL_G :Gigantisk skärmdump (Ctrl-G) +STR_02D9_ABOUT_TRANSPORT_TYCOON :Om 'OpenTTD' +############ range ends here + +STR_02DA_ON :{BLACK}På +STR_02DB_OFF :{BLACK}Av +STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Visa subventioner +STR_02DD_SUBSIDIES :Subventioner +STR_02DE_MAP_OF_WORLD :Världskarta +STR_02DF_TOWN_DIRECTORY :Lista av städer +STR_02E0_CURRENCY_UNITS :{BLACK}Valutaenheter +STR_02E1 :{BLACK}{SKIP}{STRING} +STR_02E2_CURRENCY_UNITS_SELECTION :{BLACK}Välj valutaenhet +STR_02E3_DISTANCE_UNITS :{BLACK}Måttenheter +STR_02E4 :{BLACK}{SKIP}{SKIP}{STRING} +STR_02E5_DISTANCE_UNITS_SELECTION :{BLACK}Välj måttenhet +STR_02E6_ROAD_VEHICLES :{BLACK}Vägfordon +STR_02E7 :{BLACK}{SKIP}{SKIP}{SKIP}{STRING} +STR_02E8_SELECT_SIDE_OF_ROAD_FOR :{BLACK}Välj sida av vägen som fordonen kör på +STR_02E9_DRIVE_ON_LEFT :Kör på vänster sida +STR_02EA_DRIVE_ON_RIGHT :Kör på höger sida +STR_02EB_TOWN_NAMES :{BLACK}Stadsnamn +STR_02EC :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02ED_SELECT_STYLE_OF_TOWN_NAMES :{BLACK}Välj typ på stadsnamn + +STR_02F4_AUTOSAVE :{BLACK}Autosparning +STR_02F5 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_02F6_SELECT_INTERVAL_BETWEEN :{BLACK}Välj intervall mellan autosparning +STR_02F7_OFF :Avstängd +STR_02F8_EVERY_3_MONTHS :Var 3:e månad +STR_02F9_EVERY_6_MONTHS :Var 6:e månad +STR_02FA_EVERY_12_MONTHS :Var 12:e månad +STR_02FB_START_A_NEW_GAME :{BLACK}Börja ett nytt spel +STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Öppna ett sparat spel +STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}View demonstrationer/tutorials +STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Skapa egen ny spel värld/scenario +STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Välj en spelare +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Välj två spelare +STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Visa spelinställningar +STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Visa inställningar för svårighetsgrad +STR_0303_START_A_NEW_GAME_USING :{BLACK}Starta nytt spel, som använder ett eget scenario +STR_0304_QUIT :{BLACK}Avsluta +STR_0305_LEAVE_TRANSPORT_TYCOON :{BLACK}Avsluta 'OpenTTD' +STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}Visa demonstration/tutorial +STR_0307_TRANSPORT_TYCOON_DELUXE :{WHITE}OpenTTD {REV} +STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bara byggas i städer +STR_030E_SELECT_TEMPERATE_LANDSCAPE :{BLACK}Välj 'tempererad' typ av landskap +STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE :{BLACK}Välj 'arktisk' typ av landskap +STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE :{BLACK}Välj 'tropisk' typ av landskap +STR_0311_SELECT_TOYLAND_LANDSCAPE :{BLACK}Välj 'leksaksland' som typ av landskap +STR_0312_FUND_CONSTRUCTION_OF_NEW :{BLACK}Bekosta byggnation av ny industri + +############ range for menu starts +STR_0313_FUND_NEW_INDUSTRY :Bekosta ny industri +STR_INDUSTRY_DIR :Industriförteckning +############ range ends here + +STR_0314_FUND_NEW_INDUSTRY :{WHITE}Bekosta ny industri +STR_0315 :{STRING} +STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}...kan bara byggas i städer +STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST:{WHITE}...kan bara byggas i regnskog +STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}...kan bara byggas på öken +STR_0319_PAUSED :{YELLOW}* * PAUSAD * * + +STR_031B_SCREENSHOT_SUCCESSFULLY :{WHITE}Skärmdump sparades som '{STRING}' +STR_031C_SCREENSHOT_FAILED :{WHITE}Kunde inte spara skärmdump! + +STR_0329_PURCHASE_LAND_FOR_FUTURE :{BLACK}Köp mark för framtida användning +STR_032A_1_ROAD_VEHICLE_SERVICE :{BLACK}1: Underhåll av vägfordon +STR_032B_2_RAILROAD_SERVICE :{BLACK}2: Underhåll av tåg +STR_032C_3_AIR_SERVICE :{BLACK}3: Underhåll av flygfordon +STR_032D_4_SHIP_SERVICE :{BLACK}4: Underhåll av skepp +STR_032E_5_RAILROAD_SERVICE_ADVANCED :{BLACK}5: Underhåll av tåg (avancerat) +STR_032F_AUTOSAVE :{RED}AUTOSPARNING +STR_0330_SELECT_EZY_STREET_STYLE :{BLACK}Välj 'Ezy Street style music'-program + +STR_0335_6 :{BLACK}6 +STR_0336_7 :{BLACK}7 + +############ start of townname region +STR_TOWNNAME_ENGLISH :Engelska +STR_TOWNNAME_FRENCH :Franska +STR_TOWNNAME_GERMAN :Tyska +STR_TOWNNAME_AMERICAN :Amerikanska +STR_TOWNNAME_LATIN_AMERICAN :Latinamerikanska +STR_TOWNNAME_SILLY :Löjliga +STR_TOWNNAME_SWEDISH :Svenska +STR_TOWNNAME_DUTCH :Hollänska +STR_TOWNNAME_FINNISH :Finska +STR_TOWNNAME_POLISH :Polska +STR_TOWNNAME_SLOVAKISH :Slovakiska +STR_TOWNNAME_HUNGARIAN :Hungarianska +STR_TOWNNAME_AUSTRIAN :Australienska +############ end of townname region + +STR_CURR_POUNDS :Pund ({POUNDSIGN}) +STR_CURR_DOLLARS :Dollar ($) +STR_CURR_FF :Franska franc (FF) +STR_CURR_DM :Tyska mark (DM) +STR_CURR_YEN :Yen ({YENSIGN}) +STR_CURR_PT :Pesetas (Pt) +STR_CURR_FT :Ungerska forint (Ft) +STR_CURR_ZL :Polska zloty (zl) +STR_CURR_ATS :Österrikiska shilling (ATS) +STR_CURR_BEF :Belgiska franc (BEF) +STR_CURR_DKK :Danska kronor (DKK) +STR_CURR_FIM :Finska mark (FIM) +STR_CURR_GRD :Grekiska drachmer (GRD) +STR_CURR_CHF :Schweiziska franc (CHF) +STR_CURR_NLG :Holländska guilder (NLG) +STR_CURR_ITL :Italienska lire (ITL) +STR_CURR_SEK :Svenska kronor (SEK) +STR_CURR_RUR :Ryska rubel (rur) +STR_CURR_CZK :Tjeckiska kronor (CZK) +STR_CURR_ISK :Isländska kronor (ISK) +STR_CURR_NOK :Norska kronor (NOK) +STR_CURR_EUR :Euro (€) + +STR_OPTIONS_LANG :{BLACK}Språk +STR_OPTIONS_LANG_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_LANG_TIP :{BLACK}Välj språk att använda + +STR_OPTIONS_RES :{BLACK}Skärmupplösning +STR_OPTIONS_RES_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_RES_TIP :{BLACK}Välj skärmupplösning att använda + +STR_OPTIONS_SCREENSHOT_FORMAT :{BLACK}Skärmdumpsformat +STR_OPTIONS_SCREENSHOT_FORMAT_CBO :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} +STR_OPTIONS_SCREENSHOT_FORMAT_TIP :{BLACK}Välj filformat för skärmdump + +STR_AUTOSAVE_1_MONTH :Varje månad +STR_AUTOSAVE_FAILED :{WHITE}Autosparning misslyckades + +STR_MONTH_JAN :januari +STR_MONTH_FEB :februari +STR_MONTH_MAR :mars +STR_MONTH_APR :april +STR_MONTH_MAY :maj +STR_MONTH_JUN :juni +STR_MONTH_JUL :juli +STR_MONTH_AUG :augusti +STR_MONTH_SEP :september +STR_MONTH_OCT :oktober +STR_MONTH_NOV :november +STR_MONTH_DEC :december + +STR_HEADING_FOR_STATION :{LTBLUE}På väg mot {STATION} +STR_HEADING_FOR_STATION_VEL :{LTBLUE}På väg mot {STATION}, {VELOCITY} +STR_NO_ORDERS :{LTBLUE}Inga order +STR_NO_ORDERS_VEL :{LTBLUE}Inga order, {VELOCITY} + +STR_PASSENGERS :passagerare +STR_BAGS :väskor +STR_TONS :ton +STR_LITERS :liter +STR_ITEMS :föremål +STR_CRATES :lådor +STR_RES_OTHER :annan +STR_NOTHING :ingenting + +STR_CANT_SHARE_ORDER_LIST :{WHITE}Kan inte dela orderlistan... +STR_CANT_COPY_ORDER_LIST :{WHITE}Kan inte kopiera orderlistan... +STR_END_OF_SHARED_ORDERS :{SETX 10}- - Slut på delade order - - + +STR_TRAIN_IS_LOST :{WHITE}Tåg {COMMA16} har tappat bort sig. +STR_TRAIN_IS_UNPROFITABLE :{WHITE}Tåg {COMMA16}s vinst förra året var {CURRENCY} + +STR_CONFIG_PATCHES :{BLACK}Konfigurera patchar +STR_CONFIG_PATCHES_TIP :{BLACK}Konfigurera patcharna +STR_CONFIG_PATCHES_CAPTION :{WHITE}Konfigurera patchar + +STR_CONFIG_PATCHES_OFF :Av +STR_CONFIG_PATCHES_ON :På +STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Visa fordonshastighet i statusfältet: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Tillåt byggnation på sluttningar och kuster: {ORANGE}{STRING} +STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Tillåt borttagning av mera stadsägda vägar etc.: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Tillåt väldigt långa tåg: {ORANGE}{STRING} +STR_CONFIG_PATCHES_REALISTICACCEL :{LTBLUE}Aktivera realistisk acceleration för tåg: {ORANGE}{STRING} +STR_CONFIG_PATCHES_JOINSTATIONS :{LTBLUE}Kombinera tågstationer som byggs bredvid varandra: {ORANGE}{STRING} +STR_CONFIG_PATCHES_FULLLOADANY :{LTBLUE}Lämna stationen när något gods är fullt, om 'full load': {ORANGE}{STRING} +STR_CONFIG_PATCHES_NOTRAINSERVICE :{LTBLUE}Ingen automatisk tågservice: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SELECTGOODS :{LTBLUE}Leverera gods till en station enbart om någon frågar efter det: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGBRIDGES :{LTBLUE}Tillåt väldigt långa broar: {ORANGE}{STRING} +STR_CONFIG_PATCHES_GOTODEPOT :{LTBLUE}Tillåt order att gå till depå/bussgarage: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILDXTRAIND :{LTBLUE}Tillåt byggnation av råmaterialsproducerande industrier: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MULTIPINDTOWN :{LTBLUE}Tillåt flera industrier av samma typ per stad: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SAMEINDCLOSE :{LTBLUE}Industrier av samma typ kan byggas nära varandra: {ORANGE}{STRING} +STR_CONFIG_PATCHES_LONGDATE :{LTBLUE}Visa alltid långt datum i statusfältet: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SIGNALSIDE :{LTBLUE}Visa signaler på körsidan: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SHOWFINANCES :{LTBLUE}Visa finansfönstret vid slutet av året: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_NONSTOP :{LTBLUE}TTDPatch-kompatibel nonstop-hantering: {ORANGE}{STRING} +STR_CONFIG_PATCHES_ROADVEH_QUEUE :{LTBLUE}Vägfordonsköing (med kvanteffekter): {ORANGE}{STRING} +STR_CONFIG_PATCHES_AUTOSCROLL :{LTBLUE}Scrolla vyn när musen är vid kanten: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Tillåt mutning av den lokala kommunen: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_DEPOT_FINDING :{LTBLUE}Ny algoritm för att hitta depå: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Icke-rektangulära stationer: {ORANGE}{STRING} +STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND :{LTBLUE}Ny algoritm för att hitta rutt: {ORANGE}{STRING} +STR_CONFIG_PATCHES_BUILD_IN_PAUSE :{LTBLUE}Byggnation i pause-läge: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Tillåt alltid små flygplatser: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_LOST_TRAIN_DAYS :{LTBLUE}Ett tåg är vilse om ingen vidare framgång är nådd under: {ORANGE}{STRING} dagar +STR_CONFIG_PATCHES_WARN_INCOME_LESS :{LTBLUE}Varna om ett tågs inkomst är negativ: {ORANGE}{STRING} +STR_CONFIG_AUTORENEW_VEHICLE :{LTBLUE}Byt automatiskt ut gamla fordon +STR_CONFIG_PATCHES_ERRMSG_DURATION :{LTBLUE}Hur länge felmeddelanden visas: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SNOWLINE_HEIGHT :{LTBLUE}Snölinjeshöjd: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STATION_SPREAD :{LTBLUE}Max stationsspridning: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SERVICEATHELIPAD :{LTBLUE}Serva helikoptrar vid landningplattor automatiskt: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Max antal tåg per spelare: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Max antal vägfordon per spelare: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_AIRCRAFT :{LTBLUE}Max antal flygplan per spelare: {ORANGE}{STRING} +STR_CONFIG_PATCHES_MAX_SHIPS :{LTBLUE}Max antal skepp per spelare: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_AI_BUILDS_TRAINS :{LTBLUE}Förbjud tåg för datorn: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH :{LTBLUE}Förbjud vägfordon för datorn: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT :{LTBLUE}Förbjud flygplan för datorn: {ORANGE}{STRING} +STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Förbjud skepp för datorn: {ORANGE}{STRING} + +STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Standard-serviceintervall för tåg: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_ROADVEH :{LTBLUE}Standard-serviceintervall för vägfordon: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_AIRCRAFT :{LTBLUE}Standard-serviceintervall för flygplan: {ORANGE}{STRING} days +STR_CONFIG_PATCHES_SERVINT_SHIPS :{LTBLUE}Standard-serviceintervall för skepp: {ORANGE}{STRING} days + +STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Färgade nyheter visas i: {ORANGE}{STRING} +STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Startdatum: {ORANGE}{STRING} +STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Lugn ekonomi (flera små ändringar) + +STR_CONFIG_PATCHES_GUI :{BLACK}Gränssnitt +STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstruktion +STR_CONFIG_PATCHES_VEHICLES :{BLACK}Fordon +STR_CONFIG_PATCHES_STATIONS :{BLACK}Stationer +STR_CONFIG_PATCHES_ECONOMY :{BLACK}Ekonomi + +STR_CONFIG_PATCHES_DISABLED :Avaktiverat +STR_CONFIG_PATCHES_INT32 :{INT32} + +STR_CONFIG_PATCHES_QUERY_CAPT :{WHITE}Ändra inställningsvärde + + +STR_CHEATS :{WHITE}Fusk +STR_CHEATS_TIP :{BLACK}Checkboxar indikerar om du använt det här fusket förut +STR_CHEATS_WARNING :{BLACK}Varning! Du är på väg att förråda dina motståndare. Kom ihåg att sådant aldrig glöms bort. +STR_CHEAT_MONEY :{LTBLUE}Öka pengar genom att {CURRENCY64} +STR_CHEAT_CHANGE_PLAYER :{LTBLUE}Spelar som: {ORANGE}{COMMA16} +STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}trimmad bulldozer (ta bort industrier, fyrar etc.): {ORANGE}{STRING} +STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunnlar kan korsa varandra: {ORANGE}{STRING} + + +STR_TOWNDIR_NAME :{BLACK}Namn +STR_TOWNDIR_POPULATION :{BLACK}Invånare +STR_TOWNDIR_SORT_TIP :{BLACK}Välj sorteringsordning + +STR_HEADING_FOR_CHECKPOINT :{LTBLUE}På väg mot {CHECKPOINT} +STR_HEADING_FOR_CHECKPOINT_VEL :{LTBLUE}På väg mot {CHECKPOINT}, {VELOCITY} + +STR_GO_TO_CHECKPOINT :Gå via {CHECKPOINT} + +STR_CHECKPOINTNAME_CITY :Kontrollstation {TOWN} +STR_CHECKPOINTNAME_CITY_SERIAL :Kontrollstation {TOWN} #{COMMA16} +STR_LANDINFO_CHECKPOINT :Kontrollpunkt + +STR_CHECKPOINT_VIEWPORT :{WHITE}{CHECKPOINT} +STR_CHECKPOINT_VIEWPORT_TINY :{TINYFONT}{WHITE}{CHECKPOINT} +STR_CHECKPOINT_RAW :{CHECKPOINT} +STR_EDIT_CHECKPOINT_NAME :{WHITE}Ändra namn på kontrollstation + +STR_CANT_CHANGE_CHECKPOINT_NAME :{WHITE}Kan inte ändra kontrollstationens namn... +STR_CONVERT_RAIL_TO_CHECKPOINT_TIP :{BLACK}Ändra räls till kontrollstation +STR_CANT_BUILD_TRAIN_CHECKPOINT :{WHITE}Kan inte bygga tågkontrollstation här... +STR_CANT_REMOVE_TRAIN_CHECKPOINT :{WHITE}Kan inte ta bort tågkontrollstation här... + +STR_BUILD_AUTORAIL_TIP :{BLACK}Bygg järnvägspår genom att använda Autorail-funktionen + +STR_TREES_RANDOM_TYPE :{BLACK}Träd av olika typ +STR_TREES_RANDOM_TYPE_TIP :{BLACK}Placera träd av olika typ + +STR_CANT_BUILD_CANALS :{WHITE}Kan ej bygga kanaler här... +STR_BUILD_CANALS_TIP :{BLACK}Bygg kanaler +STR_LANDINFO_CANAL :Kanal + +STR_CANT_BUILD_LOCKS :{WHITE}Kan ej bygga slussar här... +STR_BUILD_LOCKS_TIP :{BLACK}Bygg slussar +STR_LANDINFO_LOCK :Sluss + +STR_LANDINFO_COORDS :{BLACK}Koordinater: {LTBLUE}{NUMU16}x{NUMU16} ({STRING}) + +STR_CANT_REMOVE_PART_OF_STATION :{WHITE}Kan ej ta bort del av station... +STR_CANT_CONVERT_RAIL :{WHITE}Kan ej konvertera spårtyp här... +STR_CONVERT_RAIL_TIP :{BLACK}Konvertera/Uppgradera spårtyp + +STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP :{BLACK}Drag loket här för att sälja hela tåget + +STR_DRAG_DROP :{BLACK}Drag & Släpp +STR_STATION_DRAG_DROP :{BLACK}Bygg en station genom drag & släpp + +STR_FAST_FORWARD :{BLACK}Snabbspola spelet +STR_MESSAGE_HISTORY :{WHITE}Meddelandehistorik + +STR_CONSTRUCT_COAL_MINE_TIP :{BLACK}Bygg kolgruva +STR_CONSTRUCT_FOREST_TIP :{BLACK}Plantera skog +STR_CONSTRUCT_OIL_RIG_TIP :{BLACK}Bygg oljerigg +STR_CONSTRUCT_FARM_TIP :{BLACK}Bygg farm +STR_CONSTRUCT_COPPER_ORE_MINE_TIP :{BLACK}Bygg koppargruva +STR_CONSTRUCT_OIL_WELLS_TIP :{BLACK}Bygg oljekälla +STR_CONSTRUCT_GOLD_MINE_TIP :{BLACK}Bygg guldgruva +STR_CONSTRUCT_DIAMOND_MINE_TIP :{BLACK}Bygg diamantgruva +STR_CONSTRUCT_IRON_ORE_MINE_TIP :{BLACK}Bygg järnmalmsgruva +STR_CONSTRUCT_FRUIT_PLANTATION_TIP :{BLACK}Plantera fruktplantage +STR_CONSTRUCT_RUBBER_PLANTATION_TIP :{BLACK}Plantera gummiplantage +STR_CONSTRUCT_WATER_SUPPLY_TIP :{BLACK}Bygg vattentillgång +STR_CONSTRUCT_COTTON_CANDY_TIP :{BLACK}Plantera Spunnet socker-skog +STR_CONSTRUCT_BATTERY_FARM_TIP :{BLACK}Bygg batteribondgård +STR_CONSTRUCT_COLA_WELLS_TIP :{BLACK}Bygg kolakälla +STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP :{BLACK}Bygg plastfontäner +STR_CONSTRUCT_BUBBLE_GENERATOR_TIP :{BLACK}Bygg bubbelgenerator +STR_CONSTRUCT_TOFFEE_QUARRY_TIP :{BLACK}Bygg knäckbrott +STR_CONSTRUCT_SUGAR_MINE_TIP :{BLACK}Bygg sockergruva + +STR_INDUSTRYDIR_NAME :{BLACK}Namn +STR_INDUSTRYDIR_PRODUCTION :{BLACK}Produktion +STR_INDUSTRYDIR_TYPE :{BLACK}Typ +STR_INDUSTRYDIR_CAPTION :{WHITE}Industrier +STR_INDUSTRYDIR_ITEM :{ORANGE}{TOWN} {STRING}{BLACK} ({STRING}) +STR_INDUSTRYDIR_ITEM_NOPROD :{ORANGE}{TOWN} {STRING} + +STR_INDUSTRY_TOO_CLOSE :{WHITE}... för nära annan industri + +STR_RAIL_REFIT_VEHICLE_TO_CARRY :{BLACK}Anpassa tåg för att bära annan godstyp +STR_RAIL_REFIT :{WHITE}{STRING} (Anpassa) +STR_RAIL_REFIT_VEHICLE :{BLACK}Anpassa tåg +STR_RAIL_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Välj godstyp för tåget att bära +STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED :{BLACK}Anpassa tåg för att bära vald godstyp +STR_RAIL_CAN_T_REFIT_VEHICLE :{WHITE}Kan ej anpassa tåg... + +##id 0x0800 +STR_0800_COST :{TINYFONT}{RED}Kostnad: {CURRENCY} +STR_0801_COST :{RED}Kostnad: {CURRENCY} +STR_0802_INCOME :{TINYFONT}{GREEN}Inkomst: {CURRENCY} +STR_0803_INCOME :{GREEN}Inkomst: {CURRENCY} +STR_0804_ESTIMATED_COST :{TINYFONT}{WHITE}Uppskattad kostnad: {CURRENCY} +STR_0805_ESTIMATED_COST :{WHITE}Uppskattad kostnad: {CURRENCY} +STR_0806_ESTIMATED_INCOME :{TINYFONT}{WHITE}Uppskattad inkomst: {CURRENCY} +STR_0807_ESTIMATED_INCOME :{WHITE}Uppskattad inkomst: {CURRENCY} +STR_0808_CAN_T_RAISE_LAND_HERE :{WHITE}Kan inte höja marken här... +STR_0809_CAN_T_LOWER_LAND_HERE :{WHITE}Kan inte sänka marken här... +STR_080A_ROCKS :Stenar +STR_080B_ROUGH_LAND :Obearbetad mark +STR_080C_BARE_LAND :Barmark +STR_080D_GRASS :Gräs +STR_080E_FIELDS :Fält +STR_080F_SNOW_COVERED_LAND :Snötäckt land +STR_0810_DESERT :Öken + +##id 0x1000 +STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Marken lutar åt fel håll +STR_1001_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Omöjlig kombination av spår +STR_1002_EXCAVATION_WOULD_DAMAGE :{WHITE}Utgrävning skulle förstöra tunnel +STR_1003_ALREADY_AT_SEA_LEVEL :{WHITE}Redan på havsnivå +STR_1004_TOO_HIGH :{WHITE}För hög +STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Inget passande järnvägsspår +STR_1006_TRAIN_INSIDE_DEPOT :{WHITE}Tåg inuti depå +STR_1007_ALREADY_BUILT :{WHITE}...redan byggd +STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Måste ta bort järnväg först +STR_1009_TOO_MANY_DEPOTS :{WHITE}För många depåer +STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Bygg järnväg +STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Bygg monorail +STR_100C_MAGLEV_CONSTRUCTION :{WHITE}Bygg maglev +STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Välj järnvägsbro +STR_100E_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Kan inte bygga depå här... +STR_100F_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Kan inte bygga järnvägsstation här... +STR_1010_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Kan inte bygga signaler här... +STR_1011_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Kan inte bygga järnvägsspår här... +STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Kan inte ta bort järnvägspår här... +STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Kan inte ta bort signaler här... +STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Riktning för depå +STR_1015_RAILROAD_CONSTRUCTION :Bygg järnväg +STR_1016_MONORAIL_CONSTRUCTION :Bygg monorail +STR_1017_MAGLEV_CONSTRUCTION :Bygg maglev +STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Bygg järnväg +STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Bygg depå (för att bygga eller reparera tåg) +STR_101A_BUILD_RAILROAD_STATION :{BLACK}Bygg järnvägsstation +STR_101B_BUILD_RAILROAD_SIGNALS :{BLACK}Bygg järnvägssignaler +STR_101C_BUILD_RAILROAD_BRIDGE :{BLACK}Bygg järnvägsbro +STR_101D_BUILD_RAILROAD_TUNNEL :{BLACK}Bygg järnvägstunnel +STR_101E_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Växla mellan att bygga/ta bort järnväg och signaler +STR_101F_BRIDGE_SELECTION_CLICK :{BLACK}Välj bro - klicka på vald bro för att bygga den +STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO:{BLACK}Välj riktning för depå +STR_1021_RAILROAD_TRACK :Järnvägsspår +STR_1022_RAILROAD_TRACK_WITH_SIGNALS :Järnvägsspår med signaler +STR_1023_RAILROAD_TRAIN_DEPOT :Järnvägsdepå +STR_1024_AREA_IS_OWNED_BY_ANOTHER :{WHITE}...området ägs av ett annat företag +STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Järnväg med normala signaler +STR_RAILROAD_TRACK_WITH_PRESIGNALS :Järnväg med normala för-signaler +STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Järnväg med normala exit-signaler +STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Järnväg med normala kombinerade signaler + + + +##id 0x1800 +STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Marken lutar åt fel håll för väg +STR_1801_MUST_REMOVE_ROAD_FIRST :{WHITE}Måste ta bort väg först +STR_1802_ROAD_CONSTRUCTION :{WHITE}Bygg väg +STR_1803_SELECT_ROAD_BRIDGE :{WHITE}Välj vägbro +STR_1804_CAN_T_BUILD_ROAD_HERE :{WHITE}Kan inte bygga väg här... +STR_1805_CAN_T_REMOVE_ROAD_FROM :{WHITE}Kan inte ta bort väg här... +STR_1806_ROAD_DEPOT_ORIENTATION :{WHITE}Väg riktning för bussgarage +STR_1807_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan inte bygga bussgarage här... +STR_1808_CAN_T_BUILD_BUS_STATION :{WHITE}Kan inte bygga busshållplats... +STR_1809_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kan inte bygga lastbilsbrygga... +STR_180A_ROAD_CONSTRUCTION :Bygg väg +STR_180B_BUILD_ROAD_SECTION :{BLACK}Bygg väg +STR_180C_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Bygg bussgarage (för att bygga eller reparera vägfordon) +STR_180D_BUILD_BUS_STATION :{BLACK}Bygg busshållplats +STR_180E_BUILD_TRUCK_LOADING_BAY :{BLACK}Bygg lastbilsbrygga +STR_180F_BUILD_ROAD_BRIDGE :{BLACK}Bygg vägbro +STR_1810_BUILD_ROAD_TUNNEL :{BLACK}Bygg vägtunnel +STR_1811_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Växla mellan att bygga/ta bort väg +STR_1812_BRIDGE_SELECTION_CLICK :{BLACK}Välj bro - klicka på vald bro för att bygga den +STR_1813_SELECT_ROAD_VEHICLE_DEPOT :{BLACK}Välj riktning för bussgarage +STR_1814_ROAD :Väg +STR_1815_ROAD_WITH_STREETLIGHTS :Väg med gatubelysning +STR_1816_TREE_LINED_ROAD :Väg med träd +STR_1817_ROAD_VEHICLE_DEPOT :Bussgarage +STR_1818_ROAD_RAIL_LEVEL_CROSSING :Järnvägskorsning + +##id 0x2000 +STR_2000_TOWNS :{WHITE}Städer +STR_2001 :{WHITE}{STRING} +STR_2002 :{TINYFONT}{BLACK}{STRING} +STR_2003 :{TINYFONT}{WHITE}{STRING} +STR_2004_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Byggnad måste rivas först +STR_2005 :{WHITE}{TOWN} +STR_2006_POPULATION :{BLACK}Invånare: {ORANGE}{COMMA32}{BLACK} Huse: {ORANGE}{COMMA32} +STR_2007_RENAME_TOWN :Byt namn på stad +STR_2008_CAN_T_RENAME_TOWN :{WHITE}Kan inte byta namn på stad... +STR_2009_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} kommunen tillåter inte detta +STR_200A_TOWN_NAMES_CLICK_ON_NAME :{BLACK}Stadsnamn - klicka på ett namn för att centrera vyn på staden +STR_200B_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrera vyn på staden +STR_200C_CHANGE_TOWN_NAME :{BLACK}Byt namn på staden +STR_200D_PASSENGERS_LAST_MONTH_MAX :{BLACK}Passagerare förra månaden: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200E_MAIL_LAST_MONTH_MAX :{BLACK}Post förra månaden: {ORANGE}{COMMA16}{BLACK} max: {ORANGE}{COMMA16} +STR_200F_TALL_OFFICE_BLOCK :Högt kontor +STR_2010_OFFICE_BLOCK :Kontor +STR_2011_SMALL_BLOCK_OF_FLATS :Små lägenheter +STR_2012_CHURCH :Kyrka +STR_2013_LARGE_OFFICE_BLOCK :Stora kontor +STR_2014_TOWN_HOUSES :Småhus +STR_2015_HOTEL :Hotell +STR_2016_STATUE :Staty +STR_2017_FOUNTAIN :Fontän +STR_2018_PARK :Park +STR_2019_OFFICE_BLOCK :Kontorslokaler +STR_201A_SHOPS_AND_OFFICES :Affärer och kontor +STR_201B_MODERN_OFFICE_BUILDING :Moderna kontorsbyggnader +STR_201C_WAREHOUSE :Varuhus +STR_201D_OFFICE_BLOCK :Kontor +STR_201E_STADIUM :Stadium +STR_201F_OLD_HOUSES :Gamla hus +STR_2020_LOCAL_AUTHORITY :{BLACK}Kommun +STR_2021_SHOW_INFORMATION_ON_LOCAL :{BLACK}Visa kommuninformation +STR_2022_LOCAL_AUTHORITY :{WHITE}{TOWN} kommun +STR_2023_TRANSPORT_COMPANY_RATINGS :{BLACK}Transportföretags värderingar: +STR_2024 :{YELLOW}{STRING}{STRING}: {ORANGE}{STRING} +STR_2025_SUBSIDIES :{WHITE}Subventioner +STR_2026_SUBSIDIES_ON_OFFER_FOR :{BLACK}Aktuella subventioner:- +STR_2027_FROM_TO :{ORANGE}{STRING} från {STRING} till {STRING} +STR_2028_BY :{YELLOW} (tills {DATE_SHORT}) +STR_2029 :{STRING} {STRING} +STR_202A_NONE :{ORANGE}Inga +STR_202B_SERVICES_ALREADY_SUBSIDISED :{BLACK}Redan subventionerade rutter:- +STR_202C_FROM_TO :{ORANGE}{STRING} från {STATION} till {STATION}{YELLOW} ({STRING} +STR_202D_UNTIL :{YELLOW}, tills {DATE_SHORT}) +STR_202E_OFFER_OF_SUBSIDY_EXPIRED :{BLACK}{BIGFONT}Subventionen har gått ut:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad +STR_202F_SUBSIDY_WITHDRAWN_SERVICE :{BLACK}{BIGFONT}Subventionen gäller inte mer:{}{}{STRING} från {STATION} till {STATION} är inte längre subventionerad +STR_2030_SERVICE_SUBSIDY_OFFERED :{BLACK}{BIGFONT}Ny subvention:{}{}Första {STRING}transporten från {STRING} till {STRING} får ett års subvention från kommunen! +STR_2031_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention tilldelad {STRING}!{}{}{STRING} från {STATION} till {STATION} ger 50% extra nästa år! +STR_2032_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention tilldelad {STRING}!{}{}{STRING} från {STATION} till {STATION} ger dubbelt så mycket nästa år! +STR_2033_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention tilldelad {STRING}!{}{}{STRING} från {STATION} till {STATION} ger tre gånger så mycket nästa år! +STR_2034_SERVICE_SUBSIDY_AWARDED :{BLACK}{BIGFONT}Subvention tilldelad {STRING}!{}{}{STRING} från {STATION} till {STATION} ger fyra gånger så mycket nästa år! +STR_2035_LOCAL_AUTHORITY_REFUSES :{WHITE}{TOWN} kommunen tillåter inte att en ny flygplats byggs i staden +STR_2036_COTTAGES :Stuga +STR_2037_HOUSES :Hus +STR_2038_FLATS :Lägenheter +STR_2039_TALL_OFFICE_BLOCK :Höga kontor +STR_203A_SHOPS_AND_OFFICES :Affärer och kontor +STR_203B_SHOPS_AND_OFFICES :Affärer och kontor +STR_203C_THEATER :Teater +STR_203D_STADIUM :Stadium +STR_203E_OFFICES :Kontor +STR_203F_HOUSES :Hus +STR_2040_CINEMA :Biograf +STR_2041_SHOPPING_MALL :Shoppingcentrum +STR_2042_DO_IT :{BLACK}Utför +STR_2043_LIST_OF_THINGS_TO_DO_AT :{BLACK}Lista av åtgärder att utföra i staden - klicka på en rad för ytterligare detaljer +STR_2044_CARRY_OUT_THE_HIGHLIGHTED :{BLACK}Utför markerad åtgärd i ovanstående lista +STR_2045_ACTIONS_AVAILABLE :{BLACK}Tillgängliga åtgärder: +STR_2046_SMALL_ADVERTISING_CAMPAIGN :Liten reklamkampanj +STR_2047_MEDIUM_ADVERTISING_CAMPAIGN :Mellanstor reklamkampanj +STR_2048_LARGE_ADVERTISING_CAMPAIGN :Stor reklamkampanj +STR_2049_FUND_LOCAL_ROAD_RECONSTRUCTION :Bekosta ombyggnation av vägar +STR_204A_BUILD_STATUE_OF_COMPANY :Bygg staty över företagets ägare +STR_204B_FUND_NEW_BUILDINGS :Bekosta nya byggnader +STR_204C_BUY_EXCLUSIVE_TRANSPORT :Köp exklusiva transporträttigheter +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY :Muta den lokala kommunen +STR_204D_INITIATE_A_SMALL_LOCAL :{WHITE}{STRING}{}{YELLOW} Starta en liten lokal reklamkampanj, för att attrahera fler passagerare och gods till dina tranporttjänster.{} Kostnad: {CURRENCY} +STR_204E_INITIATE_A_MEDIUM_LOCAL :{WHITE}{STRING}{}{YELLOW} Starta en mellanstor lokal reklamkampanj, för att attrahera fler passagerare och gods till dina tranporttjänster.{} Kostnad: {CURRENCY} +STR_204F_INITIATE_A_LARGE_LOCAL :{WHITE}{STRING}{}{YELLOW} Starta en stor lokal reklamkampanj, för att attrahera fler passagerare och gods till dina tranporttjänster.{} Kostnad: {CURRENCY} +STR_2050_FUND_THE_RECONSTRUCTION :{WHITE}{STRING}{}{YELLOW} Bekosta ombyggnad av stadens vägnätverk. Orsakar ansenlig splittring för vägtrafik upp till 6 månader.{} Kostnad: {CURRENCY} +STR_2051_BUILD_A_STATUE_IN_HONOR :{WHITE}{STRING}{}{YELLOW} Bygg en staty i ditt företags ära.{} Kostnad: {CURRENCY} +STR_2052_FUND_THE_CONSTRUCTION_OF :{WHITE}{STRING}{}{YELLOW} Bekosta uppbyggnad av nya kommersiella byggnader i staden.{} Kostnad: {CURRENCY} +STR_2053_BUY_1_YEAR_S_EXCLUSIVE :{WHITE}{STRING}{}{YELLOW} Köp 1 års exklusiv transporträttighet i staden. Stadens kommun kommer bara tillåta passagerare och gods till användning för ditt företags stationer.{} Kostnad: {CURRENCY} +STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC :{WHITE}{STRING}{}{YELLOW} Muta den lokala kommunen för att öka din värdering, på risken av att få höga böter om du blir upptäckt.{} Kostnad: {CURRENCY} +STR_2054_CAN_T_DO_THIS :{WHITE}Kan inte utföra detta... +STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING:{BIGFONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! +STR_2056 :{TINYFONT}{WHITE}{TOWN} +STR_2057 :{ORANGE}{TOWN}{BLACK} ({COMMA32}) +STR_2058_UNDER_CONSTRUCTION :{STRING} (under byggnation) +STR_2059_IGLOO :Igloo +STR_205A_TEPEES :Kåtor +STR_205B_TEAPOT_HOUSE :Tekanne-Hus +STR_205C_PIGGY_BANK :Spargris + +##id 0x2800 +STR_2800_PLANT_TREES :Plantera träd +STR_2801_PLACE_SIGN :Placera skylt +STR_2802_TREES :{WHITE}Träd +STR_2803_TREE_ALREADY_HERE :{WHITE}...träd redan här +STR_2804_SITE_UNSUITABLE :{WHITE}...plats olämplig +STR_2805_CAN_T_PLANT_TREE_HERE :{WHITE}Kan inte plantera träd här... +STR_2806 :{WHITE}{STRING} +STR_2807 :{TINYFONT}{WHITE}{STRING} +STR_2808_TOO_MANY_SIGNS :{WHITE}...för många skyltar +STR_2809_CAN_T_PLACE_SIGN_HERE :{WHITE}Kan inte placera skylt här... +STR_280A_SIGN :Skylt +STR_280B_EDIT_SIGN_TEXT :{WHITE}Ändra skylttext +STR_280C_CAN_T_CHANGE_SIGN_NAME :{WHITE}Kan inte ändra skyltnamn... +STR_280D_SELECT_TREE_TYPE_TO_PLANT :{BLACK}Välj trädtyp att plantera +STR_280E_TREES :Träd +STR_280F_RAINFOREST :Regnskog +STR_2810_CACTUS_PLANTS :Kaktusplantor + +##id 0x3000 +STR_3000_RAIL_STATION_SELECTION :{WHITE}Val av tågstation +STR_3001_AIRPORT_SELECTION :{WHITE}Val av flygplats +STR_3002_ORIENTATION :{BLACK}Riktning +STR_3003_NUMBER_OF_TRACKS :{BLACK}Antal spår +STR_3004_PLATFORM_LENGTH :{BLACK}Längd på plattform +STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD :{WHITE}För nära en annan järnvägsstation +STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Angränsar till mer än en station/hållplats +STR_3007_TOO_MANY_STATIONS_LOADING :{WHITE}För många stationer/hållplatser i staden +STR_3008_TOO_MANY_STATIONS_LOADING :{WHITE}För många stationer/hållplatser +STR_3009_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}För nära en annan stationer/hållplatser +STR_300A_0 :{WHITE}{STATION} {STRINL 0x30D1} +STR_300B_MUST_DEMOLISH_RAILROAD :{WHITE}Måste riva järnvägsstation först +STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}För nära en annan flygplats +STR_300E_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Måste riva flygplats först + +STR_3030_RENAME_STATION_LOADING :Byt namn på station +STR_3031_CAN_T_RENAME_STATION :{WHITE}Kan inte byta namn på station... +STR_3032_RATINGS :{BLACK}Värderingar +STR_3033_ACCEPTS :{BLACK}Accepterar +STR_3034_LOCAL_RATING_OF_TRANSPORT :{BLACK}Lokal värdering av transporttjänster: + +############ range for rating starts +STR_3035_APPALLING :Skrämmande +STR_3036_VERY_POOR :Väldigt dålig +STR_3037_POOR :Dålig +STR_3038_MEDIOCRE :Medelmåttig +STR_3039_GOOD :Bra +STR_303A_VERY_GOOD :Väldigt bra +STR_303B_EXCELLENT :Utmärkt +STR_303C_OUTSTANDING :Enastående +############ range for rating ends + +STR_303D :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA8}%) +STR_303E_NO_LONGER_ACCEPTS :{WHITE}{STATION} tar inte längre emot {STRING} +STR_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION} tar inte längre emot {STRING} och {STRING} +STR_3040_NOW_ACCEPTS :{WHITE}{STATION} tar nu emot {STRING} +STR_3041_NOW_ACCEPTS_AND :{WHITE}{STATION} tar nu emot {STRING} och {STRING} +STR_3042_BUS_STATION_ORIENTATION :{WHITE}Riktning för busshållplats +STR_3043_TRUCK_STATION_ORIENT :{WHITE}Riktning för lastbilsbrygga +STR_3044_TOO_CLOSE_TO_ANOTHER_BUS :{WHITE}För nära en annan busshållplats +STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK :{WHITE}För nära en annan lastbilsbrygga +STR_3046_MUST_DEMOLISH_BUS_STATION :{WHITE}Måste riva busshållplats först +STR_3047_MUST_DEMOLISH_TRUCK_STATION :{WHITE}Måste riva lastbilsbrygga först +STR_3048_STATIONS :{WHITE}{STRING} - {COMMA16} Stationer +STR_3049_0 :{YELLOW}{STATION} {STRINL 0x30D1} +STR_304A_NONE :{YELLOW}- Inga - +STR_304B_SITE_UNSUITABLE :{WHITE}...plats olämplig +STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}För nära en annan hamn +STR_304D_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Måste riva hamn först +STR_304E_SELECT_RAILROAD_STATION :{BLACK}Välj riktning för järnvägsstation +STR_304F_SELECT_NUMBER_OF_PLATFORMS :{BLACK}Välj antal plattformar för järnvägsstation +STR_3050_SELECT_LENGTH_OF_RAILROAD :{BLACK}Välj längden på järnvägsstation +STR_3051_SELECT_BUS_STATION_ORIENTATION :{BLACK}Välj riktning för busshållplats +STR_3052_SELECT_TRUCK_LOADING_BAY :{BLACK}Välj riktning för lastbilsbrygga +STR_3053_CENTER_MAIN_VIEW_ON_STATION :{BLACK}Centrera vyn på stationen +STR_3054_SHOW_STATION_RATINGS :{BLACK}Visa stationens klassificering +STR_3055_CHANGE_NAME_OF_STATION :{BLACK}Byt namn på stationen +STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO :{BLACK}Visa lista av accepterat gods +STR_3057_STATION_NAMES_CLICK_ON :{BLACK}Stationsnamn - klicka på ett namn för att centrera vyn på stationen +STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT :{BLACK}Välj storlek/typ av flygplats +STR_3059_SMALL :{BLACK}Liten +STR_305A_LARGE :{BLACK}Stor +STR_305AA_LARGE :{BLACK}Metropolisk flygplats +STR_305AB_LARGE :{BLACK}IInternationell flygplats +STR_305B_SIZE :{BLACK}Storlek +STR_305C_0 :{STATION} {STRINL 0x30D1} +STR_305D_0 :{TINYFONT}{BLACK}{STATION} {STRINL 0x30D1} +STR_305E_RAILROAD_STATION :Järnvägsstation +STR_305F_AIRCRAFT_HANGAR :Flygplanshangar +STR_3060_AIRPORT :Flygplats +STR_3061_TRUCK_LOADING_AREA :Lastbrygga +STR_3062_BUS_STATION :Busshållplats +STR_3063_SHIP_DOCK :Hamn +STR_3064_HIGHLIGHT_COVERAGE_AREA :{BLACK}Markera täckande yta för stationen +STR_3065_DON_T_HIGHLIGHT_COVERAGE :{BLACK}Markera inte täckande yta för stationen +STR_3066_COVERAGE_AREA_HIGHLIGHT :{BLACK}Markera täckande yta +STR_3067_MONORAIL_STATION_SELECT :{WHITE}Välj monorail-station +STR_3068_DOCK :{WHITE}Hamn +STR_3069_BUOY :Boj +STR_306A_BUOY_IN_THE_WAY :{WHITE}...boj i vägen +STR_306B_HELIPORT :{BLACK}Helikopterplats +STR_306C_STATION_TOO_SPREAD_OUT :{WHITE}...station för utspridd + +##id 0x3800 +STR_3800_SHIP_DEPOT_ORIENTATION :{WHITE}Skeppsdepå riktning +STR_3801_MUST_BE_BUILT_ON_WATER :{WHITE}...måste byggas på vatten +STR_3802_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Kan inte bygga skeppsdepå här... +STR_3803_SELECT_SHIP_DEPOT_ORIENTATION :{BLACK}Välj skeppsdepå riktning +STR_3804_WATER :Vatten +STR_3805_COAST_OR_RIVERBANK :Kust eller flodbank +STR_3806_SHIP_DEPOT :skeppsdepå +STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Kan inte bygga på vatten + +##id 0x4000 +STR_4000_SAVE_GAME :{WHITE}Spara spel +STR_4001_LOAD_GAME :{WHITE}Öppna spel +STR_4002_SAVE :{BLACK}Spara +STR_4003_DELETE :{BLACK}Ta bort +STR_4004 :{STRING}, {DATE_LONG} +STR_4005_BYTES_FREE :{BLACK}{COMMA32} megabytes ledigt +STR_4006_UNABLE_TO_READ_DRIVE :{BLACK}Kan inte läsa från disk +STR_4007_GAME_SAVE_FAILED :{WHITE}Sparningen av spelet misslyckades +STR_4008_UNABLE_TO_DELETE_FILE :{WHITE}Kan inte ta bort filen +STR_4009_GAME_LOAD_FAILED :{WHITE}Läsningen av spelet misslyckades +STR_400A_LIST_OF_DRIVES_DIRECTORIES :{BLACK}Listar enheter, kataloger och sparade spel +STR_400B_CURRENTLY_SELECTED_NAME :{BLACK}Valt namn för spelet +STR_400C_DELETE_THE_CURRENTLY_SELECTED :{BLACK}Ta bort markerat sparat spel +STR_400D_SAVE_THE_CURRENT_GAME_USING :{BLACK}Spara spelet med valt namn +STR_400E_SELECT_NEW_GAME_TYPE :{WHITE}Välj typ av nytt spel +STR_400F_SELECT_SCENARIO_GREEN_PRE :{BLACK}Välj scenario (green), förbestämt spel (blue), eller slumpmässigt nytt spel +STR_4010_GENERATE_RANDOM_NEW_GAME :Skapa slumpmässigt nytt spel + +##id 0x4800 +STR_4800_IN_THE_WAY :{WHITE}{STRING} i vägen +STR_4801 :{WHITE}{TOWN} {STRING} +STR_4802_COAL_MINE :Kolgruva +STR_4803_POWER_STATION :Kraftstation +STR_4804_SAWMILL :Sågverk +STR_4805_FOREST :Skog +STR_4806_OIL_REFINERY :Oljeraffinaderi +STR_4807_OIL_RIG :Oljerigg +STR_4808_FACTORY :Fabrik +STR_4809_PRINTING_WORKS :Tryckeri +STR_480A_STEEL_MILL :Stålverk +STR_480B_FARM :Bondgård +STR_480C_COPPER_ORE_MINE :Koppargruva +STR_480D_OIL_WELLS :Oljekälla +STR_480E_BANK :Bank +STR_480F_FOOD_PROCESSING_PLANT :Livsmedelsfabrik +STR_4810_PAPER_MILL :Pappersbruk +STR_4811_GOLD_MINE :Guldgruva +STR_4812_BANK :Bank +STR_4813_DIAMOND_MINE :Diamantgruva +STR_4814_IRON_ORE_MINE :Järnmalmsgruva +STR_4815_FRUIT_PLANTATION :Fruktplantage +STR_4816_RUBBER_PLANTATION :Gummiplantage +STR_4817_WATER_SUPPLY :Vattentillgång +STR_4818_WATER_TOWER :Vattentorn +STR_4819_FACTORY :Fabrik +STR_481A_FARM :Bondgård +STR_481B_LUMBER_MILL :Sågverk +STR_481C_COTTON_CANDY_FOREST :Spunnet socker-skog +STR_481D_CANDY_FACTORY :Godisfabrik +STR_481E_BATTERY_FARM :Batteribondgård +STR_481F_COLA_WELLS :Kolakälla +STR_4820_TOY_SHOP :Leksaksaffär +STR_4821_TOY_FACTORY :Leksaksfabrik +STR_4822_PLASTIC_FOUNTAINS :Plastfontäner +STR_4823_FIZZY_DRINK_FACTORY :Läskfabrik +STR_4824_BUBBLE_GENERATOR :Bubbelgenerator +STR_4825_TOFFEE_QUARRY :Knäckbrott +STR_4826_SUGAR_MINE :Sockergruva + +############ range for requires starts +STR_4827_REQUIRES :{BLACK}Kräver: {YELLOW}{STRING} +STR_4828_REQUIRES :{BLACK}Kräver: {YELLOW}{STRING}, {STRING} +STR_4829_REQUIRES :{BLACK}Kräver: {YELLOW}{STRING}, {STRING}, {STRING} +############ range for requires ends + +STR_482A_PRODUCTION_LAST_MONTH :{BLACK}Produktion förra månaden: +STR_482B_TRANSPORTED :{YELLOW}{STRING}{BLACK} ({COMMA16}% transporterat) +STR_482C_CENTER_THE_MAIN_VIEW_ON :{BLACK}Centrera vyn ovanför industrin +STR_482D_NEW_UNDER_CONSTRUCTION :{BLACK}{BIGFONT}Ny {STRING} under byggnation nära {TOWN}! +STR_482E_NEW_BEING_PLANTED_NEAR :{BLACK}{BIGFONT}Ny {STRING} planteras nära {TOWN}! +STR_482F_COST :{BLACK}Kostnad: {YELLOW}{CURRENCY} +STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Kan inte bygga denna typ av industri här... +STR_4831_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}...skog kan bara planteras ovanför snölinjen +STR_4832_ANNOUNCES_IMMINENT_CLOSURE :{BLACK}{BIGFONT}{TOWN} {STRING} meddelar att de stänger ner snarast! +STR_4833_SUPPLY_PROBLEMS_CAUSE_TO :{BLACK}{BIGFONT}Leveransproblem får {TOWN} {STRING} att meddela att de stänger ner snarast! +STR_4834_LACK_OF_NEARBY_TREES_CAUSES :{BLACK}{BIGFONT}Avsaknad av träd får {TOWN} {STRING} att meddela att de stänger ner snarast! +STR_4835_INCREASES_PRODUCTION :{BLACK}{BIGFONT}{TOWN} {STRING} ökar produktionen! +STR_4836_NEW_COAL_SEAM_FOUND_AT :{BLACK}{BIGFONT}Nytt lager av kol funnet vid {TOWN} {STRING}!{}Produktionen fördubblas! +STR_4837_NEW_OIL_RESERVES_FOUND :{BLACK}{BIGFONT}Nya oljereserver funna vid {TOWN} {STRING}!{}Produktionen fördubblas! +STR_4838_IMPROVED_FARMING_METHODS :{BLACK}{BIGFONT}Nya jordbruksmetoder vid {TOWN} {STRING} ger fördubblad produktion! +STR_4839_PRODUCTION_DOWN_BY_50 :{BLACK}{BIGFONT}Produktionen vid {TOWN} {STRING} går ned med 50% +STR_483A_INSECT_INFESTATION_CAUSES :{BLACK}{BIGFONT}Problem med insekter orsakar kris vid {TOWN} {STRING}!{}Produktionen ned med 50% +STR_483B_CAN_ONLY_BE_POSITIONED :{WHITE}...kan bara placeras nära kartans kant +STR_INDUSTRY_PROD_GOUP :{BLACK}{BIGFONT}{STRING} produktionen vid {TOWN} {STRING} upp med {COMMA16}%! +STR_INDUSTRY_PROD_GODOWN :{BLACK}{BIGFONT}{STRING} produktionen vid {TOWN} {STRING} ner med {COMMA16}%! + +##id 0x5000 +STR_5000_TRAIN_IN_TUNNEL :{WHITE}Tåg i tunnel +STR_5001_ROAD_VEHICLE_IN_TUNNEL :{WHITE}Vägfordon i tunnel +STR_5002 : +STR_5003_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}En annan tunnel i vägen +STR_5004 : +STR_5005_UNABLE_TO_EXCAVATE_LAND :{WHITE}Kan inte gräva till marken på andra sidan av tunneln +STR_5006_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Måste riva tunnel först +STR_5007_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Måste riva bro först +STR_5008_CANNOT_START_AND_END_ON :{WHITE}Kan inte börja och sluta på samma plats +STR_5009_LEVEL_LAND_OR_WATER_REQUIRED :{WHITE}Platt land eller vatten krävs under bro +STR_500A_START_AND_END_MUST_BE_IN :{WHITE}Start- och slutpunkt måste ligga i linje +STR_500B_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Platsen passar inte för tunnelentré +STR_500C : +STR_500D :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY} +STR_500E_SUSPENSION_STEEL :Upphängd, Stål +STR_500F_GIRDER_STEEL :Balkbro, Stål +STR_5010_CANTILEVER_STEEL :Cantilever, Stål +STR_5011_SUSPENSION_CONCRETE :Upphängd, Betong +STR_5012_WOODEN :Trä +STR_5013_CONCRETE :Betong +STR_5014_TUBULAR_STEEL :Rör, Stål +STR_BRIDGE_TUBULAR_SILICON :Rör, Silikon +STR_5015_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Kan inte bygga bro här... +STR_5016_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan inte bygga tunnel här... +STR_5017_RAILROAD_TUNNEL :Järnvägstunnel +STR_5018_ROAD_TUNNEL :Vägtunnel +STR_5019 : +STR_501A : +STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE :Upphängd järnvägsbro av stål +STR_501C_STEEL_GIRDER_RAIL_BRIDGE :Järnvägsbro med stålbalkar +STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE :Järnvägsbro med utskjutande stålstöd +STR_501E_REINFORCED_CONCRETE_SUSPENSION :Järnvägsbro med förstärkt betongupphängning +STR_501F_WOODEN_RAIL_BRIDGE :Järnvägsbro av trä +STR_5020_CONCRETE_RAIL_BRIDGE :Järnvägsbro av betong +STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE :Vägbro med betongupphängning +STR_5022_STEEL_GIRDER_ROAD_BRIDGE :Vägbro med stålbalkar +STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE :Vägbro med utskjutande stålstöd +STR_5024_REINFORCED_CONCRETE_SUSPENSION :Vägbro med förstärkt betongupphängning +STR_5025_WOODEN_ROAD_BRIDGE :Vägbro av trä +STR_5026_CONCRETE_ROAD_BRIDGE :Vägbro av betong +STR_5027_TUBULAR_RAIL_BRIDGE :Järnvägsrörbro +STR_5028_TUBULAR_ROAD_BRIDGE :Vägrörbro +STR_5029_STEEL :Stål + +##id 0x5800 +STR_5800_OBJECT_IN_THE_WAY :{WHITE}Objekt i vägen +STR_5801_TRANSMITTER :Radiosändare +STR_5802_LIGHTHOUSE :Fyrtorn +STR_5803_COMPANY_HEADQUARTERS :Företags högkvarter +STR_5804_COMPANY_HEADQUARTERS_IN :{WHITE}...företags högkvarter i vägen +STR_5805_COMPANY_OWNED_LAND :Mark som ägs av företag +STR_5806_CAN_T_PURCHASE_THIS_LAND :{WHITE}Kan inte köpa denna mark... +STR_5807_YOU_ALREADY_OWN_IT :{WHITE}...du äger den redan! + + +############ WARNING, using range 0x6000 for strings that are stored in the savegame +############ These strings may never get a new id, or savegames will break! +##id 0x6000 +STR_SV_EMPTY : +STR_SV_UNNAMED :Inget namn{SKIP} +STR_SV_TRAIN_NAME :Tåg {COMMA16} +STR_SV_ROADVEH_NAME :Vägfordon {COMMA16} +STR_SV_SHIP_NAME :Skepp {COMMA16} +STR_SV_AIRCRAFT_NAME :Flygplan {COMMA16} + +STR_SV_STNAME :{STRING} +STR_SV_STNAME_NORTH :{STRING} norr +STR_SV_STNAME_SOUTH :{STRING} söder +STR_SV_STNAME_EAST :{STRING} öster +STR_SV_STNAME_WEST :{STRING} väster +STR_SV_STNAME_CENTRAL :{STRING} central +STR_SV_STNAME_TRANSFER :{STRING} transfer +STR_SV_STNAME_HALT :{STRING} stopp +STR_SV_STNAME_VALLEY :{STRING} dalgång +STR_SV_STNAME_HEIGHTS :{STRING} höjder +STR_SV_STNAME_WOODS :{STRING} skogar +STR_SV_STNAME_LAKESIDE :{STRING} sjö +STR_SV_STNAME_EXCHANGE :{STRING} växel +STR_SV_STNAME_AIRPORT :{STRING} flygplats +STR_SV_STNAME_OILFIELD :{STRING} oljefält +STR_SV_STNAME_MINES :{STRING} gruva +STR_SV_STNAME_DOCKS :{STRING} hamnar +STR_SV_STNAME_BUOY_1 :{STRING} boj 1 +STR_SV_STNAME_BUOY_2 :{STRING} boj 2 +STR_SV_STNAME_BUOY_3 :{STRING} boj 3 +STR_SV_STNAME_BUOY_4 :{STRING} boj 4 +STR_SV_STNAME_BUOY_5 :{STRING} boj 5 +STR_SV_STNAME_BUOY_6 :{STRING} boj 6 +STR_SV_STNAME_BUOY_7 :{STRING} boj 7 +STR_SV_STNAME_BUOY_8 :{STRING} boj 8 +STR_SV_STNAME_BUOY_9 :{STRING} boj 9 +STR_SV_STNAME_ANNEXE :{STRING} annex +STR_SV_STNAME_SIDINGS :{STRING} sida +STR_SV_STNAME_BRANCH :{STRING} område +STR_SV_STNAME_UPPER :Övre {STRING} +STR_SV_STNAME_LOWER :Nedre {STRING} +STR_SV_STNAME_HELIPORT :{STRING} Helikopterplats +STR_SV_STNAME_FOREST :{STRING} Skog + +############ end of savegame specific region! + +##id 0x6800 +STR_6800_DIFFICULTY_LEVEL :{WHITE}Svårighetsgrad + +############ range for difficulty levels starts +STR_6801_EASY :{BLACK}Lätt +STR_6802_MEDIUM :{BLACK}Mellan +STR_6803_HARD :{BLACK}Svår +STR_6804_CUSTOM :{BLACK}Valfri +############ range for difficulty levels ends + +############ range for difficulty settings starts +STR_6805_MAXIMUM_NO_COMPETITORS :{LTBLUE}Max antal motståndare: {ORANGE}{COMMA16} +STR_6806_COMPETITOR_START_TIME :{LTBLUE}Startpunkt för motståndare: {ORANGE}{STRING} +STR_6807_NO_OF_TOWNS :{LTBLUE}Antal städer: {ORANGE}{STRING} +STR_6808_NO_OF_INDUSTRIES :{LTBLUE}Antal industrier: {ORANGE}{STRING} +STR_6809_MAXIMUM_INITIAL_LOAN_000 :{LTBLUE}Maxstorlek på lån: {ORANGE}{CURRENCY} +STR_680A_INITIAL_INTEREST_RATE :{LTBLUE}Initial ränta: {ORANGE}{COMMA16}% +STR_680B_VEHICLE_RUNNING_COSTS :{LTBLUE}Löpande kostnader för fordon: {ORANGE}{STRING} +STR_680C_CONSTRUCTION_SPEED_OF_COMPETITOR:{LTBLUE}Bygghastighet för motståndare: {ORANGE}{STRING} +STR_680D_INTELLIGENCE_OF_COMPETITORS :{LTBLUE}Intelligens hos motståndare: {ORANGE}{STRING} +STR_680E_VEHICLE_BREAKDOWNS :{LTBLUE}Motorstopp för fordon: {ORANGE}{STRING} +STR_680F_SUBSIDY_MULTIPLIER :{LTBLUE}Subventionsmultiplikator: {ORANGE}{STRING} +STR_6810_COST_OF_CONSTRUCTION :{LTBLUE}Kostnad för byggnation: {ORANGE}{STRING} +STR_6811_TERRAIN_TYPE :{LTBLUE}Typ av terräng: {ORANGE}{STRING} +STR_6812_QUANTITY_OF_SEA_LAKES :{LTBLUE}Mängd sjöar/hav: {ORANGE}{STRING} +STR_6813_ECONOMY :{LTBLUE}Ekonomi: {ORANGE}{STRING} +STR_6814_TRAIN_REVERSING :{LTBLUE}Tåg kan vända: {ORANGE}{STRING} +STR_6815_DISASTERS :{LTBLUE}Katastrofer: {ORANGE}{STRING} +############ range for difficulty settings ends + +STR_6816_LOW :Låg +STR_6817_NORMAL :Normal +STR_6818_HIGH :Hög +STR_6819 :{BLACK}< +STR_681A :{BLACK}> +STR_681B_VERY_SLOW :Väldigt långsam +STR_681C_SLOW :Långsam +STR_681D_MEDIUM :Mellan +STR_681E_FAST :Snabb +STR_681F_VERY_FAST :Väldigt snabb +STR_VERY_LOW :Väldigt låg +STR_6820_LOW :Låg +STR_6821_MEDIUM :Mellan +STR_6822_HIGH :Hög +STR_6823_NONE :Ingen +STR_6824_REDUCED :Reducerad +STR_6825_NORMAL :Normal +STR_6826_X1_5 :x1.5 +STR_6827_X2 :x2 +STR_6828_X3 :x3 +STR_6829_X4 :x4 +STR_682A_VERY_FLAT :Väldigt platt +STR_682B_FLAT :Platt +STR_682C_HILLY :Kullig +STR_682D_MOUNTAINOUS :Bergig +STR_682E_STEADY :Stabil +STR_682F_FLUCTUATING :Fluktuerande +STR_6830_IMMEDIATE :Omedelbart +STR_6831_3_MONTHS_AFTER_PLAYER :3 månader efter spelaren +STR_6832_6_MONTHS_AFTER_PLAYER :6 månader efter spelaren +STR_6833_9_MONTHS_AFTER_PLAYER :9 månader efter spelaren +STR_6834_AT_END_OF_LINE_AND_AT_STATIONS :Vid slut på linjen, vid stationer +STR_6835_AT_END_OF_LINE_ONLY :Enbart vid slut på linjen +STR_6836_OFF :Av +STR_6837_ON :På +STR_6838_SHOW_HI_SCORE_CHART :{BLACK}Visa highscore-lista + +##id 0x7000 +STR_7000 : +STR_7001 :{WHITE}{STRING}{BLACK}{STRING} +STR_7002_PLAYER_1 : (Spelare 1) +STR_7003_PLAYER_2 : (Spelare 2) +STR_7004_NEW_FACE :{BLACK}Nytt ansikte +STR_7005_COLOR_SCHEME :{BLACK}Färgval +STR_7006_COLOR_SCHEME :{GOLD}Färgval: +STR_7007_NEW_COLOR_SCHEME :{WHITE}Nytt färgval +STR_7008_COMPANY_NAME :{BLACK}Företagsnamn +STR_7009_PRESIDENT_NAME :{BLACK}Namn på VD +STR_700A_COMPANY_NAME :Företagsnamn +STR_700B_PRESIDENT_S_NAME :Namn på VD +STR_700C_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Kan inte ändra företagsnamn... +STR_700D_CAN_T_CHANGE_PRESIDENT :{WHITE}Kan inte ändra namnet på VD:n... +STR_700E_FINANCES :{WHITE}{STRING} Budget{BLACK}{STRING} +STR_700F_EXPENDITURE_INCOME :{WHITE}Utgifter/inkomster +STR_7010 :{WHITE}{NUMU16} +STR_7011_CONSTRUCTION :{GOLD}Konstruktioner +STR_7012_NEW_VEHICLES :{GOLD}Nya fordon +STR_7013_TRAIN_RUNNING_COSTS :{GOLD}Kostnad för tåg +STR_7014_ROAD_VEH_RUNNING_COSTS :{GOLD}Kostnad för vägfordon +STR_7015_AIRCRAFT_RUNNING_COSTS :{GOLD}Kostnad för flygplan +STR_7016_SHIP_RUNNING_COSTS :{GOLD}Kostnad för skepp +STR_7017_PROPERTY_MAINTENANCE :{GOLD}Underhåll av egendomar +STR_7018_TRAIN_INCOME :{GOLD}Inkomst från tåg +STR_7019_ROAD_VEHICLES_INCOME :{GOLD}Inkomst från vägfordon +STR_701A_AIRCRAFT_INCOME :{GOLD}Inkomst från flygplan +STR_701B_SHIP_INCOME :{GOLD}Inkomst från skepp +STR_701C_LOAN_INTEREST :{GOLD}Ränta på lån +STR_701D_OTHER :{GOLD}Övrigt +STR_701E :{BLACK}-{CURRENCY64} +STR_701F :{BLACK}+{CURRENCY64} +STR_7020_TOTAL :{WHITE}Totalt: +STR_7021 :{STRING}{STRING} +STR_7022_INCOME_GRAPH :{WHITE}Graf över inkomster +STR_7023 :{CURRCOMPACT} +STR_7024 :{COMMA32} +STR_7025_OPERATING_PROFIT_GRAPH :{WHITE}Graf över vinst +STR_7026_BANK_BALANCE :{WHITE}Banksaldo +STR_7027_LOAN :{WHITE}Lån +STR_7028 :{BLACK}{CURRENCY64} +STR_7029_BORROW :{BLACK}Låna {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702A_REPAY :{BLACK}Återbetala {SKIP}{SKIP}{SKIP}{CURRENCY} +STR_702B_MAXIMUM_PERMITTED_LOAN :{WHITE}...maximal storlek på lånet är {CURRENCY} +STR_702C_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Kan inte låna mer pengar... +STR_702D_LOAN_ALREADY_REPAYED :{WHITE}...lånet redan återbetalt +STR_702E_REQUIRED :{WHITE}...{CURRENCY} krävs +STR_702F_CAN_T_REPAY_LOAN :{WHITE}Kan inte återbetala lånet... +STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT :{BLACK}Välj nytt ansikte på VD:n +STR_7031_CHANGE_THE_COMPANY_VEHICLE :{BLACK}Byt färg på företaget +STR_7032_CHANGE_THE_PRESIDENT_S :{BLACK}Byt VD:ns namn +STR_7033_CHANGE_THE_COMPANY_NAME :{BLACK}Byt företagets namn +STR_7034_CLICK_ON_SELECTED_NEW_COLOR :{BLACK}Fälj ny färg +STR_7035_INCREASE_SIZE_OF_LOAN :{BLACK}Öka lånets storlek +STR_7036_REPAY_PART_OF_LOAN :{BLACK}Återbetala en del av lånet +STR_7037_PRESIDENT :{WHITE}{STRING}{}{GOLD}(President) +STR_7038_INAUGURATED :{GOLD}Började: {WHITE}{NUMU16} +STR_7039_VEHICLES :{GOLD}Fordon: +STR_703A_TRAIN :{WHITE}{COMMA16} tåg +STR_703B_TRAINS :{WHITE}{COMMA16} tåg +STR_703C_ROAD_VEHICLE :{WHITE}{COMMA16} vägfordon +STR_703D_ROAD_VEHICLES :{WHITE}{COMMA16} vägfordon +STR_703E_AIRCRAFT :{WHITE}{COMMA16} flygplan +STR_703F_AIRCRAFT :{WHITE}{COMMA16} flygplan +STR_7040_SHIP :{WHITE}{COMMA16} skepp +STR_7041_SHIPS :{WHITE}{COMMA16} skepp +STR_7042_NONE :{WHITE}Inga +STR_7043_FACE_SELECTION :{WHITE}Välj ansikte +STR_7044_MALE :{BLACK}Man +STR_7045_FEMALE :{BLACK}Kvinna +STR_7046_NEW_FACE :{BLACK}Nytt ansikte +STR_7047_CANCEL_NEW_FACE_SELECTION :{BLACK}Avbryt val av ansikte +STR_7048_ACCEPT_NEW_FACE_SELECTION :{BLACK}Acceptera nytt ansikte +STR_7049_SELECT_MALE_FACES :{BLACK}Välj manliga ansikten +STR_704A_SELECT_FEMALE_FACES :{BLACK}Välj kvinnliga ansikten +STR_704B_GENERATE_RANDOM_NEW_FACE :{BLACK}Slumpa fram nytt ansikte +STR_704C_KEY :{BLACK}Nyckel +STR_704D_SHOW_KEY_TO_GRAPHS :{BLACK}Visa nyckel till grafer +STR_704E_KEY_TO_COMPANY_GRAPHS :{WHITE}Nyckel till företagsgrafer +STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY :{BLACK}Klicka här för att visa/dölja företaget i grafen +STR_7050_UNITS_OF_CARGO_DELIVERED :{WHITE}Enheter levererat gods +STR_7051_COMPANY_PERFORMANCE_RATINGS :{WHITE}Företagets prestationsvärderingar (maxvärdering=1000) +STR_7052_COMPANY_VALUES :{WHITE}Företagsvärde +STR_7053_COMPANY_LEAGUE_TABLE :{WHITE}Företagstabell +STR_7054 :{WHITE}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7055 :{YELLOW}{STRING}{SETX 45}{ORANGE}{STRING} {BLACK}{STRING} '{STRING}' +STR_7056_TRANSPORT_COMPANY_IN_TROUBLE :{BLACK}{BIGFONT}Transportföretag har problem! +STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED :{BLACK}{BIGFONT}{STRING} kommer att säljas eller gå bankrutt om det inte går bättre snart! +STR_7058_PRESIDENT :{BLACK}{STRING}{}(President) +STR_7059_TRANSPORT_COMPANY_MERGER :{BLACK}{BIGFONT}Transportföretag slås ihop! +STR_705A_HAS_BEEN_SOLD_TO_FOR :{BLACK}{BIGFONT}{STRING} har sålts till {STRING} för {CURRENCY}! +STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT :{WHITE}Vi letar efter någon som vill köpa och ta över vårt företag{}{}Vill du köpa {STRING} för {CURRENCY}? +STR_705C_BANKRUPT :{BLACK}{BIGFONT}Bankrutt! +STR_705D_HAS_BEEN_CLOSED_DOWN_BY :{BLACK}{BIGFONT}{STRING} has been closed ned med creditors and all assets sold off! +STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED :{BLACK}{BIGFONT}Nytt transportföretag startat! +STR_705F_STARTS_CONSTRUCTION_NEAR :{BLACK}{BIGFONT}{STRING} börjar bygga nära {TOWN}! +STR_7060_CAN_T_BUY_COMPANY :{WHITE}Kan inte köpa företag... +STR_7061_CARGO_PAYMENT_RATES :{WHITE}Fraktförtjänster +STR_7062_DAYS_IN_TRANSIT :{BLACK}{TINYFONT}Dagar i transit +STR_7063_PAYMENT_FOR_DELIVERING :{BLACK}{TINYFONT}Betalning för leverans 10 enheter (eller 10,000 liter) gods ett avstånd på 20 rutor +STR_7064_TOGGLE_GRAPH_FOR_CARGO :{BLACK}Växla graf för godstyp av/på +STR_7065 :{BLACK}{TINYFONT}{STRING} +STR_7066_ENGINEER :Ingenjör +STR_7067_TRAFFIC_MANAGER :Trafikledare +STR_7068_TRANSPORT_COORDINATOR :Transportkoordinator +STR_7069_ROUTE_SUPERVISOR :Ruttkontrollant +STR_706A_DIRECTOR :Direktör +STR_706B_CHIEF_EXECUTIVE :Versktällande chef +STR_706C_CHAIRMAN :Ordförande +STR_706D_PRESIDENT :President +STR_706E_TYCOON :Tycoon +STR_706F_BUILD_HQ :{BLACK}Bygg Högkvarter +STR_7070_BUILD_COMPANY_HEADQUARTERS :{BLACK}Bygg högkvarter / visa företagets högkvarter +STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS:{WHITE}Kan inte bygga högkvarter... +STR_7072_VIEW_HQ :{BLACK}Visa högkvarter +STR_7073_WORLD_RECESSION_FINANCIAL :{BIGFONT}{BLACK}Lågkonjuktur!{}{}Finansexperter befarar det värsta när ekonomin sjunker! +STR_7074_RECESSION_OVER_UPTURN_IN :{BIGFONT}{BLACK}Lågkonjuktur Över!{}{}Uppsving i byteshandeln ger tillförsikt till industrier när ekonomin stärks! +STR_7075_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Växla stor/liten fönsterstorlek +STR_7076_COMPANY_VALUE :{GOLD}Företagets värde: {WHITE}{CURRENCY} +STR_7077_BUY_25_SHARE_IN_COMPANY :{BLACK}Köp 25% andel i företag +STR_7078_SELL_25_SHARE_IN_COMPANY :{BLACK}Sälj 25% andel i företag +STR_7079_BUY_25_SHARE_IN_THIS_COMPANY :{BLACK}Köp 25% andel i detta företag +STR_707A_SELL_25_SHARE_IN_THIS_COMPANY :{BLACK}Sälj 25% andel i detta företag +STR_707B_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Kan inte köpa 25% andel i detta företag... +STR_707C_CAN_T_SELL_25_SHARE_IN :{WHITE}Kan inte sälja 25% andel i detta företag... +STR_707D_OWNED_BY :{WHITE}({COMMA16}% ägd av {STRING}) +STR_707E_OWNED_BY_OWNED_BY :{WHITE}({COMMA16}% ägd av {STRING}{} {COMMA16}% ägd av {STRING}) +STR_707F_HAS_BEEN_TAKEN_OVER_BY :{BLACK}{BIGFONT}{STRING} har tagits över av {STRING}! + +##id 0x8000 +STR_8000_KIRBY_PAUL_TANK_STEAM :Kirby Paul Tank (Ånga) +STR_8001_MJS_250_DIESEL :MJS 250 (Diesel) +STR_8002_PLODDYPHUT_CHOO_CHOO :Ploddyphut Choo-Choo +STR_8003_POWERNAUT_CHOO_CHOO :Powernaut Choo-Choo +STR_8004_MIGHTYMOVER_CHOO_CHOO :Mightymover Choo-Choo +STR_8005_PLODDYPHUT_DIESEL :Ploddyphut Diesel +STR_8006_POWERNAUT_DIESEL :Powernaut Diesel +STR_8007_WILLS_2_8_0_STEAM :Wills 2-8-0 (Ånga) +STR_8008_CHANEY_JUBILEE_STEAM :Chaney 'Jubilee' (Ånga) +STR_8009_GINZU_A4_STEAM :Ginzu 'A4' (Ånga) +STR_800A_SH_8P_STEAM :SH '8P' (Ånga) +STR_800B_MANLEY_MOREL_DMU_DIESEL :Manley-Morel DMU (Diesel) +STR_800C_DASH_DIESEL :'Dash' (Diesel) +STR_800D_SH_HENDRY_25_DIESEL :SH/Hendry '25' (Diesel) +STR_800E_UU_37_DIESEL :UU '37' (Diesel) +STR_800F_FLOSS_47_DIESEL :Floss '47' (Diesel) +STR_8010_CS_4000_DIESEL :CS 4000 (Diesel) +STR_8011_CS_2400_DIESEL :CS 2400 (Diesel) +STR_8012_CENTENNIAL_DIESEL :Centennial (Diesel) +STR_8013_KELLING_3100_DIESEL :Kelling 3100 (Diesel) +STR_8014_TURNER_TURBO_DIESEL :Turner Turbo (Diesel) +STR_8015_MJS_1000_DIESEL :MJS 1000 (Diesel) +STR_8016_SH_125_DIESEL :SH '125' (Diesel) +STR_8017_SH_30_ELECTRIC :SH '30' (Elektricitet) +STR_8018_SH_40_ELECTRIC :SH '40' (Elektricitet) +STR_8019_T_I_M_ELECTRIC :'T.I.M.' (Elektricitet) +STR_801A_ASIASTAR_ELECTRIC :'AsiaStar' (Elektricitet) +STR_801B_PASSENGER_CAR :Passagerarvagn +STR_801C_MAIL_VAN :Postvagn +STR_801D_COAL_CAR :Kolvagn +STR_801E_OIL_TANKER :Oljetank +STR_801F_LIVESTOCK_VAN :Boskapsvagn +STR_8020_GOODS_VAN :Godsvagn +STR_8021_GRAIN_HOPPER :Spannmålsvagn +STR_8022_WOOD_TRUCK :Timmervagn +STR_8023_IRON_ORE_HOPPER :Järnmalmsvagn +STR_8024_STEEL_TRUCK :Stålvagn +STR_8025_ARMORED_VAN :Bepansrad vagn +STR_8026_FOOD_VAN :Matvagn +STR_8027_PAPER_TRUCK :Pappersvagn +STR_8028_COPPER_ORE_HOPPER :Kopparmalmsvagn +STR_8029_WATER_TANKER :Vattentank +STR_802A_FRUIT_TRUCK :Fruktvagn +STR_802B_RUBBER_TRUCK :Gummivagn +STR_802C_SUGAR_TRUCK :Sockervagn +STR_802D_COTTON_CANDY_HOPPER :Spunnet Sockervagn +STR_802E_TOFFEE_HOPPER :Knäckvagn +STR_802F_BUBBLE_VAN :Bubbelvagn +STR_8030_COLA_TANKER :Kolatank +STR_8031_CANDY_VAN :Godisvagn +STR_8032_TOY_VAN :Leksaksvagn +STR_8033_BATTERY_TRUCK :Batterivagn +STR_8034_FIZZY_DRINK_TRUCK :Läskvagn +STR_8035_PLASTIC_TRUCK :Plastvagn +STR_8036_X2001_ELECTRIC :'X2001' (Elektricitet) +STR_8037_MILLENNIUM_Z1_ELECTRIC :'Millennium Z1' (Elektricitet) +STR_8038_WIZZOWOW_Z99 :Wizzowow Z99 +STR_8039_PASSENGER_CAR :Passagerarvagn +STR_803A_MAIL_VAN :Postvagn +STR_803B_COAL_CAR :Kolvagn +STR_803C_OIL_TANKER :Oljetank +STR_803D_LIVESTOCK_VAN :Boskapsvagn +STR_803E_GOODS_VAN :Godsvagn +STR_803F_GRAIN_HOPPER :Spannmålsvagn +STR_8040_WOOD_TRUCK :Timmervagn +STR_8041_IRON_ORE_HOPPER :Järnmalmsvagn +STR_8042_STEEL_TRUCK :Stålvagn +STR_8043_ARMORED_VAN :Bepansrad vagn +STR_8044_FOOD_VAN :Matvagn +STR_8045_PAPER_TRUCK :Pappersvagn +STR_8046_COPPER_ORE_HOPPER :Kopparmalmsvagn +STR_8047_WATER_TANKER :Vattentank +STR_8048_FRUIT_TRUCK :Frukvagn +STR_8049_RUBBER_TRUCK :Gummivagn +STR_804A_SUGAR_TRUCK :Sockervagn +STR_804B_COTTON_CANDY_HOPPER :Spunnet Sockervagn +STR_804C_TOFFEE_HOPPER :Knäckvagn +STR_804D_BUBBLE_VAN :Bubblevagn +STR_804E_COLA_TANKER :Kolatank +STR_804F_CANDY_VAN :Godisvagn +STR_8050_TOY_VAN :Leksaksvagn +STR_8051_BATTERY_TRUCK :Batterivagn +STR_8052_FIZZY_DRINK_TRUCK :Läskvagn +STR_8053_PLASTIC_TRUCK :Plastvagn +STR_8054_LEV1_LEVIATHAN_ELECTRIC :Lev1 'Leviathan' (Elektricitet) +STR_8055_LEV2_CYCLOPS_ELECTRIC :Lev2 'Cyclops' (Elektricitet) +STR_8056_LEV3_PEGASUS_ELECTRIC :Lev3 'Pegasus' (Elektricitet) +STR_8057_LEV4_CHIMAERA_ELECTRIC :Lev4 'Chimaera' (Elektricitet) +STR_8058_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer +STR_8059_PASSENGER_CAR :Passagerarbil +STR_805A_MAIL_VAN :Postvagn +STR_805B_COAL_CAR :Kolvagn +STR_805C_OIL_TANKER :Oljetank +STR_805D_LIVESTOCK_VAN :Boskapsvagn +STR_805E_GOODS_VAN :Godsvagn +STR_805F_GRAIN_HOPPER :Spannmålsvagn +STR_8060_WOOD_TRUCK :Timmervagn +STR_8061_IRON_ORE_HOPPER :Järnmalmsvagn +STR_8062_STEEL_TRUCK :Stållastvagn +STR_8063_ARMORED_VAN :Bepansrad vagn +STR_8064_FOOD_VAN :Matvagn +STR_8065_PAPER_TRUCK :Pappersvagn +STR_8066_COPPER_ORE_HOPPER :Kopparmalmsvagn +STR_8067_WATER_TANKER :Vattentank +STR_8068_FRUIT_TRUCK :Fruktvagn +STR_8069_RUBBER_TRUCK :Gummilastvagn +STR_806A_SUGAR_TRUCK :Sockerlastvagn +STR_806B_COTTON_CANDY_HOPPER :Spunnet Sockervagn +STR_806C_TOFFEE_HOPPER :Knäckvagn +STR_806D_BUBBLE_VAN :Bubbelvagn +STR_806E_COLA_TANKER :Kolatank +STR_806F_CANDY_VAN :Godisvagn +STR_8070_TOY_VAN :Leksaksvagn +STR_8071_BATTERY_TRUCK :Batterivagn +STR_8072_FIZZY_DRINK_TRUCK :Läskvagn +STR_8073_PLASTIC_TRUCK :Plastvagn +STR_8074_MPS_REGAL_BUS :MPS Regal Buss +STR_8075_HEREFORD_LEOPARD_BUS :Hereford Leopard Buss +STR_8076_FOSTER_BUS :Foster Buss +STR_8077_FOSTER_MKII_SUPERBUS :Foster MkII Super Buss +STR_8078_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Buss +STR_8079_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Buss +STR_807A_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Buss +STR_807B_BALOGH_COAL_TRUCK :Balogh Koldumper +STR_807C_UHL_COAL_TRUCK :Uhl Koldumper +STR_807D_DW_COAL_TRUCK :DW Koldumper +STR_807E_MPS_MAIL_TRUCK :MPS Postbil +STR_807F_REYNARD_MAIL_TRUCK :Reynard Postbil +STR_8080_PERRY_MAIL_TRUCK :Perry Postbil +STR_8081_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postbil +STR_8082_POWERNAUGHT_MAIL_TRUCK :Powernaught Postbil +STR_8083_WIZZOWOW_MAIL_TRUCK :Wizzowow Postbil +STR_8084_WITCOMBE_OIL_TANKER :Witcombe Oljetanker +STR_8085_FOSTER_OIL_TANKER :Foster Oljetanker +STR_8086_PERRY_OIL_TANKER :Perry Oljetanker +STR_8087_TALBOTT_LIVESTOCK_VAN :Talbott Boskapsbil +STR_8088_UHL_LIVESTOCK_VAN :Uhl Boskapsbil +STR_8089_FOSTER_LIVESTOCK_VAN :Foster Boskapsbil +STR_808A_BALOGH_GOODS_TRUCK :Balogh Godslastbil +STR_808B_CRAIGHEAD_GOODS_TRUCK :Craighead Godslastbil +STR_808C_GOSS_GOODS_TRUCK :Goss Godslastbil +STR_808D_HEREFORD_GRAIN_TRUCK :Hereford Spannmålslastare +STR_808E_THOMAS_GRAIN_TRUCK :Thomas Spannmålslastare +STR_808F_GOSS_GRAIN_TRUCK :Goss Spannmålslastare +STR_8090_WITCOMBE_WOOD_TRUCK :Witcombe Timmerlastare +STR_8091_FOSTER_WOOD_TRUCK :Foster Timmerlastare +STR_8092_MORELAND_WOOD_TRUCK :Moreland Timmerlastare +STR_8093_MPS_IRON_ORE_TRUCK :MPS Järnmalmsdumper +STR_8094_UHL_IRON_ORE_TRUCK :Uhl Järnmalmsdumper +STR_8095_CHIPPY_IRON_ORE_TRUCK :Chippy Järnmalmsdumper +STR_8096_BALOGH_STEEL_TRUCK :Balogh Ståldumper +STR_8097_UHL_STEEL_TRUCK :Uhl Ståldumper +STR_8098_KELLING_STEEL_TRUCK :Kelling Ståldumper +STR_8099_BALOGH_ARMORED_TRUCK :Balogh Bepansrad lastbil +STR_809A_UHL_ARMORED_TRUCK :Uhl Bepansrad lastbil +STR_809B_FOSTER_ARMORED_TRUCK :Foster Bepansrad lastbil +STR_809C_FOSTER_FOOD_VAN :Foster Matbil +STR_809D_PERRY_FOOD_VAN :Perry Matbil +STR_809E_CHIPPY_FOOD_VAN :Chippy Matbil +STR_809F_UHL_PAPER_TRUCK :Uhl Papperlastare +STR_80A0_BALOGH_PAPER_TRUCK :Balogh Papperslastare +STR_80A1_MPS_PAPER_TRUCK :MPS Papperslastare +STR_80A2_MPS_COPPER_ORE_TRUCK :MPS Kopparmalmsdumper +STR_80A3_UHL_COPPER_ORE_TRUCK :Uhl Kopparmalmsdumper +STR_80A4_GOSS_COPPER_ORE_TRUCK :Goss Kopparmalmsdumper +STR_80A5_UHL_WATER_TANKER :Uhl Vattentanker +STR_80A6_BALOGH_WATER_TANKER :Balogh Vattentanker +STR_80A7_MPS_WATER_TANKER :MPS Vattentanker +STR_80A8_BALOGH_FRUIT_TRUCK :Balogh Fruktlastare +STR_80A9_UHL_FRUIT_TRUCK :Uhl Fruktlastare +STR_80AA_KELLING_FRUIT_TRUCK :Kelling Fruktlastare +STR_80AB_BALOGH_RUBBER_TRUCK :Balogh Gummidumper +STR_80AC_UHL_RUBBER_TRUCK :Uhl Gummidumper +STR_80AD_RMT_RUBBER_TRUCK :RMT Gummidumper +STR_80AE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Sockerlastare +STR_80AF_POWERNAUGHT_SUGAR_TRUCK :Powernaught Sockerlastare +STR_80B0_WIZZOWOW_SUGAR_TRUCK :Wizzowow Sockerlastare +STR_80B1_MIGHTYMOVER_COLA_TRUCK :MightyMover Kolalastare +STR_80B2_POWERNAUGHT_COLA_TRUCK :Powernaught Kolalastare +STR_80B3_WIZZOWOW_COLA_TRUCK :Wizzowow Kolalastare +STR_80B4_MIGHTYMOVER_COTTON_CANDY :MightyMover Spunnet Sockerlastare +STR_80B5_POWERNAUGHT_COTTON_CANDY :Powernaught Spunnet Sockerlastare +STR_80B6_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Spunnet Sockerlastare +STR_80B7_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Knäcklastare +STR_80B8_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Knäcklastare +STR_80B9_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Knäcklastare +STR_80BA_MIGHTYMOVER_TOY_VAN :MightyMover Leksaksbil +STR_80BB_POWERNAUGHT_TOY_VAN :Powernaught Leksaksbil +STR_80BC_WIZZOWOW_TOY_VAN :Wizzowow Leksaksbil +STR_80BD_MIGHTYMOVER_CANDY_TRUCK :MightyMover Godislastare +STR_80BE_POWERNAUGHT_CANDY_TRUCK :Powernaught Godislastare +STR_80BF_WIZZOWOW_CANDY_TRUCK :Wizzowow Godislastare +STR_80C0_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Batterilastare +STR_80C1_POWERNAUGHT_BATTERY_TRUCK :Powernaught Batterilastare +STR_80C2_WIZZOWOW_BATTERY_TRUCK :Wizzowow Batterilastare +STR_80C3_MIGHTYMOVER_FIZZY_DRINK :MightyMover Läsklastbil +STR_80C4_POWERNAUGHT_FIZZY_DRINK :Powernaught Läsklastbil +STR_80C5_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Läsklastbil +STR_80C6_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastlastare +STR_80C7_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastlastare +STR_80C8_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastlastbil +STR_80C9_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Bubblelastbil +STR_80CA_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Bubblelastbil +STR_80CB_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Bubblelastbil +STR_80CC_MPS_OIL_TANKER :MPS Oljetanker +STR_80CD_CS_INC_OIL_TANKER :CS-Inc. Oljetanker +STR_80CE_MPS_PASSENGER_FERRY :MPS Passagerarfärja +STR_80CF_FFP_PASSENGER_FERRY :FFP Passagerarfärja +STR_80D0_BAKEWELL_300_HOVERCRAFT :Bakewell 300 svävfarkost +STR_80D1_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passagerarfärja +STR_80D2_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passagerarfärja +STR_80D3_YATE_CARGO_SHIP :Yate Godsskepp +STR_80D4_BAKEWELL_CARGO_SHIP :Bakewell Godsskepp +STR_80D5_MIGHTYMOVER_CARGO_SHIP :Mightymover Godsskepp +STR_80D6_POWERNAUT_CARGO_SHIP :Powernaut Godsskepp +STR_80D7_SAMPSON_U52 :Sampson U52 +STR_80D8_COLEMAN_COUNT :Coleman Count +STR_80D9_FFP_DART :FFP Dart +STR_80DA_YATE_HAUGAN :Yate Haugan +STR_80DB_BAKEWELL_COTSWALD_LB_3 :Bakewell Cotswald LB-3 +STR_80DC_BAKEWELL_LUCKETT_LB_8 :Bakewell Luckett LB-8 +STR_80DD_BAKEWELL_LUCKETT_LB_9 :Bakewell Luckett LB-9 +STR_80DE_BAKEWELL_LUCKETT_LB80 :Bakewell Luckett LB80 +STR_80DF_BAKEWELL_LUCKETT_LB_10 :Bakewell Luckett LB-10 +STR_80E0_BAKEWELL_LUCKETT_LB_11 :Bakewell Luckett LB-11 +STR_80E1_YATE_AEROSPACE_YAC_1_11 :Yate Aerospace YAC 1-11 +STR_80E2_DARWIN_100 :Darwin 100 +STR_80E3_DARWIN_200 :Darwin 200 +STR_80E4_DARWIN_300 :Darwin 300 +STR_80E5_DARWIN_400 :Darwin 400 +STR_80E6_DARWIN_500 :Darwin 500 +STR_80E7_DARWIN_600 :Darwin 600 +STR_80E8_GURU_GALAXY :Guru Galaxy +STR_80E9_AIRTAXI_A21 :Airtaxi A21 +STR_80EA_AIRTAXI_A31 :Airtaxi A31 +STR_80EB_AIRTAXI_A32 :Airtaxi A32 +STR_80EC_AIRTAXI_A33 :Airtaxi A33 +STR_80ED_YATE_AEROSPACE_YAE46 :Yate Aerospace YAe46 +STR_80EE_DINGER_100 :Dinger 100 +STR_80EF_AIRTAXI_A34_1000 :AirTaxi A34-1000 +STR_80F0_YATE_Z_SHUTTLE :Yate Z-Shuttle +STR_80F1_KELLING_K1 :Kelling K1 +STR_80F2_KELLING_K6 :Kelling K6 +STR_80F3_KELLING_K7 :Kelling K7 +STR_80F4_DARWIN_700 :Darwin 700 +STR_80F5_FFP_HYPERDART_2 :FFP Hyperdart 2 +STR_80F6_DINGER_200 :Dinger 200 +STR_80F7_DINGER_1000 :Dinger 1000 +STR_80F8_PLODDYPHUT_100 :Ploddyphut 100 +STR_80F9_PLODDYPHUT_500 :Ploddyphut 500 +STR_80FA_FLASHBANG_X1 :Flashbang X1 +STR_80FB_JUGGERPLANE_M1 :Juggerplane M1 +STR_80FC_FLASHBANG_WIZZER :Flashbang Wizzer +STR_80FD_TRICARIO_HELICOPTER :Tricario Helicopter +STR_80FE_GURU_X2_HELICOPTER :Guru X2 Helikopter +STR_80FF_POWERNAUT_HELICOPTER :Powernaut Helikopter +STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE:{WHITE}Meddelande från fordonstillverkare +STR_8101_WE_HAVE_JUST_DESIGNED_A :{GOLD}Vi har just designat ett nytt {STRING} - är du intresserad av ett års exklusiv användning av detta fordon, så vi kan se hur det fungerar innan vi släpper det på marknaden? +STR_8102_RAILROAD_LOCOMOTIVE :järnvägslokomotiv +STR_8103_ROAD_VEHICLE :vägfordon +STR_8104_AIRCRAFT :flygplan +STR_8105_SHIP :skepp +STR_8106_MONORAIL_LOCOMOTIVE :monorail-lokomotiv +STR_8107_MAGLEV_LOCOMOTIVE :maglev-lokomotiv + +##id 0x8800 +STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} depå +STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Invånarna firar . . .{}Första tåget ankommer till {STATION}! +STR_8802_DETAILS :{WHITE}{STRING} (Details) +STR_8803_TRAIN_IN_THE_WAY :{WHITE}Tåg i vägen +STR_8804 :{SETX 10}{COMMA8}: {STRING} +STR_8805 :{RIGHTARROW}{SETX 10}{COMMA8}: {STRING} +STR_8806_GO_TO :Gå till {STATION} +STR_8807_GO_TO_UNLOAD :Gå till {STATION} (Lasta av) +STR_8808_GO_TO_LOAD :Gå till {STATION} (Lasta) +STR_8809 : +STR_880A_GO_NON_STOP_TO :Gå non-stop till {STATION} +STR_880B_GO_NON_STOP_TO_UNLOAD :Gå non-stop till {STATION} (Lasta av) +STR_880C_GO_NON_STOP_TO_LOAD :Gå non-stop till {STATION} (Lasta) +STR_880D : +STR_880E_GO_TO_TRAIN_DEPOT :Gå till {TOWN} depå +STR_SERVICE_AT_TRAIN_DEPOT :Servning vid {TOWN} Tåg depå +STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Gå non-stop till {TOWN} depå +STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Servning non-stop {TOWN} Tåg depå + +STR_HEADING_FOR_TRAIN_DEPOT :{LTBLUE}På väg mot {TOWN} depå +STR_HEADING_FOR_TRAIN_DEPOT_VEL :{LTBLUE}På väg mot {TOWN} depå, {VELOCITY} + +STR_8812_EMPTY :{LTBLUE}Tom +STR_8813_FROM :{LTBLUE}{CARGO} från {STATION} +STR_8814_TRAIN_IS_WAITING_IN_DEPOT :{WHITE}Tåg {COMMA16} väntar i depå +STR_8815_NEW_VEHICLES :{BLACK}Nytt fordon +STR_8816 :{BLACK}- +STR_8817_COST_WEIGHT_T_SPEED_POWER :{BLACK}Kostnad: {GOLD}{CURRENCY}{BLACK} Vikt: {GOLD}{COMMA16}t{}{BLACK}Hastighet: {GOLD}{VELOCITY}{BLACK} Effekt: {GOLD}{COMMA16}hp{}{BLACK}Löpande kostnad: {GOLD}{CURRENCY}/yr{}{BLACK}Kapacitet: {GOLD}{STRING}{}{BLACK}Designad: {GOLD}{NUMU16}{BLACK} Livslängd: {GOLD}{COMMA16} år{}{BLACK}Max. tillförlitlighet: {GOLD}{COMMA8}% +STR_8818_INFORMATION :{BLACK}Information +STR_8819_TRAIN_TOO_LONG :{WHITE}Tåg för långt +STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Tåg kan bara ändras när det står still inuti en depå +STR_881B_TRAINS :{WHITE}{STRING} - Tåg +STR_881C_NEW_RAIL_VEHICLES :{WHITE}Nytt tågfordon +STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}Nytt monorail-Fordon +STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}Nytt maglev-Fordon +STR_881F_BUILD_VEHICLE :{BLACK}Bygg fordon +STR_8820_RENAME :{BLACK}Byt namn på +STR_8821_COST_WEIGHT_T_T_CAPACITY :{BLACK}Kostnad: {GOLD}{CURRENCY}{}{BLACK}Vikt: {GOLD}{COMMA16}t ({COMMA16}t){}{BLACK}Kapacitet: {GOLD}{STRING} +STR_8823_SKIP :{BLACK}Skippa +STR_8824_DELETE :{BLACK}Ta bort +STR_8825_NON_STOP :{BLACK}Non-stop +STR_8826_GO_TO :{BLACK}Gå Till +STR_8827_FULL_LOAD :{BLACK}Lasta +STR_8828_UNLOAD :{BLACK}Lasta av +STR_8829_ORDERS :{WHITE}{STRING} (Orders) +STR_882A_END_OF_ORDERS :{SETX 10}- - Slut på order - - +STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING} +STR_SERVICE :{BLACK}Servning +STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE :{WHITE}Kan inte bygga järnvägfordon... +STR_882C_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Byggt: {LTBLUE}{NUMU16}{BLACK} Värde: {LTBLUE}{CURRENCY} +STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Värde: {LTBLUE}{CURRENCY} +STR_882E :{WHITE}{STRING} +STR_882F_LOADING_UNLOADING :{LTBLUE}Lastar / lastar av +STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Kan inte skicka tåg till depå... +STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ingen mer plats för order +STR_8832_TOO_MANY_ORDERS :{WHITE}För många order +STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Kan inte sätta in ny order... +STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Kan inte ta bort denna order... +STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Kan inte ändra denna order... +STR_8836_MUST_BUILD_TRAIN_DEPOT :{WHITE}Måste bygga depå för tåg först +STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Kan inte flytta fordon... +STR_8838_N_A :N/A{SKIP} +STR_8839_CAN_T_SELL_RAILROAD_VEHICLE :{WHITE}Kan inte sälja järnvägfordon... +STR_883A_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Kan inte hitta rutt till närmaste depå +STR_883B_CAN_T_STOP_START_TRAIN :{WHITE}Kan inte stoppa/starta tåg... +STR_883C_SERVICING_INTERVAL_DAYS :{BLACK}Serviceintervall: {LTBLUE}{COMMA16}dagar{BLACK} Senaste service: {LTBLUE}{DATE_LONG} +STR_883D_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tåg - klicka på tåg för information +STR_883E_BUILD_NEW_TRAINS_REQUIRES :{BLACK}Bygg nytt tåg (kräver depå) +STR_883F_TRAINS_CLICK_ON_TRAIN_FOR :{BLACK}Tåg - klicka på tåg för info, drag vagn för att lägga till/ta bort från tåg +STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Bygg ny tågvagn +STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Dra tågvagn hit för att sälja den +STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrera vyn på depån +STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Lista av tågvagnar - klicka på tågvagn för information +STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Bygg markerad tågvagn +STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Byt namn på tågvagn +STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Aktuell tågorder - klicka här för att stoppa/starta tåg +STR_8847_SHOW_TRAIN_S_ORDERS :{BLACK}Visa tågets order +STR_8848_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centrera vyn ovanför tåget +STR_8849_SEND_TRAIN_TO_DEPOT :{BLACK}Skicka tåg till depå +STR_884A_FORCE_TRAIN_TO_PROCEED :{BLACK}Tvinga tåg att fortsätta utan att vänta på signal +STR_884B_REVERSE_DIRECTION_OF_TRAIN :{BLACK}Kasta om tågets riktning +STR_884C_SHOW_TRAIN_DETAILS :{BLACK}Visa tågdetaljer +STR_884D_INCREASE_SERVICING_INTERVAL :{BLACK}Öka serviceintervall +STR_884E_DECREASE_SERVICING_INTERVAL :{BLACK}Minska serviceintervall +STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED :{BLACK}Visa detaljer för lastat gods +STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES :{BLACK}Visa detaljer för tågfordon +STR_8851_SHOW_CAPACITIES_OF_EACH :{BLACK}Visa kapaciteter för varje fordon +STR_8852_SHOW_TOTAL_CARGO :{BLACK}Visa tågets totala kapacitet, separera för typ av gods +STR_8852_ORDERS_LIST_CLICK_ON_ORDER :{BLACK}Orderlista - klicka på order för att markera det +STR_8853_SKIP_THE_CURRENT_ORDER :{BLACK}Skippa nuvararande order, och börja med nästa +STR_8854_DELETE_THE_HIGHLIGHTED :{BLACK}Ta bort markerad order +STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gör markerad order non-stop +STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Infoga ny order före markerad order, eller lägg till i slutet av listan +STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gör markerad order att tvinga fordonet att vänta på full last +STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Gör markerad order att tvinga fordonet att vänta på tom last +STR_SERVICE_HINT :{BLACK}Skippa den här ordern om inte servning behövs +STR_8859_NEW_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt {STRING} nu tillgängligt! +STR_885A :{BLACK}{BIGFONT}{STRING} +STR_885B_COST_WEIGHT_T_SPEED_POWER :{BLACK}Kostnad: {CURRENCY} Vikt: {COMMA16}t{}Hastighet: {VELOCITY} Effekt: {COMMA16}hp{}Löpande kostnad: {CURRENCY}/yr{}Kapacitet: {STRING} +STR_885C_BROKEN_DOWN :{RED}Motorstopp +STR_885D_AGE_RUNNING_COST_YR :{BLACK}Ålder: {LTBLUE}{STRING}{BLACK} Löpande kostnad: {LTBLUE}{CURRENCY}/yr +STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED :{BLACK}Vikt: {LTBLUE}{COMMA16}t {BLACK}Effekt: {LTBLUE}{COMMA32}hp{BLACK} Max. hastighet: {LTBLUE}{VELOCITY} +STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Vinst detta år: {LTBLUE}{CURRENCY} (förra år: {CURRENCY}) +STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Tillförlitlighet: {LTBLUE}{COMMA8}% {BLACK}Motorstopp sedan förra service: {LTBLUE}{COMMA16} +STR_8861_STOPPED :{RED}Stoppat +STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Kan inte tillåta tåg att passera signal under fara... +STR_8863_CRASHED :{RED}Kraschad! + +STR_8865_NAME_TRAIN :{WHITE}Byt namn på tåg +STR_8866_CAN_T_NAME_TRAIN :{WHITE}Kan inte byta namn på tåg... +STR_8867_NAME_TRAIN :{BLACK}Byt namn på tåg +STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Tågkrash!{}{COMMA16} dog i eldklot efter kollision +STR_8869_CAN_T_REVERSE_DIRECTION :{WHITE}Kan inte kasta om tågets riktning... +STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Byt namn på tågets fordonstyp +STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Kan inte byta namn på tågets fordonstyp... + +STR_TRAIN_STOPPING :{RED}Stannar +STR_TRAIN_STOPPING_VEL :{RED}Stannar, {VELOCITY} + +##id 0x9000 +STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Vägfordon i vägen +STR_9001_ROAD_VEHICLES :{WHITE}{STRING} - Vägfordon +STR_9002 :{WHITE}{STRING} +STR_9003_ROAD_VEHICLE_DEPOT :{WHITE}{TOWN} Vägfordon Depå +STR_9004_NEW_VEHICLES :{BLACK}Nytt Fordon +STR_9005_INFORMATION :{BLACK}Information +STR_9006_NEW_ROAD_VEHICLES :{WHITE}Nytt Vägfordon +STR_9007_BUILD_VEHICLE :{BLACK}Bygg Fordon +STR_9008_COST_SPEED_RUNNING_COST :{BLACK}Kostnad: {GOLD}{CURRENCY}{BLACK} Hastighet: {GOLD}{VELOCITY}{}{BLACK}Löpande kostnad: {GOLD}{CURRENCY}/yr{}{BLACK}Kapacitet: {GOLD}{STRING}{}{BLACK}Designad: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} år{}{BLACK}Max. Tillförlitlighet: {GOLD}{COMMA8}% +STR_9009_CAN_T_BUILD_ROAD_VEHICLE :{WHITE}Kan inte bygga vägfordon... +STR_900A_MUST_BUILD_ROAD_VEHICLE :{WHITE}Måste bygga bussgarage först +STR_900B_ORDERS :{WHITE}{STRING} (Order) +STR_900C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_900D_AGE_RUNNING_COST_YR :{BLACK}Ålder: {LTBLUE}{STRING}{BLACK} Löpande kostnad: {LTBLUE}{CURRENCY}/yr +STR_900E_MAX_SPEED :{BLACK}Max. hastighet: {LTBLUE}{VELOCITY} +STR_900F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Vinst detta år: {LTBLUE}{CURRENCY} (förra år: {CURRENCY}) +STR_9010_RELIABILITY_BREAKDOWNS :{BLACK}Tillförlitlighet: {LTBLUE}{COMMA8}% {BLACK}Motorstopp sedan förra service: {LTBLUE}{COMMA16} +STR_9011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Byggt: {LTBLUE}{NUMU16}{BLACK} Värde: {LTBLUE}{CURRENCY} +STR_9012_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_9013_MUST_BE_STOPPED_INSIDE :{WHITE}...måste stoppas inuti ett bussgarage +STR_9014_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Kan inte sälja vägfordon... +STR_9015_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Kan inte stoppa/starta vägfordon... +STR_9016_ROAD_VEHICLE_IS_WAITING :{WHITE}Vägfordon {COMMA16} väntar i depån +STR_HEADING_FOR_ROAD_DEPOT :{LTBLUE}På väg mot {TOWN} Vägdepå +STR_HEADING_FOR_ROAD_DEPOT_VEL :{LTBLUE}På väg mot {TOWN} Vägdepå, {VELOCITY} +STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT :{WHITE}Kan inte skicka fordon till depå... +STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan inte hitta till lokal depå +STR_901A_ROAD_VEHICLES_CLICK_ON :{BLACK}Vägfordon - klicka på fordon för information +STR_901B_BUILD_NEW_ROAD_VEHICLES :{BLACK}Bygg nytt vägfordon (kräver bussgarage) +STR_901C_CURRENT_VEHICLE_ACTION :{BLACK}Nuvarande fordonsaktivitet - Klicka här till stoppa/starta fordon +STR_901D_SHOW_VEHICLE_S_ORDERS :{BLACK}Visa fordonets order +STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE :{BLACK}Centrera vyn ovanför fordonet +STR_901F_SEND_VEHICLE_TO_DEPOT :{BLACK}Skicka fordon till depå +STR_9020_FORCE_VEHICLE_TO_TURN_AROUND :{BLACK}Tvinga fordonet att vända om +STR_9021_SHOW_ROAD_VEHICLE_DETAILS :{BLACK}Visa vägfordonsdetaljer +STR_9022_VEHICLES_CLICK_ON_VEHICLE :{BLACK}Fordon - klicka på fordon för information +STR_9023_BUILD_NEW_ROAD_VEHICLE :{BLACK}Bygg nytt vägfordon +STR_9024_DRAG_ROAD_VEHICLE_TO_HERE :{BLACK}Dra vägfordon hit för att sälja det +STR_9025_CENTER_MAIN_VIEW_ON_ROAD :{BLACK}Centrera vyn ovanför bussgaraget +STR_9026_ROAD_VEHICLE_SELECTION :{BLACK}Vägfordonslista - klicka på fordon för information +STR_9027_BUILD_THE_HIGHLIGHTED_ROAD :{BLACK}Bygg markerat vägfordon +STR_9028_NEW_ROAD_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt vägfordon tillgängligt! +STR_9029 :{BLACK}{BIGFONT}{STRING} +STR_902A_COST_SPEED_RUNNING_COST :{BLACK}Kostnad: {CURRENCY}{}Hastighet: {VELOCITY}{}Löpande kostnad: {CURRENCY}/yr{}Kapacitet: {STRING} + +STR_902C_NAME_ROAD_VEHICLE :{WHITE}Byt namn på vägfordon +STR_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Kan inte byta namn på vägfordon... +STR_902E_NAME_ROAD_VEHICLE :{BLACK}Byt namn på vägfordon +STR_902F_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Invånarna firar . . .{}Första bussen ankommer till {STATION}! +STR_9030_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Invånarna firar . . .{}Första lastbilen ankommer till {STATION}! +STR_9031_ROAD_VEHICLE_CRASH_DRIVER :{BLACK}{BIGFONT}Vägfordonskrash!{}förare dör i eldklot efter kollision med tåg +STR_9032_ROAD_VEHICLE_CRASH_DIE :{BLACK}{BIGFONT}Vägfordonskrash!{}{COMMA16} dör i eldklot efter kollision med tåg +STR_9033_CAN_T_MAKE_VEHICLE_TURN :{WHITE}Kan inte tvinga fordonet att vända om... +STR_9034_RENAME :{BLACK}Byt namn på +STR_9035_RENAME_ROAD_VEHICLE_TYPE :{BLACK}Byt namn på vägfordon typ +STR_9036_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Byt namn på vägfordon typ +STR_9037_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Kan inte byta namn på vägfordon typ... +STR_9038_GO_TO_ROADVEH_DEPOT :Gå till {TOWN} vägfordonsdepå +STR_SERVICE_AT_ROADVEH_DEPOT :Servning vid {TOWN} vägfordonsdepå Depot + +##id 0x9800 +STR_9800_DOCK_CONSTRUCTION :Hamnbyggnation +STR_9801_DOCK_CONSTRUCTION :{WHITE}Hamnbyggnation +STR_9802_CAN_T_BUILD_DOCK_HERE :{WHITE}Kan inte bygga hamn här... +STR_9803_SHIP_DEPOT :{WHITE}{TOWN} Skeppsdepå +STR_9804_NEW_SHIPS :{BLACK}Nytt Skepp +STR_9805_SHIPS :{WHITE}{STRING} - Skepp +STR_9806_CAN_T_BUILD_SHIPS :{WHITE}Kan inte bygga skepp... +STR_9807_MUST_BUILD_SHIP_DEPOT_FIRST :{WHITE}Måste bygga skeppsdepå först +STR_9808_NEW_SHIPS :{WHITE}Nytt Skepp +STR_9809_BUILD_SHIP :{BLACK}Bygg Skepp +STR_980A_COST_SPEED_CAPACITY_RUNNING :{BLACK}Kostnad: {GOLD}{CURRENCY}{BLACK} Hastighet: {GOLD}{VELOCITY}{}{BLACK}Kapacitet: {GOLD}{STRING} {STRING}{}{BLACK}Löpande kostnad: {GOLD}{CURRENCY}/yr{}{BLACK}Designad: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} år{}{BLACK}Max. Tillförlitlighet: {GOLD}{COMMA8}% +STR_980B_SHIP_MUST_BE_STOPPED_IN :{WHITE}Skepp måste vara stoppat i depå +STR_980C_CAN_T_SELL_SHIP :{WHITE}Kan inte sälja skepp... +STR_980D_CAN_T_BUILD_SHIP :{WHITE}Kan inte bygga skepp... +STR_980E_SHIP_IN_THE_WAY :{WHITE}Skepp i vägen +STR_980F :{WHITE}{STRING} +STR_9810_ORDERS :{WHITE}{STRING} (Order) +STR_9811_DETAILS :{WHITE}{STRING} (Detaljer) +STR_9812_AGE_RUNNING_COST_YR :{BLACK}Ålder: {LTBLUE}{STRING}{BLACK} Löpande kostnad: {LTBLUE}{CURRENCY}/yr +STR_9813_MAX_SPEED :{BLACK}Max. hastighet: {LTBLUE}{VELOCITY} +STR_9814_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Vinst detta år: {LTBLUE}{CURRENCY} (förra år: {CURRENCY}) +STR_9815_RELIABILITY_BREAKDOWNS :{BLACK}Tillförlitlighet: {LTBLUE}{COMMA8}% {BLACK}Motorstopp sedan förra service: {LTBLUE}{COMMA16} +STR_9816_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Byggt: {LTBLUE}{NUMU16}{BLACK} Värde: {LTBLUE}{CURRENCY} +STR_9817_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_9818_CAN_T_STOP_START_SHIP :{WHITE}Kan inte stoppa/starta skepp... +STR_9819_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Kan inte skicka skepp till depå... +STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Kan inte finna lokal depå +STR_HEADING_FOR_SHIP_DEPOT :{LTBLUE}På väg mot {TOWN} Skeppsdepå +STR_HEADING_FOR_SHIP_DEPOT_VEL :{LTBLUE}På väg mot {TOWN} Skeppsdepå, {VELOCITY} +STR_981C_SHIP_IS_WAITING_IN_DEPOT :{WHITE}Skepp {COMMA16} väntar i depå +STR_981D_BUILD_SHIP_DOCK :{BLACK}Bygg skeppsdepå +STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING :{BLACK}Bygg skeppsdepå (för byggnad och lagning av skepp) +STR_981F_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skepp - klicka på skepp för information +STR_9820_BUILD_NEW_SHIP :{BLACK}Bygg nytt skepp +STR_9821_DRAG_SHIP_TO_HERE_TO_SELL :{BLACK}Dra skepp hit för att sälja det +STR_9822_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrera vyn ovanför skeppets depot +STR_9823_SHIPS_CLICK_ON_SHIP_FOR :{BLACK}Skepp - klicka på skepp för information +STR_9824_BUILD_NEW_SHIPS_REQUIRES :{BLACK}Bygg nytt skepp (kräver skeppsdepå) +STR_9825_SHIP_SELECTION_LIST_CLICK :{BLACK}Skeppslista - klicka på skepp för information +STR_9826_BUILD_THE_HIGHLIGHTED_SHIP :{BLACK}Bygg markerat skepp +STR_9827_CURRENT_SHIP_ACTION_CLICK :{BLACK}Nuvarande skeppsaktion - Klicka här till stoppa/starta skepp +STR_9828_SHOW_SHIP_S_ORDERS :{BLACK}Visa skeppets order +STR_9829_CENTER_MAIN_VIEW_ON_SHIP :{BLACK}Centrera vyn ovanför skeppet +STR_982A_SEND_SHIP_TO_DEPOT :{BLACK}Skicka skepp till depå +STR_982B_SHOW_SHIP_DETAILS :{BLACK}Visa skeppdetaljer +STR_982C_NEW_SHIP_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt skepp tillgängligt! +STR_982D :{BLACK}{BIGFONT}{STRING} +STR_982E_COST_MAX_SPEED_CAPACITY :{BLACK}Kostnad: {CURRENCY} Max. Hastighet: {VELOCITY}{}Kapacitet: {STRING}{}Löpande kostnad: {CURRENCY}/yr +STR_982F_NAME_SHIP :{BLACK}Byt namn på skepp + +STR_9831_NAME_SHIP :{WHITE}Byt namn på skepp +STR_9832_CAN_T_NAME_SHIP :{WHITE}Kan inte byta namn på skepp... +STR_9833_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Invånarna firar . . .{}Första skeppet ankommer till {STATION}! +STR_9834_POSITION_BUOY_WHICH_CAN :{BLACK}Positionsboj, som kan som kan användas för ytterligare vägpunkter +STR_9835_CAN_T_POSITION_BUOY_HERE :{WHITE}Kan inte placera boj här... +STR_9836_RENAME :{BLACK}Byt namn på +STR_9837_RENAME_SHIP_TYPE :{BLACK}Byt namn på skeppstyp +STR_9838_RENAME_SHIP_TYPE :{WHITE}Byt namn på skeppstyp +STR_9839_CAN_T_RENAME_SHIP_TYPE :{WHITE}Kan inte byta namn på skeppstyp... +STR_983A_REFIT_CARGO_SHIP_TO_CARRY :{BLACK}Anpassa godsskepp att frakta en annan godstyp +STR_983B_REFIT :{WHITE}{STRING} (Refit) +STR_983C_REFIT_SHIP :{BLACK}Anpassa skepp +STR_983D_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Välj typ av gods för skepp att frakta +STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED:{BLACK}Anpassa skepp att frakta markerad godstyp +STR_983F_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Välj godstyp att frakta:- +STR_9840_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapacitet: {GOLD}{STRING}{}{BLACK}Kostnad av anpassning: {GOLD}{CURRENCY} +STR_9841_CAN_T_REFIT_SHIP :{WHITE}Kan inte anpassa skepp... +STR_9842_REFITTABLE :(anpassningsbart) +STR_GO_TO_SHIP_DEPOT :Gå till {TOWN} Båtdepå +SERVICE_AT_SHIP_DEPOT :Servning vid {TOWN} Båtdepå + +##id 0xA000 +STR_A000_AIRPORT_CONSTRUCT :{WHITE}Flygplats Bygg. +STR_A001_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Kan inte bygga flygplats här... +STR_A002_AIRCRAFT_HANGAR :{WHITE}{STATION} Flygplanshangar +STR_A003_NEW_AIRCRAFT :{BLACK}Nytt Flygplan +STR_A004_INFORMATION :{BLACK}Information +STR_A005_NEW_AIRCRAFT :{WHITE}Nytt Flygplan +STR_A006_BUILD_AIRCRAFT :{BLACK}Bygg Flygplan +STR_A007_COST_SPEED_CAPACITY_PASSENGERS :{BLACK}Kostnad: {GOLD}{CURRENCY}{BLACK} Hastighet: {GOLD}{VELOCITY}{}{BLACK}Kapacitet: {GOLD}{COMMA16} passagerare, {COMMA16} postsäckar{}{BLACK}Löpande kostnad: {GOLD}{CURRENCY}/yr{}{BLACK}Designad: {GOLD}{NUMU16}{BLACK} Life: {GOLD}{COMMA16} år{}{BLACK}Max. Tillförlitlighet: {GOLD}{COMMA8}% +STR_A008_CAN_T_BUILD_AIRCRAFT :{WHITE}Kan inte bygga flygplan... +STR_A009_AIRCRAFT :{WHITE}{STRING} - Flygplan +STR_A00A :{WHITE}{STRING} +STR_A00B_ORDERS :{WHITE}{STRING} (Order) +STR_A00C_DETAILS :{WHITE}{STRING} (Detaljer) +STR_A00D_AGE_RUNNING_COST_YR :{BLACK}Ålder: {LTBLUE}{STRING}{BLACK} Löpande kostnad: {LTBLUE}{CURRENCY}/yr +STR_A00E_MAX_SPEED :{BLACK}Max. hastighet: {LTBLUE}{VELOCITY} +STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Vinst detta år: {LTBLUE}{CURRENCY} (förra år: {CURRENCY}) +STR_A010_RELIABILITY_BREAKDOWNS :{BLACK}Tillförlitlighet: {LTBLUE}{COMMA8}% {BLACK}Motorstopp sedan förra service: {LTBLUE}{COMMA16} +STR_A011_BUILT_VALUE :{LTBLUE}{STRING}{BLACK} Byggt: {LTBLUE}{NUMU16}{BLACK} Värde: {LTBLUE}{CURRENCY} +STR_A012_CAN_T_SEND_AIRCRAFT_TO :{WHITE}Kan inte skicka flygplan till hangar... +STR_HEADING_FOR_HANGAR :{LTBLUE}På väg mot {STATION} Hangar +STR_HEADING_FOR_HANGAR_VEL :{LTBLUE}På väg mot {STATION} Hangar, {VELOCITY} +STR_A014_AIRCRAFT_IS_WAITING_IN :{WHITE}Flygplan {COMMA16} väntar i flygplanshangar +STR_A015_AIRCRAFT_IN_THE_WAY :{WHITE}Flygplan i vägen +STR_A016_CAN_T_STOP_START_AIRCRAFT :{WHITE}Kan inte stoppa/starta flygplan... +STR_A017_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Flygplan är i luften +STR_A018_MUST_BUILD_AIRPORT_FIRST :{WHITE}Måste bygga flygplats först +STR_A019_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING}, {STRING} +STR_A01A_CAPACITY :{BLACK}Kapacitet: {LTBLUE}{STRING} +STR_A01B_AIRCRAFT_MUST_BE_STOPPED :{WHITE}Flygplan måste stoppas i hangar +STR_A01C_CAN_T_SELL_AIRCRAFT :{WHITE}Kan inte sälja flygplan... +STR_A01D_AIRPORT_CONSTRUCTION :Flygplatsbyggnation +STR_A01E_BUILD_AIRPORT :{BLACK}Bygg flygplats +STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Flygplan - Klicka på flygplan för information +STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES :{BLACK}Bygg nytt flygplan (kräver flygplats med hangar) +STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT :{BLACK}Flygplan - Klicka på flygplan för information +STR_A022_BUILD_NEW_AIRCRAFT :{BLACK}Bygg nytt flygplan +STR_A023_DRAG_AIRCRAFT_TO_HERE_TO :{BLACK}Dra flygplan hit för att sälja det +STR_A024_CENTER_MAIN_VIEW_ON_HANGAR :{BLACK}Centrera vyn ovanför hangaren +STR_A025_AIRCRAFT_SELECTION_LIST :{BLACK}Flygplanslista - Klicka på flygplan för information +STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT :{BLACK}Bygg markerat flygplan +STR_A027_CURRENT_AIRCRAFT_ACTION :{BLACK}Nuvarande flygplansaktion - Klicka här till stoppa/starta flygplan +STR_A028_SHOW_AIRCRAFT_S_ORDERS :{BLACK}Visa flygplanets order +STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT :{BLACK}Centrera vyn ovanför flygplanet +STR_A02A_SEND_AIRCRAFT_TO_HANGAR :{BLACK}Skicka flygplan till hangar +STR_A02B_SHOW_AIRCRAFT_DETAILS :{BLACK}Visa flygplan detaljer +STR_A02C_NEW_AIRCRAFT_NOW_AVAILABLE :{BLACK}{BIGFONT}Nytt flygplan tillgängligt! +STR_A02D :{BLACK}{BIGFONT}{STRING} +STR_A02E_COST_MAX_SPEED_CAPACITY :{BLACK}Kostnad: {CURRENCY} Max. Hastighet: {VELOCITY}{}Kapacitet: {COMMA16} passagerare, {COMMA16} postsäckar{}Löpande kostnad: {CURRENCY}/yr + +STR_A030_NAME_AIRCRAFT :{WHITE}Byt namn på flygplan +STR_A031_CAN_T_NAME_AIRCRAFT :{WHITE}Kan inte byta namn på flygplan... +STR_A032_NAME_AIRCRAFT :{BLACK}Byt namn på flygplan +STR_A033_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Invånarna firar . . .{}Första flygplanet ankommer till {STATION}! +STR_A034_PLANE_CRASH_DIE_IN_FIREBALL :{BLACK}{BIGFONT}Flygplanskrasch!{}{COMMA16} dör i eldklot på {STATION} +STR_A035_DESTINATIONS :{TINYFONT}{BLACK}Destinationer: +STR_A036 :{TINYFONT}{BLACK}{STATION} +STR_A037_RENAME :{BLACK}Byt namn på +STR_A038_RENAME_AIRCRAFT_TYPE :{BLACK}Byt namn på flygplanstyp +STR_A039_RENAME_AIRCRAFT_TYPE :{WHITE}Byt namn på flygplanstyp +STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Kan inte byta namn på flygplanstyp... +STR_A03B_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Anpassa flygplan att frakta en annan godstyp +STR_A03C_REFIT :{WHITE}{STRING} (Refit) +STR_A03D_REFIT_AIRCRAFT :{BLACK}Anpassa flygplan +STR_A03E_SELECT_TYPE_OF_CARGO_FOR :{BLACK}Välj godstyp för flygplan att frakta +STR_A03F_REFIT_AIRCRAFT_TO_CARRY :{BLACK}Anpassa flygplan att frakta markerad godstyp +STR_A040_SELECT_CARGO_TYPE_TO_CARRY :{GOLD}Välj godstyp att frakta:- +STR_A041_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Ny kapacitet: {GOLD}{STRING}{}{BLACK}Kostnad av anpassning: {GOLD}{CURRENCY} +STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Kan inte anpassa flygplan... +STR_A043_REFITTABLE :(anpassningsbart) +STR_GO_TO_AIRPORT_HANGAR :Gå till {STATION} Hangar +SERVICE_AT_AIRPORT_HANGAR :Servning vid {STATION} Hangar + +##id 0xB000 +STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelinare-katastrof på {STATION}! +STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Vägfordon förstört i 'UFO'-kollision! +STR_B002_OIL_REFINERY_EXPLOSION :{BLACK}{BIGFONT}Oljeraffinaderi exploderade nära {TOWN}! +STR_B003_FACTORY_DESTROYED_IN_SUSPICIOUS:{BLACK}{BIGFONT}Fabrik förstörd i misstänkta omständigheter nära {TOWN}! +STR_B004_UFO_LANDS_NEAR :{BLACK}{BIGFONT}'UFO' landar nära {TOWN}! +STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Kolgruva sjunker - lämnar spår av katastrof nära {TOWN}! + +STR_BRIBE_FAILED :{WHITE}Ditt mutningsförsök har blivit +STR_BRIBE_FAILED_2 :{WHITE}uppdagat av en regional utredare. diff --git a/langs.dsp b/langs.dsp new file mode 100644 --- /dev/null +++ b/langs.dsp @@ -0,0 +1,141 @@ +# Microsoft Developer Studio Project File - Name="langs" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=langs - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "langs.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "langs.mak" CFG="langs - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "langs - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "langs___Win32_Debug" +# PROP BASE Intermediate_Dir "langs___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" +# Begin Target + +# Name "langs - Win32 Debug" +# Begin Source File + +SOURCE=.\lang\czech.txt +# Begin Custom Build +InputPath=.\lang\czech.txt + +"lang\czech.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\czech.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\english.txt +# Begin Custom Build +InputPath=.\lang\english.txt + +"lang\english.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\french.txt +# Begin Custom Build +InputPath=.\lang\french.txt + +"lang\french.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\french.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\german.txt +# Begin Custom Build +InputPath=.\lang\german.txt + +"lang\german.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\german.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\hungarian.txt +# Begin Custom Build +InputPath=.\lang\hungarian.txt + +"lang\hungarian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\hungarian.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\italian.txt +# Begin Custom Build +InputPath=.\lang\italian.txt + +"lang\italian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\italian.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\norwegian.txt +# Begin Custom Build +InputPath=.\lang\norwegian.txt + +"lang\norwegian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\norwegian.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\slovak.txt +# Begin Custom Build +InputPath=.\lang\slovak.txt + +"lang\slovak.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\slovak.txt + +# End Custom Build +# End Source File +# Begin Source File + +SOURCE=.\lang\swedish.txt +# Begin Custom Build +InputPath=.\lang\swedish.txt + +"lang\swedish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + strgen\debug\strgen.exe lang\swedish.txt + +# End Custom Build +# End Source File +# End Target +# End Project diff --git a/langs.vcproj b/langs.vcproj new file mode 100644 --- /dev/null +++ b/langs.vcproj @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lzoconf.h b/lzoconf.h new file mode 100644 --- /dev/null +++ b/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/macros.h b/macros.h new file mode 100644 --- /dev/null +++ b/macros.h @@ -0,0 +1,215 @@ +#ifndef MACROS_H +#define MACROS_H + +#define MAX_INT 0x7FFFFFFF + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +static INLINE int min(int a, int b) { if (a <= b) return a; return b; } +static INLINE int max(int a, int b) { if (a >= b) return a; return b; } + +static INLINE uint minu(uint a, uint b) { if (a <= b) return a; return b; } +static INLINE uint maxu(uint a, uint b) { if (a >= b) return a; return b; } + + +static INLINE int clamp(int a, int min, int max) { if (a <= min) return min; if (a >= max) return max; return a; } +static INLINE int clamp2(int a, int min, int max) { if (a <= min) a=min; if (a >= max) a=max; return a; } +static INLINE bool int32_add_overflow(int32 a, int32 b) { return (int32)(a^b)>=0 && (int32)(a^(a+b))<0; } +static INLINE bool int32_sub_overflow(int32 a, int32 b) { return (int32)(a^b)<0 && (int32)(a^(a-b))<0; } + +static INLINE bool str_eq(const byte *a, const byte *b) +{ + int i=0; + while (a[i] == b[i]) { + if (a[i] == 0) + return true; + i++; + } + return false; +} + +// Will crash if strings are equal +static INLINE bool str_is_below(byte *a, byte *b) { + while (*a <= *b) { + if (*a < *b) return true; + a++; + b++; + } + return false; +} + + +static INLINE int32 BIGMULSS(int32 a, int32 b, int shift) { + return (int32)(((int64)(a) * (int64)(b)) >> (shift)); +} + +static INLINE uint32 BIGMULUS(uint32 a, uint32 b, int shift) { + return (uint32)(((uint64)(a) * (uint64)(b)) >> (shift)); +} + +static INLINE int64 BIGMULS(int32 a, int32 b) { + return (int32)(((int64)(a) * (int64)(b))); +} + +/* OPT: optimized into an unsigned comparison */ +//#define IS_INSIDE_1D(x, base, size) ((x) >= (base) && (x) < (base) + (size)) +#define IS_INSIDE_1D(x, base, size) ( (uint)((x) - (base)) < ((uint)(size)) ) + +#define TILE_X_BITS 8 +#define TILE_Y_BITS 8 +#define LANDSCAPE_SIZE_FACTOR 1 + +#define TILE_FROM_XY(x,y) (int)((((y) >> 4) << TILE_X_BITS) + ((x) >> 4)) +#define TILE_XY(x,y) (int)(((y) << TILE_X_BITS) + (x)) + +#define IS_TILETYPE(_t_, _s_) (_map_type_and_height[(_t_)] >> 4 == (_s_)) +#define GET_TILETYPE(_t_) (_map_type_and_height[(_t_)] >> 4) +#define GET_TILEHEIGHT(_t_) ((_map_type_and_height[_t_] & 0xF) * 8) + +enum { + CORRECT_Z_BITS = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 +}; +#define CORRECT_Z(tileh) (CORRECT_Z_BITS & (1 << tileh)) + +#define TILES_X (1 << TILE_X_BITS) +#define TILES_Y (1 << TILE_Y_BITS) + +#define TILE_X_MAX (TILES_X-1) +#define TILE_Y_MAX (TILES_Y-1) + +#define TILE_ASSERT(x) assert( TILE_MASK(x) == (x) ); + +extern uint SafeTileAdd(uint x, int add, const char *exp, const char *file, int line); + +#if !defined(_DEBUG) || TILE_X_BITS != 8 +# define TILE_ADD(x,y) ((x)+(y)) +#else +# if defined(__GNUC__) +# define TILE_ADD(x,y) (SafeTileAdd((x),(y), "??", __FILE__, __LINE__)) +# else +# define TILE_ADD(x,y) (SafeTileAdd((x),(y), #x ## ", " ## #y, __FILE__, __LINE__)) +# endif +#endif + +#define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TILE_XY(x,y)) + +#if TILE_X_BITS == 8 +#define GET_TILE_X(t) (uint)((byte)(t)) +#define GET_TILE_Y(t) (uint)((t) >> 8) +#define TILE_MASK(x) ((uint16)(x)) +#else +#define GET_TILE_X(t) (uint)((t) & ((1 << TILE_X_BITS)-1)) +#define GET_TILE_Y(t) (uint)((t) >> TILE_X_BITS) +#define TILE_MASK(x) (int)((x) & ((1 << (TILE_X_BITS + TILE_Y_BITS))-1)) +#endif + +//#define REMADP_COORDS(x,y,z) { int t = x; x = (y-t)*2; y+=t-z; } + +#define PACK_POINT(x,y) ((x) | ((y) << 16)) +#define UNPACK_POINT_X(p) ((uint16)(p)) +#define UNPACK_POINT_Y(p) ((uint16)(p>>16)) + +#define PACK_PPOINT(p) PACK_POINT((p).x, (p).y) + +#define HASBIT(x,y) ((x) & (1 << (y))) +#define SETBIT(x,y) ((x) |= (1 << (y))) +#define CLRBIT(x,y) ((x) &= ~(1 << (y))) + +// checking more bits. Maybe unneccessary, but easy to use +#define HASBITS(x,y) ((x) & (y)) +#define SETBITS(x,y) ((x) |= (y)) +#define CLRBITS(x,y) ((x) &= ~(y)) + +#define PLAYER_SPRITE_COLOR(owner) ((_player_colors[owner] << 16) + 0x3070000) +#define SPRITE_PALETTE(x) ((x) + 0x8000) + +extern const byte _ffb_64[128]; +#define FIND_FIRST_BIT(x) _ffb_64[(x)] +#define KILL_FIRST_BIT(x) _ffb_64[(x)+64] + +static INLINE int FindFirstBit2x64(int value) +{ + int i = 0; + if ( (byte) value == 0) { + i += 8; + value >>= 8; + } + return i + FIND_FIRST_BIT(value & 0x3F); +} + + +#if TILE_X_BITS + TILE_Y_BITS <= 16 + typedef uint16 TileIndex; + typedef int16 TileIndexDiff; +#else + typedef uint32 TileIndex; + typedef int32 TileIndexDiff; +#endif + +/* [min,max), strictly less than */ +#define IS_BYTE_INSIDE(a,min,max) ((byte)((a)-(min)) < (byte)((max)-(min))) +#define IS_INT_INSIDE(a,min,max) ((uint)((a)-(min)) < (uint)((max)-(min))) + + +#define CHANCE16(a,b) ((uint16)Random() <= (uint16)((65536 * a) / b)) +#define CHANCE16R(a,b,r) ((uint16)(r=Random()) <= (uint16)((65536 * a) / b)) +#define CHANCE16I(a,b,v) ((uint16)(v) <= (uint16)((65536 * a) / b)) + +#define BEGIN_TILE_LOOP(var,w,h,tile) \ + {int h_cur = h; \ + uint var = tile; \ + do { \ + int w_cur = w; \ + do { + +#define END_TILE_LOOP(var,w,h,tile) \ + } while (++var, --w_cur != 0); \ + } while (var += TILE_XY(0,1) - (w), --h_cur != 0);} + + +#define for_each_bit(_i,_b) \ + for(_i=0; _b!=0; _i++,_b>>=1) \ + if (_b&1) + +#define assert_array(i,j) assert(i < lengthof(j)) + +#define abs myabs + + +static INLINE int intxchg_(int *a, int b) { int t = *a; *a = b; return t; } +#define intxchg(a,b) intxchg_(&(a), (b)) +#define intswap(a,b) ((b) = intxchg_(&(a), (b))) + +static INLINE int myabs(int a) { if (a<0) a = -a; return a; } + +static INLINE void swap_byte(byte *a, byte *b) { byte t = *a; *a = *b; *b = t; } +static INLINE void swap_uint16(uint16 *a, uint16 *b) { uint16 t = *a; *a = *b; *b = t; } +static INLINE void swap_int16(int16 *a, int16 *b) { int16 t = *a; *a = *b; *b = t; } +static INLINE void swap_tile(TileIndex *a, TileIndex *b) { TileIndex t = *a; *a = *b; *b = t; } + + + +#if defined(TTD_LITTLE_ENDIAN) +# define READ_LE_UINT16(b) (*(uint16*)(b)) +# define ADD_WORD(x) (x)&0xFF, ((x) >> 8)&0xFF +# define ADD_DWORD(x) (x)&0xFF, ((x) >> 8)&0xFF, ((x) >> 16)&0xFF, ((x) >> 24)&0xFF +#elif defined(TTD_BIG_ENDIAN) + static INLINE uint16 READ_LE_UINT16(const void *b) { + return ((byte*)b)[0] + (((byte*)b)[1] << 8); + } +# define ADD_WORD(x) ((x) >> 8)&0xFF, (x)&0xFF +# define ADD_DWORD(x) ((x) >> 24)&0xFF, ((x) >> 16)&0xFF, ((x) >> 8)&0xFF, (x)&0xFF +#endif + +static INLINE void WRITE_LE_UINT16(const void *b, uint16 x) { + ((byte*)b)[0] = (byte)x; + ((byte*)b)[1] = (byte)(x >> 8); +} + +#endif /* MACROS_H */ diff --git a/main_gui.c b/main_gui.c new file mode 100644 --- /dev/null +++ b/main_gui.c @@ -0,0 +1,2225 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "player.h" +#include "command.h" +#include "news.h" +#include "town.h" +#include "vehicle.h" + +#include "table/animcursors.h" + + +extern void DoTestSave(); +extern void DoTestLoad(); + +extern bool disable_computer; + +static int _rename_id; +static int _rename_what; + +static byte _terraform_size = 1; +static byte _last_built_railtype; +extern void GenerateWorld(int mode); + +extern void GenerateIndustries(); +extern void GenerateTowns(); + +static void HandleOnEditText(WindowEvent *e) { + byte *b = e->edittext.str; + int id; + memcpy(_decode_parameters, b, 32); + + id = _rename_id; + + switch(_rename_what) { + case 0: + // for empty string send "remove sign" parameter + DoCommandP(0, id, (*b==0)?1:0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME)); + break; + case 1: + if(*b == 0) + return; + DoCommandP(0, id, 0, NULL, CMD_RENAME_CHECKPOINT | CMD_MSG(STR_CANT_CHANGE_CHECKPOINT_NAME)); + break; + } +} + +// this code is shared for the majority of the pushbuttons +bool HandlePlacePushButton(Window *w, int widget, uint32 cursor, int mode, PlaceProc *placeproc) +{ + uint32 mask = 1 << widget; + + if (w->disabled_state & mask) + return false; + + if (!_no_button_sound) SndPlayFx(0x13); + SetWindowDirty(w); + + if (w->click_state & mask) { + ResetObjectToPlace(); + return false; + } + + SetObjectToPlace(cursor, mode, w->window_class, w->window_number); + w->click_state |= mask; + _place_proc = placeproc; + return true; +} + + +void CcPlaySound10(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { SndPlayTileFx(0x10, tile); } +} + + +typedef void ToolbarButtonProc(Window *w); + +static void ToolbarPauseClick(Window *w) +{ + if (DoCommandP(0, _pause?0:1, 0, NULL, CMD_PAUSE)) + SndPlayFx(0x13); +} + +static void ToolbarFastForwardClick(Window *w) +{ + _fast_forward ^= true; + SndPlayFx(0x13); +} + + +typedef void MenuClickedProc(int index); + + +void MenuClickSettings(int index) +{ + switch(index) { + case 0: ShowGameOptions(); return; + case 1: ShowGameDifficulty(); return; + case 2: ShowPatchesSelection(); return; + case 4: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return; + case 5: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return; + case 6: _display_opt ^= DO_SHOW_SIGNS; MarkWholeScreenDirty(); return; + case 7: _display_opt ^= DO_CHECKPOINTS; MarkWholeScreenDirty(); return; + case 8: _display_opt ^= DO_FULL_ANIMATION; MarkWholeScreenDirty(); return; + case 9: _display_opt ^= DO_FULL_DETAIL; MarkWholeScreenDirty(); return; + case 10: _display_opt ^= DO_TRANS_BUILDINGS; MarkWholeScreenDirty(); return; + } +} + +void MenuClickSaveLoad(int index) +{ + if (_game_mode == GM_EDITOR) { + switch(index) { + case 0: + ShowSaveLoadDialog(SLD_SAVE_SCENARIO); + break; + case 1: + ShowSaveLoadDialog(SLD_LOAD_SCENARIO); + break; + case 2: + AskExitToGameMenu(); + break; + case 4: + AskExitGame(); + break; + } + } else { + switch(index) { + case 0: + ShowSaveLoadDialog(SLD_SAVE_GAME); + break; + case 1: + ShowSaveLoadDialog(SLD_LOAD_GAME); + break; + case 2: + AskExitToGameMenu(); + break; + case 3: + AskExitGame(); + break; + } + } +} + +void MenuClickMap(int index) +{ + switch(index) { + case 0: ShowSmallMap(); break; + } +} + +void MenuClickTown(int index) +{ + ShowTownDirectory(); +} + +void MenuClickScenMap(int index) +{ + switch(index) { + case 0: ShowSmallMap(); break; + case 1: ShowTownDirectory(); break; + } +} + +void MenuClickSubsidies(int index) +{ + ShowSubsidiesList(); +} + +void MenuClickStations(int index) +{ + ShowPlayerStations(index); +} + +void MenuClickFinances(int index) +{ + ShowPlayerFinances(index); +} + +void MenuClickCompany(int index) +{ + ShowPlayerCompany(index); +} + + +void MenuClickGraphs(int index) +{ + switch(index) { + case 0: ShowOperatingProfitGraph(); return; + case 1: ShowIncomeGraph(); return; + case 2: ShowDeliveredCargoGraph(); return; + case 3: ShowPerformanceHistoryGraph(); return; + case 4: ShowCompanyValueGraph(); return; + case 5: ShowCargoPaymentRates(); return; + } +} + +void MenuClickLeague(int index) +{ + ShowCompanyLeagueTable(); +} + +void MenuClickIndustry(int index) +{ + switch(index) { + case 0: ShowBuildIndustryWindow(); break; + case 1: ShowIndustryDirectory(); break; + } +} + +void MenuClickShowTrains(int index) +{ + ShowPlayerTrains(index); +} + +void MenuClickShowRoad(int index) +{ + ShowPlayerRoadVehicles(index); +} + +void MenuClickShowShips(int index) +{ + ShowPlayerShips(index); +} + +void MenuClickShowAir(int index) +{ + ShowPlayerAircraft(index); +} + +void MenuClickBuildRail(int index) +{ + Player *p = DEREF_PLAYER(_local_player); + _last_built_railtype = min(index, p->max_railtype-1); + ShowBuildRailToolbar(_last_built_railtype, -1); +} + +void MenuClickBuildRoad(int index) +{ + ShowBuildRoadToolbar(); +} + +void MenuClickBuildWater(int index) +{ + ShowBuildDocksToolbar(); +} + +void MenuClickBuildAir(int index) +{ + ShowBuildAirToolbar(); +} + +void ShowRenameSignWindow(SignStruct *ss) +{ + _rename_id = ss - _sign_list; + _rename_what = 0; + ShowQueryString(ss->str, STR_280B_EDIT_SIGN_TEXT, 30, 180, 1, 0); +} + +void ShowRenameCheckpointWindow(Checkpoint *cp) +{ + int id = cp - _checkpoints; + _rename_id = id; + _rename_what = 1; + SET_DPARAM16(0, id); + ShowQueryString(STR_CHECKPOINT_RAW, STR_EDIT_CHECKPOINT_NAME, 30, 180, 1, 0); +} + +static void CcPlaceSign(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + ShowRenameSignWindow(_new_sign_struct); + ResetObjectToPlace(); + } +} + +void PlaceProc_Sign(uint tile) +{ + DoCommandP(tile, 0, 0, CcPlaceSign, CMD_PLACE_SIGN | CMD_MSG(STR_2809_CAN_T_PLACE_SIGN_HERE)); +} + +static void SelectSignTool() +{ + if (_cursor.sprite == 0x2D2) + ResetObjectToPlace(); + else { + SetObjectToPlace(0x2D2, 1, 1, 0); + _place_proc = PlaceProc_Sign; + } +} + +void MenuClickForest(int index) +{ + switch(index) { + case 0: ShowTerraformToolbar(); break; + case 1: ShowBuildTreesToolbar(); break; + case 2: SelectSignTool(); break; + } +} + +void MenuClickMusicWindow(int index) +{ + ShowMusicWindow(); +} + +void MenuClickNewspaper(int index) +{ + switch(index) { + case 0: ShowLastNewsMessage(); break; + case 1: ShowMessageOptions(); break; + case 2: ShowMessageHistory(); break; + case 3: ; /* XXX: chat not done */ + } +} + +void MenuClickHelp(int index) +{ + switch(index) { + case 0: PlaceLandBlockInfo(); break; + case 2: _make_screenshot = 1; break; + case 3: _make_screenshot = 2; break; + case 4: ShowAboutWindow(); break; + } +} + +static MenuClickedProc * const _menu_clicked_procs[] = { + NULL, /* 0 */ + NULL, /* 1 */ + MenuClickSettings, /* 2 */ + MenuClickSaveLoad, /* 3 */ + MenuClickMap, /* 4 */ + MenuClickTown, /* 5 */ + MenuClickSubsidies, /* 6 */ + MenuClickStations, /* 7 */ + MenuClickFinances, /* 8 */ + MenuClickCompany, /* 9 */ + MenuClickGraphs, /* 10 */ + MenuClickLeague, /* 11 */ + MenuClickIndustry, /* 12 */ + MenuClickShowTrains, /* 13 */ + MenuClickShowRoad, /* 14 */ + MenuClickShowShips, /* 15 */ + MenuClickShowAir, /* 16 */ + MenuClickScenMap, /* 17 */ + NULL, /* 18 */ + MenuClickBuildRail, /* 19 */ + MenuClickBuildRoad, /* 20 */ + MenuClickBuildWater, /* 21 */ + MenuClickBuildAir, /* 22 */ + MenuClickForest, /* 23 */ + MenuClickMusicWindow, /* 24 */ + MenuClickNewspaper, /* 25 */ + MenuClickHelp, /* 26 */ +}; + +static void MenuWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int count,sel; + int x,y; + uint16 chk; + StringID string; + int eo; + int inc; + + DrawWindowWidgets(w); + + count = WP(w,menu_d).item_count; + sel = WP(w,menu_d).sel_index; + chk = WP(w,menu_d).checked_items; + string = WP(w,menu_d).string_id; + + x = 1; + y = 1; + + eo = 157; + + inc = (chk != 0) ? 2 : 1; + + do { + if (sel== 0) GfxFillRect(x, y, x + eo, y+9, 0); + DrawString(x + 2, y, (StringID)(string + (chk&1)), (byte)(sel==0?(byte)0xC:(byte)0x10)); + y += 10; + string += inc; + chk >>= 1; + } while (--sel,--count); + } break; + + case WE_DESTROY: { + Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); + v->click_state &= ~(1 << WP(w,menu_d).main_button); + SetWindowDirty(v); + return; + } + + case WE_POPUPMENU_SELECT: { + int index = GetMenuItemIndex(w, e->popupmenu.pt.x, e->popupmenu.pt.y); + int action_id; + + + if (index < 0) { + Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w2, e->popupmenu.pt.x - w2->left, e->popupmenu.pt.y - w2->top) == WP(w,menu_d).main_button) + index = WP(w,menu_d).sel_index; + } + + action_id = WP(w,menu_d).action_id; + DeleteWindow(w); + + if (index >= 0) + _menu_clicked_procs[action_id](index); + + break; + } + case WE_POPUPMENU_OVER: { + int index = GetMenuItemIndex(w, e->popupmenu.pt.x, e->popupmenu.pt.y); + + if (index == -1 || index == WP(w,menu_d).sel_index) + return; + + WP(w,menu_d).sel_index = index; + SetWindowDirty(w); + return; + } + } +} + +static Widget _menu_widgets[] = { +{ WWT_PANEL, 14, 0, 159, 0, 65535, 0}, +{ WWT_LAST}, +}; + + +static Widget _player_menu_widgets[] = { +{ WWT_PANEL, 14, 0, 240, 0, 81, 0}, +{ WWT_LAST}, +}; + + +static int GetPlayerIndexFromMenu(int index) +{ + Player *p; + + if (index >= 0) { + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + if (--index < 0) + return p->index; + } + } + } + return -1; +} + +static void UpdatePlayerMenuHeight(Window *w) +{ + int num = 0; + Player *p; + + FOR_ALL_PLAYERS(p) { + if (p->is_active) + num++; + } + + if (WP(w,menu_d).item_count != num) { + WP(w,menu_d).item_count = num; + SetWindowDirty(w); + num = num * 10 + 2; + w->height = num; + _player_menu_widgets[0].bottom = _player_menu_widgets[0].top + num - 1; + SetWindowDirty(w); + } +} + +static void PlayerMenuWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int x,y; + byte sel, color; + Player *p; + uint16 chk; + + UpdatePlayerMenuHeight(w); + DrawWindowWidgets(w); + + x = 1; + y = 1; + sel = WP(w,menu_d).sel_index; + chk = WP(w,menu_d).checked_items; // let this mean gray items. + + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + if (p->index == sel) { + GfxFillRect(x, y, x + 0xEE, y + 9, 0); + } + DrawSprite( ((p->player_color + 0x307)<<16)+0x82EB, x+2, y+1); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, GetPlayerNameString(p->index)); + + color = (byte)((p->index==sel) ? 0xC : 0x10); + if (chk&1) color = 14; + DrawString(x+0x13, y, STR_7021, color); + + y += 10; + } + chk >>= 1; + } + break; + } + + case WE_DESTROY: { + Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); + v->click_state &= ~(1 << WP(w,menu_d).main_button); + SetWindowDirty(v); + return; + } + + case WE_POPUPMENU_SELECT: { + int index = GetPlayerIndexFromMenu(GetMenuItemIndex(w, e->popupmenu.pt.x, e->popupmenu.pt.y)); + int action_id = WP(w,menu_d).action_id; + + if (index < 0) { + Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w2, e->popupmenu.pt.x - w2->left, e->popupmenu.pt.y - w2->top) == WP(w,menu_d).main_button) + index = WP(w,menu_d).sel_index; + } + + DeleteWindow(w); + + if (index >= 0) { + assert(index >= 0 && index < 30); + _menu_clicked_procs[action_id](index); + } + break; + } + case WE_POPUPMENU_OVER: { + int index; + UpdatePlayerMenuHeight(w); + index = GetPlayerIndexFromMenu(GetMenuItemIndex(w, e->popupmenu.pt.x, e->popupmenu.pt.y)); + + if (index == -1 || index == WP(w,menu_d).sel_index) + return; + + WP(w,menu_d).sel_index = index; + SetWindowDirty(w); + return; + } + } +} + +static Window *PopupMainToolbMenu(Window *w, int x, int main_button, StringID base_string, int item_count) +{ + int h; + + x += w->left; + + SETBIT(w->click_state, (byte)main_button); + InvalidateWidget(w, (byte)main_button); + + DeleteWindowById(WC_TOOLBAR_MENU, 0); + + _menu_widgets[0].bottom = h = item_count * 10 + 1; + w = AllocateWindow(x, 0x16, 0xA0, h+1, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets); + w->flags4 &= ~WF_WHITE_BORDER_MASK; + + WP(w,menu_d).item_count = item_count; + WP(w,menu_d).sel_index = 0; + WP(w,menu_d).main_button = main_button; + WP(w,menu_d).action_id = (main_button >> 8) ? (main_button >> 8) : main_button; + WP(w,menu_d).string_id = base_string; + WP(w,menu_d).checked_items = 0; + + _popup_menu_active = true; + + SndPlayFx(0x13); + + return w; +} + +static Window *PopupMainPlayerToolbMenu(Window *w, int x, int main_button, int gray) +{ + x += w->left; + + SETBIT(w->click_state, main_button); + InvalidateWidget(w, main_button); + + DeleteWindowById(WC_TOOLBAR_MENU, 0); + w = AllocateWindow(x, 0x16, 0xF1, 0x52, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets); + w->flags4 &= ~WF_WHITE_BORDER_MASK; + WP(w,menu_d).item_count = 0; + WP(w,menu_d).sel_index = _local_player != 0xff ? _local_player : 0; + WP(w,menu_d).action_id = main_button; + WP(w,menu_d).main_button = main_button; + WP(w,menu_d).checked_items = gray; + _popup_menu_active = true; + SndPlayFx(0x13); + return w; +} + +static void ToolbarSaveClick(Window *w) +{ + PopupMainToolbMenu(w, 66, 3, STR_015C_SAVE_GAME, 4); +} + +static void ToolbarMapClick(Window *w) +{ + PopupMainToolbMenu(w, 96, 4, STR_02DE_MAP_OF_WORLD, 1); +} + +static void ToolbarTownClick(Window *w) +{ + PopupMainToolbMenu(w, 118, 5, STR_02BB_TOWN_DIRECTORY, 1); +} + +static void ToolbarSubsidiesClick(Window *w) +{ + PopupMainToolbMenu(w, 140, 6, STR_02DD_SUBSIDIES, 1); +} + +static void ToolbarStationsClick(Window *w) +{ + PopupMainPlayerToolbMenu(w, 162, 7, 0); +} + +static void ToolbarMoneyClick(Window *w) +{ + PopupMainPlayerToolbMenu(w, 191, 8, 0); +} + +static void ToolbarPlayersClick(Window *w) +{ + PopupMainPlayerToolbMenu(w, 213, 9, 0); +} + +static void ToolbarGraphsClick(Window *w) +{ + PopupMainToolbMenu(w, 236, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6); +} + +static void ToolbarLeagueClick(Window *w) +{ + PopupMainToolbMenu(w, 258, 11, STR_015A_COMPANY_LEAGUE_TABLE, 1); +} + +static void ToolbarIndustryClick(Window *w) +{ + PopupMainToolbMenu(w, 280, 12, STR_0313_FUND_NEW_INDUSTRY, 2); +} + +static void ToolbarTrainClick(Window *w) +{ + Vehicle *v; + int dis = -1; + FOR_ALL_VEHICLES(v) + if (v->type == VEH_Train && v->subtype == 0) CLRBIT(dis, v->owner); + PopupMainPlayerToolbMenu(w, 310, 13, dis); +} + +static void ToolbarRoadClick(Window *w) +{ + Vehicle *v; + int dis = -1; + FOR_ALL_VEHICLES(v) + if (v->type == VEH_Road) CLRBIT(dis, v->owner); + PopupMainPlayerToolbMenu(w, 332, 14, dis); +} + +static void ToolbarShipClick(Window *w) +{ + Vehicle *v; + int dis = -1; + FOR_ALL_VEHICLES(v) + if (v->type == VEH_Ship) CLRBIT(dis, v->owner); + PopupMainPlayerToolbMenu(w, 354, 15, dis); +} + +static void ToolbarAirClick(Window *w) +{ + Vehicle *v; + int dis = -1; + FOR_ALL_VEHICLES(v) + if (v->type == VEH_Aircraft) CLRBIT(dis, v->owner); + PopupMainPlayerToolbMenu(w, 376, 16, dis); +} + +bool DoZoomInOut(int how) +{ + ViewPort *vp; + Window *w, *wt; + int button; + + switch(_game_mode) { + case GM_EDITOR: button = 9; break; + case GM_NORMAL: button = 17; break; + default: return false; + } + + w = FindWindowById(WC_MAIN_WINDOW, 0); + assert(w); + vp = w->viewport; + + wt = FindWindowById(WC_MAIN_TOOLBAR, 0); + assert(wt); + + if (how == ZOOM_IN) { + if (vp->zoom == 0) return false; + vp->zoom--; + vp->virtual_width >>= 1; + vp->virtual_height >>= 1; + + WP(w,vp_d).scrollpos_x += vp->virtual_width >> 1; + WP(w,vp_d).scrollpos_y += vp->virtual_height >> 1; + + SetWindowDirty(w); + } else if (how == ZOOM_OUT) { + if (vp->zoom == 2) return false; + vp->zoom++; + + WP(w,vp_d).scrollpos_x -= vp->virtual_width >> 1; + WP(w,vp_d).scrollpos_y -= vp->virtual_height >> 1; + + vp->virtual_width <<= 1; + vp->virtual_height <<= 1; + + SetWindowDirty(w); + } + + // update the toolbar button too + CLRBIT(wt->disabled_state, button); + CLRBIT(wt->disabled_state, button + 1); + if (vp->zoom == 0) SETBIT(wt->disabled_state, button); + else if (vp->zoom == 2) SETBIT(wt->disabled_state, button + 1); + SetWindowDirty(wt); + + return true; +} + +static void MaxZoomIn() +{ + while (DoZoomInOut(ZOOM_IN)) {} +} + +static void ToolbarZoomInClick(Window *w) +{ + if (DoZoomInOut(ZOOM_IN)) { + HandleButtonClick(w, 17); + SndPlayFx(0x13); + } +} + +static void ToolbarZoomOutClick(Window *w) +{ + if (DoZoomInOut(ZOOM_OUT)) { + HandleButtonClick(w, 18); + SndPlayFx(0x13); + } +} + +static void ToolbarBuildRailClick(Window *w) +{ + Player *p = DEREF_PLAYER(_local_player); + Window *w2; + w2 = PopupMainToolbMenu(w, 457, 19, STR_1015_RAILROAD_CONSTRUCTION, p->max_railtype); + WP(w2,menu_d).sel_index = _last_built_railtype; +} + +static void ToolbarBuildRoadClick(Window *w) +{ + PopupMainToolbMenu(w, 479, 20, STR_180A_ROAD_CONSTRUCTION, 1); +} + +static void ToolbarBuildWaterClick(Window *w) +{ + PopupMainToolbMenu(w, 501, 21, STR_9800_DOCK_CONSTRUCTION, 1); +} + +static void ToolbarBuildAirClick(Window *w) +{ + PopupMainToolbMenu(w, 0x1E0, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1); +} + +static void ToolbarForestClick(Window *w) +{ + PopupMainToolbMenu(w, 0x1E0, 23, STR_LANDSCAPING, 3); +} + +static void ToolbarMusicClick(Window *w) +{ + PopupMainToolbMenu(w, 0x1E0, 24, STR_01D3_SOUND_MUSIC, 1); +} + +static void ToolbarNewspaperClick(Window *w) +{ + PopupMainToolbMenu(w, 0x1E0, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, _newspaper_flag != 2 ? 3 : 4); +} + +static void ToolbarHelpClick(Window *w) +{ + PopupMainToolbMenu(w, 0x1E0, 26, STR_02D5_LAND_BLOCK_INFO, 5); +} + +static void ToolbarOptionsClick(Window *w) +{ + uint16 x; + + w = PopupMainToolbMenu(w, 43, 2, STR_02C3_GAME_OPTIONS, 11); + + x = (uint16)-1; + if (_display_opt & DO_SHOW_TOWN_NAMES) x &= ~(1<<4); + if (_display_opt & DO_SHOW_STATION_NAMES) x &= ~(1<<5); + if (_display_opt & DO_SHOW_SIGNS) x &= ~(1<<6); + if (_display_opt & DO_CHECKPOINTS) x &= ~(1<<7); + if (_display_opt & DO_FULL_ANIMATION) x &= ~(1<<8); + if (_display_opt & DO_FULL_DETAIL) x &= ~(1<<9); + if (!(_display_opt & DO_TRANS_BUILDINGS)) x &= ~(1<<10); + WP(w,menu_d).checked_items = x; +} + + +static void ToolbarScenSaveOrLoad(Window *w) +{ + PopupMainToolbMenu(w, 0x2C, 3, STR_0292_SAVE_SCENARIO, 5); +} + +static void ToolbarScenDateBackward(Window *w) +{ + // don't allow too fast scrolling + if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) { + HandleButtonClick(w, 6); + InvalidateWidget(w, 5); + + if (_date > 0x2ACE) { + SetDate(ConvertYMDToDay(_cur_year - 1, 0, 1)); + } + } + _left_button_clicked = false; +} + +static void ToolbarScenDateForward(Window *w) +{ + // don't allow too fast scrolling + if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) { + HandleButtonClick(w, 7); + InvalidateWidget(w, 5); + + if (_date < 0x4E79) { + SetDate(ConvertYMDToDay(_cur_year + 1, 0, 1)); + } + } + _left_button_clicked = false; +} + +static void ToolbarScenMapTownDir(Window *w) +{ + PopupMainToolbMenu(w, 0x16A, 8 | (17<<8), STR_02DE_MAP_OF_WORLD, 2); +} + +static void ToolbarScenZoomIn(Window *w) +{ + if (DoZoomInOut(ZOOM_IN)) { + HandleButtonClick(w, 9); + SndPlayFx(0x13); + } +} + +static void ToolbarScenZoomOut(Window *w) +{ + if (DoZoomInOut(ZOOM_OUT)) { + HandleButtonClick(w, 10); + SndPlayFx(0x13); + } +} + +void ZoomInOrOutToCursor(bool in) +{ + Point pt; + Window* w; + ViewPort* vp; + + w = FindWindowById(WC_MAIN_WINDOW, 0); + assert(w != 0); + + vp = w->viewport; + + if (_game_mode != GM_MENU) { + if ((in && vp->zoom == 0) || (!in && vp->zoom == 2)) + return; + + pt = GetTileZoomCenter(in); + if (pt.x != -1) { + ScrollMainWindowTo(pt.x, pt.y); + + DoZoomInOut(in ? ZOOM_IN : ZOOM_OUT); + } + } +} + +void ResetLandscape() +{ + _random_seed_1 = InteractiveRandom(); + _random_seed_2 = InteractiveRandom(); + + GenerateWorld(1); + MarkWholeScreenDirty(); +} + +static const Widget _ask_reset_landscape_widgets[] = { +{ WWT_TEXTBTN, 4, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 4, 11, 179, 0, 13, STR_022C_RESET_LANDSCAPE}, +{ WWT_IMGBTN, 4, 0, 179, 14, 91, 0x0}, +{ WWT_TEXTBTN, 12, 25, 84, 72, 83, STR_00C9_NO}, +{ WWT_TEXTBTN, 12, 95, 154, 72, 83, STR_00C8_YES}, +{ WWT_LAST}, +}; + +// Ask first to reset landscape or to make a random landscape +static void AskResetLandscapeWndProc(Window *w, WindowEvent *e) +{ + uint mode = w->window_number; + + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + DrawStringMultiCenter(90, 38, mode?STR_022D_ARE_YOU_SURE_YOU_WANT_TO:STR_GENERATE_RANDOM_LANDSCAPE , 168); + case WE_CLICK: + switch(e->click.widget) { + case 3: + DeleteWindow(w); + break; + case 4: + DeleteWindow(w); + if(mode) { // reset landscape + ResetLandscape(); + } + else { // make random landscape + SndPlayFx(0x13); + _switch_mode = SM_GENRANDLAND; + } + + break; + } + } +} + +static const WindowDesc _ask_reset_landscape_desc = { + 230,205, 180, 92, + WC_ASK_RESET_LANDSCAPE,0, + WDF_STD_BTN | WDF_DEF_WIDGET, + _ask_reset_landscape_widgets, + AskResetLandscapeWndProc, +}; + +static void AskResetLandscape(uint mode) +{ + AllocateWindowDescFront(&_ask_reset_landscape_desc, mode); +} + +static void CcTerraform(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1D, tile); + } else { + SetRedErrorSquare(_terraform_err_tile); + } +} + +static void CommonRaiseLowerBigLand(uint tile, int mode) +{ + int size; + uint h; + + _error_message_2 = mode ? STR_0808_CAN_T_RAISE_LAND_HERE : STR_0809_CAN_T_LOWER_LAND_HERE; + + _generating_world = true; + +// tile = TILE_FROM_XY(GET_TILE_X(tile)*16+_tile_fract_coords.x + 8,GET_TILE_Y(tile)*16+_tile_fract_coords.y + 8); + + if (_terraform_size == 1) { + DoCommandP(tile, 8, (uint32)mode, CcTerraform, CMD_TERRAFORM_LAND | CMD_AUTO); + } else { + SndPlayTileFx(0x1D, tile); + + size = _terraform_size; + assert(size != 0); + if (mode != 0) { + /* Raise land */ + h = 15; + BEGIN_TILE_LOOP(tile2, size, size, tile) + h = min(h, _map_type_and_height[tile2]&0xF); + END_TILE_LOOP(tile2, size, size, tile) + } else { + /* Lower land */ + h = 0; + BEGIN_TILE_LOOP(tile2, size, size, tile) + h = max(h, _map_type_and_height[tile2]&0xF); + END_TILE_LOOP(tile2, size, size, tile) + } + + BEGIN_TILE_LOOP(tile2, size, size, tile) + if ((uint)(_map_type_and_height[tile2]&0xF) == h) { + DoCommandP(tile2, 8, (uint32)mode, NULL, CMD_TERRAFORM_LAND | CMD_AUTO); + } + END_TILE_LOOP(tile2, size, size, tile) + } + + _generating_world = false; +} + +void PlaceProc_RaiseBigLand(uint tile) +{ + CommonRaiseLowerBigLand(tile, 1); +} + +void PlaceProc_LowerBigLand(uint tile) +{ + CommonRaiseLowerBigLand(tile, 0); +} + +//static void CcDemolish(bool success, uint tile, uint32 p1, uint32 p2) +//{ +// if (success) { + //SndPlayTileFx(0x10, tile); + //CreateEffectVehicleAbove(GET_TILE_X(tile)*16 + 8,GET_TILE_Y(tile)*16 + 8, 2, EV_DEMOLISH); +// } +//} + +//void PlaceProc_Demolish(uint tile) +//{ +// DoCommandP(tile, 0, 0, CcDemolish, CMD_LANDSCAPE_CLEAR | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); +//} + + +void PlaceProc_RockyArea(uint tile) +{ + if (!IS_TILETYPE(tile, MP_CLEAR)) + return; + + _map5[tile] = (_map5[tile] & ~0x1C) | 8; + MarkTileDirtyByTile(tile); + SndPlayTileFx(0x1D, tile); +} + +void PlaceProc_LightHouse(uint tile) +{ + TileInfo ti; + + FindLandscapeHeightByTile(&ti, tile); + if (ti.type != MP_CLEAR || (ti.tileh & 0x10)) + return; + + ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAP5, 1); + SndPlayTileFx(0x1D, tile); +} + +void PlaceProc_Transmitter(uint tile) +{ + TileInfo ti; + + FindLandscapeHeightByTile(&ti, tile); + if (ti.type != MP_CLEAR || (ti.tileh & 0x10)) + return; + + ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAP5, 0); + SndPlayTileFx(0x1D, tile); +} + +void PlaceProc_Desert(uint tile) +{ + SetMapExtraBits(tile, GetMapExtraBits(tile) == 1 ? 0 : 1); +} + +static const Widget _scen_edit_land_gen_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 153, 0, 13, STR_0223_LAND_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 7, 0, 153, 14, 99, 0x0, 0}, +{ WWT_IMGBTN, 14, 22, 43, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_IMGBTN, 14, 44, 65, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_IMGBTN, 14, 0, 21, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_TEXTBTN, 14, 125, 135, 43, 54, STR_0224, STR_0228_INCREASE_SIZE_OF_LAND_AREA}, +{ WWT_TEXTBTN, 14, 125, 135, 56, 67, STR_0225, STR_0229_DECREASE_SIZE_OF_LAND_AREA}, +{ WWT_TEXTBTN, 14, 20, 135, 75, 86, STR_0226_RANDOM_LAND, STR_022A_GENERATE_RANDOM_LAND}, +{ WWT_TEXTBTN, 14, 20, 135, 88, 99, STR_0227_RESET_LAND, STR_022B_RESET_LANDSCAPE}, + +{ WWT_IMGBTN, 14, 88, 109, 14, 35, 0xFF4, STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE}, +{ WWT_IMGBTN, 14, 110, 131, 14, 35, 0xFF5, STR_028D_PLACE_LIGHTHOUSE}, +{ WWT_IMGBTN, 14, 132, 153, 14, 35, 0xFF6, STR_028E_PLACE_TRANSMITTER}, +{ WWT_IMGBTN, 14, 66, 87, 14, 35, SPR_OPENTTD_BASE+68, STR_LEVEL_LAND_TOOLTIP}, +{ WWT_LAST}, +}; + +static const int8 _multi_terraform_coords[][2] = { + { 0, -2}, + { 4, 0},{ -4, 0},{ 0, 2}, + { -8, 2},{ -4, 4},{ 0, 6},{ 4, 4},{ 8, 2}, + {-12, 0},{ -8, -2},{ -4, -4},{ 0, -6},{ 4, -4},{ 8, -2},{ 12, 0}, + {-16, 2},{-12, 4},{ -8, 6},{ -4, 8},{ 0, 10},{ 4, 8},{ 8, 6},{ 12, 4},{ 16, 2}, + {-20, 0},{-16, -2},{-12, -4},{ -8, -6},{ -4, -8},{ 0,-10},{ 4, -8},{ 8, -6},{ 12, -4},{ 16, -2},{ 20, 0}, + {-24, 2},{-20, 4},{-16, 6},{-12, 8},{ -8, 10},{ -4, 12},{ 0, 14},{ 4, 12},{ 8, 10},{ 12, 8},{ 16, 6},{ 20, 4},{ 24, 2}, + {-28, 0},{-24, -2},{-20, -4},{-16, -6},{-12, -8},{ -8,-10},{ -4,-12},{ 0,-14},{ 4,-12},{ 8,-10},{ 12, -8},{ 16, -6},{ 20, -4},{ 24, -2},{ 28, 0}, +}; + +static void ScenEditLandGenWndProc(Window *w, WindowEvent *e) +{ + // XXX: show different tooltips in desert mode + switch(e->event) { + case WE_PAINT: + // XXX: only show reset button when nothing was built + DrawWindowWidgets(w); + + { + int n = _terraform_size * _terraform_size; + const int8 *coords = &_multi_terraform_coords[0][0]; + + assert(n != 0); + do { + DrawSprite(0xFEF, 77 + coords[0], 55 + coords[1]); + coords += 2; + } while (--n); + } + + if (_thd.window_class == WC_SCEN_LAND_GEN && (w->click_state&(1<<3|1<<4))) { + SetTileSelectSize(_terraform_size, _terraform_size); + } + break; + case WE_CLICK: + switch(e->click.widget) { + case 3: /* raise corner */ + HandlePlacePushButton(w, 3, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseBigLand); + break; + case 4: /* lower corner */ + HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerBigLand); + break; + case 5: /* demolish */ + HandlePlacePushButton(w, 5, ANIMCURSOR_DEMOLISH, 1, PlaceProc_DemolishArea); + break; + { + int size; + case 6: /* increase terraform size */ + HandleButtonClick(w, 6); + size = 1; + goto terraform_size_common; + case 7: /* decrease terraform size */ + HandleButtonClick(w, 7); + size = -1; +terraform_size_common:; + size += _terraform_size; + if (!IS_INT_INSIDE(size, 1, 8+1)) + return; + _terraform_size = size; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + + case 8: /* gen random land */ + HandleButtonClick(w, 8); + AskResetLandscape(0); + break; + + case 9: /* reset landscape */ + HandleButtonClick(w,9); + AskResetLandscape(1); + break; + + case 10: /* place rocky areas */ + HandlePlacePushButton(w, 10, 0xFF7, 1, PlaceProc_RockyArea); + break; + + case 11: /* place lighthouse */ + HandlePlacePushButton(w, 11, 0xFF8, 1, _opt.landscape == LT_DESERT ? PlaceProc_Desert : PlaceProc_LightHouse); + break; + + case 12: /* place transmitter */ + HandlePlacePushButton(w, 12, 0xFF9, 1, PlaceProc_Transmitter); + break; + + case 13: /* level Land */ + HandlePlacePushButton(w, 13, SPR_OPENTTD_BASE+69, 2, PlaceProc_LevelLand); + break; + } + break; + case WE_TIMEOUT: + UnclickSomeWindowButtons(w, ~(1<<3 | 1<<4 | 1<<5 | 1<<10|1<<11|1<<12)); + 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 & 0xF); + return; + } + case WE_PLACE_MOUSEUP: + if (e->click.pt.x != -1) { + uint start_tile = e->place.starttile; + uint end_tile = e->place.tile; + if (e->place.userdata == VPM_X_AND_Y) { + DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + } else if (e->place.userdata == (VPM_X_AND_Y | (2<<4))) { + DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO); + } + } + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + break; + } +} + +static const WindowDesc _scen_edit_land_gen_desc = { + -1,-1, 154, 100, + WC_SCEN_LAND_GEN,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scen_edit_land_gen_widgets, + ScenEditLandGenWndProc, +}; + +static void ToolbarScenGenLand(Window *w) +{ + HandleButtonClick(w, 11); + SndPlayFx(0x13); + + AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0); +} + +static void CcBuildTown(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1D, tile); + ResetObjectToPlace(); + } +} + +void PlaceProc_Town(uint tile) +{ + DoCommandP(tile, 0, 0, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE)); +} + + +static const Widget _scen_edit_town_gen_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 159, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 7, 0, 159, 14, 81, 0x0}, +{ WWT_TEXTBTN, 14, 2, 157, 16, 27, STR_0234_NEW_TOWN, STR_0235_CONSTRUCT_NEW_TOWN}, +{ WWT_TEXTBTN, 14, 2, 157, 29, 40, STR_023D_RANDOM_TOWN, STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION}, +{ WWT_TEXTBTN, 14, 2, 157, 42, 53, STR_MANY_RANDOM_TOWNS, STR_RANDOM_TOWNS_TIP}, +{ WWT_TEXTBTN, 14, 2, 53, 68, 79, STR_02A1_SMALL, STR_02A4_SELECT_TOWN_SIZE}, +{ WWT_TEXTBTN, 14, 54, 105, 68, 79, STR_02A2_MEDIUM, STR_02A4_SELECT_TOWN_SIZE}, +{ WWT_TEXTBTN, 14, 106, 157, 68, 79, STR_02A3_LARGE, STR_02A4_SELECT_TOWN_SIZE}, +{ WWT_LAST}, +}; + +static void ScenEditTownGenWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + w->click_state = (w->click_state & ~(1<<6 | 1<<7 | 1<<8) ) | (1 << (_new_town_size + 6)); + DrawWindowWidgets(w); + DrawStringCentered(80, 56, STR_02A5_TOWN_SIZE, 0); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: /* new town */ + HandlePlacePushButton(w, 3, 0xFF0, 1, PlaceProc_Town); + break; + case 4: {/* random town */ + Town *t; + + HandleButtonClick(w, 4); + _generating_world = true; + t = CreateRandomTown(); + _generating_world = false; + if (t != NULL) + ScrollMainWindowToTile(t->xy); + break; + } + case 5: {/* many random towns */ + HandleButtonClick(w, 5); + _generating_world = true; + _game_mode = GM_NORMAL; // little hack to avoid towns of the same size + GenerateTowns(); + _generating_world = false; + _game_mode = GM_EDITOR; + break; + } + + case 6: case 7: case 8: + _new_town_size = e->click.widget - 6; + SetWindowDirty(w); + break; + } + break; + + case WE_TIMEOUT: + UnclickSomeWindowButtons(w, 1<<4 | 1<<5); + break; + case WE_PLACE_OBJ: + _place_proc(e->place.tile); + break; + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + break; + } +} + +static const WindowDesc _scen_edit_town_gen_desc = { + -1,-1, 160, 82, + WC_SCEN_TOWN_GEN,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scen_edit_town_gen_widgets, + ScenEditTownGenWndProc, +}; + +static void ToolbarScenGenTown(Window *w) +{ + HandleButtonClick(w, 12); + SndPlayFx(0x13); + + AllocateWindowDescFront(&_scen_edit_town_gen_desc, 0); +} + + +static const Widget _scenedit_industry_normal_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_023F_INDUSTRY_GENERATION}, +{ WWT_IMGBTN, 7, 0, 169, 14, 224, 0x0}, + +{ WWT_TEXTBTN, 14, 2, 167, 16, 27, STR_MANY_RANDOM_INDUSTRIES, STR_RANDOM_INDUSTRIES_TIP}, + +{ WWT_TEXTBTN, 14, 2, 167, 42, 53, STR_0240_COAL_MINE, STR_0262_CONSTRUCT_COAL_MINE}, +{ WWT_TEXTBTN, 14, 2, 167, 55, 66, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_TEXTBTN, 14, 2, 167, 68, 79, STR_0242_SAWMILL, STR_0264_CONSTRUCT_SAWMILL}, +{ WWT_TEXTBTN, 14, 2, 167, 81, 92, STR_0243_FOREST, STR_0265_PLANT_FOREST}, +{ WWT_TEXTBTN, 14, 2, 167, 94, 105, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_TEXTBTN, 14, 2, 167, 107, 118, STR_0245_OIL_RIG, STR_0267_CONSTRUCT_OIL_RIG_CAN_ONLY}, +{ WWT_TEXTBTN, 14, 2, 167, 120, 131, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY}, +{ WWT_TEXTBTN, 14, 2, 167, 133, 144, STR_0247_STEEL_MILL, STR_0269_CONSTRUCT_STEEL_MILL}, +{ WWT_TEXTBTN, 14, 2, 167, 146, 157, STR_0248_FARM, STR_026A_CONSTRUCT_FARM}, +{ WWT_TEXTBTN, 14, 2, 167, 159, 170, STR_0249_IRON_ORE_MINE, STR_026B_CONSTRUCT_IRON_ORE_MINE}, +{ WWT_TEXTBTN, 14, 2, 167, 172, 183, STR_024A_OIL_WELLS, STR_026C_CONSTRUCT_OIL_WELLS}, +{ WWT_TEXTBTN, 14, 2, 167, 185, 196, STR_024B_BANK, STR_026D_CONSTRUCT_BANK_CAN_ONLY}, +{ WWT_LAST}, +}; + + +static const Widget _scenedit_industry_hilly_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_023F_INDUSTRY_GENERATION}, +{ WWT_IMGBTN, 7, 0, 169, 14, 224, 0x0}, + +{ WWT_TEXTBTN, 14, 2, 167, 16, 27, STR_MANY_RANDOM_INDUSTRIES, STR_RANDOM_INDUSTRIES_TIP}, + +{ WWT_TEXTBTN, 14, 2, 167, 42, 53, STR_0240_COAL_MINE, STR_0262_CONSTRUCT_COAL_MINE}, +{ WWT_TEXTBTN, 14, 2, 167, 55, 66, STR_0241_POWER_STATION, STR_0263_CONSTRUCT_POWER_STATION}, +{ WWT_TEXTBTN, 14, 2, 167, 68, 79, STR_024C_PAPER_MILL, STR_026E_CONSTRUCT_PAPER_MILL}, +{ WWT_TEXTBTN, 14, 2, 167, 81, 92, STR_0243_FOREST, STR_0265_PLANT_FOREST}, +{ WWT_TEXTBTN, 14, 2, 167, 94, 105, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_TEXTBTN, 14, 2, 167, 107, 118, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_TEXTBTN, 14, 2, 167, 120, 131, STR_024E_PRINTING_WORKS, STR_0270_CONSTRUCT_PRINTING_WORKS}, +{ WWT_TEXTBTN, 14, 2, 167, 133, 144, STR_024F_GOLD_MINE, STR_0271_CONSTRUCT_GOLD_MINE}, +{ WWT_TEXTBTN, 14, 2, 167, 146, 157, STR_0248_FARM, STR_026A_CONSTRUCT_FARM}, +{ WWT_TEXTBTN, 14, 2, 167, 159, 170, STR_024B_BANK, STR_0272_CONSTRUCT_BANK_CAN_ONLY}, +{ WWT_TEXTBTN, 14, 2, 167, 172, 183, STR_024A_OIL_WELLS, STR_026C_CONSTRUCT_OIL_WELLS}, +{ WWT_LAST}, +}; + +static const Widget _scenedit_industry_desert_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_023F_INDUSTRY_GENERATION}, +{ WWT_IMGBTN, 7, 0, 169, 14, 224, 0x0}, + +{ WWT_TEXTBTN, 14, 2, 167, 16, 27, STR_MANY_RANDOM_INDUSTRIES, STR_RANDOM_INDUSTRIES_TIP}, + +{ WWT_TEXTBTN, 14, 2, 167, 42, 53, STR_0250_LUMBER_MILL, STR_0273_CONSTRUCT_LUMBER_MILL_TO}, +{ WWT_TEXTBTN, 14, 2, 167, 55, 66, STR_0251_FRUIT_PLANTATION, STR_0274_PLANT_FRUIT_PLANTATION}, +{ WWT_TEXTBTN, 14, 2, 167, 68, 79, STR_0252_RUBBER_PLANTATION, STR_0275_PLANT_RUBBER_PLANTATION}, +{ WWT_TEXTBTN, 14, 2, 167, 81, 92, STR_0244_OIL_REFINERY, STR_0266_CONSTRUCT_OIL_REFINERY}, +{ WWT_TEXTBTN, 14, 2, 167, 94, 105, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING}, +{ WWT_TEXTBTN, 14, 2, 167, 107, 118, STR_0246_FACTORY, STR_0268_CONSTRUCT_FACTORY}, +{ WWT_TEXTBTN, 14, 2, 167, 120, 131, STR_0253_WATER_SUPPLY, STR_0276_CONSTRUCT_WATER_SUPPLY}, +{ WWT_TEXTBTN, 14, 2, 167, 133, 144, STR_0248_FARM, STR_026A_CONSTRUCT_FARM}, +{ WWT_TEXTBTN, 14, 2, 167, 146, 157, STR_0254_WATER_TOWER, STR_0277_CONSTRUCT_WATER_TOWER_CAN}, +{ WWT_TEXTBTN, 14, 2, 167, 159, 170, STR_024A_OIL_WELLS, STR_026C_CONSTRUCT_OIL_WELLS}, +{ WWT_TEXTBTN, 14, 2, 167, 172, 183, STR_024B_BANK, STR_0272_CONSTRUCT_BANK_CAN_ONLY}, +{ WWT_TEXTBTN, 14, 2, 167, 185, 196, STR_0255_DIAMOND_MINE, STR_0278_CONSTRUCT_DIAMOND_MINE}, +{ WWT_TEXTBTN, 14, 2, 167, 198, 209, STR_0256_COPPER_ORE_MINE, STR_0279_CONSTRUCT_COPPER_ORE_MINE}, +{ WWT_LAST}, +}; + +static const Widget _scenedit_industry_candy_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 7, 11, 169, 0, 13, STR_023F_INDUSTRY_GENERATION}, +{ WWT_IMGBTN, 7, 0, 169, 14, 224, 0x0}, + +{ WWT_TEXTBTN, 14, 2, 167, 16, 27, STR_MANY_RANDOM_INDUSTRIES, STR_RANDOM_INDUSTRIES_TIP}, + +{ WWT_TEXTBTN, 14, 2, 167, 42, 53, STR_0257_COTTON_CANDY_FOREST, STR_027A_PLANT_COTTON_CANDY_FOREST}, +{ WWT_TEXTBTN, 14, 2, 167, 55, 66, STR_0258_CANDY_FACTORY, STR_027B_CONSTRUCT_CANDY_FACTORY}, +{ WWT_TEXTBTN, 14, 2, 167, 68, 79, STR_0259_BATTERY_FARM, STR_027C_CONSTRUCT_BATTERY_FARM}, +{ WWT_TEXTBTN, 14, 2, 167, 81, 92, STR_025A_COLA_WELLS, STR_027D_CONSTRUCT_COLA_WELLS}, +{ WWT_TEXTBTN, 14, 2, 167, 94, 105, STR_025B_TOY_SHOP, STR_027E_CONSTRUCT_TOY_SHOP}, +{ WWT_TEXTBTN, 14, 2, 167, 107, 118, STR_025C_TOY_FACTORY, STR_027F_CONSTRUCT_TOY_FACTORY}, +{ WWT_TEXTBTN, 14, 2, 167, 120, 131, STR_025D_PLASTIC_FOUNTAINS, STR_0280_CONSTRUCT_PLASTIC_FOUNTAINS}, +{ WWT_TEXTBTN, 14, 2, 167, 133, 144, STR_025E_FIZZY_DRINK_FACTORY, STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY}, +{ WWT_TEXTBTN, 14, 2, 167, 146, 157, STR_025F_BUBBLE_GENERATOR, STR_0282_CONSTRUCT_BUBBLE_GENERATOR}, +{ WWT_TEXTBTN, 14, 2, 167, 159, 170, STR_0260_TOFFEE_QUARRY, STR_0283_CONSTRUCT_TOFFEE_QUARRY}, +{ WWT_TEXTBTN, 14, 2, 167, 172, 183, STR_0261_SUGAR_MINE, STR_0284_CONSTRUCT_SUGAR_MINE}, +{ WWT_LAST}, +}; + +int _industry_type_to_place; + +static bool AnyTownExists() { + Town *t; + FOR_ALL_TOWNS(t) { + if (t->xy) + return true; + } + return false; +} + +extern Industry *CreateNewIndustry(uint tile, int type); + +static bool TryBuildIndustry(TileIndex tile, int type) +{ + int n; + + n = 100; + do { + if (CreateNewIndustry(AdjustTileCoordRandomly(tile, 1), type)) return true; + } while (--n); + + n = 200; + do { + if (CreateNewIndustry(AdjustTileCoordRandomly(tile, 2), type)) return true; + } while (--n); + + n = 700; + do { + if (CreateNewIndustry(AdjustTileCoordRandomly(tile, 4), type)) return true; + } while (--n); + + return false; +} + + +static const byte _industry_type_list[4][16] = { + {0, 1, 2, 3, 4, 5, 6, 8, 9, 18, 11, 12}, + {0, 1, 14, 3, 4, 13, 7, 15, 9, 16, 11, 12}, + {25, 19, 20, 4, 13, 23, 21, 24, 22, 11, 16, 17, 10}, + {26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}, +}; + +static void ScenEditIndustryWndProc(Window *w, WindowEvent *e) +{ + int button; + + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + break; + + case WE_CLICK: + if ((button=e->click.widget) == 3) { + HandleButtonClick(w, 3); + + if (!AnyTownExists()) { + ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_CAN_T_GENERATE_INDUSTRIES, 0, 0); + return; + } + + _generating_world = true; + GenerateIndustries(); + _generating_world = false; + } + + if ((button=e->click.widget) >= 4) { + if (HandlePlacePushButton(w, button, 0xFF1, 1, NULL)) + _industry_type_to_place = _industry_type_list[_opt.landscape][button - 4]; + } + break; + case WE_PLACE_OBJ: { + int type; + + // Show error if no town exists at all + type = _industry_type_to_place; + if (!AnyTownExists()) { + SET_DPARAM16(0, type + STR_4802_COAL_MINE); + ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST,STR_0285_CAN_T_BUILD_HERE,e->place.pt.x, e->place.pt.y); + return; + } + + _current_player = OWNER_NONE; + _generating_world = true; + if (!TryBuildIndustry(e->place.tile,type)) { + SET_DPARAM16(0, type + STR_4802_COAL_MINE); + ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE,e->place.pt.x, e->place.pt.y); + } + _generating_world = false; + break; + } + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + break; + case WE_TIMEOUT: + UnclickSomeWindowButtons(w, 1<<3); + break; + } +} + +static const WindowDesc _scenedit_industry_normal_desc = { + -1,-1, 170, 225, + WC_SCEN_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scenedit_industry_normal_widgets, + ScenEditIndustryWndProc, +}; + +static const WindowDesc _scenedit_industry_hilly_desc = { + -1,-1, 170, 225, + WC_SCEN_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scenedit_industry_hilly_widgets, + ScenEditIndustryWndProc, +}; + +static const WindowDesc _scenedit_industry_desert_desc = { + -1,-1, 170, 225, + WC_SCEN_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scenedit_industry_desert_widgets, + ScenEditIndustryWndProc, +}; + +static const WindowDesc _scenedit_industry_candy_desc = { + -1,-1, 170, 225, + WC_SCEN_INDUSTRY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _scenedit_industry_candy_widgets, + ScenEditIndustryWndProc, +}; + +static const WindowDesc * const _scenedit_industry_descs[] = { + &_scenedit_industry_normal_desc, + &_scenedit_industry_hilly_desc, + &_scenedit_industry_desert_desc, + &_scenedit_industry_candy_desc, +}; + + +static void ToolbarScenGenIndustry(Window *w) +{ + HandleButtonClick(w, 13); + SndPlayFx(0x13); + AllocateWindowDescFront(_scenedit_industry_descs[_opt.landscape],0); +} + +static void ToolbarScenBuildRoad(Window *w) +{ + HandleButtonClick(w, 14); + SndPlayFx(0x13); + ShowBuildRoadScenToolbar(); +} + +static void ToolbarScenPlantTrees(Window *w) +{ + HandleButtonClick(w, 15); + SndPlayFx(0x13); + ShowBuildTreesScenToolbar(); +} + +static void ToolbarScenPlaceSign(Window *w) +{ + HandleButtonClick(w, 16); + SndPlayFx(0x13); + SelectSignTool(); +} + +static void ToolbarBtn_NULL(Window *w) +{ +} + +static ToolbarButtonProc* const _toolbar_button_procs[] = { + ToolbarPauseClick, + ToolbarFastForwardClick, + ToolbarOptionsClick, + ToolbarSaveClick, + ToolbarMapClick, + ToolbarTownClick, + ToolbarSubsidiesClick, + ToolbarStationsClick, + ToolbarMoneyClick, + ToolbarPlayersClick, + ToolbarGraphsClick, + ToolbarLeagueClick, + ToolbarIndustryClick, + ToolbarTrainClick, + ToolbarRoadClick, + ToolbarShipClick, + ToolbarAirClick, + ToolbarZoomInClick, + ToolbarZoomOutClick, + ToolbarBuildRailClick, + ToolbarBuildRoadClick, + ToolbarBuildWaterClick, + ToolbarBuildAirClick, + ToolbarForestClick, + ToolbarMusicClick, + ToolbarNewspaperClick, + ToolbarHelpClick, +}; + +static void MainToolbarWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + + // Draw brown-red toolbar bg. + GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2); + GfxFillRect(0, 0, w->width-1, w->height-1, 0x80B4); + + // if spectator, disable things + if (_current_player == 0xff){ + w->disabled_state |= (1 << 0) | (1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23); + } else { + w->disabled_state &= ~((1 << 0) | (1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)); + } + + DrawWindowWidgets(w); + break; + } + + case WE_CLICK: { + if (_game_mode != GM_MENU && !HASBIT(w->disabled_state, e->click.widget)) + _toolbar_button_procs[e->click.widget](w); + } break; + + case WE_KEYPRESS: { + int local = _local_player; + if (local == 0xff) local = 0; // spectator + + switch(e->keypress.keycode) { + case WKC_F1: ToolbarPauseClick(w); break; + case WKC_F2: ShowGameOptions(); break; + case WKC_F3: MenuClickSaveLoad(0); break; + case WKC_F4: ShowSmallMap(); break; + case WKC_F5: ShowTownDirectory(); break; + case WKC_F6: ShowSubsidiesList(); break; + case WKC_F7: ShowPlayerStations(local); break; + case WKC_F8: ShowPlayerFinances(local); break; + case WKC_F9: ShowPlayerCompany(local); break; + case WKC_F10:ShowOperatingProfitGraph(); break; + case WKC_F11: ShowCompanyLeagueTable(); break; + case WKC_F12: ShowBuildIndustryWindow(); break; + case WKC_SHIFT | WKC_F1: ShowPlayerTrains(local); break; + case WKC_SHIFT | WKC_F2: ShowPlayerRoadVehicles(local); break; + case WKC_SHIFT | WKC_F3: ShowPlayerShips(local); break; + case WKC_SHIFT | WKC_F4: ShowPlayerAircraft(local); break; + case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break; + case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break; + case WKC_SHIFT | WKC_F7: ShowBuildRailToolbar(_last_built_railtype,-1); break; + case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(); break; + case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break; + case WKC_SHIFT | WKC_F10:ShowBuildAirToolbar(); break; + case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break; + case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break; + case WKC_CTRL | 'S': _make_screenshot = 1; break; + case WKC_CTRL | 'G': _make_screenshot = 2; break; + case WKC_CTRL | WKC_ALT | 'C': if(!_networking) ShowCheatWindow(); break; + } + } break; + + case WE_PLACE_OBJ: { + _place_proc(e->place.tile); + } break; + + case WE_ABORT_PLACE_OBJ: { + w->click_state &= ~(1<<25); + SetWindowDirty(w); + } break; + + case WE_ON_EDIT_TEXT: HandleOnEditText(e); break; + + case WE_MOUSELOOP: + + if (((w->click_state) & 1) != (uint)!!_pause) { + w->click_state ^= (1 << 0); + SetWindowDirty(w); + } + + if (((w->click_state >> 1) & 1) != (uint)!!_fast_forward) { + w->click_state ^= (1 << 1); + SetWindowDirty(w); + } + break; + + case WE_TIMEOUT: + UnclickSomeWindowButtons(w, ~(1<<0 | 1<<1)); + break; + } +} + +static const Widget _toolb_normal_widgets[] = { +{ WWT_PANEL, 14, 0, 21, 0, 21, 0x2D6, STR_0171_PAUSE_GAME}, +{ WWT_PANEL, 14, 22, 43, 0, 21, SPR_OPENTTD_BASE + 57, STR_FAST_FORWARD}, +{ WWT_PANEL, 14, 44, 65, 0, 21, 0x2EF, STR_0187_OPTIONS}, +{ WWT_PANEL_2, 14, 66, 87, 0, 21, 0x2D4, STR_0172_SAVE_GAME_ABANDON_GAME}, + +{ WWT_PANEL, 14, 96, 117, 0, 21, 0x2C4, STR_0174_DISPLAY_MAP}, +{ WWT_PANEL, 14, 118, 139, 0, 21, 0xFED, STR_0176_DISPLAY_TOWN_DIRECTORY}, +{ WWT_PANEL, 14, 140, 161, 0, 21, 0x2A7, STR_02DC_DISPLAY_SUBSIDIES}, +{ WWT_PANEL, 14, 162, 183, 0, 21, 0x513, STR_0173_DISPLAY_LIST_OF_COMPANY}, + +{ WWT_PANEL, 14, 191, 212, 0, 21, 0x2E1, STR_0177_DISPLAY_COMPANY_FINANCES}, +{ WWT_PANEL, 14, 213, 235, 0, 21, 0x2E7, STR_0178_DISPLAY_COMPANY_GENERAL}, +{ WWT_PANEL, 14, 236, 257, 0, 21, 0x2E9, STR_0179_DISPLAY_GRAPHS}, +{ WWT_PANEL, 14, 258, 279, 0, 21, 0x2AC, STR_017A_DISPLAY_COMPANY_LEAGUE}, +{ WWT_PANEL, 14, 280, 301, 0, 21, 0x2E5, STR_0312_FUND_CONSTRUCTION_OF_NEW}, + +{ WWT_PANEL, 14, 310, 331, 0, 21, 0x2DB, STR_017B_DISPLAY_LIST_OF_COMPANY}, +{ WWT_PANEL, 14, 332, 353, 0, 21, 0x2DC, STR_017C_DISPLAY_LIST_OF_COMPANY}, +{ WWT_PANEL, 14, 354, 375, 0, 21, 0x2DD, STR_017D_DISPLAY_LIST_OF_COMPANY}, +{ WWT_PANEL, 14, 376, 397, 0, 21, 0x2DE, STR_017E_DISPLAY_LIST_OF_COMPANY}, + +{ WWT_PANEL, 14, 406, 427, 0, 21, 0x2DF, STR_017F_ZOOM_THE_VIEW_IN}, +{ WWT_PANEL, 14, 428, 449, 0, 21, 0x2E0, STR_0180_ZOOM_THE_VIEW_OUT}, + +{ WWT_PANEL, 14, 457, 478, 0, 21, 0x2D7, STR_0181_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 14, 479, 500, 0, 21, 0x2D8, STR_0182_BUILD_ROADS}, +{ WWT_PANEL, 14, 501, 522, 0, 21, 0x2D9, STR_0183_BUILD_SHIP_DOCKS}, +{ WWT_PANEL, 14, 523, 544, 0, 21, 0x2DA, STR_0184_BUILD_AIRPORTS}, +{ WWT_PANEL, 14, 545, 566, 0, 21, 0xFF3, STR_0185_PLANT_TREES_PLACE_SIGNS}, // tree icon is 0x2E6 + +{ WWT_PANEL, 14, 574, 595, 0, 21, 0x2C9, STR_01D4_SHOW_SOUND_MUSIC_WINDOW}, +{ WWT_PANEL, 14, 596, 617, 0, 21, 0x2A8, STR_0203_SHOW_LAST_MESSAGE_NEWS}, +{ WWT_PANEL, 14, 618, 639, 0, 21, 0x2D3, STR_0186_LAND_BLOCK_INFORMATION}, +{ WWT_LAST}, +}; + +static const WindowDesc _toolb_normal_desc = { + 0, 0, 640, 22, + WC_MAIN_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET, + _toolb_normal_widgets, + MainToolbarWndProc +}; + +static const WindowDesc _toolb_intro_desc = { + 0, -22, 640, 22, + WC_MAIN_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET, + _toolb_normal_widgets, + MainToolbarWndProc +}; + + +static const Widget _toolb_scen_widgets[] = { +{ WWT_PANEL, 14, 0, 21, 0, 21, 0x2D6, STR_0171_PAUSE_GAME}, +{ WWT_PANEL, 14, 22, 43, 0, 21, SPR_OPENTTD_BASE + 57, STR_FAST_FORWARD}, +{ WWT_PANEL, 14, 44, 65, 0, 21, 0x2EF, STR_0187_OPTIONS}, +{ WWT_PANEL_2, 14, 66, 87, 0, 21, 0x2D4, STR_0297_SAVE_SCENARIO_LOAD_SCENARIO }, + +{ WWT_PANEL, 14, 96, 225, 0, 21, 0x0}, + +{ WWT_PANEL, 14, 233, 362, 0, 21, 0x0}, +{ WWT_CLOSEBOX, 14, 236, 246, 5, 16, STR_0225, STR_029E_MOVE_THE_STARTING_DATE}, +{ WWT_CLOSEBOX, 14, 347, 357, 5, 16, STR_0224, STR_029F_MOVE_THE_STARTING_DATE}, + +{ WWT_PANEL, 14, 371, 392, 0, 21, 0x2C4, STR_0175_DISPLAY_MAP_TOWN_DIRECTORY}, + +{ WWT_PANEL, 14, 400, 421, 0, 21, 0x2DF, STR_017F_ZOOM_THE_VIEW_IN}, +{ WWT_PANEL, 14, 422, 443, 0, 21, 0x2E0, STR_0180_ZOOM_THE_VIEW_OUT}, + +{ WWT_PANEL, 14, 452, 473, 0, 21, 0xFF3, STR_022E_LANDSCAPE_GENERATION}, +{ WWT_PANEL, 14, 474, 495, 0, 21, 0xFED, STR_022F_TOWN_GENERATION}, +{ WWT_PANEL, 14, 496, 517, 0, 21, 0x2E5, STR_0230_INDUSTRY_GENERATION}, +{ WWT_PANEL, 14, 518, 539, 0, 21, 0x2D8, STR_0231_ROAD_CONSTRUCTION}, +{ WWT_PANEL, 14, 540, 561, 0, 21, 0x2E6, STR_0288_PLANT_TREES}, +{ WWT_PANEL, 14, 562, 583, 0, 21, 0xFF2, STR_0289_PLACE_SIGN}, + +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_PANEL, 14, 596, 617, 0, 21, 0x2C9,STR_01D4_SHOW_SOUND_MUSIC_WINDOW}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_PANEL, 14, 618, 639, 0, 21, 0x2D3, STR_0186_LAND_BLOCK_INFORMATION}, +{ WWT_LAST}, +}; + +static ToolbarButtonProc* const _scen_toolbar_button_procs[] = { + ToolbarPauseClick, + ToolbarFastForwardClick, + ToolbarOptionsClick, + ToolbarScenSaveOrLoad, + ToolbarBtn_NULL, + ToolbarBtn_NULL, + ToolbarScenDateBackward, + ToolbarScenDateForward, + ToolbarScenMapTownDir, + ToolbarScenZoomIn, + ToolbarScenZoomOut, + ToolbarScenGenLand, + ToolbarScenGenTown, + ToolbarScenGenIndustry, + ToolbarScenBuildRoad, + ToolbarScenPlantTrees, + ToolbarScenPlaceSign, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ToolbarMusicClick, + NULL, + ToolbarHelpClick, +}; + +static void ScenEditToolbarWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + // Draw brown-red toolbar bg. + GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2); + GfxFillRect(0, 0, w->width-1, w->height-1, 0x80B4); + + DrawWindowWidgets(w); + + SET_DPARAM16(0, _date); + DrawStringCentered(298, 6, STR_00AF, 0); + + SET_DPARAM16(0, _date); + DrawStringCentered(161, 1, STR_0221_TRANSPORT_TYCOON, 0); + DrawStringCentered(161, 11,STR_0222_SCENARIO_EDITOR, 0); + + break; + + case WE_CLICK: { + if (_game_mode == GM_MENU) + return; + _scen_toolbar_button_procs[e->click.widget](w); + } break; + + case WE_KEYPRESS: { + switch(e->keypress.keycode) { + case WKC_F1: ToolbarPauseClick(w); break; + case WKC_F2: ShowGameOptions(); break; + case WKC_F3: MenuClickSaveLoad(0); break; + case WKC_F4: ToolbarScenGenLand(w); break; + case WKC_F5: ToolbarScenGenTown(w); break; + case WKC_F6: ToolbarScenGenIndustry(w); break; + case WKC_F7: ToolbarScenBuildRoad(w); break; + case WKC_F8: ToolbarScenPlantTrees(w); break; + case WKC_F9: ToolbarScenPlaceSign(w); break; + case WKC_F10: ShowMusicWindow(); break; + case WKC_F11: PlaceLandBlockInfo(); break; + case WKC_CTRL | 'S': _make_screenshot = 1; break; + case WKC_CTRL | 'G': _make_screenshot = 2; break; + } + break; + } + + case WE_PLACE_OBJ: { + _place_proc(e->place.tile); + } break; + + case WE_ABORT_PLACE_OBJ: { + w->click_state &= ~(1<<25); + SetWindowDirty(w); + } break; + + case WE_ON_EDIT_TEXT: HandleOnEditText(e); break; + + case WE_MOUSELOOP: + if (((w->click_state >> 1) & 1) != (uint)!!_fast_forward) { + w->click_state ^= (1 << 1); + SetWindowDirty(w); + } + break; + + } +} + +static const WindowDesc _toolb_scen_desc = { + 0, 0, 640, 22, + WC_MAIN_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _toolb_scen_widgets, + ScenEditToolbarWndProc +}; + +extern GetNewsStringCallbackProc * const _get_news_string_callback[]; + + +static bool DrawScrollingStatusText(NewsItem *ni, int pos) +{ + StringID str; + byte *s, *d; + DrawPixelInfo tmp_dpi, *old_dpi; + int x; + byte buffer[256]; + + if (ni->display_mode == 3) { + str = _get_news_string_callback[ni->callback](ni); + } else { + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + str = ni->string_id; + } + + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + s = str_buffr; + d = buffer; + + for(;;s++) { + if (*s == 0) { + *d = 0; + break; + } else if (*s == 0x0D) { + d[0] = d[1] = d[2] = d[3] = ' '; + d+=4; + } else if (*s >= ' ' && (*s < 0x88 || *s >= 0x99)) { + *d++ = *s; + } + } + + if (!FillDrawPixelInfo(&tmp_dpi, NULL, 141, 1, 358, 11)) + return true; + + old_dpi = _cur_dpi; + _cur_dpi = &tmp_dpi; + + x = DoDrawString(buffer, pos, 0, 13); + _cur_dpi = old_dpi; + + return x > 0; +} + +void StatusBarWndProc(Window *w, WindowEvent *e) +{ + Player *p; + + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + SET_DPARAM16(0, _date); + DrawStringCentered(70, 1, ((_pause||_patches.status_long_date)?STR_00AF:STR_00AE), 0); + + p = _local_player == 0xff ? NULL : DEREF_PLAYER(_local_player); + + if (p) { + // Draw player money + SET_DPARAM64(0, p->money64); + DrawStringCentered(570, 1, p->player_money >= 0 ? STR_0004 : STR_0005, 0); + } + + // Draw status bar + if (_do_autosave) { + DrawStringCentered(320, 1, STR_032F_AUTOSAVE, 0); + } else if (_pause) { + DrawStringCentered(320, 1, STR_0319_PAUSED, 0); + } else if (WP(w,def_d).data_1 > -1280 && FindWindowById(WC_NEWS_WINDOW,0) == NULL && _statusbar_news_item.string_id != 0) { + // Draw the scrolling news text + if (!DrawScrollingStatusText(&_statusbar_news_item, WP(w,def_d).data_1)) + WP(w,def_d).data_1 = -1280; + } else { + if (p) { + // This is the default text + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawStringCentered(320, 1, STR_02BA, 0); + } + } + break; + + case WE_CLICK: + if (e->click.widget == 1) { + ShowLastNewsMessage(); + } else if (e->click.widget == 2) { + if (_local_player != 0xff) ShowPlayerFinances(_local_player); + } else { + ResetObjectToPlace(); + } + break; + + case WE_TICK: { + if (_pause || WP(w,def_d).data_1 <= -1280) + return; + WP(w,def_d).data_1 -= 2; + InvalidateWidget(w, 1); + break; + } + } +} + +static void ScrollMainViewport(int x, int y) +{ + if (_game_mode != GM_MENU) { + Window *w = FindWindowById(WC_MAIN_WINDOW, 0); + assert(w); + + WP(w,vp_d).scrollpos_x += x << w->viewport->zoom; + WP(w,vp_d).scrollpos_y += y << w->viewport->zoom; + } +} + + +static const Widget _main_status_widgets[] = { +{ WWT_IMGBTN, 14, 0, 139, 0, 11, 0x0, 0}, +{ WWT_PUSHIMGBTN, 14, 140, 499, 0, 11, 0x0, STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS}, +{ WWT_PUSHIMGBTN, 14, 500, 639, 0, 11, 0x0, 0}, +{ WWT_LAST}, +}; + +static WindowDesc _main_status_desc = { + WDP_CENTER, 0, 640, 12, + WC_STATUS_BAR,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _main_status_widgets, + StatusBarWndProc +}; + +extern void DebugProc(int i); + +static void MainWindowWndProc(Window *w, WindowEvent *e) { + int off_x; + + switch(e->event) { + case WE_PAINT: + DrawWindowViewport(w); + if (_game_mode == GM_MENU) { + off_x = ((_screen.width - 400) >> 1) - 70; + + DrawSprite(0x12EA, off_x+0-40, 50); // o + DrawSprite(0x12E9, off_x+28-40,50); // p + DrawSprite(SPR_OPENTTD_BASE+16, off_x+55-40,50); // e + DrawSprite(0x12E7, off_x+84-40,50); // n + + DrawSprite(0x12E4, off_x+90, 50); // t + DrawSprite(0x12E5, off_x+119, 50); // r + DrawSprite(0x12E6, off_x+148,50); // a + DrawSprite(0x12E7, off_x+181,50); // n + DrawSprite(0x12E8, off_x+215,50); // s + DrawSprite(0x12E9, off_x+246,50); // p + DrawSprite(0x12EA, off_x+275,50); // o + DrawSprite(0x12E5, off_x+307,50); // r + DrawSprite(0x12E4, off_x+337,50); // t + + DrawSprite(0x12E4, off_x+390,50); // t + DrawSprite(0x12EB, off_x+417,50); // y + DrawSprite(0x12EC, off_x+447,50); // c + DrawSprite(0x12EA, off_x+478,50); // o + DrawSprite(0x12EA, off_x+509,50); // o + DrawSprite(0x12E7, off_x+541,50); // n + } + break; + + case WE_KEYPRESS: + if (_game_mode == GM_MENU) + break; + + // this is a hack, but this needs to be called at a constant interval and i found + // no other window event that was suited for that purpose. + { + static const int8 scrollamt[16][2] = { + {0,0}, + {-1,0}, // 1:left + {0,-1}, // 2:up + {-1,-1}, // 3:left + up + {1,0}, // 4:right + {0,0}, // 5:left + right + {1,-1}, // 6:right + up + {0,0}, // 7:impossible + {0,1}, // 8:down + {-1,1}, // 9:down+left + {0,0}, // 10:impossible + {0,0}, // 11:impossible + {1,1}, // 12:down+right + {0,0}, // 13:impossible + {0,0}, // 14:impossible + {0,0}, // 15:impossible + }; + + if (_dirkeys) { + int factor = _shift_pressed ? 50 : 10; + ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor); + } + } + + switch(e->keypress.keycode) { + case 'C': + case 'Z': { + Point pt; + pt = GetTileBelowCursor(); + if (pt.x != -1) { + ScrollMainWindowTo(pt.x, pt.y); + if (e->keypress.keycode == 'Z') + MaxZoomIn(); + } + break; + } + + case WKC_ESC: ResetObjectToPlace(); break; + case WKC_DELETE: DeleteNonVitalWindows(); break; + case 'Q' | WKC_CTRL: AskExitGame(); break; + case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac + case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break; + case '0' | WKC_ALT: + case '1' | WKC_ALT: + case '2' | WKC_ALT: + case '3' | WKC_ALT: + case '4' | WKC_ALT: +#if defined(_DEBUG) + DebugProc(e->keypress.keycode - ('0' | WKC_ALT)); +#endif + break; + case 'A' | WKC_CTRL: + disable_computer^=1; + ShowInfoF("Disable Computer: %s", disable_computer?"ON":"OFF"); + break; + case 'B' | WKC_CTRL: + _local_player^=1; + ShowInfoF("Play as computer: %s", _local_player?"ON":"OFF"); + break; + + // invoke autorail + case 'A': + ShowBuildRailToolbar(_last_built_railtype, 0); + break; + + case 'X': + _display_opt ^= DO_TRANS_BUILDINGS; + MarkWholeScreenDirty(); + break; + + default: + return; + } + e->keypress.cont = false; + break; + + } +} + + +void ShowSelectGameWindow(); + +void SetupColorsAndInitialWindow() +{ + int i; + byte *b; + Window *w; + int width,height; + + for(i=0; i!=16; i++) { + b = GetSpritePtr(0x307 + i); + assert(b); + _color_list[i] = *(ColorList*)(b + 0xC6); + } + + width = _screen.width; + height = _screen.height; + + // XXX: these are not done + switch(_game_mode) { + case GM_MENU: + w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL); + AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0); +// w = AllocateWindowDesc(&_toolb_intro_desc); +// w->flags4 &= ~WF_WHITE_BORDER_MASK; + ShowSelectGameWindow(); + break; + case GM_NORMAL: + w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL); + AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0); + + w = AllocateWindowDesc(&_toolb_normal_desc); + w->disabled_state = 1 << 17; + w->flags4 &= ~WF_WHITE_BORDER_MASK; + + _main_status_desc.top = height - 12; + w = AllocateWindowDesc(&_main_status_desc); + w->flags4 &= ~WF_WHITE_BORDER_MASK; + + WP(w,def_d).data_1 = -1280; + + break; + case GM_EDITOR: + w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL); + AssignWindowViewport(w, 0, 0, width, height, 0, 0); + + w = AllocateWindowDesc(&_toolb_scen_desc); + w->disabled_state = 1 << 9; + w->flags4 &= ~WF_WHITE_BORDER_MASK; + break; + default: + NOT_REACHED(); + } +} + +void GameSizeChanged() +{ + RelocateAllWindows(_screen.width, _screen.height); + ScreenSizeChanged(); + MarkWholeScreenDirty(); +} diff --git a/mainicon.ico b/mainicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0770ed6c53435a51d451b0277387642ebded219a GIT binary patch literal 766 zc${^Tp>D%45QfjKrGSCPnlxgN!qF-X3TQ~tXpHhO%_~LekVzh;aImnT>g~?wr0%4h zbFn}FXWz*-fTFhD=D_x|0{Ec*lYC3wkSowZ>sRoP_2GlQmyR0^rfH&{XE1z#C>=MR z;-8pqUpG9uMh3> $(MAKE_CONFIG) 2> /dev/null + +$(MAKE_CONFIG): + + touch $(MAKE_CONFIG) + + $(call CONFIG_LINE,\# OpenTTD config file for makefile) + $(call CONFIG_LINE,\# Set your options here - 1 for use and empty for disable) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# User setup flags) + $(call CONFIG_LINE,\# Translator: adds TODO to any untranslated strings) + $(call CONFIG_LINE,\# Display_Warnings: when off it hides some warnings while compiling) + $(call CONFIG_LINE,\# MIDI: sets path to midi player) + $(call CONFIG_LINE,\# MIDI_ARG: sets an argument which is used when calling the midi player. Default off) + $(call CONFIG_LINE,STATIC:=$(STATIC)) + $(call CONFIG_LINE,TRANSLATOR:=$(TRANSLATOR)) + $(call CONFIG_LINE,DISPLAY_WARNINGS:=$(DISPLAY_WARNINGS)) + $(call CONFIG_LINE,DEBUG:=$(DEBUG)) + $(call CONFIG_LINE,PROFILE:=$(PROFILE)) + $(call CONFIG_LINE,MIDI:=$(MIDI)) + $(call CONFIG_LINE,MIDI_ARG:=$(MIDI_ARG)) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# DATA_DIR_PREFIX is the path to OpenTTD. It can be absolute or relative) + $(call CONFIG_LINE,\# USE_HOMEDIR sets \~/ in front of DATA_DIR_PREFIX so it uses the homedir) + $(call CONFIG_LINE,\# do not type \~/ yourself because that will not work) + $(call CONFIG_LINE,\# Folders should end with /) + $(call CONFIG_LINE,BINARY_DIR:=$(BINARY_DIR)) + $(call CONFIG_LINE,INSTALL_DIR:=$(INSTALL_DIR)) + $(call CONFIG_LINE,USE_HOMEDIR:=$(USE_HOMEDIR)) + $(call CONFIG_LINE,GAME_DATA_DIR:=$(GAME_DATA_DIR)) + $(call CONFIG_LINE,PERSONAL_DIR:=$(PERSONAL_DIR)) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# Experimental) + $(call CONFIG_LINE,WITH_NETWORK:=$(WITH_NETWORK)) + $(call CONFIG_LINE,WITH_DIRECTMUSIC:=$(WITH_DIRECTMUSIC)) + $(call CONFIG_LINE,) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# Flag to skip test for OS when building static) + $(call CONFIG_LINE,\# OpenTTD have only been succesfully tested with static builds on MorphOS and MacOSX) + $(call CONFIG_LINE,\# If you want to try anyway on other OSes, set this flag) + $(call CONFIG_LINE,\# Inform us if you have success) + $(call CONFIG_LINE,SKIP_STATIC_CHECK:=$(SKIP_STATIC_CHECK)) + $(call CONFIG_LINE,) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# Everything below this line is autogenerated) + $(call CONFIG_LINE,\#) + $(call CONFIG_LINE,\# If you need to change anything below, you should run "make upgradeconf") + $(call CONFIG_LINE,\# If that does not fix the problem, you should make a bug report.) + $(call CONFIG_LINE,\# It would really help if you could tell how to autodetect the missing setting) + $(call CONFIG_LINE,\# That info could be where the missing lib is placed) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# Libs) + $(call CONFIG_LINE,WITH_ZLIB:=$(WITH_ZLIB)) + $(call CONFIG_LINE,WITH_SDL:=$(WITH_SDL)) + $(call CONFIG_LINE,WITH_PNG:=$(WITH_PNG)) + $(call CONFIG_LINE,STATIC_ZLIB_PATH:=$(STATIC_ZLIB_PATH)) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# OS flags) + $(call CONFIG_LINE,WIN32:=$(WIN32)) + $(call CONFIG_LINE,UNIX:=$(UNIX)) + $(call CONFIG_LINE,OSX:=$(OSX)) + $(call CONFIG_LINE,FREEBSD:=$(FREEBSD)) + $(call CONFIG_LINE,MORPHOS:=$(MORPHOS)) + $(call CONFIG_LINE,CYGWIN:=$(CYGWIN)) + $(call CONFIG_LINE,MINGW:=$(MINGW)) + $(call CONFIG_LINE,) + + $(call CONFIG_LINE,\# misc) + $(call CONFIG_LINE,SDL-CONFIG:=$(SDL-CONFIG)) + $(call CONFIG_LINE,CONFIG_INCLUDED:=yes) + $(call CONFIG_LINE,PATH_SET:=$(PATH_SET)) diff --git a/makefiledir/Makefile.libdetection b/makefiledir/Makefile.libdetection new file mode 100644 --- /dev/null +++ b/makefiledir/Makefile.libdetection @@ -0,0 +1,80 @@ +# this file detects what OS and libs the computer have/are running + +# Automatically recognize if building on Win32 +ifdef WINDIR +ifndef UNIX +WIN32:=1 +endif +else +UNIX:=1 +endif + +# Automatically recognize if building on FreeBSD +ifeq ($(shell uname),FreeBSD) +FREEBSD:=1 +endif + +# Automatically recognize if building on MacOSX +ifeq ($(VENDOR), apple) +OSX:=1 +# OSX uses the unix setup too +UNIX:=1 +endif + +# Automatically recognize if building on MorphOS +ifeq ($(shell uname), MorphOS) +MORPHOS:=1 +# MorphOS uses UNIX setup too +UNIX:=1 +endif + +# FreeBSD uses sdl11 instead of sdl +ifdef FREEBSD +SDL-CONFIG:=sdl11-config +else +SDL-CONFIG:=sdl-config +endif + + +# Library detections +WITH_SDL:=$(shell $(SDL-CONFIG) --version 2>/dev/null) + +# libpng detection +ifdef FREEBSD +# a little hack was needed for FreeBSD because it misses libpng-config +WITH_PNG:=$(shell ls /usr/lib | grep "libpng" 2>/dev/null) $(shell \ +ls /usr/local/lib | grep "libpng" 2>/dev/null) +ifdef WITH_PNG +# makes the flag look nicer in makefile.config +WITH_PNG:=1 +endif +else +WITH_PNG:=$(shell libpng-config --version 2>/dev/null) +endif + +ifdef WITH_PNG +# LibPNG depends on Zlib +WITH_ZLIB:=1 +else +# We go looking for zlib with a little hack +WITH_ZLIB:=$(shell ls /usr/include | grep "zlib.h" 2>/dev/null) \ +$(shell ls /usr/local/include | grep "zlib.h" 2>/dev/null) +ifdef WITH_ZLIB +WITH_ZLIB:=1 +endif +endif + + +# sets the default paths +ifdef UNIX +ifndef OSX +ifndef MORPHOS +ifndef BIN_DIR +#BINARY_DIR:= +#DATA_DIR_PREFIX:= +#INSTALL_DIR:=/usr/local/ +#USE_HOMEDIR:= +endif +endif +endif +endif \ No newline at end of file diff --git a/media/icon-psd.zip b/media/icon-psd.zip new file mode 100644 index 0000000000000000000000000000000000000000..282b104cc18d65b113d0897b7e1d0e25d399835a GIT binary patch literal 42414 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 diff --git a/minilzo.c b/minilzo.c new file mode 100644 --- /dev/null +++ b/minilzo.c @@ -0,0 +1,1964 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define LZO_DISABLE_CHECKS +#define LZO1X + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +static const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +// static lzo_bool schedule_insns_bug(void); +// static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 12 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + register const lzo_byte *ip; + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { + register const lzo_byte *m_pos; + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { + goto match; + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++) { + + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; + register const lzo_byte *m_pos; + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif + + LZO_UNUSED(wrkmem); + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + } + else if (t >= 16) + { + m_pos = op; + m_pos -= (t & 8) << 11; + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; + } + else + { + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; + goto match_done; + } + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +match_done: + t = ip[-2] & 3; + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + + +#if 0 + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; + register const lzo_byte *m_pos; + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif + + LZO_UNUSED(wrkmem); + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + } + else if (t >= 16) + { + m_pos = op; + m_pos -= (t & 8) << 11; + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif + } + else + { +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; + goto match_done; + } + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ + + diff --git a/minilzo.h b/minilzo.h new file mode 100644 --- /dev/null +++ b/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/misc.c b/misc.c new file mode 100644 --- /dev/null +++ b/misc.c @@ -0,0 +1,785 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "gfx.h" +#include "assert.h" +#include "saveload.h" + +extern void StartupEconomy(); +extern void InitNewsItemStructs(); + +static uint32 _random_seed_3, _random_seed_4; + +byte _name_array[512][32]; + +static INLINE uint32 ROR(uint32 x, int n) +{ + return (x >> n) + (x << ((sizeof(x)*8)-n)); +} + + +uint32 Random() +{ + uint32 t = _random_seed_2; + uint32 s = _random_seed_1; + _random_seed_1 = s + ROR(t ^ 0x1234567F, 7); + return _random_seed_2 = ROR(s, 3); +} + +uint RandomRange(uint max) +{ + return (uint16)Random() * max >> 16; +} + +uint32 InteractiveRandom() +{ + uint32 t = _random_seed_4; + uint32 s = _random_seed_3; + _random_seed_3 = s + ROR(t ^ 0x1234567F, 7); + return _random_seed_4 = ROR(s, 3); +} + +void memswap(void *a, void *b, size_t size) { + void *c = alloca(size); + memcpy(c, a, size); + memcpy(a, b, size); + memcpy(b, c, size); +} + +void SetDate(uint date) +{ + YearMonthDay ymd; + ConvertDayToYMD(&ymd, _date = date); + _cur_year = ymd.year; + _cur_month = ymd.month; +} + +void InitializeClearLand(); +void InitializeRail(); +void InitializeRailGui(); +void InitializeRoad(); +void InitializeRoadGui(); +void InitializeAirportGui(); +void InitializeDock(); +void InitializeDockGui(); +void InitializeIndustries(); +void InitializeLandscape(); +void InitializeTowns(); +void InitializeTrees(); +void InitializeStations(); +void InitializeNameMgr(); +void InitializePlayers(); +void InitializeCheats(); + +void GenerateLandscape(); +void GenerateClearTile(); + +void GenerateIndustries(); +void GenerateUnmovables(); +void GenerateTowns(); + +void StartupPlayers(); +void StartupEngines(); +void StartupDisasters(); +void GenerateTrees(); + +void ConvertGroundTilesIntoWaterTiles(); + +void InitializeGame() +{ + SetObjectToPlace(1, 0, 0, 0); + + _pause = 0; + _fast_forward = 0; + _tick_counter = 0; + _date_fract = 0; + _cur_tileloop_tile = 0; + _vehicle_id_ctr_day = 0; + + { + uint starting = ConvertIntDate(_patches.starting_date); + if ( starting == (uint)-1) starting = 10958; + SetDate(starting); + } + + InitializeVehicles(); + _backup_orders_tile = 0; + + InitNewsItemStructs(); + InitializeLandscape(); + InitializeClearLand(); + InitializeRail(); + InitializeRailGui(); + InitializeRoad(); + InitializeRoadGui(); + InitializeAirportGui(); + InitializeDock(); + InitializeDockGui(); + InitializeTowns(); + InitializeTrees(); + InitializeStations(); + InitializeIndustries(); + + InitializeNameMgr(); + InitializeTrains(); + + InitializePlayers(); + InitializeCheats(); + + InitTextEffects(); + InitializeAnimatedTiles(); + + InitializeLandscapeVariables(false); + + ResetObjectToPlace(); +} + +void GenerateWorld(int mode) +{ + int i; + + _generating_world = true; + InitializeGame(); + SetObjectToPlace(1, 0, 0, 0); + + // Must start economy early because of the costs. + StartupEconomy(); + + // Don't generate landscape items when in the scenario editor. + if (mode == 1) { + // empty world in scenario editor + ConvertGroundTilesIntoWaterTiles(); + } else { + GenerateLandscape(); + GenerateClearTile(); + + // only generate towns, tree and industries in newgame mode. + if (mode == 0) { + GenerateTowns(); + GenerateTrees(); + GenerateIndustries(); + GenerateUnmovables(); + } + } + + // These are probably pointless when inside the scenario editor. + StartupPlayers(); + StartupEngines(); + StartupDisasters(); + _generating_world = false; + + // No need to run the tile loop in the scenario editor. + if (mode != 1) { + for(i=0x500; i!=0; i--) + RunTileLoop(); + } + + ResetObjectToPlace(); +} + +void DeleteName(StringID id) +{ + if ((id & 0xF800) == 0x7800) { + memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF])); + } +} + +byte *GetName(int id, byte *buff) +{ + byte *b; + + if (id & 0x600) { + if (id & 0x200) { + if (id & 0x400) { + GetParamInt32(); + GetParamUint16(); + } else { + GetParamUint16(); + } + } else { + GetParamInt32(); + } + } + + b = _name_array[(id&~0x600)]; + while ((*buff++ = *b++) != 0); + + return buff - 1; +} + + +void InitializeCheats() +{ + memset(&_cheats, 0, sizeof(Cheats)); +} + + +void InitializeNameMgr() +{ + memset(_name_array, 0, sizeof(_name_array)); +} + +StringID AllocateName(const byte *name, byte skip) +{ + int free_item = -1; + const byte *names; + byte *dst; + int i; + + names = &_name_array[0][0]; + + for(i=0; i!=512; i++,names+=sizeof(_name_array[0])) { + if (names[0] == 0) { + if (free_item == -1) + free_item = i; + } else { + if (str_eq(names, name)) { + _error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY; + return 0; + } + } + } + + if (free_item < 0) { + _error_message = STR_0131_TOO_MANY_NAMES_DEFINED; + return 0; + } + + dst=_name_array[free_item]; + + for(i=0; (dst[i] = name[i]) != 0 && ++i != 32; ) {} + dst[31] = 0; + + return free_item | 0x7800 | (skip << 8); +} + +const TileIndexDiff _tileoffs_by_dir[4] = { + TILE_XY(-1, 0), + TILE_XY(0, 1), + TILE_XY(1, 0), + TILE_XY(0, -1), +}; + + +#define M(a,b) ((a<<5)|b) +static const uint16 _month_date_from_year_day[] = { +M(0,1),M(0,2),M(0,3),M(0,4),M(0,5),M(0,6),M(0,7),M(0,8),M(0,9),M(0,10),M(0,11),M(0,12),M(0,13),M(0,14),M(0,15),M(0,16),M(0,17),M(0,18),M(0,19),M(0,20),M(0,21),M(0,22),M(0,23),M(0,24),M(0,25),M(0,26),M(0,27),M(0,28),M(0,29),M(0,30),M(0,31), +M(1,1),M(1,2),M(1,3),M(1,4),M(1,5),M(1,6),M(1,7),M(1,8),M(1,9),M(1,10),M(1,11),M(1,12),M(1,13),M(1,14),M(1,15),M(1,16),M(1,17),M(1,18),M(1,19),M(1,20),M(1,21),M(1,22),M(1,23),M(1,24),M(1,25),M(1,26),M(1,27),M(1,28),M(1,29), +M(2,1),M(2,2),M(2,3),M(2,4),M(2,5),M(2,6),M(2,7),M(2,8),M(2,9),M(2,10),M(2,11),M(2,12),M(2,13),M(2,14),M(2,15),M(2,16),M(2,17),M(2,18),M(2,19),M(2,20),M(2,21),M(2,22),M(2,23),M(2,24),M(2,25),M(2,26),M(2,27),M(2,28),M(2,29),M(2,30),M(2,31), +M(3,1),M(3,2),M(3,3),M(3,4),M(3,5),M(3,6),M(3,7),M(3,8),M(3,9),M(3,10),M(3,11),M(3,12),M(3,13),M(3,14),M(3,15),M(3,16),M(3,17),M(3,18),M(3,19),M(3,20),M(3,21),M(3,22),M(3,23),M(3,24),M(3,25),M(3,26),M(3,27),M(3,28),M(3,29),M(3,30), +M(4,1),M(4,2),M(4,3),M(4,4),M(4,5),M(4,6),M(4,7),M(4,8),M(4,9),M(4,10),M(4,11),M(4,12),M(4,13),M(4,14),M(4,15),M(4,16),M(4,17),M(4,18),M(4,19),M(4,20),M(4,21),M(4,22),M(4,23),M(4,24),M(4,25),M(4,26),M(4,27),M(4,28),M(4,29),M(4,30),M(4,31), +M(5,1),M(5,2),M(5,3),M(5,4),M(5,5),M(5,6),M(5,7),M(5,8),M(5,9),M(5,10),M(5,11),M(5,12),M(5,13),M(5,14),M(5,15),M(5,16),M(5,17),M(5,18),M(5,19),M(5,20),M(5,21),M(5,22),M(5,23),M(5,24),M(5,25),M(5,26),M(5,27),M(5,28),M(5,29),M(5,30), +M(6,1),M(6,2),M(6,3),M(6,4),M(6,5),M(6,6),M(6,7),M(6,8),M(6,9),M(6,10),M(6,11),M(6,12),M(6,13),M(6,14),M(6,15),M(6,16),M(6,17),M(6,18),M(6,19),M(6,20),M(6,21),M(6,22),M(6,23),M(6,24),M(6,25),M(6,26),M(6,27),M(6,28),M(6,29),M(6,30),M(6,31), +M(7,1),M(7,2),M(7,3),M(7,4),M(7,5),M(7,6),M(7,7),M(7,8),M(7,9),M(7,10),M(7,11),M(7,12),M(7,13),M(7,14),M(7,15),M(7,16),M(7,17),M(7,18),M(7,19),M(7,20),M(7,21),M(7,22),M(7,23),M(7,24),M(7,25),M(7,26),M(7,27),M(7,28),M(7,29),M(7,30),M(7,31), +M(8,1),M(8,2),M(8,3),M(8,4),M(8,5),M(8,6),M(8,7),M(8,8),M(8,9),M(8,10),M(8,11),M(8,12),M(8,13),M(8,14),M(8,15),M(8,16),M(8,17),M(8,18),M(8,19),M(8,20),M(8,21),M(8,22),M(8,23),M(8,24),M(8,25),M(8,26),M(8,27),M(8,28),M(8,29),M(8,30), +M(9,1),M(9,2),M(9,3),M(9,4),M(9,5),M(9,6),M(9,7),M(9,8),M(9,9),M(9,10),M(9,11),M(9,12),M(9,13),M(9,14),M(9,15),M(9,16),M(9,17),M(9,18),M(9,19),M(9,20),M(9,21),M(9,22),M(9,23),M(9,24),M(9,25),M(9,26),M(9,27),M(9,28),M(9,29),M(9,30),M(9,31), +M(10,1),M(10,2),M(10,3),M(10,4),M(10,5),M(10,6),M(10,7),M(10,8),M(10,9),M(10,10),M(10,11),M(10,12),M(10,13),M(10,14),M(10,15),M(10,16),M(10,17),M(10,18),M(10,19),M(10,20),M(10,21),M(10,22),M(10,23),M(10,24),M(10,25),M(10,26),M(10,27),M(10,28),M(10,29),M(10,30), +M(11,1),M(11,2),M(11,3),M(11,4),M(11,5),M(11,6),M(11,7),M(11,8),M(11,9),M(11,10),M(11,11),M(11,12),M(11,13),M(11,14),M(11,15),M(11,16),M(11,17),M(11,18),M(11,19),M(11,20),M(11,21),M(11,22),M(11,23),M(11,24),M(11,25),M(11,26),M(11,27),M(11,28),M(11,29),M(11,30),M(11,31), +}; +#undef M + +enum { + ACCUM_JAN = 0, + ACCUM_FEB = ACCUM_JAN + 31, + ACCUM_MAR = ACCUM_FEB + 29, + ACCUM_APR = ACCUM_MAR + 31, + ACCUM_MAY = ACCUM_APR + 30, + ACCUM_JUN = ACCUM_MAY + 31, + ACCUM_JUL = ACCUM_JUN + 30, + ACCUM_AUG = ACCUM_JUL + 31, + ACCUM_SEP = ACCUM_AUG + 31, + ACCUM_OCT = ACCUM_SEP + 30, + ACCUM_NOV = ACCUM_OCT + 31, + ACCUM_DEC = ACCUM_NOV + 30, +}; + +static const uint16 _accum_days_for_month[] = { + ACCUM_JAN,ACCUM_FEB,ACCUM_MAR,ACCUM_APR, + ACCUM_MAY,ACCUM_JUN,ACCUM_JUL,ACCUM_AUG, + ACCUM_SEP,ACCUM_OCT,ACCUM_NOV,ACCUM_DEC, +}; + + +void ConvertDayToYMD(YearMonthDay *ymd, uint16 date) +{ + uint yr = date / (365+365+365+366); + uint rem = date % (365+365+365+366); + uint x; + + yr *= 4; + + if (rem >= 366) { + rem--; + do { + rem -= 365; + yr++; + } while (rem >= 365); + if (rem >= 31+28) rem++; + } + + ymd->year = yr; + + x = _month_date_from_year_day[rem]; + ymd->month = x >> 5; + ymd->day = x & 0x1F; +} + +// year is a number between 0..? +// month is a number between 0..11 +// day is a number between 1..31 +uint ConvertYMDToDay(uint year, uint month, uint day) +{ + uint rem; + + // day in the year + rem = _accum_days_for_month[month] + day - 1; + + // remove feb 29 from year 1,2,3 + if (year & 3) rem += (year & 3) * 365 + (rem < 31+29); + + // base date. + return (year >> 2) * (365+365+365+366) + rem; +} + +// convert a date on the form +// 1920 - 2090 +// 192001 - 209012 +// 19200101 - 20901231 +// or if > 2090 and below 65536, treat it as a daycount +// returns -1 if no conversion was possible +uint ConvertIntDate(uint date) +{ + uint year, month = 0, day = 1; + + if (IS_INT_INSIDE(date, 1920, 2090 + 1)) { + year = date - 1920; + } else if (IS_INT_INSIDE(date, 192001, 209012+1)) { + month = date % 100 - 1; + year = date / 100 - 1920; + } else if (IS_INT_INSIDE(date, 19200101, 20901231+1)) { + day = date % 100; date /= 100; + month = date % 100 - 1; + year = date / 100 - 1920; + } else if (IS_INT_INSIDE(date, 2091, 65536)) + return date; + else + return (uint)-1; + + // invalid ranges? + if (month >= 12 || !IS_INT_INSIDE(day, 1, 31+1)) return (uint)-1; + + return ConvertYMDToDay(year, month, day); +} + +typedef struct LandscapePredefVar { + StringID names[NUM_CARGO]; + byte weights[NUM_CARGO]; + StringID sprites[NUM_CARGO]; + + uint16 initial_cargo_payment[NUM_CARGO]; + byte transit_days_table_1[NUM_CARGO]; + byte transit_days_table_2[NUM_CARGO]; + + byte railwagon_by_cargo[3][NUM_CARGO]; + + byte road_veh_by_cargo_start[NUM_CARGO]; + byte road_veh_by_cargo_count[NUM_CARGO]; +} LandscapePredefVar; + +#include "table/landscape_const.h" + + +// Calculate constants that depend on the landscape type. +void InitializeLandscapeVariables(bool only_constants) +{ + const LandscapePredefVar *lpd; + int i; + StringID str; + + lpd = &_landscape_predef_var[_opt.landscape]; + + memcpy(_cargoc.ai_railwagon, lpd->railwagon_by_cargo, sizeof(lpd->railwagon_by_cargo)); + memcpy(_cargoc.ai_roadveh_start, lpd->road_veh_by_cargo_start,sizeof(lpd->road_veh_by_cargo_start)); + memcpy(_cargoc.ai_roadveh_count, lpd->road_veh_by_cargo_count,sizeof(lpd->road_veh_by_cargo_count)); + + for(i=0; i!=NUM_CARGO; i++) { + _cargoc.sprites[i] = lpd->sprites[i]; + + str = lpd->names[i]; + _cargoc.names_s[i] = str; + _cargoc.names_p[i] = (str += 0x20); + _cargoc.names_long_s[i] = (str += 0x20); + _cargoc.names_long_p[i] = (str += 0x20); + _cargoc.names_short[i] = (str += 0x20); + _cargoc.weights[i] = lpd->weights[i]; + + if (!only_constants) { + _cargo_payment_rates[i] = lpd->initial_cargo_payment[i]; + _cargo_payment_rates_frac[i] = 0; + } + + _cargoc.transit_days_1[i] = lpd->transit_days_table_1[i]; + _cargoc.transit_days_2[i] = lpd->transit_days_table_2[i]; + } +} + +// distance in Manhattan metric +uint GetTileDist(TileIndex xy1, TileIndex xy2) +{ + return myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)) + + myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); +} + +// maximum distance in x _or_ y +uint GetTileDist1D(TileIndex xy1, TileIndex xy2) +{ + return max(myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)), + myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2))); +} + +uint GetTileDist1Db(TileIndex xy1, TileIndex xy2) +{ + int a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)); + int b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); + + if (a > b) + return a*2+b; + else + return b*2+a; +} + +uint GetTileDistAdv(TileIndex xy1, TileIndex xy2) +{ + uint a = myabs(GET_TILE_X(xy1) - GET_TILE_X(xy2)); + uint b = myabs(GET_TILE_Y(xy1) - GET_TILE_Y(xy2)); + return a*a+b*b; +} + +bool CheckDistanceFromEdge(TileIndex tile, uint distance) +{ + return IS_INT_INSIDE(GET_TILE_X(tile), distance, TILE_X_MAX + 1 - distance) && + IS_INT_INSIDE(GET_TILE_Y(tile), distance, TILE_Y_MAX + 1 - distance); +} + +void OnNewDay_Train(Vehicle *v); +void OnNewDay_RoadVeh(Vehicle *v); +void OnNewDay_Aircraft(Vehicle *v); +void OnNewDay_Ship(Vehicle *v); +void OnNewDay_EffectVehicle(Vehicle *v) { /* empty */ } +void OnNewDay_DisasterVehicle(Vehicle *v); + +typedef void OnNewVehicleDayProc(Vehicle *v); + +static OnNewVehicleDayProc * _on_new_vehicle_day_proc[] = { + OnNewDay_Train, + OnNewDay_RoadVeh, + OnNewDay_Ship, + OnNewDay_Aircraft, + OnNewDay_EffectVehicle, + OnNewDay_DisasterVehicle, +}; + +void EnginesDailyLoop(); +void DisasterDailyLoop(); +void PlayersMonthlyLoop(); +void EnginesMonthlyLoop(); +void TownsMonthlyLoop(); +void IndustryMonthlyLoop(); +void StationMonthlyLoop(); + +void PlayersYearlyLoop(); +void TrainsYearlyLoop(); +void RoadVehiclesYearlyLoop(); +void AircraftYearlyLoop(); +void ShipsYearlyLoop(); + +void CheckpointsDailyLoop(); + + +static const uint16 _autosave_months[] = { + 0, // never + 0xFFF, // every month + 0x249, // every 3 months + 0x041, // every 6 months + 0x001, // every 12 months +}; + +void IncreaseDate() +{ + int i,ctr,t; + YearMonthDay ymd; + + if (_game_mode == GM_MENU) { + _tick_counter++; + return; + } + + /*if the day changed, call the vehicle event but only update a part of the vehicles + old max was i!= 12. But with that and a bigger number of vehicles (2560), per day only + a part of it could be done, namely: function called max_size date_fract (uint16) / 885 x 12 ==> + 65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd + eg. aged. + So new code updates it for max vehicles. + (NUM_VEHICLES / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too) + max size of _date_fract / 885 (added each tick) is number of times before ctr is reset. + Calculation might look complicated, but compiler just replaces it with 35, so that's ok + */ + + ctr = _vehicle_id_ctr_day; + for(i=0; i!=(NUM_VEHICLES / ((1<type) != 0) + _on_new_vehicle_day_proc[t - 0x10](v); + } + _vehicle_id_ctr_day = ctr; + + /* increase day, and check if a new day is there? */ + _tick_counter++; + + if ( (_date_fract += 885) >= 885) + return; + + /* yeah, increse day counter and call various daily loops */ + _date++; + + _vehicle_id_ctr_day = 0; + + DisasterDailyLoop(); + CheckpointsDailyLoop(); + + if (_game_mode != GM_MENU) { + InvalidateWindowWidget(WC_STATUS_BAR, 0, 0); + EnginesDailyLoop(); + } + + /* check if we entered a new month? */ + ConvertDayToYMD(&ymd, _date); + if ((byte)ymd.month == _cur_month) + return; + _cur_month = ymd.month; + +// printf("Month %d, %X\n", ymd.month, _random_seed_1); + + /* yes, call various monthly loops */ + if (_game_mode != GM_MENU) { + if (HASBIT(_autosave_months[_opt.autosave], _cur_month)) { + _do_autosave = true; + RedrawAutosave(); + } + + PlayersMonthlyLoop(); + EnginesMonthlyLoop(); + TownsMonthlyLoop(); + IndustryMonthlyLoop(); + StationMonthlyLoop(); + } + + /* check if we entered a new year? */ + if ((byte)ymd.year == _cur_year) + return; + _cur_year = ymd.year; + + /* yes, call various yearly loops */ + + PlayersYearlyLoop(); + TrainsYearlyLoop(); + RoadVehiclesYearlyLoop(); + AircraftYearlyLoop(); + ShipsYearlyLoop(); + + /* check if we reached 2090, that's the maximum year. */ + if (_cur_year == 171) { + _cur_year = 170; + _date = 62093; + } + + if (_patches.auto_euro) + CheckSwitchToEuro(); + + /* XXX: check if year 2050 was reached */ +} + +int FindFirstBit(uint32 x) +{ + int i = 0; + assert(x != 0); + for(;!(x&1);i++,x>>=1); + return i; +} + + +extern uint SafeTileAdd(uint tile, int add, const char *exp, const char *file, int line) +{ + int x = GET_TILE_X(tile) + (signed char)(add & 0xFF); + int y = GET_TILE_Y(tile) + ((((0x8080 + add)>>8) & 0xFF) - 0x80); + + if (x < 0 || y < 0 || x >= TILES_X || y >= TILES_Y) { + char buf[512]; + + sprintf(buf, "TILE_ADD(%s) when adding 0x%.4X and %d failed", exp, tile, add); +#if !defined(_DEBUG) || !defined(_MSC_VER) + printf("%s\n", buf); +#else + _assert(buf, (char*)file, line); +#endif + } + + assert(TILE_XY(x,y) == TILE_MASK(tile + add)); + + return TILE_XY(x,y); +} + +static void Save_NAME() +{ + int i; + byte *b = _name_array[0]; + + for(i=0; i!=lengthof(_name_array); i++,b+=sizeof(_name_array[0])) { + if (*b) { + SlSetArrayIndex(i); + SlArray(b, strlen(b), SLE_UINT8); + } + } +} + +static void Load_NAME() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + SlArray(_name_array[index],SlGetFieldLength(),SLE_UINT8); + } +} + +static const byte _game_opt_desc[] = { + // added a new difficulty option (town attitude) in version 4 + SLE_CONDARR(GameOptions,diff, SLE_FILE_I16 | SLE_VAR_I32, 17, 0, 3), + SLE_CONDARR(GameOptions,diff, SLE_FILE_I16 | SLE_VAR_I32, 18, 4, 255), + SLE_VAR(GameOptions,diff_level, SLE_UINT8), + SLE_VAR(GameOptions,currency, SLE_UINT8), + SLE_VAR(GameOptions,kilometers, SLE_UINT8), + SLE_VAR(GameOptions,town_name, SLE_UINT8), + SLE_VAR(GameOptions,landscape, SLE_UINT8), + SLE_VAR(GameOptions,snow_line, SLE_UINT8), + SLE_VAR(GameOptions,autosave, SLE_UINT8), + SLE_VAR(GameOptions,road_side, SLE_UINT8), + SLE_END() +}; + +// Save load game options +static void SaveLoad_OPTS() +{ + SlObject(&_opt, _game_opt_desc); +} + + +static const SaveLoadGlobVarList _date_desc[] = { + {&_date, SLE_UINT16, 0, 255}, + {&_date_fract, SLE_UINT16, 0, 255}, + {&_tick_counter, SLE_UINT16, 0, 255}, + {&_vehicle_id_ctr_day, SLE_UINT16, 0, 255}, + {&_age_cargo_skip_counter, SLE_UINT8, 0, 255}, + {&_avail_aircraft, SLE_UINT8, 0, 255}, + {&_cur_tileloop_tile, SLE_UINT16, 0, 255}, + {&_disaster_delay, SLE_UINT16, 0, 255}, + {&_station_tick_ctr, SLE_UINT16, 0, 255}, + {&_random_seed_1, SLE_UINT32, 0, 255}, + {&_random_seed_2, SLE_UINT32, 0, 255}, + {&_cur_town_ctr, SLE_UINT8, 0, 255}, + {&_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_UINT, 0, 255}, + {&_next_competitor_start, SLE_FILE_U16 | SLE_VAR_UINT, 0, 255}, + {&_trees_tick_ctr, SLE_UINT8, 0, 255}, + {&_pause, SLE_UINT8, 4, 255}, + {NULL,0} +}; + +// Save load date related variables as well as persistent tick counters +// XXX: currently some unrelated stuff is just put here +static void SaveLoad_DATE() +{ + SlGlobList(_date_desc); +} + + +static const SaveLoadGlobVarList _view_desc[] = { + {&_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_INT, 0, 255}, + {&_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_INT, 0, 255}, + {&_saved_scrollpos_zoom, SLE_UINT8, 0, 255}, + {NULL,0} +}; + +static void SaveLoad_VIEW() +{ + SlGlobList(_view_desc); +} + +static void SaveLoad_MAPT() { + SlArray(_map_type_and_height, lengthof(_map_type_and_height), SLE_UINT8); +} + +static void SaveLoad_MAP2() { + SlArray(_map2, lengthof(_map2), SLE_UINT8); +} + +static void SaveLoad_M3LO() { + SlArray(_map3_lo, lengthof(_map3_lo), SLE_UINT8); +} + +static void SaveLoad_M3HI() { + SlArray(_map3_hi, lengthof(_map3_hi), SLE_UINT8); +} + +static void SaveLoad_MAPO() { + SlArray(_map_owner, lengthof(_map_owner), SLE_UINT8); +} + +static void SaveLoad_MAP5() { + SlArray(_map5, lengthof(_map5), SLE_UINT8); +} + +static void SaveLoad_MAPE() { + SlArray(_map_extra_bits, lengthof(_map_extra_bits), SLE_UINT8); +} + + +static void Save_CHTS() +{ + byte count = sizeof(_cheats)/sizeof(Cheat); + Cheat* cht = (Cheat*) &_cheats; + Cheat* cht_last = &cht[count]; + + SlSetLength(count*2); + for(; cht != cht_last; cht++) { + SlWriteByte(cht->been_used); + SlWriteByte(cht->value); + } +} + +static void Load_CHTS() +{ + Cheat* cht = (Cheat*) &_cheats; + + uint count = SlGetFieldLength()/2; + for(; count; count--, cht++) + { + cht->been_used = (byte)SlReadByte(); + cht->value = (byte)SlReadByte(); + } +} + + +const ChunkHandler _misc_chunk_handlers[] = { + { 'MAPT', SaveLoad_MAPT, SaveLoad_MAPT, CH_RIFF }, + { 'MAP2', SaveLoad_MAP2, SaveLoad_MAP2, CH_RIFF }, + { 'M3LO', SaveLoad_M3LO, SaveLoad_M3LO, CH_RIFF }, + { 'M3HI', SaveLoad_M3HI, SaveLoad_M3HI, CH_RIFF }, + { 'MAPO', SaveLoad_MAPO, SaveLoad_MAPO, CH_RIFF }, + { 'MAP5', SaveLoad_MAP5, SaveLoad_MAP5, CH_RIFF }, + { 'MAPE', SaveLoad_MAPE, SaveLoad_MAPE, CH_RIFF }, + + { 'NAME', Save_NAME, Load_NAME, CH_ARRAY}, + { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, + { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF}, + { 'OPTS', SaveLoad_OPTS, SaveLoad_OPTS, CH_RIFF}, + { 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST} +}; diff --git a/misc_cmd.c b/misc_cmd.c new file mode 100644 --- /dev/null +++ b/misc_cmd.c @@ -0,0 +1,325 @@ + +#include "stdafx.h" +#include "ttd.h" +#include "command.h" +#include "player.h" +#include "gfx.h" +#include "window.h" +#include "saveload.h" +#include "economy.h" + +/* p1 = player + p2 = face + */ + +int32 CmdSetPlayerFace(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + DEREF_PLAYER(p1)->face = p2; + MarkWholeScreenDirty(); + } + return 0; +} + +/* p1 = player + * p2 = color + */ +int32 CmdSetPlayerColor(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p,*pp; + +// /* can only set color for itself */ +// if ( (byte)p1 != _current_player) +// return CMD_ERROR; + + p = DEREF_PLAYER(p1); + + /* ensure no dups */ + FOR_ALL_PLAYERS(pp) { + if (pp->is_active && pp != p && pp->player_color == (byte)p2) + return CMD_ERROR; + } + + if (flags & DC_EXEC) { + _player_colors[p1] = (byte)p2; + p->player_color = (byte)p2; + MarkWholeScreenDirty(); + } + return 0; +} + +int32 CmdIncreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p; + int32 size; + + if ( (byte)p1 != _current_player) + return CMD_ERROR; + + p = DEREF_PLAYER(p1); + + if (p->current_loan >= _economy.max_loan) { + SET_DPARAM32(0, _economy.max_loan); + return_cmd_error(STR_702B_MAXIMUM_PERMITTED_LOAN); + } + + if (flags & DC_EXEC) { + if (p2) + size = _economy.max_loan - p->current_loan; + else + size = IS_HUMAN_PLAYER((byte)p1) ? 10000 : 50000; + + p->money64 += size; + p->current_loan += size; + UpdatePlayerMoney32(p); + InvalidatePlayerWindows(p); + } + + return 0; +} + +int32 CmdDecreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Player *p; + int32 size; + if ( (byte)p1 != _current_player) + return CMD_ERROR; + + p = DEREF_PLAYER(p1); + + if (p->current_loan == 0) + return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED); + + size = p->current_loan; + + // p2 is true while CTRL is pressed (repay all possible loan, or max money you have) + if (!p2) + size = min(size, IS_HUMAN_PLAYER((byte)p1) ? 10000 : 50000); + else { // only repay in chunks of 10K + size = min(size, p->player_money); + size = max(size, 10000); + size -= size % 10000; + } + + if (p->player_money < size) { + SET_DPARAM32(0, size); + return_cmd_error(STR_702E_REQUIRED); + } + + if (flags & DC_EXEC) { + p->money64 -= size; + p->current_loan -= size; + UpdatePlayerMoney32(p); + InvalidatePlayerWindows(p); + } + return 0; +} + +int32 CmdChangeCompanyName(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str,old_str; + Player *p; + + str = AllocateName((byte*)_decode_parameters, 4); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + p = DEREF_PLAYER(p1); + old_str = p->name_1; + p->name_1 = str; + DeleteName(old_str); + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + + return 0; +} + +int32 CmdChangePresidentName(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str,old_str; + Player *p; + + str = AllocateName((byte*)_decode_parameters, 4); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + p = DEREF_PLAYER(p1); + old_str = p->president_name_1; + p->president_name_1 = str; + DeleteName(old_str); + + if (p->name_1 == STR_SV_UNNAMED) { + byte *s = " Transport"; + byte *d = (byte*)_decode_parameters, b; + d--; do d++; while (*d); + do *d++ = b = *s++; while(d != (byte*)endof(_decode_parameters) && b != 0); + DoCommandByTile(0, p1, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME); + } + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + + return 0; +} + +static void UpdateSignVirtCoords(SignStruct *ss) +{ + Point pt = RemapCoords(ss->x, ss->y, ss->z); + SET_DPARAM16(0, ss->str); + UpdateViewportSignPos(&ss->sign, pt.x, pt.y - 6, STR_2806); +} + +void UpdateAllSignVirtCoords() +{ + SignStruct *ss; + for(ss=_sign_list; ss != endof(_sign_list); ss++) + if (ss->str != 0) + UpdateSignVirtCoords(ss); + +} + +static void MarkSignDirty(SignStruct *ss) +{ + MarkAllViewportsDirty( + ss->sign.left-6, + ss->sign.top-3, + ss->sign.left+ss->sign.width_1*4+12, + ss->sign.top + 45 + ); +} + + +int32 CmdPlaceSign(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + SignStruct *ss; + + for(ss=_sign_list; ss != endof(_sign_list); ss++) { + if (ss->str == 0) { + if (flags & DC_EXEC) { + ss->str = STR_280A_SIGN; + ss->x = x; + ss->y = y; + ss->z = GetSlopeZ(x,y); + UpdateSignVirtCoords(ss); + MarkSignDirty(ss); + _new_sign_struct = ss; + } + return 0; + } + } + + return_cmd_error(STR_2808_TOO_MANY_SIGNS); +} + +// p1 = sign index +// p2: 1 -> remove sign +int32 CmdRenameSign(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str,old_str; + SignStruct *ss; + + if (_decode_parameters[0] != 0 && !p2) { + str = AllocateName((byte*)_decode_parameters, 0); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + ss = &_sign_list[p1]; + MarkSignDirty(ss); + DeleteName(ss->str); + ss->str = str; + UpdateSignVirtCoords(ss); + MarkSignDirty(ss); + } else { + DeleteName(str); + } + } else { + if (flags & DC_EXEC) { + ss = &_sign_list[p1]; + old_str = ss->str; + ss->str = 0; + DeleteName(old_str); + MarkSignDirty(ss); + } + } + return 0; +} + +// p1 = 0 decrease pause counter +// p1 = 1 increase pause counter +int32 CmdPause(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + _pause += p1?1:-1; + if(_pause==(byte)-1) _pause = 0; + InvalidateWindow(WC_STATUS_BAR, 0); + InvalidateWindow(WC_MAIN_TOOLBAR, 0); + } + return 0; +} + + + +int32 CmdResume(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + return 0; +} + +int32 CmdMoneyCheat(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + SET_EXPENSES_TYPE(EXPENSES_OTHER); + return (int32)p1; +} + +int32 CmdChangeDifficultyLevel(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + if (p1 != (uint32)-1L) { + ((int*)&_opt_mod_ptr->diff)[p1] = p2; + _opt_mod_ptr->diff_level = 3; + } else { + _opt_mod_ptr->diff_level = p2; + } + InvalidateWindow(WC_GAME_OPTIONS, 0); + } + return 0; +} + +static const byte _sign_desc[] = { + SLE_VAR(SignStruct,str, SLE_UINT16), + SLE_VAR(SignStruct,x, SLE_INT16), + SLE_VAR(SignStruct,y, SLE_INT16), + SLE_VAR(SignStruct,z, SLE_UINT8), + SLE_END() +}; + +static void Save_SIGN() +{ + SignStruct *s; + int i; + for(i=0,s=_sign_list; i!=lengthof(_sign_list); i++,s++) { + if (s->str != 0) { + SlSetArrayIndex(i); + SlObject(s, _sign_desc); + } + } +} + +static void Load_SIGN() +{ + int index; + while ((index = SlIterateArray()) != -1) { + SlObject(&_sign_list[index], _sign_desc); + } +} + +const ChunkHandler _sign_chunk_handlers[] = { + { 'SIGN', Save_SIGN, Load_SIGN, CH_ARRAY | CH_LAST}, +}; + + diff --git a/misc_gui.c b/misc_gui.c new file mode 100644 --- /dev/null +++ b/misc_gui.c @@ -0,0 +1,1563 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "station.h" +#include "command.h" +#include "player.h" +#include "town.h" + +#include "hal.h" // Fios items + +bool _query_string_active; +static void SetFiosType(const byte fiostype); + +typedef struct LandInfoData { + Town *town; + int32 costclear; + AcceptedCargo ac; + uint tile; + TileDesc td; +} LandInfoData; + + +static void LandInfoWndProc(Window *w, WindowEvent *e) +{ + LandInfoData *lid; + StringID str; + uint32 *b; + + if (e->event == WE_PAINT) { + DrawWindowWidgets(w); + + lid = WP(w,void_d).data; + + SET_DPARAM32(0, lid->td.dparam[0]); + DrawStringCentered(140, 16, lid->td.str, 13); + + SET_DPARAM16(0, STR_01A6_N_A); + if (lid->td.owner != OWNER_NONE && lid->td.owner != OWNER_WATER) + GetNameOfOwner(lid->td.owner, lid->tile); + DrawStringCentered(140, 27, STR_01A7_OWNER, 0); + + str = STR_01A4_COST_TO_CLEAR_N_A; + if (lid->costclear != CMD_ERROR) { + SET_DPARAM32(0, lid->costclear); + str = STR_01A5_COST_TO_CLEAR; + } + DrawStringCentered(140, 38, str, 0); + + sprintf(_userstring, "%.4X", lid->tile); + SET_DPARAM16(0, GET_TILE_X(lid->tile)); + SET_DPARAM16(1, GET_TILE_Y(lid->tile)); + SET_DPARAM16(2, STR_SPEC_USERSTRING); + DrawStringCentered(140, 49, STR_LANDINFO_COORDS, 0); + + SET_DPARAM16(0, STR_01A9_NONE); + if (lid->town != NULL) { + SET_DPARAM16(0, lid->town->townnametype); + SET_DPARAM32(1, lid->town->townnameparts); + } + DrawStringCentered(140,60, STR_01A8_LOCAL_AUTHORITY, 0); + + b = &GET_DPARAM(0); + + str = STR_01CE_CARGO_ACCEPTED - 1; + + if (lid->ac.amount_1 != 0) { + if (lid->ac.amount_1 < 8) { + SET_DPARAMX16(b, 0, STR_01D1_8); + SET_DPARAMX8(b, 1, lid->ac.amount_1); + b += 2; + } + SET_DPARAMX16(b, 0, _cargoc.names_s[lid->ac.type_1]); + b++; + str++; + } + + if (lid->ac.amount_2 != 0) { + if (lid->ac.amount_2 < 8) { + SET_DPARAMX16(b, 0, STR_01D1_8); + SET_DPARAMX8(b, 1, lid->ac.amount_2); + b += 2; + } + SET_DPARAMX16(b, 0, _cargoc.names_s[lid->ac.type_2]); + b++; + str++; + } + + if (lid->ac.amount_3 != 0) { + if (lid->ac.amount_3 < 8) { + SET_DPARAMX16(b, 0, STR_01D1_8); + SET_DPARAMX8(b, 1, lid->ac.amount_3); + b += 2; + } + SET_DPARAMX16(b, 0, _cargoc.names_s[lid->ac.type_3]); + b++; + str++; + } + + if (str != (STR_01CE_CARGO_ACCEPTED - 1)) + DrawStringMultiCenter(140, 76, str, 276); + } +} + +static const Widget _land_info_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 279, 0, 13, STR_01A3_LAND_AREA_INFORMATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 279, 14, 92, 0x0, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _land_info_desc = { + -1, -1, 280, 93, + WC_LAND_INFO,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _land_info_widgets, + LandInfoWndProc +}; + +static void Place_LandInfo(uint tile) +{ + Player *p; + static LandInfoData lid; + Window *w; + int64 old_money; + + DeleteWindowById(WC_LAND_INFO, 0); + + w = AllocateWindowDesc(&_land_info_desc); + WP(w,void_d).data = &lid; + + lid.tile = tile; + lid.town = ClosestTownFromTile(tile, _patches.dist_local_authority); + + if (_local_player == 255) { + lid.costclear = 0; + } else { + p = DEREF_PLAYER(_local_player); + old_money = p->money64; + p->money64 = p->player_money = 0x7fffffff; + lid.costclear = DoCommandByTile(tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR); + p->money64 = old_money; + UpdatePlayerMoney32(p); + } + + GetAcceptedCargo(tile, &lid.ac); + GetTileDesc(tile, &lid.td); + +#if defined(_DEBUG) + { + printf("TILE: %#x (%i,%i)\n", tile, GET_TILE_X(tile), GET_TILE_Y(tile)); + printf("_map_type_and_height=%#x\n", _map_type_and_height[tile]); + printf("_map2=%#x\n", _map2[tile]); + printf("_map3_lo=%#x\n", _map3_lo[tile]); + printf("_map3_hi=%#x\n", _map3_hi[tile]); + printf("_map5=%#x\n", _map5[tile]); + printf("_map_owner=%#x\n", _map_owner[tile]); + printf("\n"); + } +#endif +} + +void PlaceLandBlockInfo() +{ + if (_cursor.sprite == 0x2CF) { + ResetObjectToPlace(); + } else { + _place_proc = Place_LandInfo; + SetObjectToPlace(0x2CF, 1, 1, 0); + } +} + + +static void AboutWindowProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int x,y; + DrawWindowWidgets(w); + + x = 200; + y = 0; + DrawStringCentered(x, y+=17, STR_00B6_COPYRIGHT_1995_CHRIS_SAWYER, 0); + DrawStringCentered(x, y+=10, STR_00B7_VERSION_3_02_011_11TH_OCTOBER, 0); + DrawStringCentered(x, y+=15, STR_00B8_DESIGNED_PROGRAMMED_BY, 0); + DrawStringCentered(x, y+=10, STR_00B9_GRAPHICS_BY_SIMON_FOSTER, 0); + DrawStringMultiCenter(x, y+0x73, STR_00BA_WINDOWS_95_CONVERSION_BY, 0x18E); + break; + } + } +} + +static const Widget _about_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 14, 11, 399, 0, 13, STR_015B_TRANSPORT_TYCOON_DELUXE}, +{ WWT_PANEL, 14, 0, 399, 14, 271, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _about_desc = { + WDP_CENTER, WDP_CENTER, 400, 272, + WC_GAME_OPTIONS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _about_widgets, + AboutWindowProc +}; + + +void ShowAboutWindow() +{ + DeleteWindowById(WC_GAME_OPTIONS, 0); + AllocateWindowDesc(&_about_desc); +} + +static int _tree_to_plant; + +static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32}; +static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9}; +static const uint32 _tree_sprites[] = { + 0x655,0x663,0x678,0x62B,0x647,0x639,0x64E,0x632,0x67F,0x68D,0x69B,0x6A9, + 0x6AF,0x6D2,0x6D9,0x6C4,0x6CB,0x6B6,0x6BD,0x6E0, + 0x72E,0x734,0x74A,0x74F,0x76B,0x78F,0x788,0x77B,0x75F,0x774,0x720,0x797, + 0x79E,0x30D87A5,0x30B87AC,0x7B3,0x7BA,0x30B87C1,0x30887C8,0x30A87CF,0x30B87D6 +}; + +static void BuildTreesWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int x,y; + int i, count; + + DrawWindowWidgets(w); + + WP(w,tree_d).base = i = _tree_base_by_landscape[_opt.landscape]; + WP(w,tree_d).count = count = _tree_count_by_landscape[_opt.landscape]; + + x = 18; + y = 54; + do { + DrawSprite(_tree_sprites[i], x, y); + x += 35; + if (!(++i & 3)) { + x -= 35*4; + y += 47; + } + } while (--count); + } break; + + case WE_CLICK: { + int wid; + + switch(wid=e->click.widget) { + case 0: + ResetObjectToPlace(); + return; + case 3: case 4: case 5: case 6: + case 7: case 8: case 9: case 10: + case 11:case 12: case 13: case 14: + if ( (uint)(wid-3) >= (uint)WP(w,tree_d).count) + return; + + if (HandlePlacePushButton(w, wid, 0x7DA, 1, NULL)) + _tree_to_plant = WP(w,tree_d).base + wid - 3; + break; + + case 15: // tree of random type. + if (HandlePlacePushButton(w, 15, 0x7DA, 1, NULL)) + _tree_to_plant = -1; + break; + + case 16: /* place trees randomly over the landscape*/ + w->click_state |= 1 << 16; + w->flags4 |= 5 << WF_TIMEOUT_SHL; + SndPlayFx(0x13); + PlaceTreesRandomly(); + MarkWholeScreenDirty(); + break; + } + } break; + + case WE_PLACE_OBJ: + VpStartPlaceSizing(e->place.tile, VPM_X_AND_Y_LIMITED); + VpSetPlaceSizingLimit(20); + 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) { + DoCommandP(e->place.tile, _tree_to_plant, e->place.starttile, NULL, + CMD_PLANT_TREE | CMD_AUTO | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE)); + } + break; + + case WE_TIMEOUT: + UnclickSomeWindowButtons(w, 1<<16); + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + break; + } +} + +static const Widget _build_trees_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 142, 14, 170, 0x0, 0}, +{ WWT_PANEL, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_CLOSEBOX, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_trees_desc = { + 497, 22, 143, 171, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_trees_widgets, + BuildTreesWndProc +}; + +static const Widget _build_trees_scen_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 142, 14, 183, 0x0, 0}, +{ WWT_PANEL, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_PANEL, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, +{ WWT_CLOSEBOX, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP}, +{ WWT_CLOSEBOX, 14, 2, 140, 170, 181, STR_028A_RANDOM_TREES,STR_028B_PLANT_TREES_RANDOMLY_OVER}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_trees_scen_desc = { + -1, -1, 143, 184, + WC_SCEN_BUILD_TREES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_trees_scen_widgets, + BuildTreesWndProc +}; + + +void ShowBuildTreesToolbar() +{ + DeleteWindowById(WC_BUILD_TOOLBAR, 0); + AllocateWindowDesc(&_build_trees_desc); +} + +void ShowBuildTreesScenToolbar() +{ + AllocateWindowDescFront(&_build_trees_scen_desc, 0); +} + +static uint32 _errmsg_decode_params[10]; +static StringID _errmsg_message_1, _errmsg_message_2; +static uint _errmsg_duration; + + +static const Widget _errmsg_widgets[] = { +{ WWT_CLOSEBOX, 4, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 4, 11, 239, 0, 13, STR_00B2_MESSAGE}, +{ WWT_PANEL, 4, 0, 239, 14, 45, 0x0}, +{ WWT_LAST}, +}; + +static const Widget _errmsg_face_widgets[] = { +{ WWT_CLOSEBOX, 4, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 4, 11, 333, 0, 13, STR_00B3_MESSAGE_FROM}, +{ WWT_PANEL, 4, 0, 333, 14, 136, 0x0}, +{ WWT_LAST}, +}; + +static void ErrmsgWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + COPY_IN_DPARAM(0, _errmsg_decode_params, lengthof(_errmsg_decode_params)); + DrawWindowWidgets(w); + COPY_IN_DPARAM(0, _errmsg_decode_params, lengthof(_errmsg_decode_params)); + if (w->widget != _errmsg_face_widgets) { + DrawStringMultiCenter( + 120, + (_errmsg_message_1 == INVALID_STRING_ID ? 25 : 15), + _errmsg_message_2, + 238); + if (_errmsg_message_1 != INVALID_STRING_ID) + DrawStringMultiCenter( + 120, + 30, + _errmsg_message_1, + 238); + } else { + Player *p = DEREF_PLAYER(_errmsg_decode_params[2]); + DrawPlayerFace(p->face, p->player_color, 2, 16); + + DrawStringMultiCenter( + 214, + (_errmsg_message_1 == INVALID_STRING_ID ? 65 : 45), + _errmsg_message_2, + 238); + if (_errmsg_message_1 != INVALID_STRING_ID) + DrawStringMultiCenter( + 214, + 90, + _errmsg_message_1, + 238); + } + break; + + case WE_MOUSELOOP: + if (_right_button_down) + DeleteWindow(w); + break; + case WE_4: + if (!--_errmsg_duration) + DeleteWindow(w); + break; + case WE_DESTROY: { + TileHighlightData *thd = _thd_ptr; + TileIndex tile = thd->redsq; + thd->redsq = 0; + if (tile != 0) + MarkTileDirtyByTile(tile); + break; + } + + case WE_KEYPRESS: + if (e->keypress.keycode == WKC_SPACE) { + // Don't continue. + e->keypress.cont = false; + DeleteWindow(w); + } + break; + } +} + +void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y) +{ + Window *w; + ViewPort *vp; + Point pt; + + DeleteWindowById(WC_ERRMSG, 0); + + //assert(msg_2); + if (msg_2 == 0) msg_2 = STR_EMPTY; + + _errmsg_message_1 = msg_1; + _errmsg_message_2 = msg_2; + COPY_OUT_DPARAM(_errmsg_decode_params, 0, lengthof(_errmsg_decode_params)); + _errmsg_duration = _patches.errmsg_duration; + if (!_errmsg_duration) + return; + + if (_errmsg_message_1 != STR_013B_OWNED_BY || GET_DPARAMX8(_errmsg_decode_params,2) >= 8) { + + if ( (x|y) != 0) { + pt = RemapCoords2(x, y); + for(w=_windows; w->window_class != WC_MAIN_WINDOW; w++) {} + vp = w->viewport; + + // move x pos to opposite corner + pt.x = ((pt.x - vp->virtual_left) >> vp->zoom) + vp->left; + pt.x = (pt.x < (_screen.width >> 1)) ? _screen.width - 260 : 20; + + // move y pos to opposite corner + pt.y = ((pt.y - vp->virtual_top) >> vp->zoom) + vp->top; + pt.y = (pt.y < (_screen.height >> 1)) ? _screen.height - 80 : 100; + + } else { + pt.x = (_screen.width - 240) >> 1; + pt.y = (_screen.height - 46) >> 1; + } + w = AllocateWindow(pt.x, pt.y, 240, 46, ErrmsgWndProc, WC_ERRMSG, _errmsg_widgets); + } else { + if ( (x|y) != 0) { + pt = RemapCoords2(x, y); + for(w=_windows; w->window_class != WC_MAIN_WINDOW; w++) {} + vp = w->viewport; + pt.x = clamp(((pt.x - vp->virtual_left) >> vp->zoom) + vp->left - (334/2), 0, _screen.width - 334); + pt.y = clamp(((pt.y - vp->virtual_top) >> vp->zoom) + vp->top - (137/2), 22, _screen.height - 137); + } else { + pt.x = (_screen.width - 334) >> 1; + pt.y = (_screen.height - 137) >> 1; + } + w = AllocateWindow(pt.x, pt.y, 334, 137, ErrmsgWndProc, WC_ERRMSG, _errmsg_face_widgets); + } + + w->desc_flags = WDF_STD_BTN | WDF_DEF_WIDGET; +} + + +void ShowEstimatedCostOrIncome(int32 cost, int x, int y) +{ + int msg = STR_0805_ESTIMATED_COST; + + if (cost < 0) { + cost = -cost; + msg = STR_0807_ESTIMATED_INCOME; + } + SET_DPARAM32(0, cost); + ShowErrorMessage(-1, msg, x, y); +} + +void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost) +{ + int msg; + Point pt = RemapCoords(x,y,z); + + msg = STR_0801_COST; + if (cost < 0) { + cost = -cost; + msg = STR_0803_INCOME; + } + SET_DPARAM32(0, cost); + AddTextEffect(msg, pt.x, pt.y, 0x250); +} + +static Widget _tooltips_widgets[] = { +{ WWT_PANEL, 14, 0, 199, 0, 31, 0x0}, +{ WWT_LAST}, +}; + + +static void TooltipsWndProc(Window *w, WindowEvent *e) +{ + + switch(e->event) { + case WE_PAINT: { + GfxFillRect(0, 0, w->width - 1, w->height - 1, 0); + GfxFillRect(1, 1, w->width - 2, w->height - 2, 0x44); + DrawStringMultiCenter((w->width>>1), (w->height>>1)-5, WP(w,tooltips_d).string_id, 197); + break; + } + case WE_MOUSELOOP: + if (!_right_button_down) + DeleteWindow(w); + break; + } +} + +void GuiShowTooltips(StringID string_id) +{ + Window *w; + int right,bottom; + int x,y; + + if (string_id == 0) + return; + + w = FindWindowById(WC_TOOLTIPS, 0); + if (w != NULL) { + if (WP(w,tooltips_d).string_id == string_id) + return; + DeleteWindow(w); + } + + GetString(str_buffr, string_id); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + right = GetStringWidth(str_buffr) + 4; + + bottom = 14; + if (right > 200) { + bottom += ((right - 4) / 176) * 10; + right = 200; + } + + _tooltips_widgets[0].right = right; + _tooltips_widgets[0].bottom = bottom; + + y = _cursor.pos.y + 30; + if (y < 22) y = 22; + + if (y > (_screen.height - 44) && (y-=52) > (_screen.height - 44)) + y = (_screen.height - 44); + + x = _cursor.pos.x - (right >> 1); + if (x < 0) x = 0; + if (x > (_screen.width - right)) x = _screen.width - right; + + w = AllocateWindow(x, y, right, bottom, TooltipsWndProc, WC_TOOLTIPS, _tooltips_widgets); + WP(w,tooltips_d).string_id = string_id; + w->flags4 &= ~WF_WHITE_BORDER_MASK; +} + + +static void DrawStationCoverageText(const uint *accepts, int str_x, int str_y, uint mask) +{ + int i; + byte *b; + + b = _userstring; + b[0] = 0x81; + b[1] = STR_000D_ACCEPTS; + b[2] = STR_000D_ACCEPTS >> 8; + b += 3; + + for(i=0; i!=NUM_CARGO; i++,mask>>=1) { + if (accepts[i] >= 8 && (mask&1) ) { + StringID id = _cargoc.names_s[i]; + b[0] = 0x81; + b[1] = (byte)(id & 255); + b[2] = (byte)(id >> 8); + b[3] = ','; + b[4] = ' '; + b += 5; + } + } + + if (b == (byte*)&_userstring[3]) { + b[0] = 0x81; + b[1] = STR_00D0_NOTHING; + b[2] = STR_00D0_NOTHING >> 8; + b[3] = 0; + } else { + b[-2] = 0; + } + + DrawStringMultiLine(str_x, str_y, STR_SPEC_USERSTRING, 144); +} + +void DrawStationCoverageAreaText(int sx, int sy, uint mask) { + int x = _thd.pos.x; + int y = _thd.pos.y; + uint accepts[NUM_CARGO]; + if (x != -1) { + GetAcceptanceAroundTiles(accepts, TILE_FROM_XY(x,y), _thd.new_size.x >> 4, _thd.new_size.y >> 4); + DrawStationCoverageText(accepts, sx, sy, mask); + } +} + +void CheckRedrawStationCoverage(Window *w) +{ + if (_thd.dirty&1) { + _thd.dirty&=~1; + SetWindowDirty(w); + } +} + + +void UnclickSomeWindowButtons(Window *w, uint32 mask) +{ + uint32 x = w->click_state & mask; + int i = 0; + w->click_state ^= x; + do { + if (x&1) InvalidateWidget(w,i); + } while(i++,x>>=1); +} + + +void UnclickWindowButtons(Window *w) +{ + UnclickSomeWindowButtons(w, (uint32)-1); +} + + +void SetVScrollCount(Window *w, int num) +{ + w->vscroll.count = num; + num -= w->vscroll.cap; + if (num < 0) num = 0; + if (num < w->vscroll.pos) w->vscroll.pos = num; +} + +void SetHScrollCount(Window *w, int num) +{ + w->hscroll.count = num; + num -= w->hscroll.cap; + if (num < 0) num = 0; + if (num < w->hscroll.pos) w->hscroll.pos = num; +} + + +int HandleEditBoxKey(Window *w, int wid, WindowEvent *we) +{ + byte *p; + int width,count; + int key = we->keypress.ascii; + + we->keypress.cont = false; + + if (we->keypress.keycode == WKC_ESC) { + return 2; + } else if (we->keypress.keycode == WKC_RETURN) { + return 1; + } else { + width = -1; + p = WP(w,querystr_d).buf - 1; + count = 0; + do { + if (*++p == 0) + break; + count++; + width += _stringwidth_table[*p - 32]; + } while (1); + + if (we->keypress.keycode == WKC_BACKSPACE) { + if (count != 0) { + WP(w,querystr_d).buf[count-1] = 0; + InvalidateWidget(w, wid); + } + } else if (IS_INT_INSIDE((key = we->keypress.ascii), 32, 256)) { + if (count < WP(w,querystr_d).maxlen && width + _stringwidth_table[key-32] <= WP(w,querystr_d).maxwidth) { + WP(w,querystr_d).buf[count] = key; + WP(w,querystr_d).buf[count+1] = 0; + InvalidateWidget(w, wid); + } + } else { + // key wasn't caught + we->keypress.cont = true; + } + } + + return 0; +} + +void HandleEditBox(Window *w, int wid) +{ + bool b; + + /* caret changed? */ + b = !!(_caret_timer & 0x20); + if (b != WP(w,querystr_d).caret) { + WP(w,querystr_d).caret = b; + InvalidateWidget(w, wid); + } +} + +void DrawEditBox(Window *w, int wid) +{ + const Widget *wi = w->widget + wid; + int x; + + GfxFillRect(wi->left+1, wi->top+1, wi->right-1, wi->bottom-1, 215); + x = DoDrawString(WP(w,querystr_d).buf, wi->left+2, wi->top+1, 8); + if (WP(w,querystr_d).caret) + DoDrawString("_", x, wi->top+1, 12); +} + + +#define MAX_QUERYSTR_LEN 64 + +static void QueryStringWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { +// int x; + + SET_DPARAM16(0, WP(w,querystr_d).caption); + DrawWindowWidgets(w); + + DrawEditBox(w, 5); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: DeleteWindow(w); break; + case 4: +press_ok:; + if (str_eq(WP(w,querystr_d).buf, WP(w,querystr_d).buf + MAX_QUERYSTR_LEN)) { + DeleteWindow(w); + } else { + Window *parent = FindWindowById(WP(w,querystr_d).wnd_class, WP(w,querystr_d).wnd_num); + byte *buf = WP(w,querystr_d).buf; + DeleteWindow(w); + if (parent != NULL) { + WindowEvent e; + e.event = WE_ON_EDIT_TEXT; + e.edittext.str = buf; + parent->wndproc(parent, &e); + } + } + break; + } + break; + + case WE_MOUSELOOP: { + if (!FindWindowById(WP(w,querystr_d).wnd_class, WP(w,querystr_d).wnd_num)) { + DeleteWindow(w); + return; + } + HandleEditBox(w, 5); + } break; + + case WE_KEYPRESS: { + switch(HandleEditBoxKey(w, 5, e)) { + case 1: // Return + goto press_ok; + case 2: // Escape + DeleteWindow(w); + break; + } + } break; + + case WE_DESTROY: + _query_string_active = false; + break; + } +} + +static const Widget _query_string_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_012D}, +{ WWT_IMGBTN, 14, 0, 259, 14, 29, 0x0}, +{ WWT_TEXTBTN, 14, 0, 129, 30, 41, STR_012E_CANCEL}, +{ WWT_TEXTBTN, 14, 130, 259, 30, 41, STR_012F_OK}, +{ WWT_IMGBTN, 14, 2, 257, 16, 27, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _query_string_desc = { + 190, 219, 260, 42, + WC_QUERY_STRING,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _query_string_widgets, + QueryStringWndProc +}; + +static byte _edit_str_buf[MAX_QUERYSTR_LEN*2]; + +void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number) +{ + Window *w; + +#define _orig_edit_str_buf (_edit_str_buf+MAX_QUERYSTR_LEN) + + if (_pause != 0 && !_patches.build_in_pause) + return; + + DeleteWindowById(WC_QUERY_STRING, 0); + DeleteWindowById(WC_SAVELOAD, 0); + + if (str == 0xFFFF) { + memcpy(_orig_edit_str_buf, str_buffr, MAX_QUERYSTR_LEN); + } else { + GetString(_orig_edit_str_buf, str); + } + _orig_edit_str_buf[maxlen] = 0; + + memcpy(_edit_str_buf, _orig_edit_str_buf, MAX_QUERYSTR_LEN); + + w = AllocateWindowDesc(&_query_string_desc); + + w->click_state = 1 << 5; + WP(w,querystr_d).caption = caption; + WP(w,querystr_d).wnd_class = window_class; + WP(w,querystr_d).wnd_num = window_number; + WP(w,querystr_d).caret = 0; + WP(w,querystr_d).maxlen = maxlen; + WP(w,querystr_d).maxwidth = maxwidth; + WP(w,querystr_d).buf = _edit_str_buf; + + _query_string_active = true; +} + +static const Widget _load_dialog_1_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 256, 0, 13, STR_4001_LOAD_GAME, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 14, 25, STR_SORT_BY_DATE,STR_SORT_TIP}, +{ WWT_IMGBTN, 14, 0, 256, 26, 47, 0x0}, +{ WWT_IMGBTN, 14, 0, 256, 48, 293, 0x0}, +{ WWT_6, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, +{ WWT_SCROLLBAR, 14, 246, 256, 48, 293, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const Widget _load_dialog_2_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 256, 0, 13, STR_0298_LOAD_SCENARIO, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 14, 25, STR_SORT_BY_DATE,STR_SORT_TIP}, +{ WWT_IMGBTN, 14, 0, 256, 26, 47, 0x0}, +{ WWT_IMGBTN, 14, 0, 256, 48, 293, 0x0}, +{ WWT_6, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, +{ WWT_SCROLLBAR, 14, 246, 256, 48, 293, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const Widget _save_dialog_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 256, 0, 13, STR_4000_SAVE_GAME, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 14, 25, STR_SORT_BY_DATE,STR_SORT_TIP}, +{ WWT_IMGBTN, 14, 0, 256, 26, 47, 0x0}, +{ WWT_IMGBTN, 14, 0, 256, 48, 291, 0x0}, +{ WWT_6, 14, 2, 243, 50, 289, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, +{ WWT_SCROLLBAR, 14, 246, 256, 48, 291, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 256, 292, 307, 0x0}, +{ WWT_IMGBTN, 14, 2, 254, 294, 305, 0x0, STR_400B_CURRENTLY_SELECTED_NAME}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 308, 319, STR_4003_DELETE, STR_400C_DELETE_THE_CURRENTLY_SELECTED}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 308, 319, STR_4002_SAVE, STR_400D_SAVE_THE_CURRENT_GAME_USING}, +{ WWT_LAST}, +}; + +static const Widget _save_dialog_scen_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 256, 0, 13, STR_0299_SAVE_SCENARIO, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 14, 25, STR_SORT_BY_DATE,STR_SORT_TIP}, +{ WWT_IMGBTN, 14, 0, 256, 26, 47, 0x0}, +{ WWT_IMGBTN, 14, 0, 256, 48, 291, 0x0}, +{ WWT_6, 14, 2, 243, 50, 289, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, +{ WWT_SCROLLBAR, 14, 246, 256, 48, 291, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 256, 292, 307, 0x0}, +{ WWT_IMGBTN, 14, 2, 254, 294, 305, 0x0, STR_400B_CURRENTLY_SELECTED_NAME}, +{ WWT_PUSHTXTBTN, 14, 0, 127, 308, 319, STR_4003_DELETE, STR_400C_DELETE_THE_CURRENTLY_SELECTED}, +{ WWT_PUSHTXTBTN, 14, 128, 256, 308, 319, STR_4002_SAVE, STR_400D_SAVE_THE_CURRENT_GAME_USING}, +{ WWT_LAST}, +}; + + +static FiosItem *_fios_list; +static int _fios_num; +static int _saveload_mode; + +static void BuildFileList() +{ + FiosFreeSavegameList(); + if(_saveload_mode==SLD_NEW_GAME || _saveload_mode==SLD_LOAD_SCENARIO || _saveload_mode==SLD_SAVE_SCENARIO) + _fios_list = FiosGetScenarioList(&_fios_num, _saveload_mode); + else + _fios_list = FiosGetSavegameList(&_fios_num, _saveload_mode); +} + +static void DrawFiosTexts() +{ + char *path; + StringID str; + + str = FiosGetDescText(&path); + if (str != 0) + DrawString(2, 37, str, 0); + DoDrawString(path, 2, 27, 16); +} + +/* FIOS_TYPE_FILE, FIOS_TYPE_OLDFILE etc. different colours */ +static const byte _fios_colors[] = {13, 9, 9, 6, 5, 6, 5}; + +#if defined(_WIN32) + extern int CDECL compare_FiosItems (const void *a, const void *b); +#else + extern int compare_FiosItems (const void *a, const void *b); +#endif + + +static void MakeSortedSaveGameList() +{ + /* Directories are always above the files (FIOS_TYPE_DIR) + * Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE) + * Only sort savegames/scenarios, not directories + */ + + int i, sort_start, sort_end, s_amount; + i = sort_start = sort_end = 0; + + while (i < _fios_num) { + if (_fios_list[i].type == FIOS_TYPE_DIR || _fios_list[i].type == FIOS_TYPE_PARENT) + sort_start++; + + if (_fios_list[i].type == FIOS_TYPE_DRIVE) + sort_end++; + + i++; + } + + s_amount = _fios_num - sort_start - sort_end; + if ((bool)s_amount) + qsort(_fios_list + sort_start, s_amount, sizeof(FiosItem), compare_FiosItems); +} + +static void SaveLoadDlgWndProc(Window *w, WindowEvent *e) +{ + const int list_start = 51; + + switch(e->event) { + case WE_PAINT: { + int y,pos; + const FiosItem *item; + + SetVScrollCount(w, _fios_num); + DrawWindowWidgets(w); + DrawFiosTexts(); + + if (_savegame_sort_dirty) { + _savegame_sort_dirty = false; + MakeSortedSaveGameList(); + } + + GfxFillRect(3, list_start, 3+239, list_start+239, 0xD7); + DoDrawString(_savegame_sort_order & 1 ? "\xAA" : "\xA0", _savegame_sort_order <= 1 ? 248 : 118, 15, 0x10); + + y = list_start; + pos = w->vscroll.pos; + while (pos < _fios_num) { + item = _fios_list + pos; + DoDrawString(item->title[0] ? item->title : item->name, 4, y, _fios_colors[item->type] ); + pos++; + y+=10; + if (y >= w->vscroll.cap*10+list_start) + break; + } + + if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { + DrawEditBox(w, 9); + } + break; + } + case WE_CLICK: + switch(e->click.widget) { + case 2: /* Sort save names by name */ + _savegame_sort_order = (_savegame_sort_order == 2) ? 3 : 2; + _savegame_sort_dirty = true; + SetWindowDirty(w); + break; + + case 3: /* Sort save names by date */ + _savegame_sort_order = (_savegame_sort_order == 0) ? 1 : 0; + _savegame_sort_dirty = true; + SetWindowDirty(w); + break; + + case 6: { /* Click the listbox */ + int y = (e->click.pt.y - list_start) / 10; + char *name; + const FiosItem *file; + + if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) + return; + + file = _fios_list + y; + + if ((name = FiosBrowseTo(file)) != NULL) { + if (_saveload_mode == SLD_LOAD_GAME) { + _switch_mode = SM_LOAD; + SetFiosType(file->type); + strcpy(_file_to_saveload.name, name); + DeleteWindow(w); + } else if (_saveload_mode == SLD_LOAD_SCENARIO) { + _switch_mode = SM_LOAD_SCENARIO; + SetFiosType(file->type); + strcpy(_file_to_saveload.name, name); + DeleteWindow(w); + } else { + // SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox + strcpy(WP(w,querystr_d).buf, file->title[0] ? file->title : file->name); + InvalidateWidget(w, 9); + } + } else { + // Changed directory, need repaint. + SetWindowDirty(w); + BuildFileList(); + } + break; + } + case 10: case 11: /* Delete, Save game */ + break; + } + break; + case WE_MOUSELOOP: + HandleEditBox(w, 9); + break; + case WE_KEYPRESS: + switch (HandleEditBoxKey(w, 9, e)) { + case 1: + HandleButtonClick(w, 11); + break; + } + break; + case WE_TIMEOUT: + if (HASBIT(w->click_state, 10)) { /* Delete button clicked */ + FiosDelete(WP(w,querystr_d).buf); + SetWindowDirty(w); + BuildFileList(); + } else if (HASBIT(w->click_state, 11)) { /* Save button clicked */ + _switch_mode = SM_SAVE; + FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).buf); + } + break; + case WE_DESTROY: + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); + _query_string_active = false; + FiosFreeSavegameList(); + break; + } +} + +static const WindowDesc _load_dialog_desc = { + WDP_CENTER, WDP_CENTER, 257, 294, + WC_SAVELOAD,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _load_dialog_1_widgets, + SaveLoadDlgWndProc, +}; + +static const WindowDesc _load_dialog_scen_desc = { + WDP_CENTER, WDP_CENTER, 257, 294, + WC_SAVELOAD,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _load_dialog_2_widgets, + SaveLoadDlgWndProc, +}; + +static const WindowDesc _save_dialog_desc = { + WDP_CENTER, WDP_CENTER, 257, 320, + WC_SAVELOAD,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _save_dialog_widgets, + SaveLoadDlgWndProc, +}; + +static const WindowDesc _save_dialog_scen_desc = { + WDP_CENTER, WDP_CENTER, 257, 320, + WC_SAVELOAD,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _save_dialog_scen_widgets, + SaveLoadDlgWndProc, +}; + +static const WindowDesc * const _saveload_dialogs[] = { + &_load_dialog_desc, + &_load_dialog_scen_desc, + &_save_dialog_desc, + &_save_dialog_scen_desc, +}; + +void ShowSaveLoadDialog(int mode) +{ + Window *w; + + SetObjectToPlace(1, 0, 0, 0); + DeleteWindowById(WC_QUERY_STRING, 0); + DeleteWindowById(WC_SAVELOAD, 0); + + _saveload_mode = mode; + + w = AllocateWindowDesc(_saveload_dialogs[mode]); + w->vscroll.cap = 24; + w->click_state |= (1 << 6); + WP(w,querystr_d).caret = 0; + WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; + WP(w,querystr_d).maxwidth = 240; + WP(w,querystr_d).buf = _edit_str_buf; + + if (mode == SLD_SAVE_GAME) { + Player *p = &_players[_local_player]; + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, _date); + GetString(_edit_str_buf, STR_4004); + } else if (mode == SLD_SAVE_SCENARIO) { + strcpy(_edit_str_buf, "UNNAMED"); + } + + if (_game_mode != GM_MENU) + DoCommandP(0, 1, 0, NULL, CMD_PAUSE); + + BuildFileList(); + + ResetObjectToPlace(); +} + +void RedrawAutosave() +{ + SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0)); +} + +static const Widget _select_scenario_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 256, 0, 13, STR_400E_SELECT_NEW_GAME_TYPE, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 7, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 7, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_TIP}, +{ WWT_IMGBTN, 7, 0, 245, 26, 319, 0x0}, +{ WWT_6, 7, 2, 243, 28, 317, 0x0, STR_400F_SELECT_SCENARIO_GREEN_PRE}, +{ WWT_SCROLLBAR, 7, 246, 256, 26, 319, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static void SelectScenarioWndProc(Window *w, WindowEvent *e) { + const int list_start = 45; + switch(e->event) { + case WE_PAINT: + { + int y,pos; + const FiosItem *item; + + if (_savegame_sort_dirty) { + _savegame_sort_dirty = false; + MakeSortedSaveGameList(); + } + + SetVScrollCount(w, _fios_num); + + DrawWindowWidgets(w); + DoDrawString(_savegame_sort_order & 1 ? "\xAA" : "\xA0", _savegame_sort_order <= 1 ? 248 : 118, 15, 0x10); + DrawString(4, 32, STR_4010_GENERATE_RANDOM_NEW_GAME, 9); + + y = list_start; + pos = w->vscroll.pos; + while (pos < _fios_num) { + item = _fios_list + pos; + DoDrawString(item->title[0] ? item->title : item->name, 4, y, _fios_colors[item->type] ); + pos++; + y+=10; + if (y >= w->vscroll.cap*10+list_start) + break; + } + } + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: /* Sort scenario names by name */ + _savegame_sort_order = (_savegame_sort_order == 2) ? 3 : 2; + _savegame_sort_dirty = true; + SetWindowDirty(w); + break; + + case 3: /* Sort scenario names by date */ + _savegame_sort_order = (_savegame_sort_order == 0) ? 1 : 0; + _savegame_sort_dirty = true; + SetWindowDirty(w); + break; + + case 5: /* Click the listbox */ + if(e->click.pt.y < list_start) + DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_GEN_RANDOM_NEW_GAME); + else { + char *name; + int y = (e->click.pt.y - list_start) / 10; + const FiosItem *file; + + if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) + return; + + file = _fios_list + y; + + if ((name = FiosBrowseTo(file)) != NULL) { + SetFiosType(file->type); + strcpy(_file_to_saveload.name, name); + DeleteWindow(w); + DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_START_SCENARIO); + } + } + break; + } + case WE_DESTROY: + break; + } +} + +static void SetFiosType(const byte fiostype) +{ + switch (fiostype) { + case FIOS_TYPE_FILE: case FIOS_TYPE_SCENARIO: + _file_to_saveload.mode = SL_LOAD; + break; + case FIOS_TYPE_OLDFILE: case FIOS_TYPE_OLD_SCENARIO: + _file_to_saveload.mode = SL_OLD_LOAD; + break; + default: + _file_to_saveload.mode = SL_INVALID; + } +} + +static const WindowDesc _select_scenario_desc = { + WDP_CENTER, WDP_CENTER, 257, 320, + WC_SAVELOAD,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, + _select_scenario_widgets, + SelectScenarioWndProc +}; + +void AskForNewGameToStart() +{ + Window *w; + + DeleteWindowById(WC_QUERY_STRING, 0); + DeleteWindowById(WC_SAVELOAD, 0); + + _saveload_mode = SLD_NEW_GAME; + BuildFileList(); + + w = AllocateWindowDesc(&_select_scenario_desc); + w->vscroll.cap = 27; +} + + + + +int32 ClickMoneyCheat(int32 p1, int32 p2) +{ + DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT); + return true; +} + +// p1 player to set to, p2 is -1 or +1 (down/up) +int32 ClickChangePlayerCheat(int32 p1, int32 p2) +{ + while(p1 >= 0 && p1 < MAX_PLAYERS) + { + if (_players[p1].is_active) + { + _local_player = p1; + return _local_player; + } + p1 += p2; + } +return _local_player; +} + +typedef int32 CheckButtonClick(int32, int32); +static CheckButtonClick * const _cheat_button_proc[] = { + ClickMoneyCheat, + ClickChangePlayerCheat, +}; + + +typedef struct CheatEntry { + byte type; // type of selector + byte flags; // selector flags + StringID str; // string with descriptive text + void *variable; // pointer to the variable + bool *been_used; // has this cheat been used before? + CheckButtonClick *click_proc; // procedure + int16 min,max; // range for spinbox setting + uint16 step; // step for spinbox +} CheatEntry; + +enum { + CE_BOOL = 0, + CE_UINT8 = 1, + CE_INT16 = 2, + CE_UINT16 = 3, + CE_INT32 = 4, + CE_BYTE = 5, + CE_CLICK = 6, + + CF_0ISDIS = 1, + CF_NOCOMMA = 2, +}; + +static int32 ReadCE(const CheatEntry*ce) +{ + switch(ce->type) { + case CE_BOOL: return *(bool*)ce->variable; + case CE_UINT8: return *(uint8*)ce->variable; + case CE_INT16: return *(int16*)ce->variable; + case CE_UINT16: return *(uint16*)ce->variable; + case CE_INT32: return *(int32*)ce->variable; + case CE_BYTE: return *(byte*)ce->variable; + case CE_CLICK: return 0; + default: + NOT_REACHED(); + } + + /* useless, but avoids compiler warning this way */ + return 0; +} + +static void WriteCE(const CheatEntry *ce, int32 val) +{ + switch(ce->type) { + case CE_BOOL: *(bool*)ce->variable = (bool)val; break; + case CE_BYTE: *(byte*)ce->variable = (byte)val; break; + case CE_UINT8: *(uint8*)ce->variable = (uint8)val; break; + case CE_INT16: *(int16*)ce->variable = (int16)val; break; + case CE_UINT16: *(uint16*)ce->variable = (uint16)val; break; + case CE_INT32: *(int32*)ce->variable = val; break; + case CE_CLICK: break; + default: + NOT_REACHED(); + } +} + + +static const CheatEntry _cheats_ui[] = { + {CE_CLICK, 0, STR_CHEAT_MONEY, &_cheats.money.value, &_cheats.money.been_used, &ClickMoneyCheat}, + {CE_UINT8, 0, STR_CHEAT_CHANGE_PLAYER, &_local_player, &_cheats.switch_player.been_used, &ClickChangePlayerCheat, 0, 11, 1}, + {CE_BOOL, 0, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used}, + {CE_BOOL, 0, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,&_cheats.crossing_tunnels.been_used}, +}; + + +static const Widget _cheat_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 399, 0, 13, STR_CHEATS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 399, 14, 147, 0x0}, + +{ WWT_IMGBTN, 14, 0, 399, 14, 147, 0x0, STR_CHEATS_TIP}, +{ WWT_LAST}, +}; + +extern void DrawPlayerIcon(int p, int x, int y); + +static void CheatsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int clk = WP(w,def_d).data_1; + const CheatEntry *ce = &_cheats_ui[0]; + int32 val; + int x, y; + int i; + + DrawWindowWidgets(w); + + DrawStringMultiCenter(200, 25, STR_CHEATS_WARNING, 350); + + x=0; + y=45; + + for(i=0; i!=lengthof(_cheats_ui); i++,ce++) { + + DrawSprite((SPR_OPENTTD_BASE + ((*ce->been_used)?67:66)), x+5, y+2); + + if (ce->type == CE_BOOL) { + DrawFrameRect(x+20, y+1, x+30+9, y+9, (*(bool*)ce->variable)?6:4, (*(bool*)ce->variable)?0x20:0); + SET_DPARAM16(0, *(bool*)ce->variable ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); + + } else if (ce->type == CE_CLICK) { + DrawFrameRect(x+20, y+1, x+30+9, y+9, 0, (WP(w,def_d).data_1==i*2+1)?0x20:0x00); + if(i==0) + SET_DPARAM64(0, (int64) 10000000); + else + SET_DPARAM16(0, false); + + } else { + DrawFrameRect(x+20, y+1, x+20+9, y+9, 3, clk == i*2+1 ? 0x20 : 0); + DrawFrameRect(x+30, y+1, x+30+9, y+9, 3, clk == i*2+2 ? 0x20 : 0); + DrawStringCentered(x+25, y+1, STR_6819, 0); + DrawStringCentered(x+35, y+1, STR_681A, 0); + + val = ReadCE(ce); + SET_DPARAM16(0, val); + + // draw colored flag for change player cheat + if(ce->str==STR_CHEAT_CHANGE_PLAYER) + DrawPlayerIcon(_current_player, 156, y+2); + + + } + + DrawString(50, y+1, ce->str, 0); + + y+=12; + } + break; + } + case WE_CLICK: { + const CheatEntry *ce; + uint btn = (e->click.pt.y - 46) / 12; + int32 val, oval; + uint x = e->click.pt.x; + + // not clicking a button? + if(!IS_INT_INSIDE(x, 20, 40) || btn>=lengthof(_cheats_ui)) + break; + + ce = &_cheats_ui[btn]; + oval = val = ReadCE(ce); + + *ce->been_used = true; + + switch(ce->type) { + case CE_BOOL: { + val ^= 1; + if (ce->click_proc != NULL) + ce->click_proc(val, 0); + break; + } + + case CE_CLICK: { + ce->click_proc(val, 0); + WP(w,def_d).data_1 = btn * 2 + 1; + break; + } + + default: { + if (x >= 30) { + //increase + val += ce->step; + if (val > ce->max) val = ce->max; + } else { + // decrease + val -= ce->step; + if (val < ce->min) val = ce->min; + } + + // take whatever the function returns + val = ce->click_proc(val, (x>=30) ? 1 : -1); + + if (val != oval) + WP(w,def_d).data_1 = btn * 2 + 1 + ((x>=30) ? 1 : 0); + + break; + } + } + + if (val != oval) { + WriteCE(ce, val); + SetWindowDirty(w); + } + + w->flags4 |= 5 << WF_TIMEOUT_SHL; + + SetWindowDirty(w); + } + break; + case WE_TIMEOUT: + WP(w,def_d).data_1 = 0; + SetWindowDirty(w); + break; + } +} +static const WindowDesc _cheats_desc = { + 240, 22, 400, 148, + WC_CHEATS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _cheat_widgets, + CheatsWndProc +}; + + +void ShowCheatWindow() +{ + Window *w; + + DeleteWindowById(WC_CHEATS, 0); + w = AllocateWindowDesc(&_cheats_desc); + + if (w) + SetWindowDirty(w); +} diff --git a/music_gui.c b/music_gui.c new file mode 100644 --- /dev/null +++ b/music_gui.c @@ -0,0 +1,453 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "sound.h" +#include "hal.h" + +#define NUM_SONGS_AVAILABLE 22 + + +static byte _playlist_all[] = { + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,0, +}; + +static byte _playlist_old_style[] = { + 1, 8, 2, 9, 14, 15, 19, 13, 0, +}; + +static byte _playlist_new_style[] = { + 6, 11, 10, 17, 21, 18, 5, 0 +}; + +static byte _playlist_ezy_street[] = { + 12, 7, 16, 3, 20, 4, 0 +}; + +static byte * const _playlists[] = { + _playlist_all, + _playlist_old_style, + _playlist_new_style, + _playlist_ezy_street, + msf.custom_1, + msf.custom_2, +}; + + +static void SkipToPrevSong() +{ + byte *b = _cur_playlist; + byte *p = b; + byte t; + + // empty playlist + if (b[0] == 0) + return; + + // find the end + do p++; while (p[0] != 0); + + // and copy the bytes + t = *--p; + while (p != b) { + p--; + p[1] = p[0]; + } + *b = t; + + _song_is_active = false; +} + +static void SkipToNextSong() +{ + byte *b = _cur_playlist, t; + + if ((t=b[0]) != 0) { + while (b[1]) { + b[0] = b[1]; + b++; + } + b[0] = t; + } + + _song_is_active = false; +} + +static void MusicVolumeChanged(byte new_vol) +{ + _music_driver->set_volume(new_vol); +} + +static void DoPlaySong() +{ + char filename[256]; + sprintf(filename, "%sgm_tt%.2d.gm", _path.gm_dir, _music_wnd_cursong - 1); + _music_driver->play_song(filename); +} + +static void DoStopMusic() +{ + _music_driver->stop_song(); +} + +static void SelectSongToPlay() +{ + int i; + + memset(_cur_playlist, 0, 33); + strcpy(_cur_playlist, _playlists[msf.playlist]); + + if (msf.shuffle) { + i = 500; + do { + uint32 r = InteractiveRandom(); + byte *a = &_cur_playlist[r & 0x1F]; + byte *b = &_cur_playlist[(r >> 8)&0x1F]; + + if (*a != 0 && *b != 0) { + byte t = *a; + *a = *b; + *b = t; + } + } while (--i); + } +} + +static void StopMusic() +{ + _music_wnd_cursong = 0; + DoStopMusic(); + _song_is_active = false; + InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9); +} + +static void PlayPlaylistSong() +{ + if (_cur_playlist[0] == 0) { + SelectSongToPlay(); + if (_cur_playlist[0] == 0) + return; + } + _music_wnd_cursong = _cur_playlist[0]; + DoPlaySong(); + _song_is_active = true; + + InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9); +} + +void ResetMusic() +{ + _music_wnd_cursong = 1; + DoPlaySong(); +} + +void MusicLoop() +{ + if (!msf.btn_down && _song_is_active) { + StopMusic(); + } else if (msf.btn_down && !_song_is_active) { + PlayPlaylistSong(); + } + + if (_song_is_active == false) + return; + + if (!_music_driver->is_song_playing()) { + StopMusic(); + SkipToNextSong(); + PlayPlaylistSong(); + } +} + +static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int y,i; + byte *p; + + w->disabled_state = (msf.playlist <= 3) ? (1 << 11) : 0; + w->click_state |= 0x18; + DrawWindowWidgets(w); + + GfxFillRect(3, 23, 3+177,23+191,0); + GfxFillRect(251, 23, 251+177,23+191,0); + + DrawStringCentered(92, 15, STR_01EE_TRACK_INDEX, 0); + + SET_DPARAM16(0, STR_01D5_ALL + msf.playlist); + DrawStringCentered(340, 15, STR_01EF_PROGRAM, 0); + + for(i=1; (uint)i <= NUM_SONGS_AVAILABLE; i++) { + SET_DPARAM16(0, i); + SET_DPARAM16(2, i); + SET_DPARAM16(1, SPECSTR_SONGNAME); + DrawString(4, 23+(i-1)*6, (i < 10) ? STR_01EC_0 : STR_01ED, 0); + } + + for(i=0; i!=6; i++) { + DrawStringCentered(216, 45 + i*8, STR_01D5_ALL + i, (i==msf.playlist) ? 0xC : 0x10); + } + + DrawStringCentered(216, 45+8*6+16, STR_01F0_CLEAR, 0); + DrawStringCentered(216, 45+8*6+16*2, STR_01F1_SAVE, 0); + + y = 23; + for(p = _playlists[msf.playlist],i=0; (i=*p) != 0; p++) { + SET_DPARAM16(0, i); + SET_DPARAM16(2, i); + SET_DPARAM16(1, SPECSTR_SONGNAME); + DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, 0); + y += 6; + } + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 3: { /* add to playlist */ + int y = (e->click.pt.y - 23) / 6; + int i; + byte *p; + if (msf.playlist < 4) return; + if ((uint)y >= NUM_SONGS_AVAILABLE) return; + + p = _playlists[msf.playlist]; + for(i=0; i!=32; i++) { + if (p[i] == 0) { + p[i] = (byte)(y + 1); + p[i+1] = 0; + SetWindowDirty(w); + SelectSongToPlay(); + break; + } + } + + } break; + case 11: /* clear */ + _playlists[msf.playlist][0] = 0; + SetWindowDirty(w); + StopMusic(); + SelectSongToPlay(); + break; + case 12: /* save */ + ShowInfo("MusicTrackSelectionWndProc:save not implemented\n"); + break; + case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */ + msf.playlist = e->click.widget - 5; + SetWindowDirty(w); + InvalidateWindow(WC_MUSIC_WINDOW, 0); + StopMusic(); + SelectSongToPlay(); + break; + } + break; + } +} + +static const Widget _music_track_selection_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 431, 14, 217, 0x0, 0}, +{ WWT_IMGBTN, 14, 2, 181, 22, 215, 0x0,STR_01FA_CLICK_ON_MUSIC_TRACK_TO}, +{ WWT_IMGBTN, 14, 250, 429, 22, 215, 0x0,STR_01F2_CURRENT_PROGRAM_OF_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 44, 51, 0x0,STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 52, 59, 0x0,STR_01F4_SELECT_OLD_STYLE_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 60, 67, 0x0,STR_01F5_SELECT_NEW_STYLE_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 68, 75, 0x0,STR_0330_SELECT_EZY_STREET_STYLE}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 76, 83, 0x0,STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 84, 91, 0x0,STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 108, 115, 0x0,STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1}, +{ WWT_PUSHIMGBTN, 14, 186, 245, 124, 131, 0x0,STR_01F9_SAVE_MUSIC_SETTINGS_TO}, +{ WWT_LAST}, +}; + +static const WindowDesc _music_track_selection_desc = { + 104, 131, 432, 218, + WC_MUSIC_TRACK_SELECTION,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _music_track_selection_widgets, + MusicTrackSelectionWndProc +}; + +static void ShowMusicTrackSelection() +{ + AllocateWindowDescFront(&_music_track_selection_desc, 0); +} + +static void MusicWindowWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int i,num; + StringID str; + + w->click_state |= 0x280; + DrawWindowWidgets(w); + + GfxFillRect(187, 16, 200, 33, 0); + + num = 8; + for (i=0; i!=num; i++) { + int color = 0xD0; + if (i > 4) { + color = 0xBF; + if (i > 6) { + color = 0xB8; + } + } + GfxFillRect(187, 33 - i*2, 200, 33 - i*2, color); + } + + GfxFillRect(60, 46, 239, 52, 0); + + str = STR_01E3; + if (_song_is_active != 0 && _music_wnd_cursong != 0) { + str = STR_01E4_0; + SET_DPARAM8(0, _music_wnd_cursong); + if (_music_wnd_cursong >= 10) + str = STR_01E5; + } + DrawString(62, 46, str, 0); + + str = STR_01E6; + if (_song_is_active != 0 && _music_wnd_cursong != 0) { + str = STR_01E7; + SET_DPARAM16(0, SPECSTR_SONGNAME); + SET_DPARAM16(1, _music_wnd_cursong); + } + DrawStringCentered(155, 46, str, 0); + + + DrawString(60, 38, STR_01E8_TRACK_XTITLE, 0); + + for(i=0; i!=6; i++) { + DrawStringCentered(25+i*50, 59, STR_01D5_ALL+i, msf.playlist == i ? 0xC : 0x10); + } + + DrawStringCentered(31, 43, STR_01E9_SHUFFLE, (msf.shuffle ? 0xC : 0x10)); + DrawStringCentered(269, 43, STR_01EA_PROGRAM, 0); + DrawStringCentered(141, 15, STR_01DB_MUSIC_VOLUME, 0); + DrawStringCentered(141, 29, STR_01DD_MIN_MAX, 0); + DrawStringCentered(247, 15, STR_01DC_EFFECTS_VOLUME, 0); + DrawStringCentered(247, 29, STR_01DD_MIN_MAX, 0); + + DrawFrameRect(108, 23, 174, 26, 14, 0x20); + DrawFrameRect(214, 23, 280, 26, 14, 0x20); + + DrawFrameRect(108 + (msf.music_vol>>1), + 22, + 111 + (msf.music_vol>>1), + 28, + 14, + 0); + + DrawFrameRect(214 + (msf.effect_vol>>1), + 22, + 217 + (msf.effect_vol>>1), + 28, + 14, + 0); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: // skip to prev + if (!_song_is_active) + return; + SkipToPrevSong(); + break; + case 3: // skip to next + if (!_song_is_active) + return; + SkipToNextSong(); + break; + case 4: // stop playing + msf.btn_down = false; + break; + case 5: // start playing + msf.btn_down = true; + break; + case 6:{ // volume sliders + byte *vol,new_vol; + int x = e->click.pt.x - 88; + + if (x < 0) + return; + + vol = &msf.music_vol; + if (x >= 106) { + vol = &msf.effect_vol; + x -= 106; + } + + new_vol = min(max(x-21,0)*2,127); + if (new_vol != *vol) { + *vol = new_vol; + if (vol == &msf.music_vol) + MusicVolumeChanged(new_vol); + SetWindowDirty(w); + } + + _left_button_clicked = false; + } break; + case 10: //toggle shuffle + msf.shuffle ^= 1; + StopMusic(); + SelectSongToPlay(); + break; + case 11: //show track selection + ShowMusicTrackSelection(); + break; + case 12: case 13: case 14: case 15: case 16: case 17: // playlist + msf.playlist = e->click.widget - 12; + SetWindowDirty(w); + InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0); + StopMusic(); + SelectSongToPlay(); + break; + } + break; + + case WE_MOUSELOOP: + InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7); + break; + } + +} + +static const Widget _music_window_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHIMGBTN, 14, 0, 21, 14, 35, 0x2C5, STR_01DE_SKIP_TO_PREVIOUS_TRACK}, +{ WWT_PUSHIMGBTN, 14, 22, 43, 14, 35, 0x2C6, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION}, +{ WWT_PUSHIMGBTN, 14, 44, 65, 14, 35, 0x2C7, STR_01E0_STOP_PLAYING_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 66, 87, 14, 35, 0x2C8, STR_01E1_START_PLAYING_MUSIC}, +{ WWT_IMGBTN, 14, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC}, +{ WWT_IMGBTN, 14, 186, 201, 15, 34, 0x0}, +{ WWT_IMGBTN, 14, 0, 299, 36, 57, 0x0}, +{ WWT_IMGBTN, 14, 59, 240, 45, 53, 0x0}, +{ WWT_PUSHIMGBTN, 14, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE}, +{ WWT_PUSHIMGBTN, 14, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION}, +{ WWT_PUSHIMGBTN, 14, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, +{ WWT_PUSHIMGBTN, 14, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, +{ WWT_PUSHIMGBTN, 14, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, +{ WWT_PUSHIMGBTN, 14, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, +{ WWT_PUSHIMGBTN, 14, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, +{ WWT_LAST}, +}; + +static const WindowDesc _music_window_desc = { + 0, 22, 300, 66, + WC_MUSIC_WINDOW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _music_window_widgets, + MusicWindowWndProc +}; + +void ShowMusicWindow() +{ + AllocateWindowDescFront(&_music_window_desc, 0); +} diff --git a/namegen.c b/namegen.c new file mode 100644 --- /dev/null +++ b/namegen.c @@ -0,0 +1,1974 @@ +#include "stdafx.h" +#include "ttd.h" + + +#define GETNUM(x, y) (((uint16)(seed >> x) * (y))>>16) + +static void AppendPart(byte **buf, int num, const char *names) +{ + byte *s; + + while (--num>=0) { + do names++; while (names[-1]); + } + + for(s=*buf; (*s++ = *names++) != 0;) {} + *buf = s - 1; +} + +#define MK(x) x "\x0" + +#define NUM_ENGLISH_1 4 +static const char english_1[] = + MK("Great ") + MK("Little ") + MK("New ") + MK("Fort ") +; + +#define NUM_ENGLISH_2 26 +static const char english_2[] = + MK("Wr") + MK("B") + MK("C") + MK("Ch") + MK("Br") + MK("D") + MK("Dr") + MK("F") + MK("Fr") + MK("Fl") + MK("G") + MK("Gr") + MK("H") + MK("L") + MK("M") + MK("N") + MK("P") + MK("Pr") + MK("Pl") + MK("R") + MK("S") + MK("S") + MK("Sl") + MK("T") + MK("Tr") + MK("W") +; + +#define NUM_ENGLISH_3 8 +static const char english_3[] = + MK("ar") + MK("a") + MK("e") + MK("in") + MK("on") + MK("u") + MK("un") + MK("en") +; + +#define NUM_ENGLISH_4 7 +static const char english_4[] = + MK("n") + MK("ning") + MK("ding") + MK("d") + MK("") + MK("t") + MK("fing") +; + +#define NUM_ENGLISH_5 23 +static const char english_5[] = + MK("ville") + MK("ham") + MK("field") + MK("ton") + MK("town") + MK("bridge") + MK("bury") + MK("wood") + MK("ford") + MK("hall") + MK("ston") + MK("way") + MK("stone") + MK("borough") + MK("ley") + MK("head") + MK("bourne") + MK("pool") + MK("worth") + MK("hill") + MK("well") + MK("hattan") + MK("burg") +; + +#define NUM_ENGLISH_6 9 +static const char english_6[] = + MK("-on-sea") + MK(" Bay") + MK(" Market") + MK(" Cross") + MK(" Bridge") + MK(" Falls") + MK(" City") + MK(" Ridge") + MK(" Springs") +; + +static byte MakeEnglishTownName(byte *buf, uint32 seed) +{ + int i; + byte result; + byte *start; + + i = GETNUM(0, 54) - 50; + if (i >= 0) + AppendPart(&buf, i, english_1); + + start = buf; + + AppendPart(&buf, GETNUM(4, NUM_ENGLISH_2), english_2); + AppendPart(&buf, GETNUM(7, NUM_ENGLISH_3), english_3); + AppendPart(&buf, GETNUM(10, NUM_ENGLISH_4), english_4); + AppendPart(&buf, GETNUM(13, NUM_ENGLISH_5), english_5); + + i = GETNUM(15, NUM_ENGLISH_6 + 60) - 60; + + result = 0; + + if (i >= 0) { + if (i <= 1) result = NG_EDGE; + AppendPart(&buf, i, english_6); + } + + if (start[0]=='C' && (start[1] == 'e' || start[1] == 'i')) + start[0] = 'K'; + + /* FIXME: skip the banned words thing for now + only replacing "Cunt" with "Cult" */ + if (start[0]=='C' && start[1] == 'u' && start[2] == 'n' && start[3] == 't') + start[2] = 'l'; + + return result; +} + +#define NUM_AUSTRIAN_A1 6 +static const char austrian_a1[] = + MK("Bad ") + MK("Deutsch ") + MK("Gross ") + MK("Klein ") + MK("Markt ") + MK("Maria ") +; + +#define NUM_AUSTRIAN_A2 42 +static const char austrian_a2[] = + MK("Aus") + MK("Alten") + MK("Braun") + MK("Vösl") + MK("Mittern") + MK("Nuss") + MK("Neu") + MK("Walters") + MK("Breiten") + MK("Eisen") + MK("Feld") + MK("Mittern") + MK("Gall") + MK("Obern") + MK("Grat") + MK("Heiligen") + MK("Hof") + MK("Holla") + MK("Stein") + MK("Eber") + MK("Eggen") + MK("Enzers") + MK("Frauen") + MK("Herren") + MK("Hof") + MK("Hütt") + MK("Kaisers") + MK("Königs") + MK("Knittel") + MK("Lang") + MK("Ober") + MK("Ollers") + MK("Pfaffen") + MK("Potten") + MK("Salz") + MK("Schwarz") + MK("Stocker") + MK("Unter") + MK("Utten") + MK("Vösen") + MK("Vill") + MK("Weissen") +; + +#define NUM_AUSTRIAN_A3 16 +static const char austrian_a3[] = + MK("see") + MK("bach") + MK("dorf") + MK("ach") + MK("stein") + MK("hofen") + MK("au") + MK("ach") + MK("kirch") + MK("kirchen") + MK("kreuz") + MK("brunn") + MK("siedl") + MK("markt") + MK("wang") + MK("haag") +; + +#define NUM_AUSTRIAN_A4 12 +static const char austrian_a4[] = + MK("Bruck") + MK("Brunn") + MK("Gams") + MK("Grein") + MK("Ried") + MK("Faak") + MK("Zell") + MK("Spital") + MK("Kirchberg") + MK("Saal") + MK("Taferl") + MK("Wald") +; + +#define NUM_AUSTRIAN_A5 2 +static const char austrian_a5[] = + MK("St. ") + MK("Sankt ") +; + +#define NUM_AUSTRIAN_A6 20 +static const char austrian_a6[] = + MK("Aegyd") + MK("Andrä") + MK("Georgen") + MK("Jakob") + MK("Johann") + MK("Leonhard") + MK("Marein") + MK("Lorenzen") + MK("Margarethen") + MK("Martin") + MK("Michael") + MK("Nikolai") + MK("Oswald") + MK("Peter") + MK("Pölten") + MK("Stefan") + MK("Stephan") + MK("Thomas") + MK("Veit") + MK("Wolfgang") +; + +#define NUM_AUSTRIAN_F1 2 +static const char austrian_f1[] = + MK(" an der ") + MK(" ob der ") +; + +#define NUM_AUSTRIAN_F2 13 +static const char austrian_f2[] = + MK("Donau") + MK("Steyr") + MK("Lafnitz") + MK("Leitha") + MK("Thaya") + MK("Gail") + MK("Drau") + MK("Salzach") + MK("Ybbs") + MK("Traisen") + MK("Enns") + MK("Mur") + MK("Ill") +; + +#define NUM_AUSTRIAN_B1 1 +static const char austrian_b1[] = + MK(" am ") +; + +#define NUM_AUSTRIAN_B2 10 +static const char austrian_b2[] = + MK("Brenner") + MK("Dachstein") + MK("Gebirge") + MK("Grossglockner") + MK("Hausruck") + MK("Semmering") + MK("Wagram") + MK("Wechsel") + MK("Wilden Kaiser") + MK("Ziller") +; + +static byte MakeAustrianTownName(byte *buf, uint32 seed) +{ + int i, j=0; + + // Bad, Maria, Gross, ... + i = GETNUM(0, NUM_AUSTRIAN_A1 + 15) - 15; + if (i >= 0) AppendPart(&buf, i, austrian_a1); + + i = GETNUM(4, 6); + if(i >= 4) { + // Kaisers-kirchen + AppendPart(&buf, GETNUM( 7, NUM_AUSTRIAN_A2), austrian_a2); + AppendPart(&buf, GETNUM(13, NUM_AUSTRIAN_A3), austrian_a3); + } + else if(i >= 2) { + // St. Johann + AppendPart(&buf, GETNUM( 7, NUM_AUSTRIAN_A5), austrian_a5); + AppendPart(&buf, GETNUM( 9, NUM_AUSTRIAN_A6), austrian_a6); + j=1; // More likely to have a " an der " or " am " + } + else { + // Zell + AppendPart(&buf, GETNUM( 7, NUM_AUSTRIAN_A4), austrian_a4); + } + + i = GETNUM(1, 6); + if(i >= 4-j) { + // an der Donau (rivers) + AppendPart(&buf, GETNUM(4, NUM_AUSTRIAN_F1), austrian_f1); + AppendPart(&buf, GETNUM(5, NUM_AUSTRIAN_F2), austrian_f2); + } + else if(i >= 2-j) { + // am Dachstein (mountains) + AppendPart(&buf, GETNUM(4, NUM_AUSTRIAN_B1), austrian_b1); + AppendPart(&buf, GETNUM(5, NUM_AUSTRIAN_B2), austrian_b2); + } + + return 0; +} + +#define NUM_GERMAN_1 114 +#define NUM_GERMAN_1_HARDCODED 21 +static const char german_1[] = + /* hardcoded names */ + MK("Berlin") + MK("Bonn") + MK("Bremen") + MK("Cottbus") + MK("Chemnitz") + MK("Dortmund") + MK("Dresden") + MK("Erfurt") + MK("Erlangen") + MK("Essen") + MK("Fulda") + MK("Gera") + MK("Kassel") + MK("Kiel") + MK("Köln") + MK("Lübeck") + MK("Magdeburg") + MK("München") + MK("Potsdam") + MK("Stuttgart") + MK("Wiesbaden") + /* randomizer names */ + MK("Alb") + MK("Als") + MK("Ander") + MK("Arns") + MK("Bruns") + MK("Bam") + MK("Biele") + MK("Cloppen") + MK("Co") + MK("Duis") + MK("Düssel") + MK("Dannen") + MK("Elb") + MK("Els") + MK("Elster") + MK("Eichen") + MK("Ems") + MK("Fahr") + MK("Falken") + MK("Flens") + MK("Frank") + MK("Frei") + MK("Freuden") + MK("Fried") + MK("Fürsten") + MK("Hahn") + MK("Ham") + MK("Harz") + MK("Heidel") + MK("Hers") + MK("Herz") + MK("Holz") + MK("Hildes") + MK("Inns") + MK("Ilsen") + MK("Ingols") + MK("Kel") + MK("Kies") + MK("Korn") + MK("Kor") + MK("Kreuz") + MK("Kulm") + MK("Langen") + MK("Lim") + MK("Lohr") + MK("Lüne") + MK("Mel") + MK("Michels") + MK("Mühl") + MK("Naum") + MK("Nest") + MK("Nord") + MK("Nort") + MK("Nien") + MK("Nidda") + MK("Nieder") + MK("Nürn") + MK("Ober") + MK("Offen") + MK("Osna") + MK("Olden") + MK("Ols") + MK("Oranien") + MK("Pader") + MK("Quedlin") + MK("Quer") + MK("Ravens") + MK("Regens") + MK("Rott") + MK("Ros") + MK("Rüssels") + MK("Saal") + MK("Saar") + MK("Salz") + MK("Schöne") + MK("Schwein") + MK("Sonder") + MK("Sonnen") + MK("Stein") + MK("Strals") + MK("Straus") + MK("Süd") + MK("Ton") + MK("Unter") + MK("Ur") + MK("Vor") + MK("Wald") + MK("War") + MK("Wert") + MK("Wester") + MK("Witten") + MK("Wolfs") + MK("Würz") +; + +#define NUM_GERMAN_2 16 +static const char german_2[] = + MK("bach") + MK("berg") + MK("brück") + MK("brücken") + MK("burg") + MK("dorf") + MK("feld") + MK("furt") + MK("hausen") + MK("haven") + MK("heim") + MK("horst") + MK("mund") + MK("münster") + MK("stadt") + MK("wald") +; + +#define NUM_GERMAN_3 5 +static const char german_3[] = + MK(" an der ") + MK(" am ") + MK("Bad ") + MK("Klein ") + MK("Neu ") +; + +#define NUM_GERMAN_4 6 +#define NUM_GERMAN_4_PRECHANGE 5 +static const char german_4[] = + /* use "an der" */ + MK("Oder") + MK("Spree") + MK("Donau") + MK("Saale") + MK("Elbe") + /* use "am" */ + MK("Main") + +; + +static byte MakeGermanTownName(byte *buf, uint32 seed) +{ + int i; + int ext; + + ext=GETNUM(7, 28); /* Extension - Prefix / Suffix */ + + if ((ext==12) || (ext==19)) { + i=GETNUM(2,NUM_GERMAN_3-2); + AppendPart(&buf, 2+i, german_3); + } + + + i=GETNUM(3,NUM_GERMAN_1); + + AppendPart(&buf, i, german_1); + + if (i>NUM_GERMAN_1_HARDCODED-1) { + AppendPart(&buf, GETNUM(5, NUM_GERMAN_2), german_2); + } + + if (ext==24) { + i=GETNUM(9,NUM_GERMAN_4); + + if (i<=NUM_GERMAN_4_PRECHANGE-1) { + AppendPart(&buf, 0, german_3); + AppendPart(&buf, i, german_4); + } else { + AppendPart(&buf, 1, german_3); + AppendPart(&buf, i, german_4); + } + } + + return 0; +} + +#define NUM_SPANISH_1 86 +static const char spanish_1[] = + MK("Caracas") + MK("Maracay") + MK("Maracaibo") + MK("Velencia") + MK("El Dorado") + MK("Morrocoy") + MK("Cata") + MK("Cataito") + MK("Ciudad Bolivar") + MK("Barquisimeto") + MK("Merida") + MK("Puerto Ordaz") + MK("Santa Elena") + MK("San Juan") + MK("San Luis") + MK("San Rafael") + MK("Santiago") + MK("Barcelona") + MK("Barinas") + MK("San Cristobal") + MK("San Fransisco") + MK("San Martin") + MK("Guayana") + MK("San Carlos") + MK("El Limon") + MK("Coro") + MK("Corocoro") + MK("Puerto Ayacucho") + MK("Elorza") + MK("Arismendi") + MK("Trujillo") + MK("Carupano") + MK("Anaco") + MK("Lima") + MK("Cuzco") + MK("Iquitos") + MK("Callao") + MK("Huacho") + MK("Camana") + MK("Puerto Chala") + MK("Santa Cruz") + MK("Quito") + MK("Cuenca") + MK("Huacho") + MK("Tulcan") + MK("Esmereldas") + MK("Ibarra") + MK("San Lorenzo") + MK("Macas") + MK("Morana") + MK("Machala") + MK("Zamora") + MK("Latacunga") + MK("Tena") + MK("Cochabamba") + MK("Ascencion") + MK("Magdalena") + MK("Santa Ana") + MK("Manoa") + MK("Sucre") + MK("Oruro") + MK("Uyuni") + MK("Potosi") + MK("Tupiza") + MK("La Quiaca") + MK("Yacuiba") + MK("San Borja") + MK("Fuerte Olimpio") + MK("Fortin Esteros") + MK("Campo Grande") + MK("Bogota") + MK("El Banco") + MK("Zaragosa") + MK("Neiva") + MK("Mariano") + MK("Cali") + MK("La Palma") + MK("Andoas") + MK("Barranca") + MK("Montevideo") + MK("Valdivia") + MK("Arica") + MK("Temuco") + MK("Tocopilla") + MK("Mendoza") + MK("Santa Rosa"); + +static byte MakeSpanishTownName(byte *buf, uint32 seed) +{ + AppendPart(&buf, GETNUM(0, NUM_SPANISH_1), spanish_1); + return 0; +} + +#define NUM_FRENCH_1 70 +static const char french_1[] = + MK("Agincourt") + MK("Lille") + MK("Dinan") + MK("Aubusson") + MK("Rodez") + MK("Bergerac") + MK("Bordeaux") + MK("Bayonne") + MK("Montpellier") + MK("Montelimar") + MK("Valence") + MK("Digne") + MK("Nice") + MK("Cannes") + MK("St. Tropez") + MK("Marseilles") + MK("Narbonne") + MK("Sète") + MK("Aurillac") + MK("Gueret") + MK("Le Creusot") + MK("Nevers") + MK("Auxerre") + MK("Versailles") + MK("Meaux") + MK("Châlons") + MK("Compiègne") + MK("Metz") + MK("Chaumont") + MK("Langres") + MK("Bourg") + MK("Lyons") + MK("Vienne") + MK("Grenoble") + MK("Toulon") + MK("Rennes") + MK("Le Mans") + MK("Angers") + MK("Nantes") + MK("Châteauroux") + MK("Orléans") + MK("Lisieux") + MK("Cherbourg") + MK("Morlaix") + MK("Cognac") + MK("Agen") + MK("Tulle") + MK("Blois") + MK("Troyes") + MK("Charolles") + MK("Grenoble") + MK("Chambéry") + MK("Tours") + MK("St. Brieuc") + MK("St. Malo") + MK("La Rochelle") + MK("St. Flour") + MK("Le Puy") + MK("Vichy") + MK("St. Valery") + MK("Beaujolais") + MK("Narbonne") + MK("Albi") + MK("St. Valery") + MK("Biarritz") + MK("Béziers") + MK("Nîmes") + MK("Chamonix") + MK("Angoulème") + MK("Alençon"); + +static byte MakeFrenchTownName(byte *buf, uint32 seed) +{ + AppendPart(&buf, GETNUM(0, NUM_FRENCH_1), french_1); + return 0; +} + +static byte MakeAmericanTownName(byte *buf, uint32 seed) +{ + // make american town names equal to english for now. + return MakeEnglishTownName(buf, seed); +} + +#define NUM_SILLY_1 88 +static const char silly_1[] = + MK("Binky") + MK("Blubber") + MK("Bumble") + MK("Crinkle") + MK("Crusty") + MK("Dangle") + MK("Dribble") + MK("Flippety") + MK("Google") + MK("Muffin") + + MK("Nosey") + MK("Pinker") + MK("Quack") + MK("Rumble") + MK("Sleepy") + MK("Sliggles") + MK("Snooze") + MK("Teddy") + MK("Tinkle") + MK("Twister") + + MK("Pinker") + MK("Hippo") + MK("Itchy") + MK("Jelly") + MK("Jingle") + MK("Jolly") + MK("Kipper") + MK("Lazy") + MK("Frogs") + MK("Mouse") + + MK("Quack") + MK("Cheeky") + MK("Lumpy") + MK("Grumpy") + MK("Mangle") + MK("Fiddle") + MK("Slugs") + MK("Noodles") + MK("Poodles") + MK("Shiver") + + MK("Rumble") + MK("Pixie") + MK("Puddle") + MK("Riddle") + MK("Rattle") + MK("Rickety") + MK("Waffle") + MK("Sagging") + MK("Sausage") + MK("Egg") + + MK("Sleepy") + MK("Scatter") + MK("Scramble") + MK("Silly") + MK("Simple") + MK("Tricky") + MK("Slippery") + MK("Slimey") + MK("Slumber") + MK("Soggy") + + MK("Sliggles") + MK("Splutter") + MK("Sulky") + MK("Swindle") + MK("Swivel") + MK("Tasty") + MK("Tangle") + MK("Toggle") + MK("Trotting") + MK("Tumble") + + MK("Snooze") + MK("Water") + MK("Windy") + MK("Amble") + MK("Bubble") + MK("Cheery") + MK("Cheese") + MK("Cockle") + MK("Cracker") + MK("Crumple") + + MK("Teddy") + MK("Evil") + MK("Fairy") + MK("Falling") + MK("Fishy") + MK("Fizzle") + MK("Frosty") + MK("Griddle") +; + +#define NUM_SILLY_2 15 +static const char silly_2[] = + MK("ton") + MK("bury") + MK("bottom") + MK("ville") + MK("well") + MK("weed") + MK("worth") + MK("wig") + MK("wick") + MK("wood") + + MK("pool") + MK("head") + MK("burg") + MK("gate") + MK("bridge") +; + + +static byte MakeSillyTownName(byte *buf, uint32 seed) +{ + AppendPart(&buf, GETNUM(0, NUM_SILLY_1), silly_1); + AppendPart(&buf, GETNUM(16, NUM_SILLY_2),silly_2); + return 0; +} + + +#define NUM_SWEDISH_1 4 +static const char swedish_1[] = + MK("Gamla ") + MK("Lilla ") + MK("Nya ") + MK("Stora "); + +#define NUM_SWEDISH_2 38 +static const char swedish_2[] = + MK("Boll") + MK("Bor") + MK("Ed") + MK("En") + MK("Erik") + MK("Es") + MK("Fin") + MK("Fisk") + MK("Grön") + MK("Hag") + MK("Halm") + MK("Karl") + MK("Kram") + MK("Kung") + MK("Land") + MK("Lid") + MK("Lin") + MK("Mal") + MK("Malm") + MK("Marie") + MK("Ner") + MK("Norr") + MK("Oskar") + MK("Sand") + MK("Skog") + MK("Stock") + MK("Stor") + MK("Ström") + MK("Sund") + MK("Söder") + MK("Tall") + MK("Tratt") + MK("Troll") + MK("Upp") + MK("Var") + MK("Väster") + MK("Ängel") + MK("Öster"); + +#define NUM_SWEDISH_2A 42 +static const char swedish_2a[] = + MK("B") + MK("Br") + MK("D") + MK("Dr") + MK("Dv") + MK("F") + MK("Fj") + MK("Fl") + MK("Fr") + MK("G") + MK("Gl") + MK("Gn") + MK("Gr") + MK("H") + MK("J") + MK("K") + MK("Kl") + MK("Kn") + MK("Kr") + MK("Kv") + MK("L") + MK("M") + MK("N") + MK("P") + MK("Pl") + MK("Pr") + MK("R") + MK("S") + MK("Sk") + MK("Skr") + MK("Sl") + MK("Sn") + MK("Sp") + MK("Spr") + MK("St") + MK("Str") + MK("Sv") + MK("T") + MK("Tr") + MK("Tv") + MK("V") + MK("Vr"); + +#define NUM_SWEDISH_2B 9 +static const char swedish_2b[] = + MK("a") + MK("e") + MK("i") + MK("o") + MK("u") + MK("y") + MK("å") + MK("ä") + MK("ö"); + +#define NUM_SWEDISH_2C 26 +static const char swedish_2c[] = + MK("ck") + MK("d") + MK("dd") + MK("g") + MK("gg") + MK("l") + MK("ld") + MK("m") + MK("n") + MK("nd") + MK("ng") + MK("nn") + MK("p") + MK("pp") + MK("r") + MK("rd") + MK("rk") + MK("rp") + MK("rr") + MK("rt") + MK("s") + MK("sk") + MK("st") + MK("t") + MK("tt") + MK("v"); + +#define NUM_SWEDISH_3 32 +static const char swedish_3[] = + MK("arp") + MK("berg") + MK("boda") + MK("borg") + MK("bro") + MK("bukten") + MK("by") + MK("byn") + MK("fors") + MK("hammar") + MK("hamn") + MK("holm") + MK("hus") + MK("hättan") + MK("kulle") + MK("köping") + MK("lund") + MK("löv") + MK("sala") + MK("skrona") + MK("slätt") + MK("spång") + MK("stad") + MK("sund") + MK("svall") + MK("svik") + MK("såker") + MK("udde") + MK("valla") + MK("viken") + MK("älv") + MK("ås"); + +static byte MakeSwedishTownName(byte *buf, uint32 seed) +{ + int i; + + i = GETNUM(0, 50 + NUM_SWEDISH_1) - 50; + if (i >= 0) AppendPart(&buf, i, swedish_1); + + if (GETNUM(4, 5) >= 3) + AppendPart(&buf, GETNUM(7, NUM_SWEDISH_2), swedish_2); + else { + AppendPart(&buf, GETNUM(7, NUM_SWEDISH_2A), swedish_2a); + AppendPart(&buf, GETNUM(10, NUM_SWEDISH_2B), swedish_2b); + AppendPart(&buf, GETNUM(13, NUM_SWEDISH_2C), swedish_2c); + } + + AppendPart(&buf, GETNUM(16, NUM_SWEDISH_3), swedish_3); + + return 0; +} + + +#define NUM_DUTCH_1 8 +static const char dutch_1[] = + MK("Nieuw ") + MK("Oud ") + MK("Groot ") + MK("Zuid ") + MK("Noord ") + MK("Oost ") + MK("West ") + MK("Klein "); + +#define NUM_DUTCH_2 57 +static const char dutch_2[] = + MK("Hoog") + MK("Laag") + MK("Klein") + MK("Groot") + MK("Noorder") + MK("Noord") + MK("Zuider") + MK("Zuid") + MK("Ooster") + MK("Oost") + MK("Wester") + MK("West") + MK("Hoofd") + MK("Midden") + MK("Eind") + MK("Amster") + MK("Amstel") + MK("Dord") + MK("Rotter") + MK("Haar") + MK("Til") + MK("Enk") + MK("Dok") + MK("Veen") + MK("Leidsch") + MK("Lely") + MK("En") + MK("Kaats") + MK("U") + MK("Maas") + MK("Mar") + MK("Bla") + MK("Al") + MK("Alk") + MK("Eer") + MK("Drie") + MK("Ter") + MK("Groes") + MK("Goes") + MK("Soest") + MK("Coe") + MK("Uit") + MK("Zwaag") + MK("Hellen") + MK("Slie") + MK("IJ") + MK("Grubben") + MK("Groen") + MK("Lek") + MK("Ridder") + MK("Schie") + MK("Olde") + MK("Roose") + MK("Haar") + MK("Til") + MK("Loos") + MK("Hil"); + +#define NUM_DUTCH_3 20 +static const char dutch_3[] = + MK("Drog") + MK("Nat") + MK("Valk") + MK("Bob") + MK("Dedem") + MK("Kollum") + MK("Best") + MK("Hoend") + MK("Leeuw") + MK("Graaf") + MK("Uithuis") + MK("Purm") + MK("Hard") + MK("Hell") + MK("Werk") + MK("Spijk") + MK("Vink") + MK("Wams") + MK("Heerhug") + MK("Koning"); + + +#define NUM_DUTCH_4 6 +static const char dutch_4[] = + MK("e") + MK("er") + MK("el") + MK("en") + MK("o") + MK("s"); + +#define NUM_DUTCH_5 56 +static const char dutch_5[] = + MK("stad") + MK("vorst") + MK("dorp") + MK("dam") + MK("beek") + MK("doorn") + MK("zijl") + MK("zijlen") + MK("lo") + MK("muiden") + MK("meden") + MK("vliet") + MK("nisse") + MK("daal") + MK("vorden") + MK("vaart") + MK("mond") + MK("zaal") + MK("water") + MK("duinen") + MK("heuvel") + MK("geest") + MK("kerk") + MK("meer") + MK("maar") + MK("hoorn") + MK("rade") + MK("wijk") + MK("berg") + MK("heim") + MK("sum") + MK("richt") + MK("burg") + MK("recht") + MK("drecht") + MK("trecht") + MK("tricht") + MK("dricht") + MK("lum") + MK("rum") + MK("halen") + MK("oever") + MK("wolde") + MK("veen") + MK("hoven") + MK("gast") + MK("kum") + MK("hage") + MK("dijk") + MK("zwaag") + MK("pomp") + MK("huizen") + MK("bergen") + MK("schede") + MK("mere") + MK("end"); + +static byte MakeDutchTownName(byte *buf, uint32 seed) +{ + int i; + + i = GETNUM(0, 50 + NUM_DUTCH_1) - 50; + if (i >= 0) + AppendPart(&buf, i, dutch_1); + + i = GETNUM(6, 9); + if(i > 4){ + AppendPart(&buf, GETNUM(9, NUM_DUTCH_2), dutch_2); + } else { + AppendPart(&buf, GETNUM(9, NUM_DUTCH_3), dutch_3); + AppendPart(&buf, GETNUM(12, NUM_DUTCH_4), dutch_4); + } + AppendPart(&buf, GETNUM(15, NUM_DUTCH_5), dutch_5); + + return 0; +} + +#define NUM_FINNISH_1 25 +static const char finnish_1[] = + MK("Aijala") + MK("Kisko") + MK("Espoo") + MK("Helsinki") + MK("Tapiola") + MK("Järvelä") + MK("Lahti") + MK("Kotka") + MK("Hamina") + MK("Loviisa") + MK("Kouvola") + MK("Tampere") + MK("Kokkola") + MK("Oulu") + MK("Salo") + MK("Malmi") + MK("Pelto") + MK("Koski") + MK("Iisalmi") + MK("Raisio") + MK("Taavetti") + MK("Joensuu") + MK("Imatra") + MK("Tapanila") + MK("Pasila"); + +#define NUM_FINNISH_2a 26 +static const char finnish_2a[] = + MK("Hiekka") + MK("Haapa") + MK("Mylly") + MK("Kivi") + MK("Lappeen") + MK("Lohjan") + MK("Savon") + MK("Sauna") + MK("Keri") + MK("Uusi") + MK("Vanha") + MK("Lapin") + MK("Kesä") + MK("Kuusi") + MK("Pelto") + MK("Tuomi") + MK("Pitäjän") + MK("Terva") + MK("Olki") + MK("Heinä") + MK("Kuusan") + MK("Seinä") + MK("Kemi") + MK("Rova") + MK("Martin") + MK("Koivu"); + +#define NUM_FINNISH_2b 18 +static const char finnish_2b[] = + MK("harju") + MK("linna") + MK("järvi") + MK("kallio") + MK("mäki") + MK("nummi") + MK("joki") + MK("kylä") + MK("lampi") + MK("lahti") + MK("metsä") + MK("suo") + MK("laakso") + MK("niitty") + MK("luoto") + MK("hovi") + MK("ranta") + MK("koski"); + +static byte MakeFinnishTownName(byte *buf, uint32 seed) +{ +// Select randomly if town name should consists of one or two parts. + if (GETNUM(0, 15) >= 10) + AppendPart(&buf, GETNUM(2, NUM_FINNISH_1), finnish_1); // One part + else { + AppendPart(&buf, GETNUM(2, NUM_FINNISH_2a), finnish_2a); // Two parts + AppendPart(&buf, GETNUM(10, NUM_FINNISH_2b), finnish_2b); + } + return 0; +} + +#define NUM_POLISH_1 11 + +static const char polish_1_m[] = + MK("Wielki ") + MK("Maly ") + MK("Zly ") + MK("Dobry ") + MK("Nowy ") + MK("Stary ") + MK("Zloty ") + MK("Zielony ") + MK("Bialy ") + MK("Modry ") + MK("Debowy ") + ; + +static const char polish_1_f[] = + MK("Wielka ") + MK("Mala ") + MK("Zla ") + MK("Dobra ") + MK("Nowa ") + MK("Stara ") + MK("Zlota ") + MK("Zielona ") + MK("Biala ") + MK("Modra ") + MK("Debowa ") + ; + +static const char polish_1_n[] = + MK("Wielkie ") + MK("Male ") + MK("Zle ") + MK("Dobre ") + MK("Nowe ") + MK("Stare ") + MK("Zlote ") + MK("Zielone ") + MK("Biale ") + MK("Modre ") + MK("Debowe ") + ; + +#define NUM_POLISH_2_O 34// single names +#define NUM_POLISH_2_M 48// masculine + pref/suf +#define NUM_POLISH_2_F 27// feminine + pref/suf +#define NUM_POLISH_2_N 29// 'it' + pref/suf + +static const char polish_2[] = +//static const char polish_2_o[] = +MK("Frombork") +MK("Gniezno") +MK("Olsztyn") +MK("Torun") +MK("Bydgoszcz") +MK("Terespol") +MK("Krakow") +MK("Poznan") +MK("Wroclaw") +MK("Katowice") +MK("Cieszyn") +MK("Bytom") +MK("Frombork") +MK("Hel") +MK("Konin") +MK("Lublin") +MK("Malbork") +MK("Sopot") +MK("Sosnowiec") +MK("Gdansk") +MK("Gdynia") +MK("Sieradz") +MK("Sandomierz") +MK("Szczyrk") +MK("Szczytno") +MK("Szczecin") +MK("Zakopane") +MK("Szklarska Poreba") +MK("Bochnia") +MK("Golub-Dobrzyn") +MK("Chojnice") +MK("Ostrowiec") +MK("Otwock") +MK("Wolsztyn") +//; + +//static const char polish_2_m[] = +MK("Jarocin") +MK("Gogolin") +MK("Tomaszow") +MK("Piotrkow") +MK("Lidzbark") +MK("Rypin") +MK("Radzymin") +MK("Wolomin") +MK("Pruszkow") +MK("Olsztynek") +MK("Rypin") +MK("Cisek") +MK("Krotoszyn") +MK("Stoczek") +MK("Lubin") +MK("Lubicz") +MK("Milicz") +MK("Targ") +MK("Ostrow") +MK("Ozimek") +MK("Puck") +MK("Rzepin") +MK("Siewierz") +MK("Stargard") +MK("Starogard") +MK("Turek") +MK("Tymbark") +MK("Wolsztyn") +MK("Strzepcz") +MK("Strzebielin") +MK("Sochaczew") +MK("Grebocin") +MK("Gniew") +MK("Lubliniec") +MK("Lubasz") +MK("Lutomiersk") +MK("Niemodlin") +MK("Przeworsk") +MK("Ursus") +MK("Tyczyn") +MK("Sztum") +MK("Szczebrzeszyn") +MK("Wolin") +MK("Wrzeszcz") +MK("Zgierz") +MK("Zieleniec") +MK("Drobin") +MK("Garwolin") +//; + +//static const char polish_2_f[] = +MK("Szprotawa") +MK("Pogorzelica") +MK("Motlawa") +MK("Lubawa") +MK("Nidzica") +MK("Kruszwica") +MK("Bierawa") +MK("Brodnica") +MK("Chojna") +MK("Krzepica") +MK("Ruda") +MK("Rumia") +MK("Tuchola") +MK("Trzebinia") +MK("Ustka") +MK("Warszawa") +MK("Bobowa") +MK("Dukla") +MK("Krynica") +MK("Murowana") +MK("Niemcza") +MK("Zaspa") +MK("Zawoja") +MK("Wola") +MK("Limanowa") +MK("Rabka") +MK("Skawina") +MK("Pilawa") +//; + +//static const char polish_2_n[] = +MK("Lipsko") +MK("Pilzno") +MK("Przodkowo") +MK("Strzelno") +MK("Susz") +MK("Jaworzno") +MK("Choszczno") +MK("Mogilno") +MK("Luzino") +MK("Miasto") +MK("Dziadowo") +MK("Kowalewo") +MK("Legionowo") +MK("Miastko") +MK("Zabrze") +MK("Zawiercie") +MK("Kochanowo") +MK("Miechucino") +MK("Mirachowo") +MK("Robakowo") +MK("Kosakowo") +MK("Borne") +MK("Braniewo") +MK("Sulinowo") +MK("Chmielno") +MK("Jastrzebie") +MK("Gryfino") +MK("Koronowo") +MK("Lubichowo") +MK("Opoczno") +; + +#define NUM_POLISH_3 29 +static const char polish_3_m[] = +MK(" Wybudowanie") +MK(" Swietokrzyski") +MK(" Gorski") +MK(" Morski") +MK(" Zdroj") +MK(" Wody") +MK(" Bajoro") +MK(" Krajenski") +MK(" Slaski") +MK(" Mazowiecki") +MK(" Pomorski") +MK(" Wielki") +MK(" Maly") +MK(" Warminski") +MK(" Mazurski") +MK(" Mniejszy") +MK(" Wiekszy") +MK(" Gorny") +MK(" Dolny") +MK(" Wielki") +MK(" Stary") +MK(" Nowy") +MK(" Wielkopolski") +MK(" Wzgorze") +MK(" Mosty") +MK(" Kujawski") +MK(" Malopolski") +MK(" Podlaski") +MK(" Lesny") +; +static const char polish_3_f[] = +MK(" Wybudowanie") +MK(" Swietokrzyska") +MK(" Gorska") +MK(" Morska") +MK(" Zdroj") +MK(" Woda") +MK(" Bajoro") +MK(" Krajenska") +MK(" Slaska") +MK(" Mazowiecka") +MK(" Pomorska") +MK(" Wielka") +MK(" Mala") +MK(" Warminska") +MK(" Mazurska") +MK(" Mniejsza") +MK(" Wieksza") +MK(" Gorna") +MK(" Dolna") +MK(" Wielka") +MK(" Stara") +MK(" Nowa") +MK(" Wielkopolska") +MK(" Wzgorza") +MK(" Mosty") +MK(" Kujawska") +MK(" Malopolska") +MK(" Podlaska") +MK(" Lesna") +; +static const char polish_3_n[] = +MK(" Wybudowanie") +MK(" Swietokrzyskie") +MK(" Gorskie") +MK(" Morskie") +MK(" Zdroj") +MK(" Wody") +MK(" Bajoro") +MK(" Krajenskie") +MK(" Slaskie") +MK(" Mazowieckie") +MK(" Pomorskie") +MK(" Wielkie") +MK(" Male") +MK(" Warminskie ") +MK(" Mazurskie ") +MK(" Mniejsze") +MK(" Wieksze") +MK(" Gorne") +MK(" Dolne") +MK(" Wielkie") +MK(" Stare") +MK(" Nowe") +MK(" Wielkopolskie") +MK(" Wzgorze") +MK(" Mosty") +MK(" Kujawskie") +MK(" Malopolskie") +MK(" Podlaskie") +MK(" Lesne") +; + +#define NUM_POLISH_2 NUM_POLISH_2_O + NUM_POLISH_2_M + NUM_POLISH_2_F + NUM_POLISH_2_N + +static const char * const _polish_types[3][2] = { + {polish_1_m, polish_3_m}, // masculine + {polish_1_f, polish_3_f}, // feminine + {polish_1_n, polish_3_n}, // neutral +}; + +static byte MakePolishTownName(byte *buf, uint32 seed) +{ + uint i, x; + const char *const (*t)[2]; + + // get a number ranging from 0 to all_towns + i = GETNUM(0, NUM_POLISH_2); + + // single name + if(i < NUM_POLISH_2_O) { + AppendPart(&buf, i, polish_2); + return 0; + } + + // a suffix (12/20), a prefix (4/20), or nothing (4/20) + x = GETNUM(5, 20); + + // no suffix of prefix + if(x < 4) { + AppendPart(&buf, i-NUM_POLISH_2_O, polish_2); + return 0; + } + + t = _polish_types; + if(IS_INT_INSIDE(i, NUM_POLISH_2_O, NUM_POLISH_2_O + NUM_POLISH_2_M)) { + // nothing + } else if (IS_INT_INSIDE(i, NUM_POLISH_2_O + NUM_POLISH_2_M, NUM_POLISH_2_O + NUM_POLISH_2_M + NUM_POLISH_2_F)) { + t += 1; + } else { + t += 2; + } + + // suffix or prefix + if(x < 8) { + AppendPart(&buf, GETNUM(10, NUM_POLISH_1), (*t)[0]); + AppendPart(&buf, i, polish_2); + } else { + AppendPart(&buf, i, polish_2); + AppendPart(&buf, GETNUM(10, NUM_POLISH_3), (*t)[1]); + } + + return 0; +} + +#define NUM_SLOVAKISH_1 87 +static const char slovakish_1[] = +MK("Bratislava") +MK("Banovce nad Bebravou") +MK("Banska Bystrica") +MK("Banska Stiavnica") +MK("Bardejov") +MK("Brezno") +MK("Brezova pod Bradlom") +MK("Bytca") +MK("Cadca") +MK("Cierna nad Tisou") +MK("Detva") +MK("Detva") +MK("Dolny Kubin") +MK("Dolny Kubin") +MK("Dunajska Streda") +MK("Gabcikovo") +MK("Galanta") +MK("Gbely") +MK("Gelnica") +MK("Handlova") +MK("Hlohovec") +MK("Holic") +MK("Humenne") +MK("Hurbanovo") +MK("Kezmarok") +MK("Komarno") +MK("Kosice") +MK("Kremnica") +MK("Krompachy") +MK("Kuty") +MK("Leopoldov") +MK("Levoca") +MK("Liptovsky Mikulas") +MK("Lucenec") +MK("Malacky") +MK("Martin") +MK("Medzilaborce") +MK("Michalovce") +MK("Modra") +MK("Myjava") +MK("Namestovo") +MK("Nitra") +MK("Nova Bana") +MK("Nove Mesto nad Vahom") +MK("Nove Zamky") +MK("Partizanske") +MK("Pezinok") +MK("Piestany") +MK("Poltar") +MK("Poprad") +MK("Povazska Bystrica") +MK("Prievidza") +MK("Puchov") +MK("Revuca") +MK("Rimavska Sobota") +MK("Roznava") +MK("Ruzomberok") +MK("Sabinov") +MK("Sala") +MK("Senec") +MK("Senica") +MK("Sered") +MK("Skalica") +MK("Sladkovicovo") +MK("Smolenice") +MK("Snina") +MK("Stara Lubovna") +MK("Stara Tura") +MK("Strazske") +MK("Stropkov") +MK("Stupava") +MK("Sturovo") +MK("Sulekovo") +MK("Topolcany") +MK("Trebisov") +MK("Trencin") +MK("Trnava") +MK("Turcianske Teplice") +MK("Tvrdosin") +MK("Vrable") +MK("Vranov nad Toplov") +MK("Zahorska Bystrica") +MK("Zdiar") +MK("Ziar nad Hronom") +MK("Zilina") +MK("Zlate Moravce") +MK("Zvolen") +; + +static byte MakeSlovakishTownName(byte *buf, uint32 seed) +{ + AppendPart(&buf, GETNUM(0, NUM_SLOVAKISH_1), slovakish_1); + return 0; +} + +// Modifiers +#define NUM_HUNGARIAN_1 5 +static const char hungarian_1[] = + MK("Nagy-") + MK("Kis-") + MK("Felsõ-") + MK("Alsó-") + MK("Új-") +; + +#define NUM_HUNGARIAN_2 54 +static const char hungarian_2[] = +// River modifiers +// 1 - 10 + MK("Bodrog") + MK("Dráva") + MK("Duna") + MK("Hejõ") + MK("Hernád") + MK("Rába") + MK("Sajó") + MK("Szamos") + MK("Tisza") + MK("Zala") +// Lake modifiers +// 11 - 12 + MK("Balaton") + MK("Fertõ") +// Mountain modifiers +// 13 - 14 + MK("Bakony") + MK("Cserhát") +// Country modifiers +// 15 - 23 + MK("Bihar") + MK("Hajdú") + MK("Jász") + MK("Kun") + MK("Magyar") + MK("Nógrád") + MK("Nyír") + MK("Somogy") + MK("Székely") +// Town modifiers +// 24 - 26 + MK("Buda") + MK("Gyõr") + MK("Pest") +// Color modifiers +// 27 + MK("Fehér") +// General terrain modifiers +// 28 - 34 + MK("Cserép") + MK("Erdõ") + MK("Hegy") + MK("Homok") + MK("Mezõ") + MK("Puszta") + MK("Sár") +// Rank modifiers +// 35 - 40 + MK("Császár") + MK("Herceg") + MK("Király") + MK("Nemes") + MK("Püspök") + MK("Szent") +// Plant modifiers +// 41 - 42 + MK("Almás") + MK("Szilvás") +// Standard stuff +// 43 - 54 + MK("Agg") + MK("Aranyos") + MK("Békés") + MK("Egyházas") + MK("Gagy") + MK("Heves") + MK("Kapos") + MK("Tápió") + MK("Torna") + MK("Vas") + MK("Vámos") + MK("Vásáros") +; + +#define NUM_HUNGARIAN_3 16 +static const char hungarian_3[] = + MK("apáti") + MK("bába") + MK("bikk") + MK("dob") + MK("fa") + MK("föld") + MK("hegyes") + MK("kak") + MK("kereszt") + MK("kürt") + MK("ladány") + MK("mérges") + MK("szalonta") + MK("telek") + MK("vas") + MK("völgy") +; + +#define NUM_HUNGARIAN_4 5 +static const char hungarian_4[] = + MK("alja") + MK("egyháza") + MK("háza") + MK("úr") + MK("vár") +; + +#define NUM_HUNGARIAN_REAL 35 +static const char hungarian_real[] = + MK("Ajka") + MK("Aszód") + MK("Badacsony") + MK("Baja") + MK("Budapest") + MK("Debrecen") + MK("Eger") + MK("Fonyód") + MK("Gödöllõ") + MK("Gyõr") + MK("Gyula") + MK("Karcag") + MK("Kecskemét") + MK("Keszthely") + MK("Kisköre") + MK("Kocsord") + MK("Komárom") + MK("Kõszeg") + MK("Makó") + MK("Mohács") + MK("Miskolc") + MK("Ózd") + MK("Paks") + MK("Pápa") + MK("Pécs") + MK("Polgár") + MK("Sarkad") + MK("Siófok") + MK("Szeged") + MK("Szentes") + MK("Szolnok") + MK("Tihany") + MK("Tokaj") + MK("Vác") + MK("Záhony") + MK("Zirc") +; + +static byte MakeHungarianTownName(byte *buf, uint32 seed) +{ + int i; + + if (GETNUM(12, 15) < 3) { + /* These are real names.. */ + AppendPart(&buf, GETNUM(0, NUM_HUNGARIAN_REAL), hungarian_real); + } else { + /* These are the generated names.. Some of them exist, LOL */ + /* Append the prefix if needed */ + i = GETNUM(3, NUM_HUNGARIAN_1 * 3); + if (i < NUM_HUNGARIAN_1) AppendPart(&buf, i, hungarian_1); + + AppendPart(&buf, GETNUM(3, NUM_HUNGARIAN_2), hungarian_2); + AppendPart(&buf, GETNUM(6, NUM_HUNGARIAN_3), hungarian_3); + + i = GETNUM(10, NUM_HUNGARIAN_4 * 3); + if (i < NUM_HUNGARIAN_4) AppendPart(&buf, i, hungarian_4); + } + return 0; +} + +TownNameGenerator * const _town_name_generators[] = { + MakeEnglishTownName, + MakeFrenchTownName, + MakeGermanTownName, + MakeAmericanTownName, + MakeSpanishTownName, + MakeSillyTownName, + MakeSwedishTownName, + MakeDutchTownName, + MakeFinnishTownName, + MakePolishTownName, + MakeSlovakishTownName, + MakeHungarianTownName, + MakeAustrianTownName +}; diff --git a/network.c b/network.c new file mode 100644 --- /dev/null +++ b/network.c @@ -0,0 +1,1183 @@ +#include "stdafx.h" +#include "ttd.h" +#include "command.h" +#include "player.h" + +#if defined(WIN32) +# include +# include + +# pragma comment (lib, "ws2_32.lib") +# define ENABLE_NETWORK +# define GET_LAST_ERROR() WSAGetLastError() +# define EWOULDBLOCK WSAEWOULDBLOCK +#endif + +#if defined(UNIX) +// Make compatible with WIN32 names +# define SOCKET int +# define INVALID_SOCKET -1 +// we need different defines for MorphOS and AmigaOS +#if !defined(__MORPHOS__) && !defined(__AMIGA__) +# define ioctlsocket ioctl +# define closesocket close +# define GET_LAST_ERROR() errno +#endif +// Need this for FIONREAD on solaris +# define BSD_COMP +# include +# include + +// Socket stuff +# include +# include +# include +# include +# include +// NetDB +# include + +# ifndef TCP_NODELAY +# define TCP_NODELAY 0x0001 +# endif + +#endif + + +#if defined(__MORPHOS__) || defined(__AMIGA__) +# include +# include // required for Open/CloseLibrary() +# if defined(__MORPHOS__) +# include // FION#? defines +# else // __AMIGA__ +# include +# endif + +// make source compatible with bsdsocket.library functions +# define closesocket(s) CloseSocket(s) +# define GET_LAST_ERROR() Errno() +# define ioctlsocket(s,request,status) IoctlSocket((LONG)s,(ULONG)request,(char*)status) + +struct Library *SocketBase = NULL; +#endif /* __MORPHOS__ || __AMIGA__ */ + + +#define SEND_MTU 1460 + +#if defined(ENABLE_NETWORK) + +// sent from client -> server whenever the client wants to exec a command. +// send from server -> client when another player execs a command. +typedef struct CommandPacket { + byte packet_length; + byte packet_type; + uint16 cmd; + uint32 p1,p2; + TileIndex tile; + byte player;// player id, this is checked by the server. + byte when; // offset from the current max_frame value minus 1. this is set by the server. + uint32 dp[8]; +} CommandPacket; + +assert_compile(sizeof(CommandPacket) == 16 + 32); + +#define COMMAND_PACKET_BASE_SIZE (sizeof(CommandPacket) - 8 * sizeof(uint32)) + +// sent from server -> client periodically to tell the client about the current tick in the server +// and how far the client may progress. +typedef struct SyncPacket { + byte packet_length; + byte packet_type; + byte frames; // how many more frames may the client execute? this is relative to the old value of max. + byte server; // where is the server currently executing? this is negatively relative to the old value of max. + uint32 random_seed_1; // current random state at server. used to detect out of sync. + uint32 random_seed_2; +} SyncPacket; + +assert_compile(sizeof(SyncPacket) == 12); + +// sent from server -> client as an acknowledgement that the server received the command. +// the command will be executed at the current value of "max". +typedef struct AckPacket { + byte packet_length; + byte packet_type; +} AckPacket; + +typedef struct FilePacketHdr { + byte packet_length; + byte packet_type; + byte unused[2]; +} FilePacketHdr; + +assert_compile(sizeof(FilePacketHdr) == 4); + +// sent from server to client when the client has joined. +typedef struct WelcomePacket { + byte packet_length; + byte packet_type; + byte unused[2]; +} WelcomePacket; + +typedef struct Packet Packet; +struct Packet { + Packet *next; // this one has to be the first element. + uint siz; + byte buf[SEND_MTU]; // packet payload +}; + +typedef struct ClientState { + int socket; + bool inactive; // disable sending of commands/syncs to client + bool writable; + uint xmitpos; + + uint eaten; + Packet *head, **last; + + uint buflen; // receive buffer len + byte buf[256]; // receive buffer +} ClientState; + + +static uint _not_packet; + +typedef struct QueuedCommand QueuedCommand; +struct QueuedCommand { + QueuedCommand *next; + CommandPacket cp; + CommandCallback *callback; + uint32 cmd; + int32 frame; +}; + +typedef struct CommandQueue CommandQueue; +struct CommandQueue { + QueuedCommand *head, **last; +}; + +#define MAX_CLIENTS (MAX_PLAYERS + 1) + +// packets waiting to be executed, for each of the players. +// this list is sorted in frame order, so the item on the front will be executed first. +static CommandQueue _command_queue; + +// in the client, this is the list of commands that have not yet been acked. +// when it is acked, it will be moved to the appropriate position at the end of the player queue. +static CommandQueue _ack_queue; + +static ClientState _clients[MAX_CLIENTS]; +static int _num_clients; + +// keep a history of the 16 most recent seeds to be able to capture out of sync errors. +static uint32 _my_seed_list[16][2]; + +typedef struct FutureSeeds { + int32 frame; + uint32 seed[2]; +} FutureSeeds; + +// remember some future seeds that the server sent to us. +static FutureSeeds _future_seed[8]; +static int _num_future_seed; + +static SOCKET _listensocket; +static SOCKET _udpsocket; + + +typedef struct UDPPacket { + byte command_code; + byte data_len; + byte command_check; + byte data[255]; +} UDPPacket; + +enum { + NET_UDPCMD_SERVERSEARCH = 1, + NET_UDPCMD_SERVERACTIVE, +}; + +uint32 _network_ip_list[10]; // Network ips +char * _network_detected_serverip = "255.255.255.255"; // UDP Broadcast detected server-ip +uint32 _network_detected_serverport = 0; // UDP Broadcast detected server-port + +void NetworkUDPSend(struct sockaddr_in recv,struct UDPPacket packet); + +static bool _network_synced; + +// this is set to point to the savegame +static byte *_transmit_file; +static size_t _transmit_file_size; + +static FILE *_recv_file; + +////////////////////////////////////////////////////////////////////// + +static QueuedCommand *AllocQueuedCommand(CommandQueue *nq) +{ + QueuedCommand *qp = (QueuedCommand*)calloc(sizeof(QueuedCommand), 1); + assert(qp); + *nq->last = qp; + nq->last = &qp->next; + return qp; +} + +// go through the player queues for each player and see if there are any pending commands +// that should be executed this frame. if there are, execute them. +void NetworkProcessCommands() +{ + CommandQueue *nq; + QueuedCommand *qp; + + // queue mode ? + if (_networking_queuing) + return; + + nq = &_command_queue; + while ( (qp=nq->head) && (!_networking_sync || qp->frame <= _frame_counter)) { + // unlink it. + if (!(nq->head = qp->next)) nq->last = &nq->head; + + if (qp->frame < _frame_counter && _networking_sync) { + error("!qp->cp.frame < _frame_counter, %d < %d\n", qp->frame, _frame_counter); + } + + // run the command + _current_player = qp->cp.player; + memcpy(_decode_parameters, qp->cp.dp, (qp->cp.packet_length - COMMAND_PACKET_BASE_SIZE)); + DoCommandP(qp->cp.tile, qp->cp.p1, qp->cp.p2, qp->callback, qp->cmd | CMD_DONT_NETWORK); + free(qp); + } + + if (!_networking_server) { + // remember the random seed so we can check if we're out of sync. + _my_seed_list[_frame_counter & 15][0] = _sync_seed_1; + _my_seed_list[_frame_counter & 15][1] = _sync_seed_2; + + while (_num_future_seed) { + assert(_future_seed[0].frame >= _frame_counter); + if (_future_seed[0].frame != _frame_counter) break; + if (_future_seed[0].seed[0] != _sync_seed_1 ||_future_seed[0].seed[1] != _sync_seed_2) + error("!network sync error"); + memcpy_overlapping(_future_seed, _future_seed + 1, --_num_future_seed * sizeof(FutureSeeds)); + } + } +} + +// send a packet to a client +static void SendBytes(ClientState *cs, void *bytes, uint len) +{ + byte *b = (byte*)bytes; + uint n; + Packet *p; + + assert(len != 0); + + // see if there's space in the last packet? + if (!cs->head || (p = (Packet*)cs->last, p->siz == sizeof(p->buf))) + p = NULL; + + do { + if (!p) { + // need to allocate a new packet buffer. + p = (Packet*)malloc(sizeof(Packet)); + + // insert at the end of the linked list. + *cs->last = p; + cs->last = &p->next; + p->next = NULL; + p->siz = 0; + } + + // copy bytes to packet. + n = minu(sizeof(p->buf) - p->siz, len); + memcpy(p->buf + p->siz, b, n); + p->siz += n; + b += n; + p = NULL; + } while (len -= n); +} + +// client: +// add it to the client's ack queue, and send the command to the server +// server: +// add it to the server's player queue, and send it to all clients. +void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) +{ + int nump; + QueuedCommand *qp; + ClientState *cs; + + qp = AllocQueuedCommand(_networking_server ? &_command_queue : &_ack_queue); + qp->cp.packet_type = 0; + qp->cp.tile = tile; + qp->cp.p1 = p1; + qp->cp.p2 = p2; + qp->cp.cmd = (uint16)cmd; + qp->cp.player = _local_player; + qp->cp.when = 0; + qp->cmd = cmd; + qp->callback = callback; + + // so the server knows when to execute it. + qp->frame = _frame_counter_max; + + // calculate the amount of extra bytes. + nump = 8; + while ( nump != 0 && ((uint32*)_decode_parameters)[nump-1] == 0) nump--; + qp->cp.packet_length = COMMAND_PACKET_BASE_SIZE + nump * sizeof(uint32); + if (nump != 0) memcpy(qp->cp.dp, _decode_parameters, nump * sizeof(uint32)); + +#if defined(TTD_BIG_ENDIAN) + // need to convert the command to little endian before sending it. + { + CommandPacket cp; + cp = qp->cp; + cp.cmd = TO_LE16(cp.cmd); + cp.tile = TO_LE16(cp.tile); + cp.p1 = TO_LE32(cp.p1); + cp.p2 = TO_LE32(cp.p2); + for(cs=_clients; cs->socket != INVALID_SOCKET; cs++) if (!cs->inactive) SendBytes(cs, &cp, cp.packet_length); + } +#else + // send it to the peers + for(cs=_clients; cs->socket != INVALID_SOCKET; cs++) if (!cs->inactive) SendBytes(cs, &qp->cp, qp->cp.packet_length); + +#endif +} + +// client: +// server sends a command from another player that we should execute. +// put it in the command queue. +// +// server: +// client sends a command that it wants to execute. +// fill the when field so the client knows when to execute it. +// put it in the appropriate player queue. +// send it to all other clients. +// send an ack packet to the actual client. + +static void HandleCommandPacket(ClientState *cs, CommandPacket *np) +{ + QueuedCommand *qp; + ClientState *c; + AckPacket ap; + + printf("net: cmd size %d\n", np->packet_length); + + assert(np->packet_length >= COMMAND_PACKET_BASE_SIZE); + + // put it into the command queue + qp = AllocQueuedCommand(&_command_queue); + qp->cp = *np; + + qp->frame = _frame_counter_max; + + qp->callback = NULL; + + // extra params + memcpy(&qp->cp.dp, np->dp, np->packet_length - COMMAND_PACKET_BASE_SIZE); + + ap.packet_type = 2; + ap.packet_length = 2; + + // send it to the peers + if (_networking_server) { + for(c=_clients; c->socket != INVALID_SOCKET; c++) { + if (c == cs) { + SendBytes(c, &ap, 2); + } else { + if (!cs->inactive) SendBytes(c, &qp->cp, qp->cp.packet_length); + } + } + } + +// convert from little endian to big endian? +#if defined(TTD_BIG_ENDIAN) + qp->cp.cmd = TO_LE16(qp->cp.cmd); + qp->cp.tile = TO_LE16(qp->cp.tile); + qp->cp.p1 = TO_LE32(qp->cp.p1); + qp->cp.p2 = TO_LE32(qp->cp.p2); +#endif + + qp->cmd = qp->cp.cmd; +} + +// sent from server -> client periodically to tell the client about the current tick in the server +// and how far the client may progress. +static void HandleSyncPacket(SyncPacket *sp) +{ + uint32 s1,s2; + + _frame_counter_srv = _frame_counter_max - sp->server; + _frame_counter_max += sp->frames; + + printf("net: sync max=%d cur=%d server=%d\n", _frame_counter_max, _frame_counter, _frame_counter_srv); + + // queueing only? + if (_networking_queuing || _frame_counter == 0) + return; + + s1 = TO_LE32(sp->random_seed_1); + s2 = TO_LE32(sp->random_seed_2); + + if (_frame_counter_srv <= _frame_counter) { + // we are ahead of the server check if the seed is in our list. + if (_frame_counter_srv + 16 > _frame_counter) { + // the random seed exists in our array check it. + if (s1 != _my_seed_list[_frame_counter_srv & 0xF][0] || s2 != _my_seed_list[_frame_counter_srv & 0xF][1]) + error("!network is desynched\n"); + } + } else { + // the server's frame has not been executed yet. store the server's seed in a list. + if (_num_future_seed < lengthof(_future_seed)) { + _future_seed[_num_future_seed].frame = _frame_counter_srv; + _future_seed[_num_future_seed].seed[0] = s1; + _future_seed[_num_future_seed].seed[1] = s2; + _num_future_seed++; + } + } +} + +// sent from server -> client as an acknowledgement that the server received the command. +// the command will be executed at the current value of "max". +static void HandleAckPacket() +{ + QueuedCommand *q; + // move a packet from the ack queue to the end of this player's queue. + q = _ack_queue.head; + assert(q); + if (!(_ack_queue.head = q->next)) _ack_queue.last = &_ack_queue.head; + q->next = NULL; + q->frame = _frame_counter_max; + + *_command_queue.last = q; + _command_queue.last = &q->next; + + printf("net: ack\n"); +} + +static void HandleFilePacket(FilePacketHdr *fp) +{ + int n = fp->packet_length - sizeof(FilePacketHdr); + if (n == 0) { + assert(_networking_queuing); + assert(!_networking_sync); + // eof + if (_recv_file) { fclose(_recv_file); _recv_file = NULL; } + + // attempt loading the game. + _game_mode = GM_NORMAL; + if (SaveOrLoad("networkc.tmp", SL_LOAD) != SL_OK) error("network load failed"); + + // sync to server. + _networking_queuing = false; + + _networking_sync = true; + _frame_counter = 0; // start executing at frame 0. + _sync_seed_1 = _sync_seed_2 = 0; + _num_future_seed = 0; + memset(_my_seed_list, 0, sizeof(_my_seed_list)); + + if (_network_playas == 0) { + // send a command to make a new player + _local_player = 0; + NetworkSendCommand(0, 0, 0, CMD_PLAYER_CTRL, NULL); + _local_player = 0xff; + } else { + // take control over an existing company + if (DEREF_PLAYER(_network_playas-1)->is_active) + _local_player = _network_playas-1; + else + _local_player = 0xff; + } + + } else { + if(!_recv_file) { + _recv_file = fopen("networkc.tmp", "wb"); + if (!_recv_file) error("can't open savefile"); + } + fwrite( (char*)fp + sizeof(*fp), n, 1, _recv_file); + } +} + +static void CloseClient(ClientState *cs) +{ + Packet *p, *next; + + printf("CloseClient\n"); + + assert(cs->socket != INVALID_SOCKET); + + closesocket(cs->socket); + + // free buffers + for(p = cs->head; p; p=next) { + next = p->next; + free(p); + } + + // copy up structs... + while ((cs+1)->socket != INVALID_SOCKET) { + *cs = *(cs+1); + cs++; + } + cs->socket = INVALID_SOCKET; + + _num_clients--; +} + +#define NETWORK_BUFFER_SIZE 4096 +static bool ReadPackets(ClientState *cs) +{ + byte network_buffer[NETWORK_BUFFER_SIZE]; + uint pos,size; + unsigned long recv_bytes; + + size = cs->buflen; + + for(;;) { + if (size != 0) memcpy(network_buffer, cs->buf, size); + + recv_bytes = recv(cs->socket, (char*)network_buffer + size, sizeof(network_buffer) - size, 0); + if ( recv_bytes == (unsigned long)-1) { + int err = GET_LAST_ERROR(); + if (err == EWOULDBLOCK) break; + printf("net: recv() failed with error %d\n", err); + CloseClient(cs); + return false; + } + // no more bytes for now? + if (recv_bytes == 0) + break; + + size += recv_bytes; // number of bytes read. + pos = 0; + while (size >= 2) { + byte *packet = network_buffer + pos; + // whole packet not there yet? + if (size < packet[0]) break; + size -= packet[0]; + pos += packet[0]; + + switch(packet[1]) { + case 0: + HandleCommandPacket(cs, (CommandPacket*)packet); + break; + case 1: + assert(_networking_sync || _networking_queuing); + assert(!_networking_server); + HandleSyncPacket((SyncPacket*)packet); + break; + case 2: + assert(!_networking_server); + HandleAckPacket(); + break; + case 3: + HandleFilePacket((FilePacketHdr*)packet); + break; + default: + error("unknown packet type"); + } + } + + assert(size>=0 && size < sizeof(cs->buf)); + + memcpy(cs->buf, network_buffer + pos, size); + } + + cs->buflen = size; + + return true; +} + + +static bool SendPackets(ClientState *cs) +{ + Packet *p; + int n; + uint nskip = cs->eaten, nsent = nskip; + + // try sending as much as possible. + for(p=cs->head; p ;p = p->next) { + if (p->siz) { + assert(nskip < p->siz); + + n = send(cs->socket, p->buf + nskip, p->siz - nskip, 0); + if (n == -1) { + int err = GET_LAST_ERROR(); + if (err == EWOULDBLOCK) break; + printf("net: send() failed with error %d\n", err); + CloseClient(cs); + return false; + } + nsent += n; + // send was not able to send it all? then we assume that the os buffer is full and break. + if (nskip + n != p->siz) + break; + nskip = 0; + } + } + + // nsent bytes in the linked list are not invalid. free as many buffers as possible. + // don't actually free the last buffer. + while (nsent) { + p = cs->head; + assert(p->siz != 0); + + // some bytes of the packet are still unsent. + if ( (int)(nsent - p->siz) < 0) + break; + nsent -= p->siz; + p->siz = 0; + if (p->next) { + cs->head = p->next; + free(p); + } + } + + cs->eaten = nsent; + + return true; +} + +// transmit the file.. +static void SendXmit(ClientState *cs) +{ + uint pos, n; + FilePacketHdr hdr; + int p; + + // if too many unsent bytes left in buffer, don't send more. + if (cs->head && cs->head->next) + return; + + pos = cs->xmitpos - 1; + + p = 20; + do { + // compute size of data to xmit + n = minu(_transmit_file_size - pos, 248); + + hdr.packet_length = n + sizeof(hdr); + hdr.packet_type = 3; + hdr.unused[0] = hdr.unused[1] = 0; + SendBytes(cs, &hdr, sizeof(hdr)); + + if (n == 0) { + pos = -1; // eof + break; + } + SendBytes(cs, _transmit_file + pos, n); + pos += n; + } while (--p); + + cs->xmitpos = pos + 1; + + printf("net: client xmit at %d\n", pos + 1); +} + +static ClientState *AllocClient(SOCKET s) +{ + ClientState *cs; + + if (_num_clients == MAX_CLIENTS) + return NULL; + + cs = &_clients[_num_clients++]; + memset(cs, 0, sizeof(*cs)); + cs->last = &cs->head; + cs->socket = s; + return cs; +} + + +static void NetworkAcceptClients() +{ + struct sockaddr_in sin; + SOCKET s; + ClientState *cs; +#ifndef __MORPHOS__ + int sin_len; +#else + LONG sin_len; // for some reason we need a 'LONG' under MorphOS +#endif + + assert(_listensocket != INVALID_SOCKET); + + for(;;) { + sin_len = sizeof(sin); + s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len); + if (s == INVALID_SOCKET) return; + + // set nonblocking mode for client socket + { unsigned long blocking = 1; ioctlsocket(s, FIONBIO, &blocking); } + + printf("net: got client from %s\n", inet_ntoa(sin.sin_addr)); + + // set nodelay + {int b = 1; setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b));} + + cs = AllocClient(s); + if (cs == NULL) { + // no more clients allowed? + closesocket(s); + continue; + } + + if (_networking_sync) { + // a new client has connected. it needs a snapshot. + cs->inactive = true; + } + } + + // when a new client has joined. it needs different information depending on if it's at the game menu or in an active game. + // Game menu: + // - list of players already in the game (name, company name, face, color) + // - list of game settings and patch settings + // Active game: + // - the state of the world (includes player name, company name, player face, player color) + // - list of the patch settings + + // Networking can be in several "states". + // * not sync - games don't need to be in sync, and frame counter is not synced. for example intro screen. all commands are executed immediately. + // * sync - games are in sync +} + + +static void SendQueuedCommandsToNewClient(ClientState *cs) +{ + // send the commands in the server queue to the new client. + QueuedCommand *qp; + SyncPacket sp; + int32 frame; + + printf("net: sending queued commands to client\n"); + + sp.packet_length = sizeof(sp); + sp.packet_type = 1; + sp.random_seed_1 = sp.random_seed_2 = 0; + sp.server = 0; + + frame = _frame_counter; + + for(qp=_command_queue.head; qp; qp = qp->next) { + printf("net: sending cmd to be executed at %d (old %d)\n", qp->frame, frame); + if (qp->frame > frame) { + assert(qp->frame <= _frame_counter_max); + sp.frames = qp->frame - frame; + frame = qp->frame; + SendBytes(cs, &sp, sizeof(sp)); + } + SendBytes(cs, &qp->cp, qp->cp.packet_length); + } + + if (frame < _frame_counter_max) { + printf("net: sending queued sync %d (%d)\n", _frame_counter_max, frame); + sp.frames = _frame_counter_max - frame; + SendBytes(cs, &sp, sizeof(sp)); + } + +} + +void NetworkReceive() +{ + ClientState *cs; + int n; + fd_set read_fd, write_fd; + struct timeval tv; + + NetworkUDPReceive(); // udp handling + + FD_ZERO(&read_fd); + FD_ZERO(&write_fd); + + for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { + FD_SET(cs->socket, &read_fd); + FD_SET(cs->socket, &write_fd); + } + + // take care of listener port + if (_networking_server) { + FD_SET(_listensocket, &read_fd); + } + + tv.tv_sec = tv.tv_usec = 0; // don't block at all. +#if !defined(__MORPHOS__) && !defined(__AMIGA__) + n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv); +#else + n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL); +#endif + if (n == -1) error("select failed"); + + // accept clients.. + if (_networking_server && FD_ISSET(_listensocket, &read_fd)) + NetworkAcceptClients(); + + // read stuff from clients + for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { + cs->writable = !!FD_ISSET(cs->socket, &write_fd); + if (FD_ISSET(cs->socket, &read_fd)) { + if (!ReadPackets(cs)) + cs--; + } + } + + // if we're a server, and any client needs a snapshot, create a snapshot and send all commands from the server queue to the client. + if (_networking_server && _transmit_file == NULL) { + bool didsave = false; + + for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { + if (cs->inactive) { + cs->inactive = false; + // found a client waiting for a snapshot. make a snapshot. + if (!didsave) { + char filename[256]; + sprintf(filename, "%snetwork.tmp", _path.autosave_dir); + didsave = true; + if (SaveOrLoad(filename, SL_SAVE) != SL_OK) error("network savedump failed"); + _transmit_file = ReadFileToMem(filename, &_transmit_file_size, 500000); + if (_transmit_file == NULL) error("network savedump failed to load"); + } + // and start sending the file.. + cs->xmitpos = 1; + + // send queue of commands to client. + SendQueuedCommandsToNewClient(cs); + } + } + } +} + +void NetworkSend() +{ + ClientState *cs; + void *free_xmit; + + // send sync packets? + if (_networking_server && _networking_sync && !_pause) { + if (++_not_packet >= _network_sync_freq) { + SyncPacket sp; + uint new_max; + + _not_packet = 0; + + new_max = max(_frame_counter + (int)_network_ahead_frames, _frame_counter_max); + + sp.packet_length = sizeof(sp); + sp.packet_type = 1; + sp.frames = new_max - _frame_counter_max; + sp.server = _frame_counter_max - _frame_counter; + sp.random_seed_1 = TO_LE32(_sync_seed_1); + sp.random_seed_2 = TO_LE32(_sync_seed_2); + _frame_counter_max = new_max; + + // send it to all the clients + for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) SendBytes(cs, &sp, sizeof(sp)); + } + } + + free_xmit = _transmit_file; + + // send stuff to all clients + for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { + if (cs->xmitpos) { + if (cs->writable) + SendXmit(cs); + free_xmit = NULL; + } + if (cs->writable) { + if (!SendPackets(cs)) cs--; + } + } + + // no clients left that xmit the file, free it. + if (free_xmit) { + _transmit_file = NULL; + free(free_xmit); + } +} + +void NetworkConnect(const char *hostname, int port) +{ + SOCKET s; + struct sockaddr_in sin; + int b; + + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) error("socket() failed"); + + b = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)); + + if (strcmp(hostname,"auto")==0) { + // autodetect server over udp broadcast [works 4 lan] + if (NetworkUDPSearchServer()) { + hostname=_network_detected_serverip; + port=_network_detected_serverport; + } else { + error("udp: server not found"); + } + } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(hostname); + sin.sin_port = htons(port); + + if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) + error("connect() failed"); + + // set nonblocking mode for socket.. + { unsigned long blocking = 1; ioctlsocket(s, FIONBIO, &blocking); } + + // in client mode, only the first client field is used. it's pointing to the server. + AllocClient(s); + + // queue packets.. because we're waiting for the savegame. + _networking_queuing = true; + _frame_counter_max = 0; + +} + +void NetworkListen(int port) +{ + + SOCKET ls; + struct sockaddr_in sin; + + ls = socket(AF_INET, SOCK_STREAM, 0); + if (ls == INVALID_SOCKET) + error("socket() on listen socket failed"); + + // reuse the socket + { + int reuse = 1; if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) == -1) + error("setsockopt() on listen socket failed"); + } + + // set nonblocking mode for socket + { unsigned long blocking = 1; ioctlsocket(ls, FIONBIO, &blocking); } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = 0; + sin.sin_port = htons(port); + + if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) + error("bind() failed"); + + if (listen(ls, 1) != 0) + error("listen() failed"); + + _listensocket = ls; +} + +void NetworkInitialize() +{ + ClientState *cs; +#if defined(WIN32) + WSADATA wsa; + if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) + error("WSAStartup failed"); +#endif + +#if defined(__MORPHOS__) || defined(__AMIGA__) + if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) { + error("Couldn't open bsdsocket.library version 4."); + } +#endif + + _command_queue.last = &_command_queue.head; + _ack_queue.last = &_ack_queue.head; + + // invalidate all clients + for(cs=_clients; cs != &_clients[MAX_CLIENTS]; cs++) + cs->socket = INVALID_SOCKET; + + // startup udp listener + NetworkUDPListen(_network_port); +} + +void NetworkShutdown() +{ +#if defined(__MORPHOS__) || defined(__AMIGA__) + if (SocketBase) { + CloseLibrary(SocketBase); + } +#endif +} + +// switch to synced mode. +void NetworkStartSync() +{ + _networking_sync = true; + _frame_counter = 0; + _frame_counter_max = 0; + _frame_counter_srv = 0; + _num_future_seed = 0; + _sync_seed_1 = _sync_seed_2 = 0; + memset(_my_seed_list, 0, sizeof(_my_seed_list)); +} + +// ************************** // +// * UDP Network Extensions * // +// ************************** // + +/* multi os compatible sleep function */ +void CSleep(int milliseconds) { +#if defined(WIN32) +Sleep(milliseconds); +#endif +#if defined(UNIX) +#ifndef __BEOS__ +usleep(milliseconds*1000); +#endif +#ifdef __BEOS__ +snooze(milliseconds*1000); +#endif +#endif +} + +void NetworkUDPListen(int port) +{ + SOCKET udp; + struct sockaddr_in sin; + + DEBUG(misc,0) ("udp: listener initiated on port %i", port); + NetworkIPListInit(); + + udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udp == INVALID_SOCKET) + error("udp: socket() on listen socket failed"); + + // set nonblocking mode for socket + { unsigned long blocking = 1; ioctlsocket(udp, FIONBIO, &blocking); } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = 0; + sin.sin_port = htons(port); + + if (bind(udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) + error("udp: bind() failed"); + + // enable broadcasting + { unsigned long val=1; setsockopt(udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val)); } + + _udpsocket = udp; + +} + +void NetworkUDPReceive() { + struct sockaddr_in client_addr; + int client_len; + int nbytes; + struct UDPPacket packet; + int packet_len; + + packet_len = sizeof(packet); + client_len = sizeof(client_addr); + + nbytes = recvfrom(_udpsocket, (char *) &packet, packet_len , 0, (struct sockaddr *) &client_addr, &client_len); + if (nbytes>0) { + if (packet.command_code==packet.command_check) switch (packet.command_code) { + + case NET_UDPCMD_SERVERSEARCH: + if (_networking_server) { + packet.command_check=packet.command_code=NET_UDPCMD_SERVERACTIVE; + NetworkUDPSend(client_addr, packet); + } + break; + case NET_UDPCMD_SERVERACTIVE: + if (!_networking_server) { + _network_detected_serverip=inet_ntoa(*(struct in_addr *) &client_addr.sin_addr); + _network_detected_serverport=ntohs(client_addr.sin_port); + } + break; + } + } +} + +void NetworkIPListInit() { + struct hostent* he; + char hostname[250]; + uint32 bcaddr; + int i=0; + + _network_detected_serverip=""; + + gethostname(hostname,250); + DEBUG(misc,0) ("iplist: init for host %s", hostname); + he=gethostbyname((char *) hostname); + + while(he->h_addr_list[i]) { + bcaddr = inet_addr(inet_ntoa(*(struct in_addr *) he->h_addr_list[i])); + _network_ip_list[i]=bcaddr; + DEBUG(misc,0) ("iplist: add %s",inet_ntoa(*(struct in_addr *) he->h_addr_list[i])); + i++; + } + _network_ip_list[i]=0; + +} + +void NetworkUDPBroadCast(struct UDPPacket packet) { + int i=0, res; + struct sockaddr_in out_addr; + uint32 bcaddr; + byte * bcptr; + while (_network_ip_list[i]!=0) { + bcaddr=_network_ip_list[i]; + out_addr.sin_family = AF_INET; + out_addr.sin_port = htons(_network_port); + bcptr = (byte *) &bcaddr; + bcptr[3]=255; + out_addr.sin_addr.s_addr = bcaddr; + res=sendto(_udpsocket,(char *) &packet,sizeof(packet),0,(struct sockaddr *) &out_addr,sizeof(out_addr)); + if (res==-1) error("udp: broadcast error: %i",GET_LAST_ERROR()); + i++; + } + +} + +void NetworkUDPSend(struct sockaddr_in recv,struct UDPPacket packet) { + sendto(_udpsocket,(char *) &packet,sizeof(packet),0,(struct sockaddr *) &recv,sizeof(recv)); +} + +bool NetworkUDPSearchServer() { + struct UDPPacket packet; + int timeout=3000; + DEBUG(misc,0) ("udp: searching server"); + _network_detected_serverip = "255.255.255.255"; + _network_detected_serverport = 0; + + packet.command_check=packet.command_code=NET_UDPCMD_SERVERSEARCH; + packet.data_len=0; + NetworkUDPBroadCast(packet); + while (timeout>=0) { + CSleep(100); + timeout-=100; + NetworkUDPReceive(); + if (_network_detected_serverport>0) { + timeout=-1; + DEBUG(misc,0) ("udp: server found on %s", _network_detected_serverip); + } + } + return (_network_detected_serverport>0); + +} + + +#else // ENABLE_NETWORK + +// stubs +void NetworkInitialize() {} +void NetworkShutdown() {} +void NetworkListen(int port) {} +void NetworkConnect(const char *hostname, int port) {} +void NetworkReceive() {} +void NetworkSend() {} +void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) {} +void NetworkProcessCommands() {} +void NetworkStartSync() {} +void NetworkUDPListen(int port) {} +void NetworkUDPReceive() {} +bool NetworkUDPSearchServer() {} +#endif // ENABLE_NETWORK diff --git a/network_gui.c b/network_gui.c new file mode 100644 --- /dev/null +++ b/network_gui.c @@ -0,0 +1,426 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "command.h" + +#define BGC 5 +#define BTC 15 +#define MAX_QUERYSTR_LEN 64 +static byte _edit_str_buf[MAX_QUERYSTR_LEN*2]; +static void ShowNetworkStartServerWindow(); +static void ShowNetworkLobbyWindow(); + +extern void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask); +extern int HandleEditBoxKey(Window *w, int wid, WindowEvent *we); + +void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number); + + +static byte _selected_field; +char *direct_ip = NULL; + + +void ConnectToServer(byte* b) +{ + _networking = true; + + NetworkInitialize(); + DEBUG(misc, 1) ("Connecting to %s %d\n", b, _network_port); + NetworkConnect(b, _network_port); +} + +static const StringID _connection_types_dropdown[] = { + STR_NETWORK_LAN, + STR_NETWORK_INTERNET, + INVALID_STRING_ID +}; + +static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + + SET_DPARAM16(0, 0x00); + SET_DPARAM16(2, STR_NETWORK_LAN + _opt_mod_ptr->road_side); + DrawWindowWidgets(w); + + DrawEditBox(w, 6); + + DrawString(9, 43, STR_NETWORK_PLAYER_NAME, 2); + DrawString(9, 63, STR_NETWORK_SELECT_CONNECTION, 2); + + DrawString(15, 82, STR_NETWORK_GAME_NAME, 2); + DrawString(238, 82, STR_NETWORK_PLAYERS, 2); + DrawString(288, 82, STR_NETWORK_MAP_SIZE, 2); + + break; + } + + case WE_CLICK: + _selected_field = e->click.widget; + switch(e->click.widget) { + + case 0: // close X + case 15: // cancel button + DeleteWindowById(WC_NETWORK_WINDOW, 0); + break; + case 4: // connect via direct ip + { + StringID str; + str = AllocateName((byte*)_decode_parameters, 0); + + ShowQueryString( + str, + STR_NETWORK_ENTER_IP, + 15, + 160, + w->window_class, + w->window_number); + DeleteName(str); + } + break; + + case 5: // start server + ShowNetworkStartServerWindow(); + break; + + case 8: + ShowDropDownMenu(w, _connection_types_dropdown, _opt_mod_ptr->currency, e->click.widget, 0); + return; + } + + case WE_MOUSELOOP: + if(_selected_field != 6) + break; + HandleEditBox(w, 6); + break; + + case WE_KEYPRESS: + if(_selected_field != 6) + break; + switch (HandleEditBoxKey(w, 6, e)) { + case 1: + HandleButtonClick(w, 9); + break; + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + ConnectToServer(b); + } break; + + } +} + +static const Widget _network_game_window_widgets[] = { +{ WWT_PUSHTXTBTN, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, BGC, 10, 399, 0, 13, STR_NETWORK_MULTIPLAYER}, +{ WWT_IMGBTN, BGC, 0, 399, 14, 199, 0x0}, + +{ WWT_PUSHTXTBTN, BTC, 20, 130, 22, 33, STR_NETWORK_FIND_SERVER, STR_NETWORK_FIND_SERVER_TIP}, +{ WWT_PUSHTXTBTN, BTC, 145, 255, 22, 33, STR_NETWORK_DIRECT_CONNECT, STR_NETWORK_DIRECT_CONNECT_TIP}, +{ WWT_PUSHTXTBTN, BTC, 270, 380, 22, 33, STR_NETWORK_START_SERVER, STR_NETWORK_START_SERVER_TIP}, + +{ WWT_IMGBTN, BGC, 250, 394, 42, 53, 0x0, STR_NETWORK_ENTER_NAME_TIP}, + +{ WWT_6, BGC, 250, 393, 62, 73, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TYPE_TIP}, +{ WWT_CLOSEBOX, BGC, 382, 392, 63, 72, STR_0225, STR_NETWORK_CONNECTION_TYPE_TIP}, + +{ WWT_SCROLLBAR, BGC, 382, 392, 81, 175, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, + +{ WWT_IMGBTN, BTC, 10, 231, 81, 92, 0x0, STR_NETWORK_GAME_NAME_TIP }, +{ WWT_IMGBTN, BTC, 232, 281, 81, 92, 0x0, STR_NETWORK_PLAYERS_TIP }, +{ WWT_IMGBTN, BTC, 282, 331, 81, 92, 0x0, STR_NETWORK_MAP_SIZE_TIP }, +{ WWT_IMGBTN, BTC, 332, 381, 81, 92, 0x0, STR_NETWORK_INFO_ICONS_TIP }, + +{ WWT_MATRIX, BGC, 10, 381, 93, 175, 0x601, STR_NETWORK_CLICK_GAME_TO_SELECT}, + +{ WWT_PUSHTXTBTN, BTC, 145, 255, 180, 191, STR_012E_CANCEL, STR_NULL}, +{ WWT_PUSHTXTBTN, BTC, 270, 392, 180, 191, STR_NETWORK_JOIN_GAME, STR_NULL}, + +{ WWT_LAST}, +}; + +static const WindowDesc _network_game_window_desc = { + WDP_CENTER, WDP_CENTER, 400, 200, + WC_NETWORK_WINDOW,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _network_game_window_widgets, + NetworkGameWindowWndProc, +}; + + +void ShowNetworkGameWindow() +{ + Window *w; + DeleteWindowById(WC_NETWORK_WINDOW, 0); + + w = AllocateWindowDesc(&_network_game_window_desc); + strcpy(_edit_str_buf, "Your name"); + + + WP(w,querystr_d).caret = 1; + WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; + WP(w,querystr_d).maxwidth = 240; + WP(w,querystr_d).buf = _edit_str_buf; + + + ShowErrorMessage(-1, TEMP_STRING_NO_NETWORK, 0, 0); +} + + +void StartServer() +{ + _networking = true; + NetworkInitialize(); + DEBUG(misc, 1) ("Listening on port %d\n", _network_port); + NetworkListen(_network_port); + _networking_server = true; + DoCommandP(0, 0, 0, NULL, CMD_START_NEW_GAME); +} + + + +static const StringID _players_dropdown[] = { + STR_NETWORK_2_PLAYERS, + STR_NETWORK_3_PLAYERS, + STR_NETWORK_4_PLAYERS, + STR_NETWORK_5_PLAYERS, + STR_NETWORK_6_PLAYERS, + STR_NETWORK_7_PLAYERS, + STR_NETWORK_8_PLAYERS, + INVALID_STRING_ID +}; + + +static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + + SET_DPARAM16(7, STR_NETWORK_2_PLAYERS + _opt_mod_ptr->road_side); + DrawWindowWidgets(w); + + GfxFillRect(11, 63, 237, 168, 0xD7); + + DrawEditBox(w, 3); + DrawEditBox(w, 4); + + DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2); + DrawString(210, 22, STR_NETWORK_PASSWORD, 2); + + DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2); + DrawString(260, 63, STR_NETWORK_NUMBER_OF_PLAYERS, 2); + + break; + } + + case WE_CLICK: + _selected_field = e->click.widget; + switch(e->click.widget) { + + case 0: // close X + case 10: // cancel button + ShowNetworkGameWindow(); + break; + case 8: + ShowDropDownMenu(w, _players_dropdown, _opt_mod_ptr->currency, e->click.widget, 0); + return; + case 9: // start game + StartServer(); + ShowNetworkLobbyWindow(); + break; + } + + case WE_MOUSELOOP: + if(_selected_field == 3) + { + HandleEditBox(w, 3); + break; + } + if(_selected_field == 4) + { + HandleEditBox(w, 4); + break; + } + + break; + + case WE_KEYPRESS: + if(_selected_field != 3 && _selected_field != 4) + break; + switch (HandleEditBoxKey(w, _selected_field, e)) { + case 1: + HandleButtonClick(w, 9); + break; + } + break; + + } +} + +static const Widget _network_start_server_window_widgets[] = { +{ WWT_PUSHTXTBTN, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, +{ WWT_CAPTION, BGC, 10, 399, 0, 13, STR_NETWORK_START_GAME_WINDOW }, +{ WWT_IMGBTN, BGC, 0, 399, 14, 199, 0x0}, + +{ WWT_IMGBTN, BGC, 80, 190, 22, 33, 0x0, STR_NETWORK_NEW_GAME_NAME_TIP}, +{ WWT_IMGBTN, BGC, 280, 390, 22, 33, 0x0, STR_NETWORK_PASSWORD_TIP}, + +{ WWT_IMGBTN, BGC, 10, 240, 62, 170, 0x0, STR_NETWORK_SELECT_MAP_TIP}, +{ WWT_SCROLLBAR, BGC, 241, 251, 62, 170, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, + +{ WWT_6, BGC, 260, 390, 81, 92, STR_NETWORK_COMBO2, STR_NETWORK_NUMBER_OF_PLAYERS_TIP}, +{ WWT_CLOSEBOX, BGC, 378, 388, 82, 91, STR_0225, STR_NETWORK_NUMBER_OF_PLAYERS_TIP}, + +{ WWT_PUSHTXTBTN, BTC, 80, 180, 180, 191, STR_NETWORK_START_GAME, STR_NULL}, +{ WWT_PUSHTXTBTN, BTC, 220, 320, 180, 191, STR_012E_CANCEL, STR_NULL}, + +{ WWT_LAST}, +}; + +static const WindowDesc _network_start_server_window_desc = { + WDP_CENTER, WDP_CENTER, 400, 200, + WC_NETWORK_WINDOW,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _network_start_server_window_widgets, + NetworkStartServerWindowWndProc, +}; + + +static void ShowNetworkStartServerWindow() +{ + Window *w; + DeleteWindowById(WC_NETWORK_WINDOW, 0); + + w = AllocateWindowDesc(&_network_start_server_window_desc); + strcpy(_edit_str_buf, ""); + + + WP(w,querystr_d).caret = 1; + WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; + WP(w,querystr_d).maxwidth = 240; + WP(w,querystr_d).buf = _edit_str_buf; +} + + + + + +static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + + SET_DPARAM16(7, STR_NETWORK_2_PLAYERS + _opt_mod_ptr->road_side); + DrawWindowWidgets(w); + + GfxFillRect( 11, 31, 239, 239, 0xD7); + GfxFillRect(261, 31, 378, 220, 0xD7); + + DrawEditBox(w, 5); + DrawEditBox(w, 7); + + DrawString(10, 255, STR_NETWORK_COMPANY_NAME, 2); + + break; + } + + case WE_CLICK: + _selected_field = e->click.widget; + switch(e->click.widget) { + + case 0: // close X + case 13: // cancel button + ShowNetworkGameWindow(); + break; + + } + + case WE_MOUSELOOP: + if(_selected_field == 5) + { + HandleEditBox(w, 5); + break; + } + if(_selected_field == 7) + { + HandleEditBox(w, 7); + break; + } + + break; + + case WE_KEYPRESS: + if(_selected_field != 5 && _selected_field != 7) + break; + switch (HandleEditBoxKey(w, _selected_field, e)) { + case 1: + HandleButtonClick(w, 12); + break; + } + break; + + } +} + +static const Widget _network_lobby_window_widgets[] = { +{ WWT_PUSHTXTBTN, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, +{ WWT_CAPTION, BGC, 10, 399, 0, 13, STR_NETWORK_GAME_LOBBY }, +{ WWT_IMGBTN, BGC, 0, 399, 14, 299, 0x0}, + +// chat widget +{ WWT_IMGBTN, BGC, 10, 240, 30, 240, 0x0}, +{ WWT_SCROLLBAR, BGC, 241, 251, 30, 240, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, + +// send message prompt +{ WWT_IMGBTN, BGC, 10, 200, 241, 252, 0x0, STR_NETWORK_ENTER_NAME_TIP}, +{ WWT_PUSHTXTBTN, BTC, 201, 251, 241, 252, STR_NETWORK_SEND, STR_NETWORK_SEND_TIP}, + +// company name +{ WWT_IMGBTN, BGC, 100, 251, 254, 265, 0x0, STR_NETWORK_COMPANY_NAME_TIP}, + +// player information +{ WWT_IMGBTN, BGC, 260, 379, 30, 221, 0x0}, +{ WWT_SCROLLBAR, BGC, 380, 390, 30, 221, 0x1, STR_0190_SCROLL_BAR_SCROLLS_LIST}, + +// buttons +{ WWT_PUSHTXTBTN, BTC, 260, 390, 233, 244, STR_NETWORK_NEW_COMPANY, STR_NETWORK_NEW_COMPANY_TIP}, +{ WWT_PUSHTXTBTN, BTC, 260, 390, 254, 265, STR_NETWORK_SPECTATE_GAME, STR_NETWORK_SPECTATE_GAME_TIP}, + +{ WWT_PUSHTXTBTN, BTC, 80, 180, 280, 291, STR_NETWORK_READY, STR_NULL}, +{ WWT_PUSHTXTBTN, BTC, 220, 320, 280, 291, STR_012E_CANCEL, STR_NULL}, + +{ WWT_LAST}, +}; + +static const WindowDesc _network_lobby_window_desc = { + WDP_CENTER, WDP_CENTER, 400, 300, + WC_NETWORK_WINDOW,0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _network_lobby_window_widgets, + NetworkLobbyWindowWndProc, +}; + + +static void ShowNetworkLobbyWindow() +{ + Window *w; + DeleteWindowById(WC_NETWORK_WINDOW, 0); + + w = AllocateWindowDesc(&_network_lobby_window_desc); + strcpy(_edit_str_buf, ""); + + + WP(w,querystr_d).caret = 1; + WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; + WP(w,querystr_d).maxwidth = 240; + WP(w,querystr_d).buf = _edit_str_buf; +} + + diff --git a/news.h b/news.h new file mode 100644 --- /dev/null +++ b/news.h @@ -0,0 +1,68 @@ +#ifndef NEWS_H +#define NEWS_H + +struct NewsItem { + StringID string_id; + uint16 duration; + uint16 date; + byte flags; + byte display_mode; + byte type; + byte callback; + + TileIndex data_a; + TileIndex data_b; + + uint32 params[10]; +}; + + +#define NEWS_FLAGS(mode,flag,type,cb) ((cb)<<24 | (type)<<16 | (flag)<<8 | (mode)) +void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b); +void NewsLoop(); +void DrawNewsBorder(Window *w); +void InitNewsItemStructs(); + +VARDEF NewsItem _statusbar_news_item; + +typedef void DrawNewsCallbackProc(Window *w); +typedef StringID GetNewsStringCallbackProc(NewsItem *ni); + +enum { + NT_ARRIVAL_PLAYER = 0, + NT_ARRIVAL_OTHER = 1, + NT_ACCIDENT = 2, + NT_COMPANY_INFO = 3, + NT_ECONOMY = 4, + NT_ADVICE = 5, + NT_NEW_VEHICLES = 6, + NT_ACCEPTANCE = 7, + NT_SUBSIDIES = 8, + NT_GENERAL = 9, +}; + +enum NewsMode { + NM_SMALL = 0, + NM_NORMAL = 1, + NM_THIN = 2, + NM_CALLBACK = 3, +}; + +enum NewsFlags { + NF_VIEWPORT = 1, + NF_TILE = 4, + NF_VEHICLE = 8, + NF_FORCE_BIG = 0x10, + NF_NOEXPIRE = 0x20, + NF_INCOLOR = 0x40, +}; + +enum { + DNC_TRAINAVAIL = 0, + DNC_ROADAVAIL = 1, + DNC_SHIPAVAIL = 2, + DNC_AIRCRAFTAVAIL = 3, + DNC_BANKRUPCY = 4, +}; + +#endif /* NEWS_H */ diff --git a/news_gui.c b/news_gui.c new file mode 100644 --- /dev/null +++ b/news_gui.c @@ -0,0 +1,615 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "news.h" +#include "vehicle.h" + +static NewsItem _news_items[10]; +static NewsItem _active_news_items[20]; + +void ExpireNewsItem(); + +void DrawNewsNewTrainAvail(Window *w); +void DrawNewsNewRoadVehAvail(Window *w); +void DrawNewsNewShipAvail(Window *w); +void DrawNewsNewAircraftAvail(Window *w); +void DrawNewsBankrupcy(Window *w); + +StringID GetNewsStringNewTrainAvail(NewsItem *ni); +StringID GetNewsStringNewRoadVehAvail(NewsItem *ni); +StringID GetNewsStringNewShipAvail(NewsItem *ni); +StringID GetNewsStringNewAircraftAvail(NewsItem *ni); +StringID GetNewsStringBankrupcy(NewsItem *ni); + +static DrawNewsCallbackProc * const _draw_news_callback[] = { + DrawNewsNewTrainAvail, /* DNC_TRAINAVAIL */ + DrawNewsNewRoadVehAvail, /* DNC_ROADAVAIL */ + DrawNewsNewShipAvail, /* DNC_SHIPAVAIL */ + DrawNewsNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ + DrawNewsBankrupcy, /* DNC_BANKRUPCY */ +}; + +GetNewsStringCallbackProc * const _get_news_string_callback[] = { + GetNewsStringNewTrainAvail, /* DNC_TRAINAVAIL */ + GetNewsStringNewRoadVehAvail, /* DNC_ROADAVAIL */ + GetNewsStringNewShipAvail, /* DNC_SHIPAVAIL */ + GetNewsStringNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ + GetNewsStringBankrupcy, /* DNC_BANKRUPCY */ +}; + + +void DrawNewsBorder(Window *w) +{ + int left = 0; + int right = w->width - 1; + int top = 0; + int bottom = w->height - 1; + + GfxFillRect(left, top, right, bottom, 0xF); + + GfxFillRect(left, top, left, bottom, 0xD7); + GfxFillRect(right, top, right, bottom, 0xD7); + GfxFillRect(left, top, right, top, 0xD7); + GfxFillRect(left, bottom, right, bottom, 0xD7); + + DrawString(left + 2, top + 1, STR_00C6, 0); +} + +static void NewsWindowProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + NewsItem *ni = WP(w,news_d).ni; + ViewPort *vp; + + if (ni->display_mode == NM_NORMAL || ni->display_mode == NM_THIN) { + DrawNewsBorder(w); + + DrawString(2, 1, STR_00C6, 0); + + SET_DPARAM16(0, ni->date); + DrawStringRightAligned(428, 1, STR_01FF, 0); + + if (!(ni->flags & NF_VIEWPORT)) { + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + DrawStringMultiCenter(215, ni->display_mode == NM_NORMAL ? 76 : 56, ni->string_id, 426); + } else { + byte bk = _display_opt; + _display_opt |= DO_TRANS_BUILDINGS; + DrawWindowViewport(w); + _display_opt = bk; + + /* Shade the viewport into gray, or color*/ + vp = w->viewport; + GfxFillRect(vp->left - w->left, vp->top - w->top, vp->left - w->left + vp->width - 1, vp->top - w->top + vp->height - 1, + ni->flags & NF_INCOLOR ? 0x4322:0x4323 + ); + + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + DrawStringMultiCenter((w->width>>1), 20, ni->string_id, 428); + } + } else if (ni->display_mode == NM_CALLBACK) { + _draw_news_callback[ni->callback](w); + } else { + DrawWindowWidgets(w); + if (!(ni->flags & NF_VIEWPORT)) { + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + DrawStringMultiCenter(140,38, ni->string_id, 276); + } else { + DrawWindowViewport(w); + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + DrawStringMultiCenter((w->width>>1), w->height - 16, ni->string_id, 276); + } + } + } break; + + case WE_CLICK: { + switch(e->click.widget) { + case 1:DeleteWindow(w); ExpireNewsItem(); break; + case 0: { + NewsItem *ni = WP(w,news_d).ni; + if (ni->flags & NF_VEHICLE) { + Vehicle *v = &_vehicles[ni->data_a]; + ScrollMainWindowTo(v->x_pos, v->y_pos); + } else if (ni->flags & NF_TILE) { + if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) + ScrollMainWindowToTile(ni->data_b); + } + } break; + } + } break; + + case WE_KEYPRESS: + if (e->keypress.keycode == WKC_SPACE) { + // Don't continue. + e->keypress.cont = false; + DeleteWindow(w); + ExpireNewsItem(); + } + break; + + case WE_TICK: { + int y = max(w->top - 4, _screen.height - w->height); + if (y == w->top) + return; + + if (w->viewport != NULL) + w->viewport->top += y - w->top; + + w->top = y; + + SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height + 4); + } break; + } +} + + +void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b) +{ + NewsItem *ni; + + if (_game_mode == GM_MENU) + return; + + // Find a free place and add it there. + for(ni=_news_items; ni!=endof(_news_items); ni++) { + if (ni->string_id==0) { + ni->string_id = string; + ni->display_mode = (byte)flags; + ni->flags = (byte)(flags >> 8) | NF_NOEXPIRE; + + // show this news message in color? + if (_date >= ConvertIntDate(_patches.colored_news_date)) + ni->flags |= NF_INCOLOR; + + ni->type = (byte)(flags >> 16); + ni->callback = (byte)(flags >> 24); + ni->duration = 555; + ni->data_a = data_a; + ni->data_b = data_b; + ni->date = _date; + COPY_OUT_DPARAM(ni->params, 0, lengthof(ni->params)); + break; + } + } +} + +// _active_news_items 0..9 are the ones that have already been shown +// _active_news_items 10..19 are the ones that are to be shown next + +static void MoveNewsItems() +{ + Window *w; + NewsItem *ni; + + // No new news item? + if (_news_items[0].string_id == 0) + return; + + // Check if the status bar message is still being displayed? + w = FindWindowById(WC_STATUS_BAR, 0); + if (w != NULL && WP(w,def_d).data_1 > -1280) + return; + + // Add the news items to the list of pending ones. + for(ni=_active_news_items + 10; ni != _active_news_items + 20; ni++) { + if (ni->string_id == 0) { + *ni = _news_items[0]; + memcpy_overlapping(_news_items, _news_items+1, sizeof(_news_items) - sizeof(_news_items[0]) * 1); + endof(_news_items)[-1].string_id = 0; + break; + } + } +} + +void ExpireNewsItem() +{ + memcpy_overlapping(_active_news_items, _active_news_items + 1, sizeof(_active_news_items) - sizeof(_active_news_items[0])); + endof(_active_news_items)[-1].string_id = 0; +} + +static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; + +static void RemoveOldNewsItems() +{ + NewsItem *ni, *nit; + + ni = _active_news_items; + do { + if (ni->string_id != 0 && + ni != _active_news_items + 10 && + _date - _news_items_age[ni->type] > ni->date) { + + if (ni >= _active_news_items + 10) { + nit = ni; + while (nit != _active_news_items + 19) { + nit[0] = nit[1]; + nit++; + } + nit->string_id = 0; + } else { + nit = ni + 1; + while (nit != _active_news_items + 1) { + nit--; + nit[0] = nit[-1]; + } + _active_news_items[0].string_id = 0; + } + } + } while (++ni != endof(_active_news_items) ); +} + +static const Widget _news_type13_widgets[] = { +{ WWT_PANEL, 15, 0, 429, 0, 169, 0x0}, +{ WWT_PANEL, 15, 0, 10, 0, 11, 0x0}, +{ WWT_LAST}, +}; + +static WindowDesc _news_type13_desc = { + WDP_CENTER, 476, 430, 170, + WC_NEWS_WINDOW,0, + WDF_DEF_WIDGET, + _news_type13_widgets, + NewsWindowProc +}; + +static const Widget _news_type2_widgets[] = { +{ WWT_PANEL, 15, 0, 429, 0, 129, 0x0}, +{ WWT_PANEL, 15, 0, 10, 0, 11, 0x0}, +{ WWT_LAST}, +}; + +static WindowDesc _news_type2_desc = { + WDP_CENTER, 476, 430, 130, + WC_NEWS_WINDOW,0, + WDF_DEF_WIDGET, + _news_type2_widgets, + NewsWindowProc +}; + +static const Widget _news_type0_widgets[] = { +{ WWT_PANEL, 5, 0, 279, 14, 86, 0x0}, +{ WWT_CLOSEBOX, 5, 0, 10, 0, 13, STR_00C5}, +{ WWT_CAPTION, 5, 11, 279, 0, 13, STR_012C_MESSAGE}, +{ WWT_6, 5, 2, 277, 16, 64, 0}, +{ WWT_LAST}, +}; + +static WindowDesc _news_type0_desc = { + WDP_CENTER, 476, 280, 87, + WC_NEWS_WINDOW,0, + WDF_DEF_WIDGET, + _news_type0_widgets, + NewsWindowProc +}; + +static byte _news_sounds[] = { 27, 27, 0, 0, 0, 0, 28, 0, 0, 0 }; + +static void ProcessNewsItem(NewsItem *ni) +{ + Window *w; + int sound; + + // No news item, quit + if (ni->string_id == 0) + return; + + // Delete the item once the duration reaches 0 + if (ni->duration == 0) { + DeleteWindowById(WC_NEWS_WINDOW, 0); + ExpireNewsItem(); + return; + } + ni->duration--; + + // As long as the window still is shown, don't go further + w = FindWindowById(WC_NEWS_WINDOW, 0); + if (w != NULL) + return; + + // Expire the item if NF_NOEXPIRE was removed + if (!(ni->flags & NF_NOEXPIRE)) { + ExpireNewsItem(); + return; + } + + if (!HASBIT(_news_display_opt, ni->type) && !(ni->flags&NF_FORCE_BIG)) { + SndPlayFx(20); + _statusbar_news_item = *ni; + w = FindWindowById(WC_STATUS_BAR, 0); + if (w != 0) + WP(w,def_d).data_1 = 360; + ExpireNewsItem(); + } else { + int top; + + ni->flags &= ~(NF_NOEXPIRE|NF_FORCE_BIG); + + sound = _news_sounds[ni->type]; + if (sound != 0) + SndPlayFx(sound); + + top = _screen.height - 4; + if (ni->display_mode == NM_NORMAL || ni->display_mode == NM_CALLBACK) { + _news_type13_desc.top = top; + w = AllocateWindowDesc(&_news_type13_desc); + if (ni->flags & NF_VIEWPORT) { + AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); + } + } else if (ni->display_mode == NM_THIN) { + _news_type2_desc.top = top; + w = AllocateWindowDesc(&_news_type2_desc); + if (ni->flags & NF_VIEWPORT) { + AssignWindowViewport(w, 2, 58, 0x1AA, 0x46, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); + } + } else { + _news_type0_desc.top = top; + w = AllocateWindowDesc(&_news_type0_desc); + if (ni->flags & NF_VIEWPORT) { + AssignWindowViewport(w, 3, 17, 0x112, 0x2F, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); + } + } + WP(w,news_d).ni = _active_news_items + 10; + w->flags4 |= WF_DISABLE_VP_SCROLL; + } +} + +void NewsLoop() +{ + RemoveOldNewsItems(); + MoveNewsItems(); + ProcessNewsItem(_active_news_items + 10); +} + +void ShowLastNewsMessage() +{ + // No news item immediately before 10? + if (_active_news_items[9].string_id == 0) + return; + + // Delete the news window + DeleteWindowById(WC_NEWS_WINDOW, 0); + + // Move all items one step + memmove(_active_news_items+1, _active_news_items, sizeof(NewsItem)*19); + _active_news_items[0].string_id = 0; + + // Default duration and flags for re-shown items + _active_news_items[10].duration = 555; + _active_news_items[10].flags |= NF_NOEXPIRE | NF_FORCE_BIG; +} + +void InitNewsItemStructs() +{ + memset(_news_items, 0, sizeof(_news_items)); + memset(_active_news_items, 0, sizeof(_active_news_items)); +} + +static void MessageOptionsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + uint16 x = _news_display_opt; + uint32 cs = 0; + int i, y; + + for(i=3; i!=23; i+=2) { + cs |= 1 << (i + (x&1)); + x >>= 1; + } + cs |= (w->click_state >> 23) << 23; + + w->click_state = cs; + DrawWindowWidgets(w); + + DrawStringCentered(185, 15, STR_0205_MESSAGE_TYPES, 0); + + y = 27; + for(i=STR_0206_ARRIVAL_OF_FIRST_VEHICLE; i <= STR_020F_GENERAL_INFORMATION; i++) { + DrawString(124, y, i, 0); + y += 12; + } + + break; + } + + case WE_CLICK: { + int wid; + if ( (uint)(wid=e->click.widget - 3) < 20) { + if (!(wid & 1)) { + _news_display_opt &= ~(1 << (wid>>1)); + } else { + _news_display_opt |= (1 << (wid>>1)); + } + SetWindowDirty(w); + /* XXX: write settings */ + } + if( e->click.widget == 23) { + _news_display_opt = 0; + HandleButtonClick(w, 23); + SetWindowDirty(w); + } + if( e->click.widget == 24) { + _news_display_opt = ~0; + HandleButtonClick(w, 24); + SetWindowDirty(w); + } + } break; + } +} + +static const Widget _message_options_widgets[] = { +{ WWT_CLOSEBOX, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 369, 0, 13, STR_0204_MESSAGE_OPTIONS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 13, 0, 369, 14, 172, 0x0}, +{ WWT_CLOSEBOX, 3, 2, 61, 26, 37, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 26, 37, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 38, 49, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 38, 49, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 50, 61, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 50, 61, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 62, 73, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 62, 73, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 74, 85, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 74, 85, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 86, 97, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 86, 97, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 98, 109, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 98, 109, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 110, 121, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 110, 121, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 122, 133, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 122, 133, STR_02B9_FULL}, +{ WWT_CLOSEBOX, 3, 2, 61, 134, 145, STR_02B8_SUMMARY}, +{ WWT_CLOSEBOX, 3, 62, 121, 134, 145, STR_02B9_FULL}, + +{ WWT_PUSHTXTBTN, 3, 15, 170, 154, 165, STR_MESSAGES_DISABLE_ALL, STR_NULL }, +{ WWT_PUSHTXTBTN, 3, 200, 355, 154, 165, STR_MESSAGES_ENABLE_ALL, STR_NULL }, + +{ WWT_LAST}, +}; + +static const WindowDesc _message_options_desc = { + 270, 22, 370, 173, + WC_GAME_OPTIONS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _message_options_widgets, + MessageOptionsWndProc +}; + + + + +void ShowMessageOptions() +{ + DeleteWindowById(WC_GAME_OPTIONS, 0); + AllocateWindowDesc(&_message_options_desc); +} + + +static void GetNewsString(NewsItem *ni, byte *buffer) +{ + StringID str; + byte *s, *d; + + if (ni->display_mode == 3) { + str = _get_news_string_callback[ni->callback](ni); + } else { + COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); + str = ni->string_id; + } + + GetString(str_buffr, str); + assert(strlen(str_buffr) < sizeof(str_buffr) - 1); + + s = str_buffr; + d = buffer; + + for(;;s++) { + // cut strings that are too long + if(s >= str_buffr + 55) { + d[0] = d[1] = d[2] = '.'; + d+=3; + *d = 0; + break; + } + + if (*s == 0) { + *d = 0; + break; + } else if (*s == 13) { + d[0] = d[1] = d[2] = d[3] = ' '; + d+=4; + } else if (*s >= ' ' && (*s < 0x88 || *s >= 0x99)) { + *d++ = *s; + } + } +} + + +static void MessageHistoryWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + uint n, y, i; + char buffer[256]; + NewsItem *ni; + + for(n=10; n!=0; n--) + if (!_active_news_items[n - 1].string_id) + break; + n = 10 - n; + + SetVScrollCount(w, n); + DrawWindowWidgets(w); + + y = 18; + for(i=w->vscroll.pos; i!=n; i++) { + ni = &_active_news_items[i + (10 - n)]; + + assert(ni->string_id); + + SET_DPARAM16(0, ni->date); + DrawString(4, y, STR_00AF, 16); + + GetNewsString(ni, buffer); + DoDrawString(buffer, 85, y, 16); + y += 12; + } + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 2: { + uint y = (e->click.pt.y - 18) / 12; + NewsItem *ni; + + if (y >= (uint)w->vscroll.count) + return; + + ni = &_active_news_items[w->vscroll.pos + y + (10 - w->vscroll.count)]; + +// NOT YET... +// ShowNewsMessage(y); + + break; + } + } + break; + } +} + +static const Widget _message_history_widgets[] = { +{ WWT_CLOSEBOX, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 399, 0, 13, STR_MESSAGE_HISTORY, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 0, 388, 14, 147, 0x0, STR_MESSAGE_HISTORY_TIP}, +{ WWT_SCROLLBAR, 13, 389, 399, 14, 147, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _message_history_desc = { + 240, 22, 400, 148, + WC_MESSAGE_HISTORY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _message_history_widgets, + MessageHistoryWndProc +}; + +void ShowMessageHistory() +{ + Window *w; + + DeleteWindowById(WC_MESSAGE_HISTORY, 0); + w = AllocateWindowDesc(&_message_history_desc); + + if (w) { + w->vscroll.cap = 11; + SetWindowDirty(w); + } +} + diff --git a/oldloader.c b/oldloader.c new file mode 100644 --- /dev/null +++ b/oldloader.c @@ -0,0 +1,1151 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "town.h" +#include "industry.h" +#include "station.h" +#include "economy.h" +#include "player.h" +#include "engine.h" +#include "vehicle.h" + +extern byte _name_array[512][32]; +extern TileIndex _animated_tile_list[256]; + +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif + +typedef struct { + uint16 string_id; + uint16 x; + uint16 right; + uint16 y; + uint16 bottom; + uint16 duration; + uint32 params[2]; +} GCC_PACK OldTextEffect; +assert_compile(sizeof(OldTextEffect) == 0x14); + +typedef struct { + uint16 xy; + uint16 population; + uint16 townnametype; + uint32 townnameparts; + byte grow_counter; + byte sort_index; + int16 sign_left, sign_top; + byte namewidth_1, namewidth_2; + uint16 flags12; + uint16 radius[5]; + uint16 ratings[8]; + uint32 have_ratings; + uint32 statues; + uint16 num_houses; + byte time_until_rebuild; + byte growth_rate; + uint16 new_max_pass, new_max_mail; + uint16 new_act_pass, new_act_mail; + uint16 max_pass, max_mail; + uint16 act_pass, act_mail; + byte pct_pass_transported, pct_mail_transported; + uint16 new_act_food, new_act_paper; + uint16 act_food, act_paper; + byte road_build_months; + byte fund_buildings_months; + uint32 unk56; + uint32 unk5A; +} GCC_PACK OldTown; +assert_compile(sizeof(OldTown) == 0x5E); + +typedef struct { + uint16 xy; + uint32 town; +} GCC_PACK OldDepot; +assert_compile(sizeof(OldDepot) == 0x6); + +typedef struct { + uint32 price; + uint16 frac; +} GCC_PACK OldPrice; +assert_compile(sizeof(OldPrice) == 0x6); + +typedef struct { + uint32 price; + uint16 frac; + uint16 unused; +} GCC_PACK OldPaymentRate; +assert_compile(sizeof(OldPaymentRate) == 8); + +typedef struct { + uint16 waiting_acceptance; + byte days_since_pickup; + byte rating; + byte enroute_from; + byte enroute_time; + byte last_speed; + byte last_age; +} GCC_PACK OldGoodsEntry; +assert_compile(sizeof(OldGoodsEntry) == 8); + +typedef struct { + uint16 xy; + uint32 town; + uint16 bus_tile, lorry_tile, train_tile, airport_tile, dock_tile; + byte platforms; + byte alpha_order_obsolete; // alpha_order is obsolete since savegame format 4 + byte namewidth_1, namewidth_2; + uint16 string_id; + int16 sign_left, sign_top; + uint16 had_vehicle_of_type; + OldGoodsEntry goods[12]; + byte time_since_load, time_since_unload; + byte delete_ctr; + byte owner; + byte facilities; + byte airport_type; + byte truck_stop_status, bus_stop_status; + byte blocked_months; + byte unk85; + uint16 airport_flags; + uint16 last_vehicle; + uint32 unk8A; +} GCC_PACK OldStation; +assert_compile(sizeof(OldStation) == 0x8E); + +typedef struct { + uint16 xy; + uint32 town; + byte width; + byte height; + byte produced_cargo[2]; + uint16 cargo_waiting[2]; + byte production_rate[2]; + byte accepts_cargo[3]; + byte prod_level; + uint16 last_mo_production[2]; + uint16 last_mo_transported[2]; + byte pct_transported[2]; + uint16 total_production[2]; + uint16 total_transported[2]; + byte type; + byte owner; + byte color_map; + byte last_prod_year; + uint16 counter; + byte was_cargo_delivered; + byte nothing; + uint32 unk2E; + uint32 unk32; +} GCC_PACK OldIndustry; +assert_compile(sizeof(OldIndustry) == 0x36); + +typedef struct { + int32 cost[13]; +} GCC_PACK OldPlayerExpenses; +assert_compile(sizeof(OldPlayerExpenses) == 0x34); + +typedef struct { + int32 income; + int32 expenses; + uint32 delivered_cargo; + uint32 performance_history; + uint32 company_value; +} GCC_PACK OldPlayerEconomy; +assert_compile(sizeof(OldPlayerEconomy) == 0x14); + +typedef struct { + uint16 spec_tile; + uint16 use_tile; + byte rand_rng; + byte cur_rule; + byte unk6; + byte unk7; + byte buildcmd_a; + byte buildcmd_b; + byte direction; + byte cargo; + byte unused[8]; +} GCC_PACK OldAiBuildRec; +assert_compile(sizeof(OldAiBuildRec) == 0x14); + +typedef struct { + uint16 tile; + byte data; +} GCC_PACK OldAiBannedTile; +assert_compile(sizeof(OldAiBannedTile) == 3); + +typedef struct { + uint16 name_1; + uint32 name_2; + uint32 face; + uint16 pres_name_1; + uint32 pres_name_2; + uint32 money; + uint32 loan; + byte color; + byte money_fract; + byte quarters_of_bankrupcy; + byte bankrupt_asked; + uint32 bankrupt_value; + uint16 bankrupt_timeout; + uint32 cargo_types; + OldPlayerExpenses expenses[3]; + OldPlayerEconomy economy[24 + 1]; + uint16 inaugurated_date; + uint16 last_build_coordinate; + byte num_valid_stat_ent; + byte ai_state; + byte unused; + byte ai_state_mode; + uint16 ai_state_counter; + uint16 ai_timeout_counter; + OldAiBuildRec ai_src, ai_dst, ai_mid1, ai_mid2; + byte unused_2[20]; + byte ai_cargo_type; + byte ai_num_wagons; + byte ai_build_kind; + byte ai_num_build_rec; + byte ai_num_loco_to_build; + byte ai_num_want_fullload; + byte unused_3[14]; + uint16 ai_loco_id; // NOT USED + uint16 ai_wagonlist[9]; + byte ai_order_list_blocks[20]; + uint16 ai_start_tile_a; + uint16 ai_start_tile_b; + uint16 ai_cur_tile_a; + uint16 ai_cur_tile_b; + byte ai_start_dir_a; + byte ai_start_dir_b; + byte ai_cur_dir_a; + byte ai_cur_dir_b; + byte ai_banned_tile_count; + OldAiBannedTile banned_tiles[16]; + byte ai_railtype_to_use; + byte ai_route_type_mask; + byte block_preview; + byte ai_tick; + byte max_railtype; + uint16 location_of_house; + byte share_owners[4]; + uint32 unk3AA; + uint32 unk3AE; +} GCC_PACK OldPlayer; +assert_compile(sizeof(OldPlayer) == 0x3B2); + +typedef struct { + byte track; + byte force_proceed; + uint16 crash_anim_pos; + byte railtype; +} GCC_PACK OldVehicleRailUnion; +assert_compile(sizeof(OldVehicleRailUnion) == 5); + +typedef struct { + byte unk0; + byte targetairport; + uint16 crashed_counter; + byte state; +} GCC_PACK OldVehicleAirUnion; +assert_compile(sizeof(OldVehicleAirUnion) == 5); + +typedef struct { + byte state; + byte frame; + uint16 unk2; + byte overtaking; + byte overtaking_ctr; + uint16 crashed_ctr; + byte reverse_ctr; +} GCC_PACK OldVehicleRoadUnion; +assert_compile(sizeof(OldVehicleRoadUnion) == 9); + +typedef struct { + uint16 unk0; + byte unk2; +} GCC_PACK OldVehicleSpecialUnion; +assert_compile(sizeof(OldVehicleSpecialUnion) == 3); + +typedef struct { + uint16 image_override; + uint16 unk2; +} GCC_PACK OldVehicleDisasterUnion; +assert_compile(sizeof(OldVehicleDisasterUnion) == 4); + +typedef struct { + byte state; +} OldVehicleShipUnion; +assert_compile(sizeof(OldVehicleShipUnion) == 1); + +typedef union { + OldVehicleRailUnion rail; + OldVehicleAirUnion air; + OldVehicleRoadUnion road; + OldVehicleSpecialUnion special; + OldVehicleDisasterUnion disaster; + OldVehicleShipUnion ship; + byte pad[10]; +} GCC_PACK OldVehicleUnion; +assert_compile(sizeof(OldVehicleUnion) == 10); + +typedef struct { + byte type; + byte subtype; + uint16 next_hash; // NOLOAD, calculated automatically. + uint16 index; // NOLOAD, calculated automatically. + uint32 schedule_ptr; + byte next_order, next_order_param; + byte num_orders; + byte cur_order_index; + uint16 dest_tile; + uint16 load_unload_time_rem; + uint16 date_of_last_service; + uint16 service_interval; + byte last_station_visited; + byte tick_counter; + uint16 max_speed; + uint16 x_pos, y_pos; + byte z_pos; + byte direction; + byte x_offs, y_offs; + byte sprite_width, sprite_height, z_height; + byte owner; + uint16 tile; + uint16 cur_image; + + int16 left_coord, right_coord, top_coord, bottom_coord; // NOLOAD, calculated automatically. + uint16 vehstatus; + uint16 cur_speed; + byte subspeed; + byte acceleration; + byte progress; + byte cargo_type; + uint16 capacity; + uint16 number_of_pieces; + byte source_of_pieces; + byte days_in_transit; + uint16 age_in_days, max_age_in_days; + byte build_year; + byte unitnumber; + uint16 engine_type; + byte spritenum; + byte day_counter; + byte breakdowns_since_last_service; + byte breakdown_ctr, breakdown_delay, breakdown_chance; + uint16 reliability, reliability_spd_dec; + uint32 profit_this_year, profit_last_year; + uint16 next_in_chain; + uint32 value; + uint16 string_id; + OldVehicleUnion u; + byte unused[20]; +} GCC_PACK OldVehicle; +assert_compile(sizeof(OldVehicle) == 0x80); + +typedef struct { + byte name[32]; +} GCC_PACK OldName; + +typedef struct { + uint16 text; + int16 x,y,z; + byte namewidth_1, namewidth_2; + int16 sign_left, sign_top; +} GCC_PACK OldSign; +assert_compile(sizeof(OldSign) == 0xE); + +typedef struct { + uint16 player_avail; + uint16 intro_date; + uint16 age; + uint16 reliability, reliability_spd_dec, 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 unk1B; +} GCC_PACK OldEngine; +assert_compile(sizeof(OldEngine) == 0x1C); + +typedef struct { + byte cargo_type; + byte age; + byte from; + byte to; +} GCC_PACK OldSubsidy; +assert_compile(sizeof(OldSubsidy) == 4); + +typedef struct { + uint16 max_no_competitors; + uint16 competitor_start_time; + uint16 number_towns; + uint16 number_industries; + uint16 max_loan; + uint16 initial_interest; + uint16 vehicle_costs; + uint16 competitor_speed; + uint16 competitor_intelligence; + uint16 vehicle_breakdowns; + uint16 subsidy_multiplier; + uint16 construction_cost; + uint16 terrain_type; + uint16 quantity_sea_lakes; + uint16 economy; + uint16 line_reverse_mode; + uint16 disasters; +} GCC_PACK OldGameSettings; +assert_compile(sizeof(OldGameSettings) == 0x22); + +typedef struct { + uint16 date; + uint16 date_fract; + + OldTextEffect te_list[30]; // NOLOAD: not so important. + uint32 seed_1, seed_2; + + OldTown town_list[70]; + uint16 order_list[5000]; + + uint16 animated_tile_list[256]; + uint32 ptr_to_next_order; + OldDepot depots[255]; + + uint32 cur_town_ptr; + uint16 timer_counter; + uint16 land_code; // NOLOAD: never needed in game + uint16 age_cargo_skip_counter; + uint16 tick_counter; + uint16 cur_tileloop_tile; + + OldPrice prices[49]; + OldPaymentRate cargo_payment_rates[12]; + + byte map_owner[256*256]; + byte map2[256*256]; + uint16 map3[256*256]; + byte map_extra[256*256/4]; + + OldStation stations[250]; + OldIndustry industries[90]; + OldPlayer players[8]; + OldVehicle vehicles[850]; + OldName names[500]; + + uint16 vehicle_position_hash[0x1000]; // NOLOAD, calculated automatically. + + OldSign signs[40]; + OldEngine engines[256]; + + uint16 vehicle_id_ctr_day; + OldSubsidy subsidies[8]; + + uint16 next_competitor_start; + + uint16 saved_main_scrollpos_x, saved_main_scrollpos_y, saved_main_scrollpos_zoom; + uint32 maximum_loan, maximum_loan_unround; + uint16 economy_fluct; + uint16 disaster_delay; + + //NOLOAD. These are calculated from InitializeLandscapeVariables + uint16 cargo_names_s[12], cargo_names_p[12], cargo_names_long_s[12], cargo_names_long_p[12], cargo_names_short[12]; + uint16 cargo_sprites[12]; + + uint16 engine_name_strings[256]; + + //NOLOAD. These are calculated from InitializeLandscapeVariables + uint16 railveh_by_cargo_1[12], railveh_by_cargo_2[12], railveh_by_cargo_3[12]; + uint16 roadveh_by_cargo_start[12]; + byte roadveh_by_cargo_count[12]; + uint16 ship_of_type_start[12]; + byte ship_of_type_count[12]; + + byte human_player_1, human_player_2; //NOLOAD. Calculated automatically. + byte station_tick_ctr; + byte currency; + byte use_kilometers; + byte cur_player_tick_index; + byte cur_year, cur_month; //NOLOAD. Calculated automatically. + byte player_colors[8]; //NOLOAD. Calculated automatically + + byte inflation_amount; + byte inflation_amount_payment_rates; + byte interest_rate; + + byte avail_aircraft; + byte road_side; + byte town_name_type; + OldGameSettings game_diff; + byte difficulty_level; + byte landscape_type; + byte trees_tick_ctr; + byte vehicle_design_names; + byte snow_line_height; + + byte new_industry_randtable[32]; // NOLOAD. Not needed due to different code design. + + //NOLOAD. Initialized by InitializeLandscapeVariables + byte cargo_weights[12]; + byte transit_days_table_1[12]; + byte transit_days_table_2[12]; + + byte map_type_and_height[256*256]; + byte map5[256*256]; +} GCC_PACK OldMain; +assert_compile(sizeof(OldMain) == 487801 + 256*256*2); + +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +#define REMAP_TOWN_IDX(x) (x - (0x0459154 - 0x0458EF0)) / sizeof(OldTown) +#define REMAP_TOWN_PTR(x) DEREF_TOWN( REMAP_TOWN_IDX(x) ) + +#define REMAP_ORDER_IDX(x) (x - (0x045AB08 - 0x0458EF0)) / sizeof(uint16) + +typedef struct LoadSavegameState { + int8 mode; + byte rep_char; + + size_t count; + size_t buffer_count; + FILE *fin; + + byte *buffer_cur; + + byte buffer[4096]; + +} LoadSavegameState; + +static LoadSavegameState *_cur_state; + +static byte GetSavegameByteFromBuffer() +{ + LoadSavegameState *lss = _cur_state; + + if (lss->buffer_count == 0) { + int count = fread(lss->buffer, 1, 4096, lss->fin) ; +/* if (count == 0) { + memset(lss->buffer, 0, sizeof(lss->buffer)); + count = 4096; + }*/ + assert(count != 0); + lss->buffer_count = count; + lss->buffer_cur = lss->buffer; + } + + lss->buffer_count--; + return *lss->buffer_cur++; +} + +static byte DecodeSavegameByte() +{ + LoadSavegameState *lss = _cur_state; + int8 x; + + if (lss->mode < 0) { + if (lss->count != 0) { + lss->count--; + return lss->rep_char; + } + } else if (lss->mode > 0) { + if (lss->count != 0) { + lss->count--; + return GetSavegameByteFromBuffer(); + } + } + + x = GetSavegameByteFromBuffer(); + if (x >= 0) { + lss->count = x; + lss->mode = 1; + return GetSavegameByteFromBuffer(); + } else { + lss->mode = -1; + lss->count = -x; + lss->rep_char = GetSavegameByteFromBuffer(); + return lss->rep_char; + } +} + +static void LoadSavegameBytes(void *p, size_t count) +{ + byte *ptr = (byte*)p; + assert(count > 0); + do { + *ptr++ = DecodeSavegameByte(); + } while (--count); +} + +static void FixTown(Town *t, OldTown *o, int num) +{ + do { + t->xy = o->xy; + t->population = o->population; + t->townnametype = o->townnametype; + t->townnameparts = o->townnameparts; + if (IS_INT_INSIDE(o->townnametype, 0x20C1, 0x20C2 + 1)) + t->townnametype = SPECSTR_TOWNNAME_ENGLISH; + + t->grow_counter = o->grow_counter; + t->flags12 = o->flags12; + memcpy(t->ratings,o->ratings,sizeof(t->ratings)); + t->have_ratings = o->have_ratings; + t->statues = o->statues; + t->num_houses = o->num_houses; + t->time_until_rebuild = o->time_until_rebuild; + t->growth_rate = o->growth_rate; + t->new_max_pass = o->new_max_pass; + t->new_max_mail = o->new_max_mail; + t->new_act_pass = o->new_act_pass; + t->new_act_mail = o->new_act_mail; + t->max_pass = o->max_pass; + t->max_mail = o->max_mail; + t->act_pass = o->act_pass; + t->act_mail = o->act_mail; + t->pct_pass_transported = o->pct_pass_transported; + t->pct_mail_transported = o->pct_mail_transported; + t->new_act_food = o->new_act_food; + t->new_act_paper = o->new_act_paper; + t->act_food = o->act_food; + t->act_paper = o->act_paper; + t->road_build_months = o->road_build_months; + t->fund_buildings_months = o->fund_buildings_months; + } while (t++,o++,--num); +} + +static void FixIndustry(Industry *i, OldIndustry *o, int num) +{ + do { + i->xy = o->xy; + i->town = REMAP_TOWN_PTR(o->town); + i->width = o->width; + i->height = o->height; + i->produced_cargo[0] = o->produced_cargo[0]; + i->produced_cargo[1] = o->produced_cargo[1]; + i->cargo_waiting[0] = o->cargo_waiting[0]; + i->cargo_waiting[1] = o->cargo_waiting[1]; + i->production_rate[0] = o->production_rate[0]; + i->production_rate[1] = o->production_rate[1]; + i->accepts_cargo[0] = o->accepts_cargo[0]; + i->accepts_cargo[1] = o->accepts_cargo[1]; + i->accepts_cargo[2] = o->accepts_cargo[2]; + i->prod_level = o->prod_level; + i->last_mo_production[0] = o->last_mo_production[0]; + i->last_mo_production[1] = o->last_mo_production[1]; + + i->last_mo_transported[0] = o->last_mo_transported[0]; + i->last_mo_transported[1] = o->last_mo_transported[1]; + i->last_mo_transported[2] = o->last_mo_transported[2]; + + i->pct_transported[0] = o->pct_transported[0]; + i->pct_transported[1] = o->pct_transported[1]; + + i->total_production[0] = o->total_production[0]; + i->total_production[1] = o->total_production[1]; + + i->total_transported[0] = i->total_transported[0]; + i->total_transported[1] = i->total_transported[1]; + + i->type = o->type; + i->owner = o->owner; + i->color_map = o->color_map; + i->last_prod_year = o->last_prod_year; + i->counter = o->counter; + i->was_cargo_delivered = o->was_cargo_delivered; + } while (i++,o++,--num); +} + +static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num) +{ + do { + g->waiting_acceptance = o->waiting_acceptance; + g->days_since_pickup = o->days_since_pickup; + g->rating = o->rating; + g->enroute_from = o->enroute_from; + g->enroute_time = o->enroute_time; + g->last_speed = o->last_speed; + g->last_age = o->last_age; + } while (g++,o++,--num); +} + +static void FixStation(Station *s, OldStation *o, int num) +{ + do { + s->xy = o->xy; + s->town = REMAP_TOWN_PTR(o->town); + s->bus_tile = o->bus_tile; + s->lorry_tile = o->lorry_tile; + s->train_tile = o->train_tile; + s->airport_tile = o->airport_tile; + s->dock_tile = o->dock_tile; + + if (o->train_tile) { + int w = (o->platforms >> 3) & 0x7; + int h = (o->platforms & 0x7); + if (_map5[o->train_tile]&1) intswap(w,h); + s->trainst_w = w; + s->trainst_h = h; + } + + s->string_id = RemapOldStringID(o->string_id); + s->had_vehicle_of_type = o->had_vehicle_of_type; + FixGoodsEntry(s->goods, o->goods, lengthof(o->goods)); + s->time_since_load = o->time_since_load; + s->time_since_unload = o->time_since_unload; + s->delete_ctr = o->delete_ctr; + s->owner = o->owner; + s->facilities = o->facilities; + s->airport_type = o->airport_type; + s->truck_stop_status = o->truck_stop_status; + s->bus_stop_status = o->bus_stop_status; + s->blocked_months = o->blocked_months; + s->airport_flags = o->airport_flags; + s->last_vehicle = o->last_vehicle; + } while (s++,o++,--num); +} + +static void FixDepot(Depot *n, OldDepot *o, int num) +{ + do { + n->town_index = REMAP_TOWN_IDX(o->town); + n->xy = o->xy; + } while (n++,o++,--num); +} + +static void FixVehicle(Vehicle *n, OldVehicle *o, int num) +{ + do { + n->type = o->type; + n->subtype = o->subtype; + + if (o->schedule_ptr == 0xFFFFFFFF || o->schedule_ptr == 0) { + n->schedule_ptr = NULL; + } else { + n->schedule_ptr = _order_array + REMAP_ORDER_IDX(o->schedule_ptr); + assert(n->schedule_ptr >= _order_array && n->schedule_ptr < _ptr_to_next_order); + } + + n->next_order = o->next_order; + n->next_order_param = o->next_order_param; + n->num_orders = o->num_orders; + n->cur_order_index = o->cur_order_index; + n->dest_tile = o->dest_tile; + n->load_unload_time_rem = o->load_unload_time_rem; + n->date_of_last_service = o->date_of_last_service; + n->service_interval = o->service_interval; + n->last_station_visited = o->last_station_visited; + n->tick_counter = o->tick_counter; + n->max_speed = o->max_speed; + n->x_pos = o->x_pos; + n->y_pos = o->y_pos; + n->z_pos = o->z_pos; + n->direction = o->direction; + n->x_offs = o->x_offs; + n->y_offs = o->y_offs; + n->sprite_width = o->sprite_width; + n->sprite_height = o->sprite_height; + n->z_height = o->z_height; + n->owner = o->owner; + n->tile = o->tile; + n->cur_image = o->cur_image; + + n->vehstatus = o->vehstatus; + n->cur_speed = o->cur_speed; + n->subspeed = o->subspeed; + n->acceleration = o->acceleration; + n->progress = o->progress; + n->cargo_type = o->cargo_type; + n->cargo_cap = o->capacity; + n->cargo_count = o->number_of_pieces; + n->cargo_source = o->source_of_pieces; + n->cargo_days = o->days_in_transit; + n->age = o->age_in_days; + n->max_age = o->max_age_in_days; + n->build_year = o->build_year; + n->unitnumber = o->unitnumber; + n->engine_type = o->engine_type; + n->spritenum = o->spritenum>>1; + n->day_counter = o->day_counter; + n->breakdowns_since_last_service = o->breakdowns_since_last_service; + n->breakdown_ctr = o->breakdown_ctr; + n->breakdown_delay = o->breakdown_delay; + n->breakdown_chance = o->breakdown_chance; + n->reliability = o->reliability; + n->reliability_spd_dec = o->reliability_spd_dec; + n->profit_this_year = o->profit_this_year; + n->profit_last_year = o->profit_last_year; + n->next = o->next_in_chain == 0xffff ? NULL : &_vehicles[o->next_in_chain]; + n->value = o->value; + n->string_id = RemapOldStringID(o->string_id); + + switch(o->type) { + case VEH_Train: + n->u.rail.track = o->u.rail.track; + n->u.rail.force_proceed = o->u.rail.force_proceed; + n->u.rail.crash_anim_pos = o->u.rail.crash_anim_pos; + n->u.rail.railtype = o->u.rail.railtype; + break; + + case VEH_Road: + n->u.road.state = o->u.road.state; + n->u.road.frame = o->u.road.frame; + n->u.road.unk2 = o->u.road.unk2; + n->u.road.overtaking = o->u.road.overtaking; + n->u.road.overtaking_ctr = o->u.road.overtaking_ctr; + n->u.road.crashed_ctr = o->u.road.crashed_ctr; + n->u.road.reverse_ctr = o->u.road.reverse_ctr; + break; + case VEH_Ship: + n->u.ship.state = o->u.ship.state; + break; + case VEH_Aircraft: + n->u.air.crashed_counter = o->u.air.crashed_counter; + n->u.air.pos = o->u.air.unk0; + n->u.air.targetairport = o->u.air.targetairport; + n->u.air.state = o->u.air.state; + break; + case VEH_Special: + n->u.special.unk0 = o->u.special.unk0; + n->u.special.unk2 = o->u.special.unk2; + n->subtype = o->subtype >> 1; + break; + case VEH_Disaster: + n->u.disaster.image_override = o->u.disaster.image_override; + n->u.disaster.unk2 = o->u.disaster.unk2; + break; + } + } while (n++,o++,--num); +} + +static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num) +{ + do { + n->age = o->age; + n->cargo_type = o->cargo_type; + n->from = o->from; + n->to = o->to; + } while (n++,o++,--num); +} + +static void FixEconomy(PlayerEconomyEntry *n, OldPlayerEconomy *o) +{ + n->company_value = o->company_value; + n->delivered_cargo = o->delivered_cargo; + n->income = -o->income; + n->expenses = -o->expenses; + n->performance_history = o->performance_history; +} + +static void FixAiBuildRec(AiBuildRec *n, OldAiBuildRec *o) +{ + n->spec_tile = o->spec_tile; + n->use_tile = o->use_tile; + n->rand_rng = o->rand_rng; + n->cur_building_rule = o->cur_rule; + n->unk6 = o->unk6; + n->unk7 = o->unk7; + n->buildcmd_a = o->buildcmd_a; + n->buildcmd_b = o->buildcmd_b; + n->direction = o->direction; + n->cargo = o->cargo; +} + +static void FixPlayer(Player *n, OldPlayer *o, int num) +{ + int i, j; + int x = 0; + + do { + n->name_1 = RemapOldStringID(o->name_1); + n->name_2 = o->name_2; + if (o->name_1 == 0 && x == 0) + n->name_1 = STR_SV_UNNAMED; + else + n->is_active=true; + + n->face = o->face; + n->president_name_1 = o->pres_name_1; + n->president_name_2 = o->pres_name_2; + + n->money64 = n->player_money = o->money; + n->current_loan = o->loan; + + // Correct money for scenario loading. + // It's always 893288 pounds (and no loan), if not corrected + if(o->money==0xda168) + n->money64 = n->player_money = n->current_loan =100000; + + n->player_color = o->color; + _player_colors[x] = o->color; + x++; + + n->player_money_fraction = o->money_fract; + n->quarters_of_bankrupcy = o->quarters_of_bankrupcy; + n->bankrupt_asked = o->bankrupt_asked; + n->bankrupt_value = o->bankrupt_value; + n->bankrupt_timeout = o->bankrupt_timeout; + n->cargo_types = o->cargo_types; + + for(i=0; i!=3; i++) + for(j=0; j!=13; j++) + n->yearly_expenses[i][j] = o->expenses[i].cost[j]; + + FixEconomy(&n->cur_economy, &o->economy[0]); + for(i=0; i!=24; i++) FixEconomy(&n->old_economy[i], &o->economy[i+1]); + n->inaugurated_year = o->inaugurated_date - 1920; + n->last_build_coordinate = o->last_build_coordinate; + n->num_valid_stat_ent = o->num_valid_stat_ent; + + n->ai.state = o->ai_state; + n->ai.state_mode = o->ai_state_mode; + n->ai.state_counter = o->ai_state_counter; + n->ai.timeout_counter = o->ai_timeout_counter; + n->ai.banned_tile_count = o->ai_banned_tile_count; + n->ai.railtype_to_use = o->ai_railtype_to_use; + + FixAiBuildRec(&n->ai.src, &o->ai_src); + FixAiBuildRec(&n->ai.dst, &o->ai_dst); + FixAiBuildRec(&n->ai.mid1, &o->ai_mid1); + FixAiBuildRec(&n->ai.mid2, &o->ai_mid2); + + n->ai.cargo_type = o->ai_cargo_type; + n->ai.num_wagons = o->ai_num_wagons; + n->ai.num_build_rec = o->ai_num_build_rec; + n->ai.num_loco_to_build = o->ai_num_loco_to_build; + n->ai.num_want_fullload = o->ai_num_want_fullload; + + for(i=0; i!=9; i++) n->ai.wagon_list[i] = o->ai_wagonlist[i]; + memcpy(n->ai.order_list_blocks, o->ai_order_list_blocks, 20); + n->ai.start_tile_a = o->ai_start_tile_a; + n->ai.start_tile_b = o->ai_start_tile_b; + n->ai.cur_tile_a = o->ai_cur_tile_a; + n->ai.cur_tile_b = o->ai_cur_tile_b; + n->ai.start_dir_a = o->ai_start_dir_a; + n->ai.start_dir_b = o->ai_start_dir_b; + n->ai.cur_dir_a = o->ai_cur_dir_a; + n->ai.cur_dir_b = o->ai_cur_dir_b; + + for(i=0; i!=16; i++) { + n->ai.banned_tiles[i] = o->banned_tiles[i].tile; + n->ai.banned_val[i] = o->banned_tiles[i].data; + } + + n->ai.build_kind = o->ai_build_kind; + n->ai.route_type_mask = o->ai_route_type_mask; + n->ai.tick = o->ai_tick; + + n->block_preview = o->block_preview; + n->max_railtype = (o->max_railtype == 0) ? 1 : o->max_railtype; + n->location_of_house = o->location_of_house; + if (o->location_of_house == 0xFFFF) n->location_of_house = 0; + + n->share_owners[0] = o->share_owners[0]; + n->share_owners[1] = o->share_owners[1]; + n->share_owners[2] = o->share_owners[2]; + n->share_owners[3] = o->share_owners[3]; + + if (o->ai_state == 2) { + n->ai.cur_veh = NULL; + } + } while (n++,o++,--num); +} + +static void FixName(OldName *o, int num) +{ + int i; + for(i=0; i!=num; i++) { + memcpy(_name_array[i], o[i].name, sizeof(o[i].name)); + } +} + +static void FixSign(SignStruct *n, OldSign *o, int num) +{ + do { + n->str = o->text; + n->x = o->x; + n->y = o->y; + n->z = o->z; + } while (n++,o++,--num); +} + +static void FixEngine(Engine *n, OldEngine *o, int num) +{ + int i = 0; + + do { + n->player_avail = o->player_avail; + n->intro_date = o->intro_date; + n->age = o->age; + if ((i >= 27 && i < 54) || (i >= 57 && i < 84) || (i >= 89 && i < 116)) + n->age = 0xffff; + n->reliability = o->reliability; + n->reliability_spd_dec = o->reliability_spd_dec; + n->reliability_start = o->reliability_start; + n->reliability_max = o->reliability_max; + n->reliability_final = o->reliability_final; + n->duration_phase_1 = o->duration_phase_1; + n->duration_phase_2 = o->duration_phase_2; + n->duration_phase_3 = o->duration_phase_3; + n->lifelength = o->lifelength; + n->flags = o->flags; + n->preview_player = o->preview_player; + n->preview_wait = o->preview_wait; + n->railtype = o->railtype; + } while (n++,o++,i++,--num); +} + +void FixGameDifficulty(GameDifficulty *n, OldGameSettings *o) +{ + n->max_no_competitors = o->max_no_competitors; + n->competitor_start_time = o->competitor_start_time; + n->number_towns = o->number_towns; + n->number_industries = o->number_industries; + n->max_loan = o->max_loan; + n->initial_interest = o->initial_interest; + n->vehicle_costs = o->vehicle_costs; + n->competitor_speed = o->competitor_speed; + n->competitor_intelligence = o->competitor_intelligence; + n->vehicle_breakdowns = o->vehicle_breakdowns; + n->subsidy_multiplier = o->subsidy_multiplier; + n->construction_cost = o->construction_cost; + n->terrain_type = o->terrain_type; + n->quantity_sea_lakes = o->quantity_sea_lakes; + n->economy = o->economy; + n->line_reverse_mode = o->line_reverse_mode; + n->disasters = o->disasters; +} + + +// loader for old style savegames +bool LoadOldSaveGame(const char *file) +{ + LoadSavegameState lss; + OldMain *m; + int i; + + _cur_state = &lss; + memset(&lss, 0, sizeof(lss)); + + lss.fin = fopen(file, "rb"); + if (lss.fin == NULL) return false; + + fseek(lss.fin, 49, SEEK_SET); + + // load the file into memory + m = (OldMain *)malloc(sizeof(OldMain)); + LoadSavegameBytes(m, sizeof(OldMain)); + + // copy sections of it to our datastructures. + memcpy(_map_owner, m->map_owner, sizeof(_map_owner)); + memcpy(_map2, m->map2, sizeof(_map2)); + memcpy(_map_type_and_height, m->map_type_and_height, sizeof(_map_type_and_height)); + memcpy(_map5, m->map5, sizeof(_map5)); + for(i=0; i!=256*256; i++) { + _map3_lo[i] = m->map3[i] & 0xFF; + _map3_hi[i] = m->map3[i] >> 8; + } + memcpy(_map_extra_bits, m->map_extra, sizeof(_map_extra_bits)); + + // go through the tables and see if we can find any ttdpatch presignals. Then convert those to our format. + for(i=0; i!=256*256; i++) { + if (IS_TILETYPE(i, MP_RAILWAY) && (_map5[i] & 0xC0) == 0x40) { + // this byte is always zero in real ttd. + if (_map3_hi[i]) { + // convert ttdpatch presignal format to openttd presignal format. + _map3_hi[i] = (_map3_hi[i] >> 1) & 7; + } + } + } + + memcpy(_order_array, m->order_list, sizeof(m->order_list)); + _ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order); + + FixTown(_towns, m->town_list, lengthof(m->town_list)); + FixIndustry(_industries, m->industries, lengthof(m->industries)); + FixStation(_stations, m->stations, lengthof(m->stations)); + + FixDepot(_depots, m->depots, lengthof(m->depots)); + FixVehicle(_vehicles, m->vehicles, lengthof(m->vehicles)); + FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies)); + + FixPlayer(_players, m->players, lengthof(m->players)); + FixName(m->names, lengthof(m->names)); + FixSign(_sign_list, m->signs, lengthof(m->signs)); + FixEngine(_engines, m->engines, lengthof(m->engines)); + + _opt.diff_level = m->difficulty_level; + _opt.currency = m->currency; + _opt.kilometers = m->use_kilometers; + _opt.town_name = m->town_name_type; + _opt.landscape = m->landscape_type; + _opt.snow_line = m->snow_line_height; + _opt.autosave = 0; + _opt.road_side = m->road_side; + FixGameDifficulty(&_opt.diff, &m->game_diff); + + // Load globals + _date = m->date; + _date_fract = m->date_fract; + _tick_counter = m->tick_counter; + _vehicle_id_ctr_day = m->vehicle_id_ctr_day; + _age_cargo_skip_counter = m->age_cargo_skip_counter; + _avail_aircraft = m->avail_aircraft; + _cur_tileloop_tile = m->cur_tileloop_tile; + _disaster_delay = m->disaster_delay; + _station_tick_ctr = m->station_tick_ctr; + _random_seed_1 = m->seed_1; + _random_seed_2 = m->seed_2; + _cur_town_ctr = REMAP_TOWN_IDX(m->cur_town_ptr); + _cur_player_tick_index = m->cur_player_tick_index; + _next_competitor_start = m->next_competitor_start; + _trees_tick_ctr = m->trees_tick_ctr; + _saved_scrollpos_x = m->saved_main_scrollpos_x; + _saved_scrollpos_y = m->saved_main_scrollpos_y; + _saved_scrollpos_zoom = m->saved_main_scrollpos_zoom; + + // Load economy stuff + _economy.max_loan = m->maximum_loan; + _economy.max_loan_unround = m->maximum_loan_unround; + _economy.fluct = m->economy_fluct; + _economy.interest_rate = m->interest_rate; + _economy.infl_amount = m->inflation_amount; + _economy.infl_amount_pr = m->inflation_amount_payment_rates; + + memcpy(_animated_tile_list, m->animated_tile_list, sizeof(m->animated_tile_list)); + memcpy(_engine_name_strings, m->engine_name_strings, sizeof(m->engine_name_strings)); + + for(i=0; i!=lengthof(m->prices); i++) { + ((uint32*)&_price)[i] = m->prices[i].price; + _price_frac[i] = m->prices[i].frac; + } + + for(i=0; i!=lengthof(m->cargo_payment_rates); i++) { + _cargo_payment_rates[i] = -(int32)m->cargo_payment_rates[i].price; + _cargo_payment_rates_frac[i] = m->cargo_payment_rates[i].frac; + } + + free(m); + fclose(lss.fin); + return true; +} + +void GetOldSaveGameName(char *title, const char *file) +{ + FILE *f; + + f = fopen(file, "rb"); + title[0] = 0; + title[48] = 0; + + if (!f) return; + if (fread(title, 1, 48, f) != 48) title[0] = 0; + fclose(f); +} + +void GetOldScenarioGameName(char *title, const char *file) +{ + GetOldSaveGameName(title, file); +} diff --git a/order_cmd.c b/order_cmd.c new file mode 100644 --- /dev/null +++ b/order_cmd.c @@ -0,0 +1,332 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "command.h" +#include "station.h" +#include "player.h" + +/* p1 & 0xFFFF = vehicle + * p1 >> 16 = index in order list + * p2 = order command to insert + */ +int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1 & 0xFFFF]; + int sel = p1 >> 16; + int t; + + if (sel > v->num_orders) return_cmd_error(STR_EMPTY); + if (_ptr_to_next_order == endof(_order_array)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); + if (v->num_orders >= 40) return_cmd_error(STR_8832_TOO_MANY_ORDERS); + + // for ships, make sure that the station is not too far away from the previous destination. + if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) && + sel != 0 && ((t=v->schedule_ptr[sel-1])&OT_MASK) == OT_GOTO_STATION) { + + int dist = GetTileDist(DEREF_STATION(t >> 8)->xy, DEREF_STATION(p2 >> 8)->xy); + if (dist >= 130) + return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO); + } + + if (flags & DC_EXEC) { + uint16 *s1, *s2; + Vehicle *u; + + s1 = &v->schedule_ptr[sel]; + s2 = _ptr_to_next_order++; + do s2[1] = s2[0]; while (--s2 >= s1); + s1[0] = (uint16)p2; + + s1 = v->schedule_ptr; + + FOR_ALL_VEHICLES(u) { + if (u->type != 0 && u->schedule_ptr != NULL) { + if (s1 < u->schedule_ptr) { + u->schedule_ptr++; + } else if (s1 == u->schedule_ptr) { // handle shared orders + u->num_orders++; + + if ((byte)sel <= u->cur_order_index) { + sel++; + if ((byte)sel < u->num_orders) + u->cur_order_index = sel; + } + InvalidateWindow(WC_VEHICLE_VIEW, u->index); + InvalidateWindow(WC_VEHICLE_ORDERS, u->index); + } + } + } + } + + return 0; +} + +static int32 DecloneOrder(Vehicle *dst, uint32 flags) +{ + if (_ptr_to_next_order == endof(_order_array)) + return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); + + if (flags & DC_EXEC) { + DeleteVehicleSchedule(dst); + + dst->num_orders = 0; + *(dst->schedule_ptr = _ptr_to_next_order++) = 0; + + InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + } + return 0; +} + +/* p1 = vehicle + * p2 = sel + */ +int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1], *u; + uint sel = (uint)p2; + + _error_message = STR_EMPTY; + if (sel >= v->num_orders) + return DecloneOrder(v, flags); + + if (flags & DC_EXEC) { + uint16 *s1; + + s1 = &v->schedule_ptr[sel]; + + // copy all orders to get rid of the hole + do s1[0] = s1[1]; while (++s1 != _ptr_to_next_order); + _ptr_to_next_order--; + + s1 = v->schedule_ptr; + + FOR_ALL_VEHICLES(u) { + if (u->type != 0 && u->schedule_ptr != NULL) { + if (s1 < u->schedule_ptr) { + u->schedule_ptr--; + } else if (s1 == u->schedule_ptr) {// handle shared orders + u->num_orders--; + if ((byte)sel < u->cur_order_index) + u->cur_order_index--; + + if ((byte)sel == u->cur_order_index && (u->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP)) + u->next_order = OT_LOADING; + + InvalidateWindow(WC_VEHICLE_VIEW, u->index); + InvalidateWindow(WC_VEHICLE_ORDERS, u->index); + } + } + } + } + + return 0; +} + +/* p1 = vehicle */ +int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + Vehicle *v = &_vehicles[p1]; + + { + byte b = v->cur_order_index + 1; + if (b >= v->num_orders) b = 0; + v->cur_order_index = b; + + if (v->type == VEH_Train) + v->u.rail.days_since_order_progr = 0; + } + + if ((v->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP)) + v->next_order = OT_LOADING; + + InvalidateWindow(WC_VEHICLE_ORDERS, v->index); + } + return 0; +} + +/* p1 = vehicle + * p2&0xFF = sel + * p2>>8 = mode + */ +int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1]; + byte sel = (byte)p2; + uint16 *sched; + + if (sel >= v->num_orders) + return CMD_ERROR; + + sched = &v->schedule_ptr[sel]; + if (!((*sched & OT_MASK) == OT_GOTO_STATION || + ((*sched & OT_MASK) == OT_GOTO_DEPOT && (p2>>8) != 1))) + return CMD_ERROR; + + if (flags & DC_EXEC) { + switch(p2 >> 8) { + case 0: // full load + *sched ^= OF_FULL_LOAD; + if ((*sched & OT_MASK) != OT_GOTO_DEPOT) + *sched &= ~OF_UNLOAD; + break; + case 1: // unload + *sched ^= OF_UNLOAD; + *sched &= ~OF_FULL_LOAD; + break; + case 2: // non stop + *sched ^= OF_NON_STOP; + break; + } + sched = v->schedule_ptr; + + FOR_ALL_VEHICLES(v) { + if (v->schedule_ptr == sched) + InvalidateWindow(WC_VEHICLE_ORDERS, v->index); + } + + } + + return 0; +} + +// Clone an order +// p1 & 0xFFFF is destination vehicle +// p1 >> 16 is source vehicle + +// p2 is +// 0 - clone +// 1 - copy +// 2 - unclone + + +int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *dst = &_vehicles[p1 & 0xFFFF]; + + if (!(dst->type && dst->owner == _current_player)) + return CMD_ERROR; + + switch(p2) { + + // share vehicle orders? + case 0: { + Vehicle *src = &_vehicles[p1 >> 16]; + + // sanity checks + if (!(src->owner == _current_player && dst->type == src->type && dst != src)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DeleteVehicleSchedule(dst); + dst->schedule_ptr = src->schedule_ptr; + dst->num_orders = src->num_orders; + + InvalidateWindow(WC_VEHICLE_ORDERS, src->index); + InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + } + break; + } + + // copy vehicle orders? + case 1: { + Vehicle *src = &_vehicles[p1 >> 16]; + int delta; + + // sanity checks + if (!(src->owner == _current_player && dst->type == src->type && dst != src)) + return CMD_ERROR; + + // make sure there's orders available + delta = IsScheduleShared(dst) ? src->num_orders + 1 : src->num_orders - dst->num_orders; + if (delta > endof(_order_array) - _ptr_to_next_order) + return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); + + if (flags & DC_EXEC) { + DeleteVehicleSchedule(dst); + dst->schedule_ptr = _ptr_to_next_order; + dst->num_orders = src->num_orders; + _ptr_to_next_order += src->num_orders + 1; + memcpy(dst->schedule_ptr, src->schedule_ptr, (src->num_orders + 1) * sizeof(uint16)); + + InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + } + break; + } + + // declone vehicle orders? + case 2: return DecloneOrder(dst, flags); + } + + return 0; +} + +void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak) +{ + Vehicle *u = IsScheduleShared(v); + uint16 *sched, ord, *os; + + bak->orderindex = v->cur_order_index; + bak->service_interval = v->service_interval; + + if ((v->string_id & 0xF800) != 0x7800) { + bak->name[0] = 0; + } else { + GetName(v->string_id & 0x7FF, bak->name); + } + + os = bak->order; + // stored shared orders in this special way? + if (u) { + os[0] = 0xFFFF; + os[1] = u->index; + return; + } + + sched = v->schedule_ptr; + do { + ord = *sched++; + *os++ = ord; + } while (ord != 0); +} + +void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak) +{ + uint16 ord, *os; + int ind; + + if (bak->name[0]) { + strcpy((char*)_decode_parameters, bak->name); + DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE); + } + + DoCommandP(0, v->index, bak->orderindex|(bak->service_interval<<16) , NULL, CMD_RESTORE_ORDER_INDEX | CMD_ASYNC); + + os = bak->order; + if (os[0] == 0xFFFF) { + DoCommandP(0, v->index | os[1]<<16, 0, NULL, CMD_CLONE_ORDER); + return; + } + + ind = 0; + while ((ord = *os++) != 0) { + if (!DoCommandP(0, v->index + (ind << 16), ord, NULL, CMD_INSERT_ORDER | CMD_ASYNC)) + break; + ind++; + } +} + +/* p1 = vehicle + * upper 16 bits p2 = service_interval + * lower 16 bits p2 = cur_order_index + */ +int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + // nonsense to update the windows, since, train rebought will have its window deleted + if (flags & DC_EXEC) { + Vehicle *v = &_vehicles[p1]; + v->service_interval = (uint16)(p2>>16); + v->cur_order_index = (byte)(p2&0xFFFF); + } + return 0; +} diff --git a/order_gui.c b/order_gui.c new file mode 100644 --- /dev/null +++ b/order_gui.c @@ -0,0 +1,534 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "vehicle.h" +#include "station.h" +#include "town.h" +#include "command.h" +#include "viewport.h" + +static int OrderGetSel(Window *w) +{ + Vehicle *v = &_vehicles[w->window_number]; + uint16 *sched = v->schedule_ptr; + int num = WP(w,order_d).sel; + int count = 0; + + if (num == 0) + return 0; + + while (*sched != 0) { + sched++; + count++; + if (--num == 0) + break; + } + + return count; +} + +static void DrawOrdersWindow(Window *w) +{ + Vehicle *v; + int num, sel; + uint16 *sched, ord; + int y, i; + StringID str; + bool shared_schedule; + + v = &_vehicles[w->window_number]; + + w->disabled_state = (v->owner == _local_player) ? 0 : 0x3F0; + + shared_schedule = IsScheduleShared(v) != NULL; + + sched = v->schedule_ptr; + num=0; + while (*sched != 0) + sched++,num++; + + if ((uint)num + shared_schedule <= (uint)WP(w,order_d).sel) + SETBIT(w->disabled_state, 5); /* delete */ + + if (num == 0) + SETBIT(w->disabled_state, 4); /* skip */ + + SetVScrollCount(w, num+1); + + sel = OrderGetSel(w); + + SET_DPARAM16(2,STR_8827_FULL_LOAD); + switch(v->schedule_ptr[sel] & 0x1F) { + case OT_GOTO_STATION: + break; + case OT_GOTO_DEPOT: + SETBIT(w->disabled_state, 9); /* unload */ + SET_DPARAM16(2,STR_SERVICE); + break; + default: + SETBIT(w->disabled_state, 6); /* nonstop */ + SETBIT(w->disabled_state, 8); /* full load */ + SETBIT(w->disabled_state, 9); /* unload */ + } + + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + y = 15; + + i = 0; + for(;;) { + str = ((byte)v->cur_order_index == i) ? STR_8805 : STR_8804; + + ord = v->schedule_ptr[i]; + + if ( (uint)(i - w->vscroll.pos) < 6) { + + if (ord == 0) { + str = shared_schedule ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS; + } else { + SET_DPARAM16(1, 6); + + if ( (ord & OT_MASK) == OT_GOTO_STATION) { + SET_DPARAM16(1, STR_8806_GO_TO + ((ord >> 5) & 7)); + SET_DPARAM16(2, ord >> 8); + } else if ((ord & OT_MASK) == OT_GOTO_DEPOT) { + StringID s = STR_NULL; + if (v->type == VEH_Aircraft) { + s = STR_GO_TO_AIRPORT_HANGAR; + SET_DPARAM16(2, ord>>8); + } else { + SET_DPARAM16(2, _depots[ord >> 8].town_index); + switch (v->type) { + case VEH_Train: s = STR_880E_GO_TO_TRAIN_DEPOT; break; + case VEH_Road: s = STR_9038_GO_TO_ROADVEH_DEPOT; break; + case VEH_Ship: s = STR_GO_TO_SHIP_DEPOT; break; + } + } + if (v->type == VEH_Train) + s += (ord>>6)&2; + SET_DPARAM16(1, s + ((ord>>6)&1) ); + } else if ((ord & OT_MASK) == OT_GOTO_CHECKPOINT) { + SET_DPARAM16(2, ord >> 8); + SET_DPARAM16(1, STR_GO_TO_CHECKPOINT); + } + } + { + byte color = (i == WP(w,order_d).sel) ? 0xC : 0x10; + SET_DPARAM(0, i+1); + DrawString(2, y, str, color); + } + y += 10; + } + + i++; + + if (ord == 0) + break; + } +} + + +// lookup a vehicle on a tile +typedef struct { + TileIndex tile; + byte owner; + byte type; +} FindVehS; + +static void *FindVehicleCallb(Vehicle *v, FindVehS *f) +{ + if (v->tile != f->tile || v->owner != f->owner || v->vehstatus & VS_HIDDEN ) return NULL; + return v; +} + +Vehicle *GetVehicleOnTile(TileIndex tile, byte owner) +{ + FindVehS fs = {tile, owner}; + return VehicleFromPos(tile, &fs, (VehicleFromPosProc*)FindVehicleCallb); +} + +static uint GetOrderCmdFromTile(Vehicle *v, uint tile) +{ + Station *st; + int st_index; + + // check depot first + if (_patches.gotodepot) { + switch(GET_TILETYPE(tile)) { + case MP_RAILWAY: + if (v->type == VEH_Train && _map_owner[tile] == _local_player) { + if ((_map5[tile]&0xFC)==0xC0) + return (GetDepotByTile(tile)<<8) | OT_GOTO_DEPOT | OF_UNLOAD; + + if ((_map5[tile]&0xFE)==0xC4) + return (GetCheckpointByTile(tile)<<8) | OT_GOTO_CHECKPOINT; + } + break; + + case MP_STREET: + if ((_map5[tile] & 0xF0) == 0x20 && v->type == VEH_Road && _map_owner[tile] == _local_player) + return (GetDepotByTile(tile)<<8) | OT_GOTO_DEPOT | OF_UNLOAD; + break; + + case MP_STATION: + if (v->type != VEH_Aircraft) break; + if ( IsAircraftHangarTile(tile) && _map_owner[tile] == _local_player) + return (_map2[tile]<<8) | OF_UNLOAD | OT_GOTO_DEPOT | OF_NON_STOP; + break; + + case MP_WATER: + if (v->type != VEH_Ship) break; + if ( IsShipDepotTile(tile) && _map_owner[tile] == _local_player) { + switch (_map5[tile]) { + case 0x81: tile--; break; + case 0x83: tile-= TILE_XY(0,1); break; + } + return (GetDepotByTile(tile)<<8) | OT_GOTO_DEPOT | OF_UNLOAD; + } + } + } + + if (IS_TILETYPE(tile, MP_STATION)) { + st = DEREF_STATION(st_index = _map2[tile]); + + if (st->owner == _current_player || st->owner == OWNER_NONE) { + byte facil; + (facil=FACIL_DOCK, v->type == VEH_Ship) || + (facil=FACIL_TRAIN, v->type == VEH_Train) || + (facil=FACIL_AIRPORT, v->type == VEH_Aircraft) || + (facil=FACIL_BUS_STOP, v->type == VEH_Road && v->cargo_type == CT_PASSENGERS) || + (facil=FACIL_TRUCK_STOP, 1); + if (st->facilities & facil) + return (st_index << 8) | OT_GOTO_STATION; + } + } + + // not found + return (uint)-1; +} + +static bool HandleOrderVehClick(Vehicle *v, Vehicle *u, Window *w) +{ + if (u->type != v->type) + return false; + + if (u->type == VEH_Train && u->subtype != 0) { + u = GetFirstVehicleInChain(u); + if (u->subtype != 0) + return false; + } + + // v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet + // obviously if you press CTRL on a non-empty orders vehicle you know what you are doing + if (v->num_orders != 0 && _ctrl_pressed == 0) {return false;} + + if (DoCommandP(v->tile, v->index | (u->index << 16), _ctrl_pressed ? 0 : 1, NULL, + _ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_CANT_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_CANT_COPY_ORDER_LIST))) { + WP(w,order_d).sel = -1; + ResetObjectToPlace(); + } + + return true; +} + +static void OrdersPlaceObj(Vehicle *v, uint tile, Window *w) +{ + uint cmd; + Vehicle *u; + + // check if we're clicking on a vehicle first.. clone orders in that case. + u = CheckMouseOverVehicle(); + if (u && HandleOrderVehClick(v, u, w)) + return; + + cmd = GetOrderCmdFromTile(v, tile); + if ( cmd == (uint)-1) return; + + if (DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), cmd, NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER))) { + if (WP(w,order_d).sel != -1) + WP(w,order_d).sel++; + ResetObjectToPlace(); + } +} + + +static void OrdersWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawOrdersWindow(w); + break; + + case WE_CLICK: { + Vehicle *v = &_vehicles[w->window_number]; + int mode; + switch(e->click.widget) { + case 2: {/* orders list */ + int sel; + sel = (e->click.pt.y - 15) / 10; + + if ( (uint) sel >= 6) + return; + + sel += w->vscroll.pos; + + if (sel == WP(w,order_d).sel) sel = -1; + WP(w,order_d).sel = sel; + SetWindowDirty(w); + } break; + + case 4: /* skip button */ + DoCommandP(v->tile,v->index, 0, NULL, CMD_SKIP_ORDER); + break; + + case 5: /* delete button */ + DoCommandP(v->tile,v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER)); + break; + + case 7: /* goto button */ + InvalidateWidget(w, 7); + w->click_state ^= 1<<7; + if (HASBIT(w->click_state, 7)) { + _place_clicked_vehicle = NULL; + SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, 1, w); + } else { + ResetObjectToPlace(); + } + break; + + case 8: /* full load button */ + mode = 0; + DoCommandP(v->tile, v->index, OrderGetSel(w) | (mode << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); + break; + + case 9: /* unload button */ + mode = 1; + DoCommandP(v->tile, v->index, OrderGetSel(w) | (mode << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); + break; + + case 6: /* non stop button */ + mode = 2; + DoCommandP(v->tile, v->index, OrderGetSel(w) | (mode << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); + break; + } + } break; + + + case WE_RCLICK: { + Vehicle *v = &_vehicles[w->window_number]; + if (e->click.widget != 8) break; + if ((v->schedule_ptr[OrderGetSel(w)] & OT_MASK) == OT_GOTO_DEPOT) + GuiShowTooltips(STR_SERVICE_HINT); + else + GuiShowTooltips(STR_8857_MAKE_THE_HIGHLIGHTED_ORDER); + } break; + + case WE_4: { + if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL) + DeleteWindow(w); + } break; + + case WE_PLACE_OBJ: { + OrdersPlaceObj(&_vehicles[w->window_number], e->place.tile, w); + } break; + + case WE_ABORT_PLACE_OBJ: { + w->click_state &= ~(1<<7); + InvalidateWidget(w, 7); + } break; + + // check if a vehicle in a depot was clicked.. + case WE_MOUSELOOP: { + Vehicle *v = _place_clicked_vehicle; + if (v) { + _place_clicked_vehicle = NULL; + HandleOrderVehClick(&_vehicles[w->window_number], v, w); + } + } break; + + } +} + +static const Widget _train_orders_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_8829_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 308, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 52, 76, 87, STR_8823_SKIP, STR_8853_SKIP_THE_CURRENT_ORDER}, +{ WWT_PUSHTXTBTN, 14, 53, 105, 76, 87, STR_8824_DELETE, STR_8854_DELETE_THE_HIGHLIGHTED}, +{ WWT_PUSHTXTBTN, 14, 106, 158, 76, 87, STR_8825_NON_STOP, STR_8855_MAKE_THE_HIGHLIGHTED_ORDER}, +{WWT_NODISTXTBTN, 14, 159, 211, 76, 87, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, +{ WWT_PUSHTXTBTN, 14, 212, 264, 76, 87, STR_FULLLOAD_OR_SERVICE, 0}, +{ WWT_PUSHTXTBTN, 14, 265, 319, 76, 87, STR_8828_UNLOAD, STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, +{ WWT_LAST}, +}; + +static const WindowDesc _train_orders_desc = { + -1,-1, 320, 88, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, + _train_orders_widgets, + OrdersWndProc +}; + +static const Widget _other_train_orders_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_8829_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 308, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_train_orders_desc = { + -1,-1, 320, 76, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_train_orders_widgets, + OrdersWndProc +}; + + +static const Widget _roadveh_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_900B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0,STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 63, 76, 87, STR_8823_SKIP, STR_8853_SKIP_THE_CURRENT_ORDER}, +{ WWT_PUSHTXTBTN, 14, 64, 127, 76, 87, STR_8824_DELETE, STR_8854_DELETE_THE_HIGHLIGHTED}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{WWT_NODISTXTBTN, 14, 128, 191, 76, 87, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, +{ WWT_PUSHTXTBTN, 14, 192, 255, 76, 87, STR_FULLLOAD_OR_SERVICE, 0}, +{ WWT_PUSHTXTBTN, 14, 256, 319, 76, 87, STR_8828_UNLOAD, STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, +{ WWT_LAST}, +}; + +static const WindowDesc _roadveh_orders_desc = { + -1,-1, 320, 88, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, + _roadveh_orders_widgets, + OrdersWndProc +}; + +static const Widget _other_roadveh_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_900B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0,STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_roadveh_orders_desc = { + -1,-1, 320, 76, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_roadveh_orders_widgets, + OrdersWndProc +}; + +static const Widget _ship_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_9810_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0,STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 63, 76, 87, STR_8823_SKIP, STR_8853_SKIP_THE_CURRENT_ORDER}, +{ WWT_PUSHTXTBTN, 14, 64, 127, 76, 87, STR_8824_DELETE, STR_8854_DELETE_THE_HIGHLIGHTED}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{WWT_NODISTXTBTN, 14, 128, 191, 76, 87, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, +{ WWT_PUSHTXTBTN, 14, 192, 255, 76, 87, STR_FULLLOAD_OR_SERVICE, 0}, +{ WWT_PUSHTXTBTN, 14, 256, 319, 76, 87, STR_8828_UNLOAD, STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, +{ WWT_LAST}, +}; + +static const WindowDesc _ship_orders_desc = { + -1,-1, 320, 88, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, + _ship_orders_widgets, + OrdersWndProc +}; + +static const Widget _other_ship_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_9810_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0,STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_ship_orders_desc = { + -1,-1, 320, 76, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_ship_orders_widgets, + OrdersWndProc +}; + + +static const Widget _aircraft_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_A00B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 63, 76, 87, STR_8823_SKIP, STR_8853_SKIP_THE_CURRENT_ORDER}, +{ WWT_PUSHTXTBTN, 14, 64, 127, 76, 87, STR_8824_DELETE, STR_8854_DELETE_THE_HIGHLIGHTED}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{WWT_NODISTXTBTN, 14, 128, 191, 76, 87, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, +{ WWT_PUSHTXTBTN, 14, 192, 255, 76, 87, STR_FULLLOAD_OR_SERVICE, 0}, +{ WWT_PUSHTXTBTN, 14, 256, 319, 76, 87, STR_8828_UNLOAD, STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, +{ WWT_LAST}, +}; + +static const WindowDesc _aircraft_orders_desc = { + -1,-1, 320, 88, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, + _aircraft_orders_widgets, + OrdersWndProc +}; + +static const Widget _other_aircraft_orders_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 319, 0, 13, STR_A00B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 308, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, +{ WWT_SCROLLBAR, 14, 309, 319, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_aircraft_orders_desc = { + -1,-1, 320, 76, + WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_aircraft_orders_widgets, + OrdersWndProc +}; + +static const WindowDesc * const _order_window_desc[8] = { + &_train_orders_desc, &_other_train_orders_desc, + &_roadveh_orders_desc, &_other_roadveh_orders_desc, + &_ship_orders_desc, &_other_ship_orders_desc, + &_aircraft_orders_desc, &_other_aircraft_orders_desc, +}; + + +void ShowOrdersWindow(Vehicle *v) +{ + Window *w; + VehicleID veh = v->index; + + DeleteWindowById(WC_VEHICLE_ORDERS, veh); + DeleteWindowById(WC_VEHICLE_DETAILS, veh); + + _alloc_wnd_parent_num = veh; + w = AllocateWindowDesc( + _order_window_desc[(v->type - VEH_Train)*2 + (v->owner != _local_player)]); + + w->window_number = veh; + w->caption_color = v->owner; + w->vscroll.cap = 6; + WP(w,order_d).sel = -1; +} diff --git a/os/macos/Crash_Log_Opener.sit b/os/macos/Crash_Log_Opener.sit new file mode 100644 index 0000000000000000000000000000000000000000..29cf89c3a3f56eef1d4128c52067175078588592 GIT binary patch literal 16831 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 pgV + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + Open Transport Tycoon + CFBundleExecutable + ttd + CFBundleGetInfoString + $VERSION, Copyright 2004 The Open Transport Tycoon team + CFBundleIconFile + ttd.icns + CFBundleIdentifier + org.ludde-ottd.ludde-ottd + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ottd + CFBundlePackageType + APPL + CFBundleShortVersionString + $VERSION + CFBundleVersion + $VERSION + NSHumanReadableCopyright + Copyright 2004 The Open Transport Tycoon team + NSPrincipalClass + NSApplication + +" > "$1"/contents/Info.plist diff --git a/os/macos/track_starter b/os/macos/track_starter new file mode 100644 --- /dev/null +++ b/os/macos/track_starter @@ -0,0 +1,2 @@ +#!/bin/bash +exec /usr/bin/java -cp OpenTTD.app/contents/macos OpenTTDMidi "$1" diff --git a/os/macos/ttd.icns b/os/macos/ttd.icns new file mode 100644 index 0000000000000000000000000000000000000000..676840df9e28912f42e8fe8209a068562c85f8e6 GIT binary patch literal 41855 zc%1CKcR-WZ_dk9~@+2e>rfd+|Ae*rF-h>g702%DPrz|y-jk1@3ii)7tRadKZuWDOu z>#BQHYqid5YwLKv_er$1{k-kF@4tTk{6c~I-19o;+H>4J3msJC>YH?w9wHW{) z5Oen08D>SN;<0k0OL@axUuSMdAI;)e?R6$Jl{URX_YftcqKpg<;f0$l$Pp$#Ae z@tLy=^;-auP_uJpAyA;Iz#ncAOTa2Xm=_jeuHOofSYtgM(+)To0GetR39SI1dAK8?0}#wQ zPi!`92l%-rX@f0*q_$K`T@%C+S^z;y832kDD9!V<^>Vec_6oOlQW64+o{g`qot~w= zou7>uDCj{8C@86I2GC^LIUN9>_sQ-;Xfv*0v7jIb3d~E9)HL+?IY|IHWwB#N-GU0c zx(sM2Mt#4vK?G0K)4zZ%0Dg?Z#s!sbYMNH*^^JuLK}xyXvWPa`L#$Bo><) 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 + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with 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. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/os/win32/installer/install.nsi b/os/win32/installer/install.nsi new file mode 100644 --- /dev/null +++ b/os/win32/installer/install.nsi @@ -0,0 +1,341 @@ +; Define your application name +!define APPNAME "OpenTTD" +!define APPNAMEANDVERSION "OpenTTD 0.3.2.1" +!define APPVERSION "0.3.2.1" +!define INSTALLERVERSION 11 + +BrandingText "OpenTTD Installer" + + +; Version Info +Var AddWinPrePopulate +VIProductVersion "0.3.2.1" +VIAddVersionKey "ProductName" "OpenTTD Installer" +VIAddVersionKey "Comments" "Installs ${APPNAMEANDVERSION}" +VIAddVersionKey "CompanyName" "OpenTTD Developers" +VIAddVersionKey "FileDescription" "Installs ${APPNAMEANDVERSION}" +VIAddVersionKey "ProductVersion" "${APPVERSION}" +VIAddVersionKey "InternalName" "InstOpenTTD" +VIAddVersionKey "FileVersion" "${APPVERSION}" +VIAddVersionKey "LegalCopyright" " " +; Main Install settings +Name "${APPNAMEANDVERSION}" + +; NOTE: Keep trailing backslash! +InstallDir "$PROGRAMFILES\OpenTTD\" +InstallDirRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" +OutFile "openttd-${APPVERSION}.exe" + +ShowInstDetails show +ShowUninstDetails show +SetCompressor LZMA + +Var SHORTCUTS +Var CDDRIVE + +; Modern interface settings +!include "MUI.nsh" + +!define MUI_ABORTWARNING + +!insertmacro MUI_PAGE_WELCOME +LicenseForceSelection radiobuttons "I &accept this Agreement" "I &do not accept this agreement" + +!insertmacro MUI_PAGE_LICENSE "gpl.txt" + +;-------------------------------- +; Rest of pages +!insertmacro MUI_PAGE_COMPONENTS + + +;-------------------------------- +; New custom page for finding CD +Page custom SelectCD SelectCD2 ": TTD folder" + +!insertmacro MUI_PAGE_DIRECTORY + +;Start Menu Folder Page Configuration +!define MUI_STARTMENUPAGE_DEFAULTFOLDER $SHORTCUTS +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKEY_LOCAL_MACHINE" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Shortcut Folder" + +!insertmacro MUI_PAGE_STARTMENU "OpenTTD" $SHORTCUTS + +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_RUN "$INSTDIR\openttd.exe" +!define MUI_FINISHPAGE_LINK "Visit OpenTTD's homepage" +!define MUI_FINISHPAGE_LINK_LOCATION "http://www.openttd.com/" +!define MUI_FINISHPAGE_NOREBOOTSUPPORT +!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt" + +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +; Set languages (first is default language) +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_RESERVEFILE_LANGDLL + +;-------------------------------- +; Sections +Section "!OpenTTD" Section1 + + ; Set Section properties + SetOverwrite try + + ; Make savegame folder + SetOutPath "$INSTDIR\save" + ; define root variable relative to installer + !define PATH_ROOT "..\..\..\" + + ; Copy language files + SetOutPath "$INSTDIR\lang\" + File ${PATH_ROOT}lang\*.lng + File ${PATH_ROOT}lang\english.txt + + ; Copy data files + SetOutPath "$INSTDIR\data\" + File ${PATH_ROOT}data\opntitle.dat + File ${PATH_ROOT}data\signalsw.grf + File ${PATH_ROOT}data\openttd.grf + File ${PATH_ROOT}data\canalsw.grf + File ${PATH_ROOT}ReleasePNG\ttd.map + + ; Copy the rest of the stuff + SetOutPath "$INSTDIR\" + + ;Copy text files + File ${PATH_ROOT}changelog.txt +; File "gpl.txt" + File ${PATH_ROOT}readme.txt + + ; Copy executable + File /oname=openttd.exe ${PATH_ROOT}ReleasePNG\ttd.exe + File ${PATH_ROOT}strgen\Release\strgen.exe + + + ; Delete old files from the main dir. they are now placed in data/ and lang/ + Delete "$INSTDIR\*.lng" + Delete "$INSTDIR\*.grf" + Delete "$INSTDIR\sample.cat" + Delete "$INSTDIR\ttd.exe" + + + ;Creates the Registry Entries + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Comments" "Visit http://www.openttd.com" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayIcon" "$INSTDIR\setup.ico" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayName" "OpenTTD ${APPVERSION}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" "${APPVERSION}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "HelpLink" "http://www.openttd.com" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" "$INSTDIR" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Publisher" "OpenTTD" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" "$SHORTCUTS" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" "$INSTDIR\uninstall.exe" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "URLInfoAbout" "http://www.openttd.com" + ;This key sets the Version DWORD that patches will check against + WriteRegDWORD HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" ${INSTALLERVERSION} + + !insertmacro MUI_STARTMENU_WRITE_BEGIN "OpenTTD" + CreateShortCut "$DESKTOP\OpenTTD.lnk" "$INSTDIR\openttd.exe" + CreateDirectory "$SMPROGRAMS\$SHORTCUTS" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" "$INSTDIR\openttd.exe" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" "$INSTDIR\uninstall.exe" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" "$INSTDIR\Readme.txt" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" "$INSTDIR\Changelog.txt" + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd + +Section "Copy Game Graphics" Section2 + ; Include files from CD + ;Let's copy the files from the CD + SetOutPath "$INSTDIR\gm" + CopyFiles "$CDDRIVE\gm\*.gm" "$INSTDIR\gm\" + SetOutPath "$INSTDIR\data\" + CopyFiles "$CDDRIVE\sample.cat" "$INSTDIR\data\sample.cat" 1566 + CopyFiles "$CDDRIVE\trg1r.grf" "$INSTDIR\data\trg1r.grf" 2365 + CopyFiles "$CDDRIVE\trgcr.grf" "$INSTDIR\data\trgcr.grf" 260 + CopyFiles "$CDDRIVE\trghr.grf" "$INSTDIR\data\trghr.grf" 400 + CopyFiles "$CDDRIVE\trgir.grf" "$INSTDIR\data\trgir.grf" 334 + CopyFiles "$CDDRIVE\trgtr.grf" "$INSTDIR\data\trgtr.grf" 546 + SetOutPath "$INSTDIR\" +SectionEnd + +;---------------------- +Section -FinishSection + WriteUninstaller "$INSTDIR\uninstall.exe" +SectionEnd + +; Modern install component descriptions +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${Section1} "OpenTTD is a fully functional clone of TTD and is very playable." + !insertmacro MUI_DESCRIPTION_TEXT ${Section2} "Copies the game graphics. Requires TTD for Windows." +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;!undef SHORTCUTS +;Uninstall section + +Section Uninstall + MessageBox MB_YESNOCANCEL|MB_ICONQUESTION "Would you like to remove the Saved Game Folder located at '$INSTDIR\Save?' If you choose Yes, your Saved Games will be removed." IDYES RemoveSavedGames IDNO NoRemoveSavedGames + RemoveSavedGames: + Delete "$INSTDIR\Save\*.*" + Delete "$INSTDIR\AutoSave\*.*" + RMDir "$INSTDIR\Save" + RMDir "$INSTDIR\AutoSave" + NoRemoveSavedGames: + + ;Remove from registry... + !insertmacro MUI_STARTMENU_GETFOLDER "OpenTTD" $SHORTCUTS + ReadRegStr $SHORTCUTS HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" + + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" + + ; Delete self + Delete "$INSTDIR\uninstall.exe" + + ; Delete Shortcuts + Delete "$DESKTOP\OpenTTD.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" + + ; Clean up OpenTTD dir + Delete "$INSTDIR\changelog.txt" + Delete "$INSTDIR\readme.txt" + Delete "$INSTDIR\openttd.exe" + Delete "$INSTDIR\strgen.exe" + Delete "$INSTDIR\data\ttd.map" + Delete "$INSTDIR\gpl.txt" + Delete "$INSTDIR\INSTALL.LOG" + Delete "$INSTDIR\crash.log" + Delete "$INSTDIR\openttd.cfg" + + ; Data files + Delete "$INSTDIR\data\opntitle.dat" + Delete "$INSTDIR\data\signalsw.grf" + Delete "$INSTDIR\data\openttd.grf" + Delete "$INSTDIR\data\canalsw.grf" + Delete "$INSTDIR\data\trg1r.grf" + Delete "$INSTDIR\data\trghr.grf" + Delete "$INSTDIR\data\trgtr.grf" + Delete "$INSTDIR\data\sample.cat" + Delete "$INSTDIR\data\trgcr.grf" + Delete "$INSTDIR\data\trgir.grf" + + ;Music + Delete "$INSTDIR\gm\*.gm" + + ;Language files + Delete "$INSTDIR\lang\*.lng" + Delete "$INSTDIR\lang\english.txt" + + ; Remove remaining directories + RMDir "$SMPROGRAMS\$SHORTCUTS\Extras\" + RMDir "$SMPROGRAMS\$SHORTCUTS" + RMDir "$INSTDIR\gm" + RMDir "$INSTDIR\lang" + RMDir "$INSTDIR\data" + RMDir "$INSTDIR" +SectionEnd + +Function SelectCD + SectionGetFlags ${Section2} $0 + IntOp $0 $0 & 1 + IntCmp $0 1 NoAbort + Abort +NoAbort: + + GetTempFileName $R0 + !insertmacro MUI_HEADER_TEXT "Locate TTD" "Setup needs the location of Transport Tycoon Deluxe in order to continue." + File /oname=$R0 CDFinder.ini + ClearErrors + ;Now, let's populate $CDDRIVE + ReadRegStr $CDDRIVE HKLM "SOFTWARE\Fish Technology Group\Transport Tycoon Deluxe" "HDPath" + IfErrors NoTTD + StrCpy $AddWinPrePopulate "Setup has detected your TTD folder. Don't change the folder. Simply press Next." + Goto TruFinish +NoTTD: + StrCpy $CDDRIVE "" + StrCpy $AddWinPrePopulate "Setup couldn't find TTD. Please enter the path where the graphics files from TTD for Windows are stored and press Next to continue." +TruFinish: + ClearErrors + WriteINIStr $R0 "Field 2" "State" $CDDRIVE + WriteINIStr $R0 "Field 3" "Text" $AddWinPrePopulate + + InstallOptions::dialog $R0 + Pop $R1 +FunctionEnd + +; Exit from page function +Function SelectCD2 + ReadINIStr $CDDRIVE $R0 "Field 2" "State" + IfFileExists $CDDRIVE\trg1r.grf "" NoCD + IfFileExists $CDDRIVE\sample.cat "" NoCD + IfFileExists $CDDRIVE\trgir.grf hasCD "" +NoCD: + MessageBox MB_OK "Setup cannot continue without the Transport Tycoon Deluxe Location!" + Abort +hasCD: +FunctionEnd + + +Var OLDVERSION +Var UninstallString + +Function .onInit + StrCpy $SHORTCUTS "OpenTTD" + + SectionSetFlags 0 17 + + ;Want to have a splash BMP? Uncomment these lines - CAREFUL WITH FILE SIZE + +; # the plugins dir is automatically deleted when the installer exits +; InitPluginsDir +; File /oname=$PLUGINSDIR\splash.bmp "C:\Documents and Settings\Administrator\My Documents\My Pictures\OpenTTD Splash.bmp" +; #optional +; #File /oname=$PLUGINSDIR\splash.wav "C:\myprog\sound.wav" +; +; ;MessageBox MB_OK "Fading" +; +; advsplash::show 3000 600 400 -1 $PLUGINSDIR\splash +; +; Pop $0 ; $0 has '1' if the user closed the splash screen early, +; ; '0' if everything closed normal, and '-1' if some error occured. +;End Splash Area + ;Starts Setup - let's look for an older version of OpenTTD + ReadRegDWORD $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" + + IfErrors ShowWelcomeMessage ShowUpgradeMessage +ShowWelcomeMessage: + ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" + ;In the event someone still has OpenTTD 0.1, this will detect that (that installer used a string instead of dword entry) + IfErrors FinishCallback + +ShowUpgradeMessage: + IntCmp ${INSTALLERVERSION} $R8 VersionsAreEqual InstallerIsOlder WelcomeToSetup +WelcomeToSetup: + ;An older version was found. Let's let the user know there's an upgrade that will take plce. + ReadRegStr $OLDVERSION HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" + ;Gets the older version then displays it in a message box + MessageBox MB_OK|MB_ICONINFORMATION "Welcome to ${APPNAMEANDVERSION} Setup.$\n$\nThis will allow you to upgrade from version $OLDVERSION." + Goto FinishCallback + +VersionsAreEqual: + ReadRegStr $UninstallString HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" + IfFileExists "$UninstallString" "" FinishCallback + MessageBox MB_YESNO|MB_ICONQUESTION "Setup detected ${APPNAMEANDVERSION} on your system. That's the version this program will install.$\n$\nAre you trying to uninstall it?" IDYES DoUninstall IDNO FinishCallback +DoUninstall: ;You have the same version as this installer. This allows you to uninstall. + Exec "$UninstallString" + Quit + +InstallerIsOlder: + MessageBox MB_OK|MB_ICONSTOP "You have a newer version of ${APPNAME}.$\n$\nSetup will now exit." + Quit + +FinishCallback: + ClearErrors +FunctionEnd +; eof + diff --git a/pathfind.c b/pathfind.c new file mode 100644 --- /dev/null +++ b/pathfind.c @@ -0,0 +1,722 @@ +#include "stdafx.h" +#include "ttd.h" +#include "pathfind.h" + +// remember which tiles we have already visited so we don't visit them again. +static bool TPFSetTileBit(TrackPathFinder *tpf, uint tile, int dir) +{ + uint hash, val, offs; + TrackPathFinderLink *link, *new_link; + uint bits = 1 << dir; + + if (tpf->disable_tile_hash) + return true; + + hash = PATHFIND_HASH_TILE(tile); + + val = tpf->hash_head[hash]; + + if (val == 0) { + /* unused hash entry, set the appropriate bit in it and return true + * to indicate that a bit was set. */ + tpf->hash_head[hash] = bits; + tpf->hash_tile[hash] = (TileIndex)tile; + return true; + } else if (!(val & 0x8000)) { + /* single tile */ + + if ( (TileIndex)tile == tpf->hash_tile[hash] ) { + /* found another bit for the same tile, + * check if this bit is already set, if so, return false */ + if (val & bits) + return false; + + /* otherwise set the bit and return true to indicate that the bit + * was set */ + tpf->hash_head[hash] = val | bits; + return true; + } else { + /* two tiles with the same hash, need to make a link */ + + /* allocate a link. if out of links, handle this by returning + * that a tile was already visisted. */ + if (tpf->num_links_left == 0) + return false; + tpf->num_links_left--; + link = tpf->new_link++; + + /* move the data that was previously in the hash_??? variables + * to the link struct, and let the hash variables point to the link */ + link->tile = tpf->hash_tile[hash]; + tpf->hash_tile[hash] = PATHFIND_GET_LINK_OFFS(tpf, link); + + link->flags = tpf->hash_head[hash]; + tpf->hash_head[hash] = 0xFFFF; /* multi link */ + + link->next = 0xFFFF; + } + } else { + /* a linked list of many tiles, + * find the one corresponding to the tile, if it exists. + * otherwise make a new link */ + + offs = tpf->hash_tile[hash]; + do { + link = PATHFIND_GET_LINK_PTR(tpf, offs); + if ( (TileIndex)tile == link->tile) { + /* found the tile in the link list, + * check if the bit was alrady set, if so return false to indicate that the + * bit was already set */ + if (link->flags & bits) + return false; + link->flags |= bits; + return true; + } + } while ((offs=link->next) != 0xFFFF); + } + + /* get here if we need to add a new link to link, + * first, allocate a new link, in the same way as before */ + if (tpf->num_links_left == 0) + return false; + tpf->num_links_left--; + new_link = tpf->new_link++; + + /* then fill the link with the new info, and establish a ptr from the old + * link to the new one */ + new_link->tile = (TileIndex)tile; + new_link->flags = bits; + new_link->next = 0xFFFF; + + link->next = PATHFIND_GET_LINK_OFFS(tpf, new_link); + return true; +} + +static const byte _bits_mask[4] = { + 0x19, + 0x16, + 0x25, + 0x2A, +}; + +static const byte _tpf_new_direction[14] = { + 0,1,0,1,2,1, 0,0, + 2,3,3,2,3,0, +}; + +static const byte _tpf_prev_direction[14] = { + 0,1,1,0,1,2, 0,0, + 2,3,2,3,0,3, +}; + + +static const byte _otherdir_mask[4] = { + 0x10, + 0, + 0x5, + 0x2A, +}; + +#ifdef DEBUG_TILE_PUSH +extern void dbg_push_tile(uint tile, int track); +extern void dbg_pop_tile(); +#endif + +void TPFMode2(TrackPathFinder *tpf, uint tile, int direction) +{ + uint bits; + int i; + RememberData rd; + + // This addition will sometimes overflow by a single tile. + // The use of TILE_MASK here makes sure that we still point at a valid + // tile, and then this tile will be in the sentinel row/col, so GetTileTrackStatus will fail. + tile = TILE_MASK(tile + _tileoffs_by_dir[direction]); + + if (++tpf->rd.cur_length > 50) + return; + + bits = GetTileTrackStatus(tile, tpf->tracktype); + bits = (byte)((bits | (bits >> 8)) & _bits_mask[direction]); + if (bits == 0) + return; + + assert(GET_TILE_X(tile) != 255 && GET_TILE_Y(tile) != 255); + + if ( (bits & (bits - 1)) == 0 ) { + /* only one direction */ + i = 0; + while (!(bits&1)) + i++, bits>>=1; + + rd = tpf->rd; + goto continue_here; + } + /* several directions */ + i=0; + do { + if (!(bits & 1)) continue; + rd = tpf->rd; + + // Change direction 4 times only + if ((byte)i != tpf->rd.pft_var6) { + if(++tpf->rd.depth > 4) { + tpf->rd = rd; + return; + } + tpf->rd.pft_var6 = (byte)i; + } + +continue_here:; + tpf->the_dir = HASBIT(_otherdir_mask[direction],i) ? (i+8) : i; + +#ifdef DEBUG_TILE_PUSH + dbg_push_tile(tile, tpf->the_dir); +#endif + if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, NULL)) { + TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]); + } +#ifdef DEBUG_TILE_PUSH + dbg_pop_tile(); +#endif + + tpf->rd = rd; + } while (++i, bits>>=1); + +} + +static const int8 _get_tunlen_inc[5] = { -16, 0, 16, 0, -16 }; + +FindLengthOfTunnelResult FindLengthOfTunnel(uint tile, int direction, byte type) +{ + FindLengthOfTunnelResult flotr; + int x,y; + byte z; + + flotr.length = 0; + + x = GET_TILE_X(tile) * 16; + y = GET_TILE_Y(tile) * 16; + + z = GetSlopeZ(x+8, y+8); + + for(;;) { + flotr.length++; + + x += _get_tunlen_inc[direction]; + y += _get_tunlen_inc[direction+1]; + + tile = TILE_FROM_XY(x,y); + + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && + (_map5[tile] & 0xF0) == 0 && + ((_map5[tile]>>1)&6) == type && + ((_map5[tile] & 3)^2) == direction && + GetSlopeZ(x+8, y+8) == z) + break; + } + + flotr.tile = tile; + return flotr; +} + +static const uint16 _tpfmode1_and[4] = { 0x1009, 0x16, 0x520, 0x2A00 }; + +static uint SkipToEndOfTunnel(TrackPathFinder *tpf, uint tile, int direction) { + FindLengthOfTunnelResult flotr; + TPFSetTileBit(tpf, tile, 14); + flotr = FindLengthOfTunnel(tile, direction, tpf->tracktype); + tpf->rd.cur_length += flotr.length; + TPFSetTileBit(tpf, flotr.tile, 14); + return flotr.tile; +} + +const byte _ffb_64[128] = { +0,0,1,0,2,0,1,0, +3,0,1,0,2,0,1,0, +4,0,1,0,2,0,1,0, +3,0,1,0,2,0,1,0, +5,0,1,0,2,0,1,0, +3,0,1,0,2,0,1,0, +4,0,1,0,2,0,1,0, +3,0,1,0,2,0,1,0, + +0,0,0,2,0,4,4,6, +0,8,8,10,8,12,12,14, +0,16,16,18,16,20,20,22, +16,24,24,26,24,28,28,30, +0,32,32,34,32,36,36,38, +32,40,40,42,40,44,44,46, +32,48,48,50,48,52,52,54, +48,56,56,58,56,60,60,62, +}; + +void TPFMode1(TrackPathFinder *tpf, uint tile, int direction) +{ + uint bits; + int i; + RememberData rd; + uint tile_org = tile; + + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile] & 0xF0)==0) { + if ((_map5[tile] & 3) != direction || ((_map5[tile]>>1)&6) != tpf->tracktype) + return; + tile = SkipToEndOfTunnel(tpf, tile, direction); + } + tile += _tileoffs_by_dir[direction]; + tpf->rd.cur_length++; + + bits = GetTileTrackStatus(tile, tpf->tracktype); + + if ((byte)bits != tpf->var2) { + bits &= _tpfmode1_and[direction]; + bits = bits | (bits>>8); + } + bits &= 0xBF; + + if (bits != 0) { + if (!tpf->disable_tile_hash || (tpf->rd.cur_length <= 64 && (KILL_FIRST_BIT(bits) == 0 || ++tpf->rd.depth <= 7))) { + do { + i = FIND_FIRST_BIT(bits); + bits = KILL_FIRST_BIT(bits); + + tpf->the_dir = (_otherdir_mask[direction] & (byte)(1 << i)) ? (i+8) : i; + rd = tpf->rd; + +#ifdef DEBUG_TILE_PUSH + dbg_push_tile(tile, tpf->the_dir); +#endif + if (TPFSetTileBit(tpf, tile, tpf->the_dir) && + !tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, &tpf->rd.pft_var6) ) { + TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]); + } +#ifdef DEBUG_TILE_PUSH + dbg_pop_tile(); +#endif + tpf->rd = rd; + } while (bits != 0); + } + } + + /* the next is only used when signals are checked. + * seems to go in 2 directions simultaneously */ + + /* if i can get rid of this, tail end recursion can be used to minimize + * stack space dramatically. */ + if (tpf->hasbit_13) + return; + + tile = tile_org; + direction ^= 2; + + bits = GetTileTrackStatus(tile, tpf->tracktype); + bits |= (bits >> 8); + + if ( (byte)bits != tpf->var2) { + bits &= _bits_mask[direction]; + } + + bits &= 0xBF; + if (bits == 0) + return; + + do { + i = FIND_FIRST_BIT(bits); + bits = KILL_FIRST_BIT(bits); + + tpf->the_dir = (_otherdir_mask[direction] & (byte)(1 << i)) ? (i+8) : i; + rd = tpf->rd; + if (TPFSetTileBit(tpf, tile, tpf->the_dir) && + !tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length, &tpf->rd.pft_var6) ) { + TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]); + } + tpf->rd = rd; + } while (bits != 0); +} + +void FollowTrack(uint tile, uint16 flags, byte direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data) +{ + TrackPathFinder *tpf = alloca(sizeof(TrackPathFinder)); + + assert(direction < 4); + + /* initialize path finder variables */ + tpf->userdata = data; + tpf->enum_proc = enum_proc; + tpf->new_link = tpf->links; + tpf->num_links_left = 0x400; + + tpf->rd.cur_length = 0; + tpf->rd.depth = 0; + tpf->rd.pft_var6 = 0; + + tpf->var2 = HASBIT(flags, 15) ? 0x43 : 0xFF; /* 0x8000 */ + + tpf->disable_tile_hash = HASBIT(flags, 12) != 0; /* 0x1000 */ + tpf->hasbit_13 = HASBIT(flags, 13) != 0; /* 0x2000 */ + + + tpf->tracktype = (byte)flags; + + if (HASBIT(flags, 11)) { + tpf->rd.pft_var6 = 0xFF; + tpf->enum_proc(tile, data, 0, 0, 0); + TPFMode2(tpf, tile, direction); + } else { + /* clear the hash_heads */ + memset(tpf->hash_head, 0, sizeof(tpf->hash_head)); + TPFMode1(tpf, tile, direction); + } + + if (after_proc != NULL) + after_proc(tpf); +} + +typedef struct { + TileIndex tile; + uint16 cur_length; + byte track; + byte depth; + byte state; + byte first_track; +} StackedItem; + +static const byte _new_dir[6][4] = { +{0,0xff,2,0xff,}, +{0xff,1,0xff,3,}, +{0xff,0,3,0xff,}, +{1,0xff,0xff,2,}, +{3,2,0xff,0xff,}, +{0xff,0xff,1,0,}, +}; + +static const byte _new_track[6][4] = { +{0,0xff,8,0xff,}, +{0xff,1,0xff,9,}, +{0xff,2,10,0xff,}, +{3,0xff,0xff,11,}, +{12,4,0xff,0xff,}, +{0xff,0xff,5,13,}, +}; + +typedef struct HashLink { + TileIndex tile; + uint16 typelength; + uint16 next; +} HashLink; + +typedef struct { + TPFEnumProc *enum_proc; + void *userdata; + + byte tracktype; + uint maxlength; + + HashLink *new_link; + uint num_links_left; + + int nstack; + StackedItem stack[256]; // priority queue of stacked items + + uint16 hash_head[0x400]; // hash heads. 0 means unused. 0xFFC0 = length, 0x3F = type + TileIndex hash_tile[0x400]; // tiles. or links. + + HashLink links[0x400]; // hash links + +} NewTrackPathFinder; +#define NTP_GET_LINK_OFFS(tpf, link) ((byte*)(link) - (byte*)tpf->links) +#define NTP_GET_LINK_PTR(tpf, link_offs) (HashLink*)((byte*)tpf->links + (link_offs)) + +#define ARR(i) tpf->stack[(i)-1] + +// called after a new element was added in the queue at the last index. +// move it down to the proper position +static void INLINE HeapifyUp(NewTrackPathFinder *tpf) +{ + StackedItem si; + int i = ++tpf->nstack; + + while (i != 1 && ARR(i).cur_length < ARR(i>>1).cur_length) { + // the child element is larger than the parent item. + // swap the child item and the parent item. + si = ARR(i); ARR(i) = ARR(i>>1); ARR(i>>1) = si; + i>>=1; + } +} + +// called after the element 0 was eaten. fill it with a new element +static void INLINE HeapifyDown(NewTrackPathFinder *tpf) +{ + StackedItem si; + int i = 1, j; + int n = --tpf->nstack; + + if (n == 0) return; // heap is empty so nothing to do? + + // copy the last item to index 0. we use it as base for heapify. + ARR(1) = ARR(n+1); + + while ((j=i*2) <= n) { + // figure out which is smaller of the children. + if (j != n && ARR(j).cur_length > ARR(j+1).cur_length) + j++; // right item is smaller + + assert(i <= n && j <= n); + if (ARR(i).cur_length <= ARR(j).cur_length) + break; // base elem smaller than smallest, done! + + // swap parent with the child + si = ARR(i); ARR(i) = ARR(j); ARR(j) = si; + i = j; + } +} + +// mark a tile as visited and store the length of the path. +// if we already had a better path to this tile, return false. +// otherwise return true. +static bool NtpVisit(NewTrackPathFinder *tpf, uint tile, uint dir, uint length) +{ + uint hash,head; + HashLink *link, *new_link; + + assert(length < 1024); + + hash = PATHFIND_HASH_TILE(tile); + + // never visited before? + if ((head=tpf->hash_head[hash]) == 0) { + tpf->hash_tile[hash] = tile; + tpf->hash_head[hash] = dir | (length << 2); + return true; + } + + if (head != 0xffff) { + if ( (TileIndex)tile == tpf->hash_tile[hash] && (head & 0x3) == dir ) { + + // longer length + if (length >= (head >> 2)) return false; + + tpf->hash_head[hash] = dir | (length << 2); + return true; + } + // two tiles with the same hash, need to make a link + // allocate a link. if out of links, handle this by returning + // that a tile was already visisted. + if (tpf->num_links_left == 0) + return false; + tpf->num_links_left--; + link = tpf->new_link++; + + /* move the data that was previously in the hash_??? variables + * to the link struct, and let the hash variables point to the link */ + link->tile = tpf->hash_tile[hash]; + tpf->hash_tile[hash] = NTP_GET_LINK_OFFS(tpf, link); + + link->typelength = tpf->hash_head[hash]; + tpf->hash_head[hash] = 0xFFFF; /* multi link */ + link->next = 0xFFFF; + } else { + // a linked list of many tiles, + // find the one corresponding to the tile, if it exists. + // otherwise make a new link + + uint offs = tpf->hash_tile[hash]; + do { + link = NTP_GET_LINK_PTR(tpf, offs); + if ( (TileIndex)tile == link->tile && (uint)(link->typelength & 0x3) == dir) { + if (length >= (uint)(link->typelength >> 2)) return false; + link->typelength = dir | (length << 2); + return true; + } + } while ((offs=link->next) != 0xFFFF); + } + + /* get here if we need to add a new link to link, + * first, allocate a new link, in the same way as before */ + if (tpf->num_links_left == 0) + return false; + tpf->num_links_left--; + new_link = tpf->new_link++; + + /* then fill the link with the new info, and establish a ptr from the old + * link to the new one */ + new_link->tile = (TileIndex)tile; + new_link->typelength = dir | (length << 2); + new_link->next = 0xFFFF; + + link->next = NTP_GET_LINK_OFFS(tpf, new_link); + return true; +} + +static bool NtpCheck(NewTrackPathFinder *tpf, uint tile, uint dir, uint length) +{ + uint hash,head,offs; + HashLink *link; + + hash = PATHFIND_HASH_TILE(tile); + head=tpf->hash_head[hash]; + assert(head); + + if (head != 0xffff) { + assert( tpf->hash_tile[hash] == tile && (head & 3) == dir); + assert( (head >> 2) <= length); + return length == (head >> 2); + } + + // else it's a linked list of many tiles + offs = tpf->hash_tile[hash]; + for(;;) { + link = NTP_GET_LINK_PTR(tpf, offs); + if ( (TileIndex)tile == link->tile && (uint)(link->typelength & 0x3) == dir) { + assert( (uint)(link->typelength >> 2) <= length); + return length == (uint)(link->typelength >> 2); + } + offs = link->next; + assert(offs != 0xffff); + } +} + + +// new more optimized pathfinder for trains... +void NTPEnum(NewTrackPathFinder *tpf, uint tile, uint direction) +{ + uint bits, tile_org; + int i; + StackedItem si; + FindLengthOfTunnelResult flotr; + + si.cur_length = 0; + si.depth = 0; + si.state = 0; + +restart: + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile] & 0xF0)==0) { + if ( (uint)(_map5[tile] & 3) != direction || ((_map5[tile]>>1)&6) != tpf->tracktype) + goto popnext; + flotr = FindLengthOfTunnel(tile, direction, tpf->tracktype); + si.cur_length += flotr.length; + tile = flotr.tile; + } + + // remember the start tile so we know if we're in an inf loop. + tile_org = tile; + + for(;;) { + tile += _tileoffs_by_dir[direction]; + + // too long search length? bail out. + if (++si.cur_length >= tpf->maxlength) + goto popnext; + + // not a regular rail tile? + if (!IS_TILETYPE(tile, MP_RAILWAY) || (bits = _map5[tile]) & 0xC0) { + bits = GetTileTrackStatus(tile, 0) & _tpfmode1_and[direction]; + bits = (bits | (bits >> 8)) & 0x3F; + break; + } + + // regular rail tile, determine the tracks that are actually reachable. + bits &= _bits_mask[direction]; + if (bits == 0) goto popnext; // no tracks there? stop searching. + + // complex tile?, let the generic handler handle that.. + if (KILL_FIRST_BIT(bits) != 0) break; + + // don't bother calling the callback when we have regular tracks only. + // it's usually not needed anyway. that will speed up things. + direction = _new_dir[FIND_FIRST_BIT(bits)][direction]; + assert(direction != 0xFF); + if (tile == tile_org) goto popnext; // detect infinite loop.. + } + + if (!bits) goto popnext; + + // if only one reachable track, use tail recursion optimization. + if (KILL_FIRST_BIT(bits) == 0) { + i = _new_track[FIND_FIRST_BIT(bits)][direction]; + // call the callback + if (tpf->enum_proc(tile, tpf->userdata, i, si.cur_length, &si.state)) + goto popnext; // we should stop searching in this direction. + + // we should continue searching. determine new direction. + direction = _tpf_new_direction[i]; + goto restart; // use tail recursion optimization. + } + + // too high recursion depth.. bail out.. + if (si.depth >= _patches.pf_maxdepth) + goto popnext; + + si.depth++; // increase recursion depth. + + // see if this tile was already visited..? + if (NtpVisit(tpf, tile, direction, si.cur_length)) { + // push all possible alternatives + si.tile = tile; + do { + si.track = _new_track[FIND_FIRST_BIT(bits)][direction]; + + // out of stack items, bail out? + if (tpf->nstack >= lengthof(tpf->stack)) + break; + tpf->stack[tpf->nstack] = si; + HeapifyUp(tpf); + } while ((bits = KILL_FIRST_BIT(bits)) != 0); + + // if this is the first recursion step, we need to fill the first_track member. + // so the code outside knows which path is better. + // also randomize the order in which we search through them. + if (si.depth == 1) { + uint32 r = Random(); + assert(tpf->nstack == 2 || tpf->nstack == 3); + if (r&1) swap_byte(&tpf->stack[0].track, &tpf->stack[1].track); + if (tpf->nstack != 2) { + byte t = tpf->stack[2].track; + if (r&2) swap_byte(&tpf->stack[0].track, &t); + if (r&4) swap_byte(&tpf->stack[1].track, &t); + tpf->stack[2].first_track = tpf->stack[2].track = t; + } + tpf->stack[0].first_track = tpf->stack[0].track; + tpf->stack[1].first_track = tpf->stack[1].track; + } + } + +popnext: + // where to continue. + do { + if (tpf->nstack == 0) return; // nothing left? + si = tpf->stack[0]; + tile = si.tile; + HeapifyDown(tpf); + } while ( + !NtpCheck(tpf, tile, _tpf_prev_direction[si.track], si.cur_length) || // already have better path to that tile? + tpf->enum_proc(tile, tpf->userdata, si.track, si.cur_length, &si.state) + ); + + direction = _tpf_new_direction[si.track]; + goto restart; +} + + +// new pathfinder for trains. better and faster. +void NewTrainPathfind(uint tile, byte direction, TPFEnumProc *enum_proc, void *data, byte *cache) +{ + if (!_patches.new_pathfinding) { + FollowTrack(tile, 0x3000, direction, enum_proc, NULL, data); + } else { + NewTrackPathFinder *tpf; + + tpf = alloca(sizeof(NewTrackPathFinder)); + tpf->userdata = data; + tpf->enum_proc = enum_proc; + tpf->tracktype = 0; + tpf->maxlength = _patches.pf_maxlength; + tpf->nstack = 0; + tpf->new_link = tpf->links; + tpf->num_links_left = 0x400; + memset(tpf->hash_head, 0, sizeof(tpf->hash_head)); + + NTPEnum(tpf, tile, direction); + } +} + diff --git a/pathfind.h b/pathfind.h new file mode 100644 --- /dev/null +++ b/pathfind.h @@ -0,0 +1,65 @@ +#ifndef PATHFIND_H +#define PATHFIND_H + +typedef struct TrackPathFinder TrackPathFinder; +typedef bool TPFEnumProc(uint tile, void *data, int track, uint length, byte *state); +typedef void TPFAfterProc(TrackPathFinder *tpf); + + +#define PATHFIND_GET_LINK_OFFS(tpf, link) ((byte*)(link) - (byte*)tpf->links) +#define PATHFIND_GET_LINK_PTR(tpf, link_offs) (TrackPathFinderLink*)((byte*)tpf->links + (link_offs)) + +/* y7 y6 y5 y4 y3 y2 y1 y0 x7 x6 x5 x4 x3 x2 x1 x0 + * y7 y6 y5 y4 y3 y2 y1 y0 x4 x3 x2 x1 x0 0 0 0 + * 0 0 y7 y6 y5 y4 y3 y2 y1 y0 x4 x3 x2 x1 x0 0 + * 0 0 0 0 y5 y4 y3 y2 y1 y0 x4 x3 x2 x1 x0 0 + */ +#define PATHFIND_HASH_TILE(tile) (GET_TILE_X(tile) & 0x1F) + ((GET_TILE_Y(tile)&0x1F)<<5) + +typedef struct TrackPathFinderLink { + TileIndex tile; + uint16 flags; + uint16 next; +} TrackPathFinderLink; + +typedef struct RememberData { + uint16 cur_length; + byte depth; + byte pft_var6; +} RememberData; + +struct TrackPathFinder { + + int num_links_left; + TrackPathFinderLink *new_link; + + TPFEnumProc *enum_proc; + + void *userdata; + + RememberData rd; + + int the_dir; + + byte tracktype; + byte var2; + bool disable_tile_hash; + bool hasbit_13; + + uint16 hash_head[0x400]; + TileIndex hash_tile[0x400]; /* stores the link index when multi link. */ + + TrackPathFinderLink links[0x400]; /* hopefully, this is enough. */ +}; + +void FollowTrack(uint tile, uint16 flags, byte direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data); + +typedef struct { + uint tile; + int length; +} FindLengthOfTunnelResult; +FindLengthOfTunnelResult FindLengthOfTunnel(uint tile, int direction, byte type); + +void NewTrainPathfind(uint tile, byte direction, TPFEnumProc *enum_proc, void *data, byte *cache); + +#endif /* PATHFIND_H */ diff --git a/player.h b/player.h new file mode 100644 --- /dev/null +++ b/player.h @@ -0,0 +1,123 @@ +#ifndef PLAYER_H +#define PLAYER_H + +typedef struct PlayerEconomyEntry { + int32 income; + int32 expenses; + int32 delivered_cargo; + int32 performance_history; + int32 company_value; +} PlayerEconomyEntry; + +typedef struct AiBuildRec { + TileIndex spec_tile; + TileIndex use_tile; + byte rand_rng; + byte cur_building_rule; + byte unk6; + byte unk7; + byte buildcmd_a; + byte buildcmd_b; + byte direction; + byte cargo; +} AiBuildRec; + +typedef struct PlayerAI { + byte state; + byte tick; // Used to determine how often to move + uint16 state_counter; + uint16 timeout_counter; + + byte state_mode; + byte banned_tile_count; + byte railtype_to_use; + + byte cargo_type; + byte num_wagons; + byte build_kind; + byte num_build_rec; + byte num_loco_to_build; + byte num_want_fullload; + + byte route_type_mask; + + TileIndex start_tile_a; + TileIndex cur_tile_a; + byte cur_dir_a; + byte start_dir_a; + + TileIndex start_tile_b; + TileIndex cur_tile_b; + byte cur_dir_b; + byte start_dir_b; + + Vehicle *cur_veh; /* only used by some states */ + + AiBuildRec src, dst, mid1, mid2; + + VehicleID wagon_list[9]; + byte order_list_blocks[20]; + + TileIndex banned_tiles[16]; + byte banned_val[16]; +} PlayerAI; + +typedef struct Player { + uint32 name_2; + uint16 name_1; + + uint16 president_name_1; + uint32 president_name_2; + + uint32 face; + + int32 player_money; + int32 current_loan; + int64 money64; // internal 64-bit version of the money. the 32-bit field will be clamped to plus minus 2 billion + + byte player_color; + byte player_money_fraction; + byte max_railtype; + byte block_preview; + byte index; + + uint16 cargo_types; /* which cargo types were transported the last year */ + + TileIndex location_of_house; + TileIndex last_build_coordinate; + + byte share_owners[4]; + + byte inaugurated_year; + byte num_valid_stat_ent; + + byte quarters_of_bankrupcy; + byte bankrupt_asked; // which players were asked about buying it? + int16 bankrupt_timeout; + int32 bankrupt_value; + + bool is_active; + byte is_ai; + PlayerAI ai; + + int64 yearly_expenses[3][13]; + PlayerEconomyEntry cur_economy; + PlayerEconomyEntry old_economy[24]; +} Player; + +void ChangeOwnershipOfPlayerItems(byte old_player, byte new_player); +void GetNameOfOwner(byte owner, uint tile); +uint32 CalculateCompanyValue(Player *p); +void InvalidatePlayerWindows(Player *p); +void AiDoGameLoop(Player *p); +void UpdatePlayerMoney32(Player *p); +#define DEREF_PLAYER(i) (&_players[i]) +#define FOR_ALL_PLAYERS(p) for(p=_players; p != endof(_players); p++) + +#define MAX_PLAYERS 8 +VARDEF Player _players[MAX_PLAYERS]; + +#define IS_HUMAN_PLAYER(p) (!DEREF_PLAYER((byte)(p))->is_ai) +#define IS_INTERACTIVE_PLAYER(p) (((byte)p) == _local_player) + +#endif /* PLAYER_H */ diff --git a/player_gui.c b/player_gui.c new file mode 100644 --- /dev/null +++ b/player_gui.c @@ -0,0 +1,678 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "player.h" +#include "command.h" +#include "vehicle.h" + +static void DoShowPlayerFinances(int player, bool small); + + +static void DrawPlayerEconomyStats(Player *p, byte mode) +{ + int x,y,i,j,year; + int64 (*tbl)[13], sum,cost; + StringID str; + + if (!(mode & 1)) { + /* draw categories */ + DrawStringCenterUnderline(61, 15, STR_700F_EXPENDITURE_INCOME, 0); + for(i=0; i!=13; i++) + DrawString(2, 27 + i*10, STR_7011_CONSTRUCTION + i, 0); + DrawStringRightAligned(111, 27 + 10*13 + 2, STR_7020_TOTAL, 0); + + /* draw the price columns */ + year = _cur_year - 2; + j = 3; + x = 215; + tbl = p->yearly_expenses + 2; + do { + if (year >= p->inaugurated_year) { + SET_DPARAM16(0, year + 1920); + DrawStringCenterUnderline(x-17, 15, STR_7010, 0); + sum = 0; + for(i=0; i!=13; i++) { + /* draw one row in the price column */ + cost = (*tbl)[i]; + if (cost != 0) { + sum += cost; + + str = STR_701E; + if (cost < 0) { cost = -cost; str++; } + SET_DPARAM64(0, cost); + DrawStringRightAligned(x, 27+i*10, str, 0); + } + } + + str = STR_701E; + if (sum < 0) { sum = -sum; str++; } + SET_DPARAM64(0, sum); + DrawStringRightAligned(x, 27 + 13*10 + 2, str, 0); + + GfxFillRect(x - 75, 27 + 10*13, x, 27 + 10*13, 215); + x += 95; + } + year++; + tbl--; + } while (--j != 0); + + y = 171; + } else { + y = 15; + } + + DrawString(2, y, STR_7026_BANK_BALANCE, 0); + SET_DPARAM64(0, p->money64); + DrawStringRightAligned(182, y, STR_7028, 0); + + y += 10; + + DrawString(2, y, STR_7027_LOAN, 0); + SET_DPARAM64(0, p->current_loan); + DrawStringRightAligned(182, y, STR_7028, 0); + + y += 12; + + GfxFillRect(182 - 75, y-2, 182, y-2, 215); + + SET_DPARAM64(0, p->money64 - p->current_loan); + DrawStringRightAligned(182, y, STR_7028, 0); +} + +static const Widget _player_finances_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 392, 0, 13, STR_700E_FINANCES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 393, 406, 0, 13, 0x2AA, STR_7075_TOGGLE_LARGE_SMALL_WINDOW}, +{ WWT_IMGBTN, 14, 0, 406, 14, 169, 0x0, 0}, +{ WWT_IMGBTN, 14, 0, 406, 170, 203, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 202, 204, 215, STR_7029_BORROW, STR_7035_INCREASE_SIZE_OF_LOAN}, +{ WWT_PUSHTXTBTN, 14, 203, 406, 204, 215, STR_702A_REPAY, STR_7036_REPAY_PART_OF_LOAN}, +{ WWT_LAST}, +}; + +static const Widget _other_player_finances_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 392, 0, 13, STR_700E_FINANCES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 393, 406, 0, 13, 0x2AA, STR_7075_TOGGLE_LARGE_SMALL_WINDOW}, +{ WWT_IMGBTN, 14, 0, 406, 14, 169, 0x0, 0}, +{ WWT_IMGBTN, 14, 0, 406, 170, 203, 0x0, 0}, +{ WWT_LAST}, +}; + +static const Widget _other_player_finances_small_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 265, 0, 13, STR_700E_FINANCES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 266, 279, 0, 13, 0x2AA, STR_7075_TOGGLE_LARGE_SMALL_WINDOW}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_IMGBTN, 14, 0, 279, 14, 47, 0x0}, +{ WWT_LAST}, +}; + +static const Widget _player_finances_small_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 265, 0, 13, STR_700E_FINANCES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 266, 279, 0, 13, 0x2AA, STR_7075_TOGGLE_LARGE_SMALL_WINDOW}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_IMGBTN, 14, 0, 279, 14, 47, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 139, 48, 59, STR_7029_BORROW, STR_7035_INCREASE_SIZE_OF_LOAN}, +{ WWT_PUSHTXTBTN, 14, 140, 279, 48, 59, STR_702A_REPAY, STR_7036_REPAY_PART_OF_LOAN}, +{ WWT_LAST}, +}; + + +static void PlayerFinancesWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p = DEREF_PLAYER(w->window_number); + + w->disabled_state = p->current_loan != 0 ? 0 : (1 << 6); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, GetPlayerNameString((byte)w->window_number)); + SET_DPARAM32(3, 10000); + DrawWindowWidgets(w); + + DrawPlayerEconomyStats(p, (byte)WP(w,def_d).data_1); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: {/* toggle size */ + byte mode = (byte)WP(w,def_d).data_1; + int player = w->window_number; + DeleteWindow(w); + DoShowPlayerFinances(player, (mode & 1) == 0); + } break; + + case 5: /* increase loan */ + DoCommandP(0, w->window_number, _ctrl_pressed, NULL, CMD_INCREASE_LOAN | CMD_MSG(STR_702C_CAN_T_BORROW_ANY_MORE_MONEY)); + break; + + case 6: /* repay loan */ + DoCommandP(0, w->window_number, _ctrl_pressed, NULL, CMD_DECREASE_LOAN | CMD_MSG(STR_702F_CAN_T_REPAY_LOAN)); + break; + } + break; + } +} + +static const WindowDesc _player_finances_desc = { + -1,-1, 407, 216, + WC_FINANCES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESTORE_DPARAM | WDF_UNCLICK_BUTTONS, + _player_finances_widgets, + PlayerFinancesWndProc +}; + +static const WindowDesc _player_finances_small_desc = { + -1,-1, 280, 60, + WC_FINANCES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESTORE_DPARAM | WDF_UNCLICK_BUTTONS, + _player_finances_small_widgets, + PlayerFinancesWndProc +}; + +static const WindowDesc _other_player_finances_desc = { + -1,-1, 407, 204, + WC_FINANCES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESTORE_DPARAM | WDF_UNCLICK_BUTTONS, + _other_player_finances_widgets, + PlayerFinancesWndProc +}; + +static const WindowDesc _other_player_finances_small_desc = { + -1,-1, 280, 48, + WC_FINANCES,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESTORE_DPARAM | WDF_UNCLICK_BUTTONS, + _other_player_finances_small_widgets, + PlayerFinancesWndProc +}; + +static const WindowDesc * const desc_table[2*2] = { + &_player_finances_desc,&_player_finances_small_desc, + &_other_player_finances_desc,&_other_player_finances_small_desc, +}; + +static void DoShowPlayerFinances(int player, bool small) +{ + Window *w; + int mode; + + mode = ((byte)player != _local_player)*2 + small; + w = AllocateWindowDescFront( desc_table[mode], player); + if (w) { + w->caption_color = w->window_number; + WP(w,def_d).data_1 = mode; + } +} + +void ShowPlayerFinances(int player) +{ + DoShowPlayerFinances(player, false); +} + +static void SelectPlayerColorWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p; + uint used_colors = 0; + int num_free = 16; + int x,y,pos; + int i; + + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + SETBIT(used_colors, p->player_color); + num_free--; + } + } + WP(w,def_d).data_1 = used_colors; + SetVScrollCount(w, num_free); + DrawWindowWidgets(w); + + x = 2; + y = 17; + pos = w->vscroll.pos; + + for(i=0; i!=16; i++) { + if (!(used_colors & 1) && --pos < 0 && pos >= -8) { + DrawString(x + 30, y, STR_00D1_DARK_BLUE + i, 2); + DrawSprite((i << 16) + 0x3078C1A, x + 14, y + 4); + y += 14; + } + used_colors >>= 1; + } + } break; + + case WE_CLICK: + if (e->click.widget == 2) { + int item = (e->click.pt.y - 13) / 14; + uint used_colors; + int i; + + if ((uint)item >= 8) + return; + item += w->vscroll.pos; + used_colors = WP(w,def_d).data_1; + + for(i=0; i!=16; i++) { + if (!(used_colors & 1) && --item < 0) { + DoCommandP(0, w->window_number, i, NULL, CMD_SET_PLAYER_COLOR); + DeleteWindow(w); + break; + } + used_colors >>= 1; + } + } + break; + } +} + +static const Widget _select_player_color_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 149, 0, 13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 138, 14, 127, 0x0, STR_7034_CLICK_ON_SELECTED_NEW_COLOR}, +{ WWT_SCROLLBAR, 14, 139, 149, 14, 127, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _select_player_color_desc = { + -1,-1, 150, 128, + WC_PLAYER_COLOR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _select_player_color_widgets, + SelectPlayerColorWndProc +}; + +static void SelectPlayerFaceWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p; + w->click_state = (w->click_state & ~(1<<5|1<<6)) | ((1<<5) << WP(w,facesel_d).gender); + DrawWindowWidgets(w); + p = DEREF_PLAYER(w->window_number); + DrawPlayerFace(WP(w,facesel_d).face, p->player_color, 2, 16); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: DeleteWindow(w); break; + case 4: /* ok click */ + DoCommandP(0, w->window_number, WP(w,facesel_d).face, NULL, CMD_SET_PLAYER_FACE); + DeleteWindow(w); + break; + case 5: /* male click */ + case 6: /* female click */ + WP(w,facesel_d).gender = e->click.widget - 5; + SetWindowDirty(w); + break; + case 7: + WP(w,facesel_d).face = (InteractiveRandom() & 0x7FFFFFFF) + (WP(w,facesel_d).gender << 31); + SetWindowDirty(w); + break; + } + break; + } +} + +static const Widget _select_player_face_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 189, 0, 13, STR_7043_FACE_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 189, 14, 136, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 94, 137, 148, STR_012E_CANCEL, STR_7047_CANCEL_NEW_FACE_SELECTION}, +{ WWT_PUSHTXTBTN, 14, 95, 189, 137, 148, STR_012F_OK, STR_7048_ACCEPT_NEW_FACE_SELECTION}, +{ WWT_TEXTBTN, 14, 95, 187, 25, 36, STR_7044_MALE, STR_7049_SELECT_MALE_FACES}, +{ WWT_TEXTBTN, 14, 95, 187, 37, 48, STR_7045_FEMALE, STR_704A_SELECT_FEMALE_FACES}, +{ WWT_PUSHTXTBTN, 14, 95, 187, 79, 90, STR_7046_NEW_FACE, STR_704B_GENERATE_RANDOM_NEW_FACE}, +{ WWT_LAST}, +}; + +static const WindowDesc _select_player_face_desc = { + -1,-1, 190, 149, + WC_PLAYER_FACE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _select_player_face_widgets, + SelectPlayerFaceWndProc +}; + +static const Widget _my_player_company_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 359, 0, 13, STR_7001, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 359, 14, 157, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 89, 158, 169, STR_7004_NEW_FACE, STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT}, +{ WWT_PUSHTXTBTN, 14, 90, 179, 158, 169, STR_7005_COLOR_SCHEME, STR_7031_CHANGE_THE_COMPANY_VEHICLE}, +{ WWT_PUSHTXTBTN, 14, 180, 269, 158, 169, STR_7009_PRESIDENT_NAME, STR_7032_CHANGE_THE_PRESIDENT_S}, +{ WWT_PUSHTXTBTN, 14, 270, 359, 158, 169, STR_7008_COMPANY_NAME, STR_7033_CHANGE_THE_COMPANY_NAME}, +{ WWT_PUSHTXTBTN, 14, 266, 355, 18, 29, STR_706F_BUILD_HQ, STR_7070_BUILD_COMPANY_HEADQUARTERS}, +{ WWT_LAST}, +}; + +static const Widget _other_player_company_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 359, 0, 13, STR_7001, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 359, 14, 157, 0x0, 0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 266, 355, 18, 29, STR_7072_VIEW_HQ, STR_7070_BUILD_COMPANY_HEADQUARTERS}, +{ WWT_PUSHTXTBTN, 14, 0, 179, 158, 169, STR_7077_BUY_25_SHARE_IN_COMPANY, STR_7079_BUY_25_SHARE_IN_THIS_COMPANY}, +{ WWT_PUSHTXTBTN, 14, 180, 359, 158, 169, STR_7078_SELL_25_SHARE_IN_COMPANY, STR_707A_SELL_25_SHARE_IN_THIS_COMPANY}, +{ WWT_LAST}, +}; + +static const Widget _my_player_company_bh_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 359, 0, 13, STR_7001, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 359, 14, 157, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 89, 158, 169, STR_7004_NEW_FACE, STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT}, +{ WWT_PUSHTXTBTN, 14, 90, 179, 158, 169, STR_7005_COLOR_SCHEME, STR_7031_CHANGE_THE_COMPANY_VEHICLE}, +{ WWT_PUSHTXTBTN, 14, 180, 269, 158, 169, STR_7009_PRESIDENT_NAME, STR_7032_CHANGE_THE_PRESIDENT_S}, +{ WWT_PUSHTXTBTN, 14, 270, 359, 158, 169, STR_7008_COMPANY_NAME, STR_7033_CHANGE_THE_COMPANY_NAME}, +{ WWT_PUSHTXTBTN, 14, 266, 355, 18, 29, STR_7072_VIEW_HQ, STR_7070_BUILD_COMPANY_HEADQUARTERS}, +{ WWT_LAST}, +}; + +static void DrawPlayerVehiclesAmount(int player) +{ + const int x = 110; + int y = 72; + Vehicle *v; + uint train,road,air,ship; + + DrawString(x, y, STR_7039_VEHICLES, 0); + + train = road = air = ship = 0; + + FOR_ALL_VEHICLES(v) { + if (v->owner == player) { + if (v->type == VEH_Train) { + if (v->subtype == 0) + train++; + } else if (v->type == VEH_Road) { + road++; + } else if (v->type == VEH_Aircraft) { + if (v->subtype <= 2) + air++; + } else if (v->type == VEH_Ship) { + ship++; + } + } + } + + if (train+road+air+ship == 0) { + DrawString(x+70, y, STR_7042_NONE, 0); + } else { + if (train != 0) { + SET_DPARAM16(0, train); + DrawString(x + 70, y, train==1 ? STR_703A_TRAIN : STR_703B_TRAINS, 0); + y += 10; + } + + if (road != 0) { + SET_DPARAM16(0, road); + DrawString(x + 70, y, road==1 ? STR_703C_ROAD_VEHICLE : STR_703D_ROAD_VEHICLES, 0); + y += 10; + } + + if (air != 0) { + SET_DPARAM16(0, air); + DrawString(x + 70, y, air==1 ? STR_703E_AIRCRAFT : STR_703F_AIRCRAFT, 0); + y += 10; + } + + if (ship != 0) { + SET_DPARAM16(0, ship); + DrawString(x + 70, y, ship==1 ? STR_7040_SHIP : STR_7041_SHIPS, 0); + } + } +} + +static int GetAmountOwnedBy(Player *p, byte owner) +{ + return (p->share_owners[0] == owner) + + (p->share_owners[1] == owner) + + (p->share_owners[2] == owner) + + (p->share_owners[3] == owner); +} + +static void DrawCompanyOwnerText(Player *p) +{ + int num = -1; + Player *p2; + int amt; + + FOR_ALL_PLAYERS(p2) { + if ((amt=GetAmountOwnedBy(p, p2->index)) != 0) { + num++; + + SET_DPARAM16(num*3+0, amt*25); + SET_DPARAM16(num*3+1, p2->name_1); + SET_DPARAM32(num*3+2, p2->name_2); + + if (num != 0) + break; + } + } + + if (num >= 0) + DrawString(120, 124, STR_707D_OWNED_BY+num, 0); +} + +static void PlayerCompanyWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p = DEREF_PLAYER(w->window_number); + uint32 dis; + + if (w->widget == _my_player_company_widgets && + p->location_of_house != 0) + w->widget = _my_player_company_bh_widgets; + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, GetPlayerNameString((byte)w->window_number)); + + dis = 0; + if (GetAmountOwnedBy(p, 0xFF) == 0) dis |= 1 << 8; + if (GetAmountOwnedBy(p, _local_player) == 0) dis |= 1 << 9; + + w->disabled_state = dis; + DrawWindowWidgets(w); + + SET_DPARAM16(0, p->inaugurated_year + 1920); + DrawString(110, 25, STR_7038_INAUGURATED, 0); + + DrawPlayerVehiclesAmount(w->window_number); + + DrawString(110,48, STR_7006_COLOR_SCHEME, 0); + DrawSprite((p->player_color<<16) + 0x3078C19, 215,49); + + DrawPlayerFace(p->face, p->player_color, 2, 16); + + SET_DPARAM16(0, p->president_name_1); + SET_DPARAM32(1, p->president_name_2); + DrawStringMultiCenter(48, 141, STR_7037_PRESIDENT, 94); + + SET_DPARAM32(0, CalculateCompanyValue(p)); + DrawString(110, 114, STR_7076_COMPANY_VALUE, 0); + + DrawCompanyOwnerText(p); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: { /* select face */ + w = AllocateWindowDescFront(&_select_player_face_desc, w->window_number); + if (w) { + w->caption_color = w->window_number; + WP(w,facesel_d).face = DEREF_PLAYER(w->window_number)->face; + WP(w,facesel_d).gender = 0; + } + } break; + + case 4: {/* change color */ + w = AllocateWindowDescFront(&_select_player_color_desc,w->window_number); + if (w) { + w->caption_color = w->window_number; + w->vscroll.cap = 8; + } + } break; + + case 5: {/* change president name */ + Player *p = DEREF_PLAYER(w->window_number); + WP(w,def_d).byte_1 = 0; + SET_DPARAM32(0, p->president_name_2); + ShowQueryString(p->president_name_1, STR_700B_PRESIDENT_S_NAME, 31, 94, w->window_class, w->window_number); + } break; + + case 6: {/* change company name */ + Player *p = DEREF_PLAYER(w->window_number); + WP(w,def_d).byte_1 = 1; + SET_DPARAM32(0, p->name_2); + ShowQueryString(p->name_1, STR_700A_COMPANY_NAME, 31, 150, w->window_class, w->window_number); + } break; + + case 7: {/* build hq */ + TileIndex tile = DEREF_PLAYER(w->window_number)->location_of_house; + if (tile == 0) { + if ((byte)w->window_number != _local_player) + return; + SetObjectToPlaceWnd(0x2D0, 1, w); + SetTileSelectSize(2, 2); + } else { + ScrollMainWindowToTile(tile); + } + } break; + + case 8: /* buy 25% */ + DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_707B_CAN_T_BUY_25_SHARE_IN_THIS)); + break; + + case 9: /* sell 25% */ + DoCommandP(0, w->window_number, 0, NULL, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_707C_CAN_T_SELL_25_SHARE_IN)); + break; + } + break; + + case WE_MOUSELOOP: + /* redraw the window every now and then */ + if ((++w->vscroll.pos & 0x1F) == 0) + SetWindowDirty(w); + break; + + case WE_PLACE_OBJ: + if (DoCommandP(e->place.tile, 0, 0, NULL, CMD_BUILD_COMPANY_HQ | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS))) + ResetObjectToPlace(); + break; + + case WE_DESTROY: + DeleteWindowById(WC_PLAYER_COLOR, w->window_number); + DeleteWindowById(WC_PLAYER_FACE, w->window_number); + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + if (WP(w,def_d).byte_1) { + DoCommandP(0, w->window_number, 0, NULL, CMD_CHANGE_COMPANY_NAME | CMD_MSG(STR_700C_CAN_T_CHANGE_COMPANY_NAME)); + } else { + DoCommandP(0, w->window_number, 0, NULL, CMD_CHANGE_PRESIDENT_NAME | CMD_MSG(STR_700D_CAN_T_CHANGE_PRESIDENT)); + } + } break; + + } +} + + +static const WindowDesc _my_player_company_desc = { + -1,-1, 360, 170, + WC_COMPANY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _my_player_company_widgets, + PlayerCompanyWndProc +}; + +static const WindowDesc _other_player_company_desc = { + -1,-1, 360, 170, + WC_COMPANY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_player_company_widgets, + PlayerCompanyWndProc +}; + +void ShowPlayerCompany(int player) +{ + Window *w; + w = AllocateWindowDescFront((byte)player == _local_player ? &_my_player_company_desc : &_other_player_company_desc, player); + if (w) + w->caption_color = w->window_number; +} + + + +static void BuyCompanyWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawWindowWidgets(w); + + DrawPlayerFace(p->face, p->player_color, 2, 16); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM32(2, p->bankrupt_value); + DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238); + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 3: + DeleteWindow(w); + break; + case 4: { + DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY)); + break; + } + } + break; + } +} + +static const Widget _buy_company_widgets[] = { +{ WWT_TEXTBTN, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 5, 11, 333, 0, 13, STR_00B3_MESSAGE_FROM, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 5, 0, 333, 14, 136, 0x0}, +{ WWT_TEXTBTN, 5, 148, 207, 117, 128, STR_00C9_NO}, +{ WWT_TEXTBTN, 5, 218, 277, 117, 128, STR_00C8_YES}, +{ WWT_LAST}, +}; + +static const WindowDesc _buy_company_desc = { + 153,171, 334, 137, + WC_BUY_COMPANY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _buy_company_widgets, + BuyCompanyWndProc +}; + + +void ShowBuyCompanyDialog(uint player) +{ + AllocateWindowDescFront(&_buy_company_desc, player); +} diff --git a/players.c b/players.c new file mode 100644 --- /dev/null +++ b/players.c @@ -0,0 +1,825 @@ +#include "stdafx.h" +#include "ttd.h" +#include "player.h" +#include "town.h" +#include "vehicle.h" +#include "station.h" +#include "gfx.h" +#include "news.h" +#include "saveload.h" +#include "command.h" + +extern void StartupEconomy(); + +static const SpriteID cheeks_table[4] = { + 0x325, 0x326, + 0x390, 0x3B0, +}; + +static const SpriteID mouth_table[3] = { + 0x34C, 0x34D, 0x34F +}; + +void DrawPlayerFace(uint32 face, int color, int x, int y) +{ + byte flag = 0; + + if ( (int32)face < 0) + flag |= 1; + if ((((((face >> 7) ^ face) >> 7) ^ face) & 0x8080000) == 0x8000000) + flag |= 2; + + /* draw the gradient */ + DrawSprite( (color<<16) + 0x0307836A, x, y); + + /* draw the cheeks */ + DrawSprite(cheeks_table[flag&3], x, y); + + /* draw the chin */ + /* FIXME: real code uses -2 in zoomlevel 1 */ + { + uint val = (face >> 4) & 3; + if (!(flag & 2)) { + DrawSprite(0x327 + (flag&1?0:val), x, y); + } else { + DrawSprite((flag&1?0x3B1:0x391) + (val>>1), x, y); + } + } + /* draw the eyes */ + { + uint val1 = (face >> 6)&15; + uint val2 = (face >> 20)&7; + uint32 high = 0x314<<16; + + if (val2 >= 6) { + high = 0x30F<<16; + if (val2 != 6) + high = 0x30D<<16; + } + + if (!(flag & 2)) { + if (!(flag & 1)) { + DrawSprite(high+((val1 * 12 >> 4) + 0x832B), x, y); + } else { + DrawSprite(high+(val1 + 0x8337), x, y); + } + } else { + if (!(flag & 1)) { + DrawSprite(high+((val1 * 11 >> 4) + 0x839A), x, y); + } else { + DrawSprite(high+(val1 + 0x83B8), x, y); + } + } + } + + /* draw the mouth */ + { + uint val = (face >> 10) & 63; + uint val2; + + if (!(flag&1)) { + val2 = ((val&0xF) * 15 >> 4); + + if (val2 < 3) { + DrawSprite((flag&2 ? 0x397 : 0x367) + val2, x, y); + /* skip the rest */ + goto skip_mouth; + } + + val2 -= 3; + if (flag & 2) { + if (val2 > 8) val2 = 0; + val2 += 0x3A5 - 0x35B; + } + DrawSprite(val2 + 0x35B, x, y); + } else if (!(flag&2)) { + DrawSprite(((val&0xF) * 10 >> 4) + 0x351, x, y); + } else { + DrawSprite(((val&0xF) * 9 >> 4) + 0x3C8, x, y); + } + + val >>= 3; + + if (!(flag&2)) { + if (!(flag&1)) { + DrawSprite(0x349 + val, x, y); + } else { + DrawSprite( mouth_table[(val*3>>3)], x, y); + } + } else { + if (!(flag&1)) { + DrawSprite(0x393 + (val&3), x, y); + } else { + DrawSprite(0x3B3 + (val*5>>3), x, y); + } + } + + skip_mouth:; + } + + + /* draw the hair */ + { + uint val = (face >> 16) & 15; + if (!(flag&2)) { + if (!(flag&1)) { + DrawSprite(0x382 + (val*9>>4), x, y); + } else { + DrawSprite(0x38B + (val*5>>4), x, y); + } + } else { + if (!(flag&1)) { + DrawSprite(0x3D4 + (val*5>>4), x, y); + } else { + DrawSprite(0x3D9 + (val*5>>4), x, y); + } + } + } + + /* draw the tie */ + { + uint val = (face >> 20) & 0xFF; + + if (!(flag&1)) { + DrawSprite(0x36B + ((val&3)*3>>2), x, y); + DrawSprite(0x36E + ((val>>2)&3), x, y); + DrawSprite(0x372 + ((val>>4)*6>>4), x, y); + } else { + DrawSprite(0x378 + ((val&3)*3>>2), x, y); + DrawSprite(0x37B + ((val>>2)&3), x, y); + + val >>= 4; + if (val < 3) { + DrawSprite((flag&2 ? 0x3D1 : 0x37F) + val, x, y); + } + } + } + + /* draw the glasses */ + { + uint val = (face >> 28) & 7; + + if (!(flag&2)) { + if (val<=1) { + DrawSprite(0x347 + val, x, y); + } + } else { + if (val<=1) { + DrawSprite(0x3AE + val, x, y); + } + } + } +} + +void InvalidatePlayerWindows(Player *p) +{ + uint pid = p->index; + if ( (byte)pid == _local_player) + InvalidateWindow(WC_STATUS_BAR, 0); + + InvalidateWindow(WC_FINANCES, pid); +} + +bool CheckPlayerHasMoney(int32 cost) +{ + if (cost > 0) { + uint pid = _current_player; + if (pid < MAX_PLAYERS && cost > DEREF_PLAYER(pid)->player_money) { + SET_DPARAM32(0, cost); + _error_message = STR_0003_NOT_ENOUGH_CASH_REQUIRES; + return false; + } + } + return true; +} + +static void SubtractMoneyFromAnyPlayer(Player *p, int32 cost) +{ + p->money64 -= cost; + UpdatePlayerMoney32(p); + + p->yearly_expenses[0][_yearly_expenses_type] += cost; + + if ( ( 1 << _yearly_expenses_type ) & (1<<7|1<<8|1<<9|1<<10)) + p->cur_economy.income -= cost; + else if (( 1 << _yearly_expenses_type ) & (1<<2|1<<3|1<<4|1<<5|1<<6|1<<11)) + p->cur_economy.expenses -= cost; + + InvalidatePlayerWindows(p); +} + +void SubtractMoneyFromPlayer(int32 cost) +{ + uint pid = _current_player; + if (pid < MAX_PLAYERS) + SubtractMoneyFromAnyPlayer(DEREF_PLAYER(pid), cost); +} + +void SubtractMoneyFromPlayerFract(byte player, int32 cost) +{ + Player *p = DEREF_PLAYER(player); + byte m = p->player_money_fraction; + p->player_money_fraction = m - (byte)cost; + cost >>= 8; + if (p->player_money_fraction > m) + cost++; + if (cost != 0) + SubtractMoneyFromAnyPlayer(p, cost); +} + +// the player_money field is kept as it is, but money64 contains the actual amount of money. +void UpdatePlayerMoney32(Player *p) +{ + if (p->money64 < -2000000000) + p->player_money = -2000000000; + else if (p->money64 > 2000000000) + p->player_money = 2000000000; + else + p->player_money = (int32)p->money64; +} + +void GetNameOfOwner(byte owner, uint tile) +{ + SET_DPARAM8(2, owner); + + if (owner != OWNER_TOWN) { + if (owner >= 8) + SET_DPARAM16(0, STR_0150_SOMEONE); + else { + Player *p = DEREF_PLAYER(owner); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + } + } else { + Town *t = ClosestTownFromTile(tile, (uint)-1); + SET_DPARAM16(0, t->townnametype); + SET_DPARAM32(1, t->townnameparts); + } +} + + +bool CheckOwnership(byte owner) +{ + assert(owner <= OWNER_WATER); + + if (owner == _current_player) + return true; + _error_message = STR_013B_OWNED_BY; + GetNameOfOwner(owner, 0); + return false; +} + +bool CheckTileOwnership(uint tile) +{ + byte owner = _map_owner[tile]; + assert(owner <= OWNER_WATER); + if (owner == _current_player) + return true; + _error_message = STR_013B_OWNED_BY; + + // no need to get the name of the owner unless we're the local player (saves some time) + if (_current_player == _local_player) + GetNameOfOwner(owner, tile); + return false; +} + +static void GenerateCompanyName(Player *p) +{ + uint tile; + Town *t; + StringID str; + Player *pp; + uint32 strp; + char buffer[100]; + + if (p->name_1 != STR_SV_UNNAMED) + return; + + tile = p->last_build_coordinate; + if (tile == 0) + return; + + t = ClosestTownFromTile(tile, (uint)-1); + + if (IS_INT_INSIDE(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST+1)) { + str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_PLAYERNAME_START; + strp = t->townnameparts; + +verify_name:; + // No player must have this name already + FOR_ALL_PLAYERS(pp) { + if (pp->name_1 == str && pp->name_2 == strp) + goto bad_town_name; + } + + GetString(buffer, str); + if (strlen(buffer) >= 32 || GetStringWidth(buffer) >= 150) + goto bad_town_name; + +set_name:; + p->name_1 = str; + p->name_2 = strp; + + MarkWholeScreenDirty(); + + if (!IS_HUMAN_PLAYER(p->index)) { + SET_DPARAM16(0, t->index); + AddNewsItem(p->index + (4 << 4), NEWS_FLAGS(NM_CALLBACK, NF_TILE, NT_COMPANY_INFO, DNC_BANKRUPCY), p->last_build_coordinate, 0); + } + return; + } +bad_town_name:; + + if (p->president_name_1 == SPECSTR_PRESIDENT_NAME) { + str = SPECSTR_ANDCO_NAME; + strp = p->president_name_2; + goto set_name; + } else { + str = SPECSTR_ANDCO_NAME; + strp = Random(); + goto verify_name; + } +} + +#define COLOR_SWAP(i,j) do { byte t=colors[i];colors[i]=colors[j];colors[j]=t; } while(0) + +static const byte _color_sort[16] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1}; +static const byte _color_similar_1[16] = {8, 6, 255, 12, 255, 0, 1, 1, 0, 13, 11, 10, 3, 9, 15, 14}; +static const byte _color_similar_2[16] = {5, 7, 255, 255, 255, 8, 7, 6, 5, 12, 255, 255, 9, 255, 255, 255}; + +static byte GeneratePlayerColor() +{ + byte colors[16], pcolor, t2; + int i,j,n; + uint32 r; + Player *p; + + // Initialize array + for(i=0; i!=16; i++) + colors[i] = i; + + // And randomize it + n = 100; + do { + r = Random(); + COLOR_SWAP(r & 0xF, (r >> 4) & 0xF); + } while (--n); + + // Bubble sort it according to the values in table 1 + i = 16; + do { + for(j=0; j!=15; j++) { + if (_color_sort[colors[j]] < _color_sort[colors[j+1]]) { + COLOR_SWAP(j,j+1); + } + } + } while (--i); + + // Move the colors that look similar to each player's color to the side + FOR_ALL_PLAYERS(p) if (p->is_active) { + pcolor = p->player_color; + for(i=0; i!=16; i++) if (colors[i] == pcolor) { + colors[i] = 0xFF; + + t2 = _color_similar_1[pcolor]; + if (t2 == 0xFF) break; + for(i=0; i!=15; i++) { + if (colors[i] == t2) { + do COLOR_SWAP(i,i+1); while (++i != 15); + break; + } + } + + t2 = _color_similar_2[pcolor]; + if (t2 == 0xFF) break; + for(i=0; i!=15; i++) { + if (colors[i] == t2) { + do COLOR_SWAP(i,i+1); while (++i != 15); + break; + } + } + break; + } + } + + // Return the first available color + i = 0; + for(;;) { + if (colors[i] != 0xFF) + return colors[i]; + i++; + } +} + +static void GeneratePresidentName(Player *p) +{ + Player *pp; + char buffer[100], buffer2[40]; + + for(;;) { +restart:; + + p->president_name_2 = Random(); + p->president_name_1 = SPECSTR_PRESIDENT_NAME; + + SET_DPARAM32(0, p->president_name_2); + GetString(buffer, p->president_name_1); + if (strlen(buffer) >= 32 || GetStringWidth(buffer) >= 94) + continue; + + FOR_ALL_PLAYERS(pp) { + if (pp->is_active && p != pp) { + SET_DPARAM32(0, pp->president_name_2); + GetString(buffer2, pp->president_name_1); + if (str_eq(buffer2, buffer)) + goto restart; + } + } + return; + } +} + +extern int GetPlayerMaxRailtype(int p); + +static Player *AllocatePlayer() +{ + Player *p; + // Find a free slot + FOR_ALL_PLAYERS(p) { + if (!p->is_active) { + int i = p->index; + memset(p, 0, sizeof(Player)); + p->index = i; + return p; + } + } + return NULL; +} + +Player *DoStartupNewPlayer(bool is_ai) +{ + Player *p; + int index; + + p = AllocatePlayer(); + if (p == NULL) return NULL; + + index = p->index; + + // Make a color + p->player_color = GeneratePlayerColor(); + _player_colors[index] = p->player_color; + p->name_1 = STR_SV_UNNAMED; + p->is_active = true; + + p->money64 = p->player_money = p->current_loan = 100000; + + p->is_ai = is_ai; + p->ai.state = 5; /* AIS_WANT_NEW_ROUTE */ + p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = 0xFF; + + p->max_railtype = GetPlayerMaxRailtype(index); + p->inaugurated_year = _cur_year; + p->face = Random(); + + GeneratePresidentName(p); + + InvalidateWindow(WC_GRAPH_LEGEND, 0); + InvalidateWindow(WC_TOOLBAR_MENU, 0); + + return p; +} + +void StartupPlayers() +{ + uint32 r; + + r = Random(); + _next_competitor_start = (byte)r + _opt.diff.competitor_start_time * 6882 + 1; +} + +static void MaybeStartNewPlayer() +{ + uint n; + Player *p; + + // count number of competitors + n = 0; + for(p=_players; p!=endof(_players); p++) + if (p->is_active && p->is_ai) + n++; + + // when there's a lot of computers in game, the probability that a new one starts is lower + if (n < (uint)_opt.diff.max_no_competitors && n < RandomRange(_opt.diff.max_no_competitors)) + DoStartupNewPlayer(true); + + _next_competitor_start = RandomRange(19980) + 11100; +} + +void InitializePlayers() +{ + int i; + memset(_players, 0, sizeof(_players)); + for(i = 0; i != MAX_PLAYERS; i++) + _players[i].index=i; + _cur_player_tick_index = 0; +} + +void OnTick_Players() +{ + Player *p; + + if (_game_mode == GM_EDITOR) + return; + + p = DEREF_PLAYER(_cur_player_tick_index); + _cur_player_tick_index = (_cur_player_tick_index + 1) % MAX_PLAYERS; + if (p->name_1 != 0) GenerateCompanyName(p); + + if (_game_mode != GM_MENU && !--_next_competitor_start) { + MaybeStartNewPlayer(); + } +} + +void RunOtherPlayersLoop() +{ + Player *p; + + _is_ai_player = true; + + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + _current_player = p->index; + AiDoGameLoop(p); + } + } + + _is_ai_player = false; +// XXX: is this needed? + _current_player = 0; +} + +StringID GetPlayerNameString(byte player) +{ + if (IS_HUMAN_PLAYER(player) && player < 2) // temporarily fixes the names in the list. + return STR_7002_PLAYER_1+player; + return STR_EMPTY; +} + +extern void ShowPlayerFinances(int player); + +void PlayersYearlyLoop() +{ + Player *p; + + // Copy statistics + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + memmove(&p->yearly_expenses[1], &p->yearly_expenses[0], sizeof(p->yearly_expenses) - sizeof(p->yearly_expenses[0])); + memset(&p->yearly_expenses[0], 0, sizeof(p->yearly_expenses[0])); + InvalidateWindow(WC_FINANCES, p->index); + } + } + + if (_patches.show_finances && _local_player != 0xff) { + ShowPlayerFinances(_local_player); + p = DEREF_PLAYER(_local_player); + if (p->num_valid_stat_ent > 5 && p->old_economy[0].performance_history < p->old_economy[4].performance_history) { + SndPlayFx(0x28); + } else { + SndPlayFx(0x27); + } + } +} + +void DeletePlayerWindows(int pi) +{ + DeleteWindowById(WC_COMPANY, pi); + DeleteWindowById(WC_FINANCES, pi); + DeleteWindowById(WC_STATION_LIST, pi); + DeleteWindowById(WC_TRAINS_LIST, pi); + DeleteWindowById(WC_ROADVEH_LIST, pi); + DeleteWindowById(WC_SHIPS_LIST, pi); + DeleteWindowById(WC_AIRCRAFT_LIST, pi); + DeleteWindowById(WC_BUY_COMPANY, pi); +} + +static void DeletePlayerStuff(int pi) +{ + Player *p; + + DeletePlayerWindows(pi); + p = DEREF_PLAYER(pi); + DeleteName(p->name_1); + DeleteName(p->president_name_1); + p->name_1 = 0; + p->president_name_1 = 0; +} + +// functionality. +// 0 - make new player +// 1 - make new AI player +// 2 - delete player (p1 >> 8) & 0xFF +// 3 - join player (p1 >> 8) & 0xFF with (p1 >> 16) & 0xFF +int32 CmdPlayerCtrl(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int pi; + Player *p; + + if (!(flags & DC_EXEC)) + return 0; + + switch(p1 & 0xff) { + case 0: // make new player + p = DoStartupNewPlayer(false); + if (_local_player == 0xff && p != NULL) { + _local_player = p->index; + MarkWholeScreenDirty(); + } + break; + case 1: // make new ai player + DoStartupNewPlayer(true); + break; + case 2: // delete player + pi = (byte)(p1 >> 8); + ChangeOwnershipOfPlayerItems(pi, 255); + DeletePlayerStuff(pi); + break; + + case 3: // join player + pi = (byte)(p1 >> 8); + ChangeOwnershipOfPlayerItems(pi, (byte)(p1 >> 16)); + DeletePlayerStuff(pi); + break; + } + + + return 0; +} + +// Save/load of players +static const byte _player_desc[] = { + SLE_VAR(Player,name_2, SLE_UINT32), + SLE_VAR(Player,name_1, SLE_STRINGID), + + SLE_VAR(Player,president_name_1,SLE_UINT16), + SLE_VAR(Player,president_name_2,SLE_UINT32), + + SLE_VAR(Player,face, SLE_UINT32), + + // money was changed to a 64 bit field in savegame version 1. + SLE_CONDVAR(Player,money64, SLE_VAR_I64 | SLE_FILE_I32, 0, 0), + SLE_CONDVAR(Player,money64, SLE_INT64, 1, 255), + + SLE_VAR(Player,current_loan, SLE_INT32), + + SLE_VAR(Player,player_color, SLE_UINT8), + SLE_VAR(Player,player_money_fraction,SLE_UINT8), + SLE_VAR(Player,max_railtype, SLE_UINT8), + SLE_VAR(Player,block_preview, SLE_UINT8), + + SLE_VAR(Player,cargo_types, SLE_UINT16), + SLE_VAR(Player,location_of_house,SLE_UINT16), + SLE_VAR(Player,last_build_coordinate,SLE_UINT16), + SLE_VAR(Player,inaugurated_year,SLE_UINT8), + + SLE_ARR(Player,share_owners, SLE_UINT8, 4), + + SLE_VAR(Player,num_valid_stat_ent,SLE_UINT8), + + SLE_VAR(Player,quarters_of_bankrupcy,SLE_UINT8), + SLE_VAR(Player,bankrupt_asked, SLE_UINT8), + SLE_VAR(Player,bankrupt_timeout,SLE_INT16), + SLE_VAR(Player,bankrupt_value, SLE_INT32), + + // yearly expenses was changed to 64-bit in savegame version 2. + SLE_CONDARR(Player,yearly_expenses, SLE_FILE_I32|SLE_VAR_I64, 3*13, 0, 1), + SLE_CONDARR(Player,yearly_expenses, SLE_INT64, 3*13, 2, 255), + + SLE_CONDVAR(Player,is_ai, SLE_UINT8, 2, 255), + SLE_CONDVAR(Player,is_active, SLE_UINT8, 4, 255), + + // reserve extra space in savegame here. (currently 64 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 8, 2, 255), + + SLE_END() +}; + +static const byte _player_economy_desc[] = { + // these were changed to 64-bit in savegame format 2 + SLE_CONDVAR(PlayerEconomyEntry,income, SLE_INT32, 0, 1), + SLE_CONDVAR(PlayerEconomyEntry,expenses, SLE_INT32, 0, 1), + SLE_CONDVAR(PlayerEconomyEntry,company_value, SLE_INT32, 0, 1), + SLE_CONDVAR(PlayerEconomyEntry,income, SLE_FILE_I64 | SLE_VAR_I32, 2, 255), + SLE_CONDVAR(PlayerEconomyEntry,expenses,SLE_FILE_I64 | SLE_VAR_I32, 2, 255), + SLE_CONDVAR(PlayerEconomyEntry,company_value,SLE_FILE_I64 | SLE_VAR_I32, 2, 255), + + SLE_VAR(PlayerEconomyEntry,delivered_cargo, SLE_INT32), + SLE_VAR(PlayerEconomyEntry,performance_history, SLE_INT32), + + SLE_END() +}; + +static const byte _player_ai_desc[] = { + SLE_VAR(PlayerAI,state, SLE_UINT8), + SLE_VAR(PlayerAI,tick, SLE_UINT8), + SLE_VAR(PlayerAI,state_counter, SLE_UINT16), + SLE_VAR(PlayerAI,timeout_counter, SLE_UINT16), + + SLE_VAR(PlayerAI,state_mode, SLE_UINT8), + SLE_VAR(PlayerAI,banned_tile_count, SLE_UINT8), + SLE_VAR(PlayerAI,railtype_to_use, SLE_UINT8), + + SLE_VAR(PlayerAI,cargo_type, SLE_UINT8), + SLE_VAR(PlayerAI,num_wagons, SLE_UINT8), + SLE_VAR(PlayerAI,build_kind, SLE_UINT8), + SLE_VAR(PlayerAI,num_build_rec, SLE_UINT8), + SLE_VAR(PlayerAI,num_loco_to_build, SLE_UINT8), + SLE_VAR(PlayerAI,num_want_fullload, SLE_UINT8), + + SLE_VAR(PlayerAI,route_type_mask, SLE_UINT8), + + SLE_VAR(PlayerAI,start_tile_a, SLE_UINT16), + SLE_VAR(PlayerAI,cur_tile_a, SLE_UINT16), + SLE_VAR(PlayerAI,start_dir_a, SLE_UINT8), + SLE_VAR(PlayerAI,cur_dir_a, SLE_UINT8), + + SLE_VAR(PlayerAI,start_tile_b, SLE_UINT16), + SLE_VAR(PlayerAI,cur_tile_b, SLE_UINT16), + SLE_VAR(PlayerAI,start_dir_b, SLE_UINT8), + SLE_VAR(PlayerAI,cur_dir_b, SLE_UINT8), + + SLE_REF(PlayerAI,cur_veh, REF_VEHICLE), + + SLE_ARR(PlayerAI,wagon_list, SLE_UINT16, 9), + SLE_ARR(PlayerAI,order_list_blocks, SLE_UINT8, 20), + SLE_ARR(PlayerAI,banned_tiles, SLE_UINT16, 16), + + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 8, 2, 255), + SLE_END() +}; + +static const byte _player_ai_build_rec_desc[] = { + SLE_VAR(AiBuildRec,spec_tile, SLE_UINT16), + SLE_VAR(AiBuildRec,use_tile, SLE_UINT16), + SLE_VAR(AiBuildRec,rand_rng, SLE_UINT8), + SLE_VAR(AiBuildRec,cur_building_rule,SLE_UINT8), + SLE_VAR(AiBuildRec,unk6, SLE_UINT8), + SLE_VAR(AiBuildRec,unk7, SLE_UINT8), + SLE_VAR(AiBuildRec,buildcmd_a, SLE_UINT8), + SLE_VAR(AiBuildRec,buildcmd_b, SLE_UINT8), + SLE_VAR(AiBuildRec,direction, SLE_UINT8), + SLE_VAR(AiBuildRec,cargo, SLE_UINT8), + SLE_END() +}; + +static void SaveLoad_PLYR(Player *p) { + int i; + + SlObject(p, _player_desc); + + // Write AI? + if (!IS_HUMAN_PLAYER(p->index)) { + SlObject(&p->ai, _player_ai_desc); + for(i=0; i!=p->ai.num_build_rec; i++) + SlObject(&p->ai.src + i, _player_ai_build_rec_desc); + } + + // Write economy + SlObject(&p->cur_economy, _player_economy_desc); + + // Write old economy entries. + { + PlayerEconomyEntry *pe; + for(i=p->num_valid_stat_ent,pe=p->old_economy; i!=0; i--,pe++) + SlObject(pe, _player_economy_desc); + } +} + +static void Save_PLYR() +{ + Player *p; + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + SlSetArrayIndex(p->index); + SlAutolength((AutolengthProc*)SaveLoad_PLYR, p); + } + } +} + +static void Load_PLYR() +{ + int index; + while ((index = SlIterateArray()) != -1) { + Player *p = DEREF_PLAYER(index); + p->is_ai = (index != 0); + SaveLoad_PLYR(p); + _player_colors[index] = p->player_color; + UpdatePlayerMoney32(p); + } +} + +const ChunkHandler _player_chunk_handlers[] = { + { 'PLYR', Save_PLYR, Load_PLYR, CH_ARRAY | CH_LAST}, +}; + diff --git a/rail_cmd.c b/rail_cmd.c new file mode 100644 --- /dev/null +++ b/rail_cmd.c @@ -0,0 +1,1927 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "viewport.h" +#include "command.h" +#include "pathfind.h" +#include "town.h" + +void ShowTrainDepotWindow(uint tile); + +enum { + RAIL_TYPE_NORMAL = 0, + RAIL_TYPE_SIGNALS = 0x40, + RAIL_TYPE_SPECIAL = 0x80, // If this bit is set, then it's not a regular track. + RAIL_TYPE_DEPOT = 0xC0, + RAIL_TYPE_MASK = 0xC0, + + RAIL_BIT_DIAG1 = 1, // 0 + RAIL_BIT_DIAG2 = 2, // 1 + RAIL_BIT_UPPER = 4, // 2 + RAIL_BIT_LOWER = 8, // 3 + RAIL_BIT_LEFT = 16, // 4 + RAIL_BIT_RIGHT = 32, // 5 + RAIL_BIT_MASK = 0x3F, + + RAIL_DEPOT_TRACK_MASK = 1, + RAIL_DEPOT_DIR = 3, + RAIL_DEPOT_UNUSED_BITS = 0x3C, + + RAIL_TYPE_CHECKPOINT = 0xC4, + RAIL_CHECKPOINT_TRACK_MASK = 1, + RAIL_CHECKPOINT_UNUSED_BITS = 0x3E, +}; + +#define IS_RAIL_DEPOT(x) (((x) & (RAIL_TYPE_DEPOT|RAIL_DEPOT_UNUSED_BITS)) == RAIL_TYPE_DEPOT) +#define IS_RAIL_CHECKPOINT(x) (((x) & (RAIL_TYPE_CHECKPOINT|RAIL_CHECKPOINT_UNUSED_BITS)) == RAIL_TYPE_CHECKPOINT) + +/* Format of rail map5 byte. + * 00 abcdef => Normal rail + * 01 abcdef => Rail with signals + * 10 ?????? => Unused + * 11 ????dd => Depot + */ + +/* 4 + * --------- + * |\ /| + * | \ 1/ | + * | \ / | + * | \ / | + * 16| \ |32 + * | / \2 | + * | / \ | + * | / \ | + * |/ \| + * --------- + * 8 + */ + + +// Constants for lower part of Map2 byte. +enum RailMap2Lower4 { + RAIL_MAP2LO_GROUND_MASK = 0xF, + RAIL_GROUND_BROWN = 0, + RAIL_GROUND_GREEN = 1, + RAIL_GROUND_FENCE_NW = 2, + RAIL_GROUND_FENCE_SE = 3, + RAIL_GROUND_FENCE_SENW = 4, + RAIL_GROUND_FENCE_NE = 5, + RAIL_GROUND_FENCE_SW = 6, + RAIL_GROUND_FENCE_NESW = 7, + RAIL_GROUND_FENCE_VERT1 = 8, + RAIL_GROUND_FENCE_VERT2 = 9, + RAIL_GROUND_FENCE_HORIZ1 = 10, + RAIL_GROUND_FENCE_HORIZ2 = 11, + RAIL_GROUND_ICE_DESERT = 12, +}; + + +/* MAP2 byte: abcd???? => Signal On? + * MAP3LO byte: abcd???? => Signal Exists? + * MAP2 byte: ????abcd => Type of ground. + * MAP3LO byte: ????abcd => Type of rail. + * MAP5: 00abcdef => rail + * 01abcdef => rail w/ signals + * 10uuuuuu => unused + * 11uuuudd => rail depot + */ + +static bool CheckTrackCombination(byte map5, byte trackbits, byte flags) +{ + _error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION; + + if ((map5&RAIL_TYPE_MASK) == RAIL_TYPE_SIGNALS) { + + if (map5 & trackbits) { + _error_message = STR_1007_ALREADY_BUILT; + return false; + } + + map5 |= trackbits; + return (map5 == (RAIL_TYPE_SIGNALS|RAIL_BIT_UPPER|RAIL_BIT_LOWER) || map5 == (RAIL_TYPE_SIGNALS|RAIL_BIT_LEFT|RAIL_BIT_RIGHT)); + + } else if ((map5&RAIL_TYPE_MASK) == RAIL_TYPE_NORMAL) { + _error_message = STR_1007_ALREADY_BUILT; + if (map5 & trackbits) + return false; + + // Computer players are not allowed to intersect pieces of rail. + if (!(flags&DC_NO_RAIL_OVERLAP)) + return true; + + map5 |= trackbits; + return (map5 == (RAIL_BIT_UPPER|RAIL_BIT_LOWER) || map5 == (RAIL_BIT_LEFT|RAIL_BIT_RIGHT)); + } else { + return false; + } +} + + +static const byte _valid_tileh_slopes[3][15] = { + +// set of normal ones +{ + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_RIGHT, + RAIL_BIT_UPPER, + RAIL_BIT_DIAG1, + + RAIL_BIT_LEFT, + 0, + RAIL_BIT_DIAG2, + RAIL_BIT_LOWER, + + RAIL_BIT_LOWER, + RAIL_BIT_DIAG2, + 0, + RAIL_BIT_LEFT, + + RAIL_BIT_DIAG1, + RAIL_BIT_UPPER, + RAIL_BIT_RIGHT, +}, + +// allowed rail for an evenly raised platform +{ + 0, + RAIL_BIT_LEFT, + RAIL_BIT_LOWER, + RAIL_BIT_DIAG2 | RAIL_BIT_LOWER | RAIL_BIT_LEFT, + + RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1 | RAIL_BIT_LOWER | RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + + RAIL_BIT_UPPER, + RAIL_BIT_DIAG1 | RAIL_BIT_UPPER | RAIL_BIT_LEFT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + + RAIL_BIT_DIAG2 | RAIL_BIT_UPPER | RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, +}, + +// allowed rail on coast tile +{ + 0, + RAIL_BIT_LEFT, + RAIL_BIT_LOWER, + RAIL_BIT_DIAG2|RAIL_BIT_LEFT|RAIL_BIT_LOWER, + + RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_RIGHT|RAIL_BIT_LOWER, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + + RAIL_BIT_UPPER, + RAIL_BIT_DIAG1|RAIL_BIT_LEFT|RAIL_BIT_UPPER, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + + RAIL_BIT_DIAG2|RAIL_BIT_RIGHT|RAIL_BIT_UPPER, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT, + } +}; + +static uint GetRailFoundation(uint tileh, uint bits) +{ + int i; + + if ((~_valid_tileh_slopes[0][tileh] & bits) == 0) + return 0; + + if ((~_valid_tileh_slopes[1][tileh] & bits) == 0) + return tileh; + + if ( ((i=0, tileh == 1) || (i+=2, tileh == 2) || (i+=2, tileh == 4) || (i+=2, tileh == 8)) && (bits == RAIL_BIT_DIAG1 || (i++, bits == RAIL_BIT_DIAG2))) + return i + 15; + + return 0; +} + +// +static uint32 CheckRailSlope(int tileh, uint rail_bits, uint existing, uint tile) +{ + // never allow building on top of steep tiles + if (!(tileh & 0x10)) { + rail_bits |= existing; + + // don't allow building on the lower side of a coast + if (IS_TILETYPE(tile, MP_WATER) && ~_valid_tileh_slopes[2][tileh] & rail_bits) { + return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); + } + + // no special foundation + if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) + return 0; + + if (((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0) || // whole tile is leveled up + ((rail_bits == RAIL_BIT_DIAG1 || rail_bits == RAIL_BIT_DIAG2) && (tileh == 1 || tileh == 2 || tileh == 4 || tileh == 8))) { // partly up + return existing ? 0 : _price.terraform; + } + } + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); +} + +/* Build a single track. + * p1 - railroad type normal/maglev + * p2 - tile direction + */ + +int32 CmdBuildSingleRail(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int32 ret, cost = 0; + byte rail_bit = 1 << p2; + byte rail_type = (byte)(p1 & 0xF); + uint tile; + byte existing = 0; + bool need_clear = false; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + _error_message = STR_1007_ALREADY_BUILT; + + FindLandscapeHeight(&ti, x, y); + tile = ti.tile; + + // allow building rail under bridge + if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (ti.type == MP_TUNNELBRIDGE) { +/* BUILD ON BRIDGE CODE */ + if (!EnsureNoVehicleZ(tile, GET_TILEHEIGHT(tile))) + return CMD_ERROR; + + if ((ti.map5 & 0xF8) == 0xC0) { + if (ti.tileh & 0x10 || rail_bit != (byte)((ti.map5 & 1) ? 1 : 2)) goto need_clear; + + if (!(flags & DC_EXEC)) + return _price.build_rail; + + _map5[tile] = (ti.map5 & 0xC7) | 0x20; + goto set_ownership; + } else if ((ti.map5 & 0xF8) == 0xE0) { + if ((_map3_lo[tile] & 0xF) != (int)p1) goto need_clear; + if (rail_bit != (byte)((ti.map5 & 1) ? 1 : 2)) goto need_clear; + return CMD_ERROR; + } else + goto need_clear; + } else if (ti.type == MP_STREET) { + byte m5; +/* BUILD ON STREET CODE */ + if (ti.tileh != 0) goto need_clear; + + if (!(ti.map5 & 0xF0)) { + if ((ti.map5 & 0x0F) == 0xA) { + if (rail_bit != 2) goto need_clear; + m5 = 0x10; + } else if ((ti.map5 & 0x0F) == 0x5) { + if (rail_bit != 1) goto need_clear; + m5 = 0x18; + } else + goto need_clear; + + if (!(flags & DC_EXEC)) + return _price.build_rail; + + ModifyTile(tile, + MP_SETTYPE(MP_STREET) | + MP_MAP3LO | MP_MAP3HI | MP_MAPOWNER_CURRENT | MP_MAP5, + _map_owner[tile], /* map3_lo */ + p1, /* map3_hi */ + m5 /* map5 */ + ); + goto fix_signals; + } else if (!(ti.map5 & 0xE0)) { + if (rail_bit != (byte)((ti.map5 & 8) ? 1 : 2)) goto need_clear; + return CMD_ERROR; + } else + goto need_clear; + } else if (ti.type == MP_RAILWAY) { + +/* BUILD ON RAILWAY CODE */ + if (_map_owner[tile] != _current_player || (byte)(_map3_lo[tile]&0xF) != rail_type) + goto need_clear; + if (!CheckTrackCombination(ti.map5, rail_bit, (byte)flags)) + return CMD_ERROR; + + existing = ti.map5 & 0x3F; + } else { + +/* DEFAULT BUILD ON CODE */ +need_clear:; + /* isnot_railway */ + if (!(flags & DC_EXEC)) { + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + cost += ret; + } + need_clear = true; + } + + ret = CheckRailSlope(ti.tileh, rail_bit, existing, tile); + if (ret & 0x80000000) + return ret; + cost += ret; + + // the AI is not allowed to used foundationed tiles. + if (ret && (_is_ai_player || !_patches.build_on_slopes)) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + if (flags & DC_EXEC && need_clear) { + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + cost += ret; + } + + if (flags & DC_EXEC) { + _map_type_and_height[tile] &= 0xF; + _map_type_and_height[tile] |= MP_RAILWAY << 4; + _map5[tile] |= rail_bit; + _map2[tile] &= ~RAIL_MAP2LO_GROUND_MASK; + + // In case it's a tile without signals, clear the signal bits. Why? + if ((_map5[tile] & RAIL_TYPE_MASK) != RAIL_TYPE_SIGNALS) + _map2[tile] &= ~0xF0; + +set_ownership: + _map_owner[tile] = _current_player; + + _map3_lo[tile] &= ~0xF; + _map3_lo[tile] |= rail_type; + + MarkTileDirtyByTile(tile); + +fix_signals: + SetSignalsOnBothDir(tile, (byte)p2); + } + + return cost + _price.build_rail; +} + +static const byte _signals_table[] = { + 0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0, // direction 1 + 0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0 // direction 2 +}; + +static const byte _signals_table_other[] = { + 0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0, // direction 1 + 0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0 // direction 2 +}; + +static const byte _signals_table_both[] = { + 0xC0, 0xC0, 0xC0, 0x30, 0xC0, 0x30, 0, 0, // both directions combined + 0xC0, 0xC0, 0xC0, 0x30, 0xC0, 0x30, 0, 0 +}; + + +/* Remove a single track. + * p1 - unused + * p2 - tile direction + */ + +int32 CmdRemoveSingleRail(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + byte rail_bit = 1 << p2; + byte m5; + uint tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + + tile = ti.tile; + + if (!((1< sx + 10, 9, 0,11, // y > sy + 13, 9, 8,12, // x > sx && y > sy +}}; + + +/* Build either NE or NW sequence of tracks. + * p1 0:15 - start pt X + * p1 16:31 - start pt y + * + * p2 0:3 - rail type + * p2 4:7 - rail direction + */ + + +int32 CmdBuildRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int sx, sy; + int32 ret, total_cost = 0; + int railbit; + + if (flags & DC_EXEC) + SndPlayTileFx(0x1E, TILE_FROM_XY(x,y)); + + /* unpack start point */ + sx = (p1 & 0xFFFF) & ~0xF; + sy = (p1 >> 16) & ~0xF; + + railbit = _railbit.initial[(p2 >> 4) + (x > sx ? 4 : 0) + (y > sy ? 8 : 0)]; + + for(;;) { + ret = DoCommand(x, y, p2&0xF, railbit&7, flags, CMD_BUILD_SINGLE_RAIL); + + if (ret == CMD_ERROR) { + if (_error_message != STR_1007_ALREADY_BUILT) + break; + } else + total_cost += ret; + + if (x == sx && y == sy) + break; + + x += _railbit.xinc[railbit]; + y += _railbit.yinc[railbit]; + + // toggle railbit for the diagonal tiles + if (railbit & 0x6) railbit ^= 1; + } + + if (total_cost == 0) + return CMD_ERROR; + + return total_cost; +} + + +/* Remove either NE or NW sequence of tracks. + * p1 0:15 - start pt X + * p1 16:31 - start pt y + * + * p2 0:3 - rail type + * p2 4:7 - rail direction + */ + + +int32 CmdRemoveRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int sx, sy; + int32 ret, total_cost = 0; + int railbit; + + if (flags & DC_EXEC) + SndPlayTileFx(0x1E, TILE_FROM_XY(x,y)); + + /* unpack start point */ + sx = (p1 & 0xFFFF) & ~0xF; + sy = (p1 >> 16) & ~0xF; + + railbit = _railbit.initial[(p2 >> 4) + (x > sx ? 4 : 0) + (y > sy ? 8 : 0)]; + + for(;;) { + ret = DoCommand(x, y, p2&0xF, railbit&7, flags, CMD_REMOVE_SINGLE_RAIL); + if (ret != CMD_ERROR) total_cost += ret; + if (x == sx && y == sy) + break; + x += _railbit.xinc[railbit]; + y += _railbit.yinc[railbit]; + // toggle railbit for the diagonal tiles + if (railbit & 0x6) railbit ^= 1; + } + + if (total_cost == 0) + return CMD_ERROR; + + return total_cost; +} + +/* Build a train depot + * p1 = rail type + * p2 = depot direction + */ +int32 CmdBuildTrainDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + int32 cost, ret; + Depot *dep; + uint tileh; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + if (!EnsureNoVehicle(tile)) return CMD_ERROR; + + tileh = GetTileSlope(tile, NULL); + if (tileh != 0) { + if (_is_ai_player || !_patches.build_on_slopes || (tileh & 0x10 || !((0x4C >> p2) & tileh) )) + return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); + } + + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + cost = ret; + + dep = AllocateDepot(); + if (dep == NULL) + return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_current_player == _local_player) + _last_built_train_depot_tile = (TileIndex)tile; + + ModifyTile(tile, + MP_SETTYPE(MP_RAILWAY) | + MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, + p1, /* map3_lo */ + p2 | RAIL_TYPE_DEPOT /* map5 */ + ); + + dep->xy = tile; + dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; + + SetSignalsOnBothDir(tile, (p2&1) ? 2 : 1); + + } + + return cost + _price.build_train_depot; +} + +static void MakeDefaultCheckpointName(Checkpoint *cp) +{ + int townidx = ClosestTownFromTile(cp->xy, (uint)-1)->index; + Checkpoint *cc; + bool used_checkpoint[64]; + int i; + + memset(used_checkpoint, 0, sizeof(used_checkpoint)); + + // find an unused checkpoint number belonging to this town + for(cc = _checkpoints; cc != endof(_checkpoints); cc++) { + if (cc->xy && cc->town_or_string & 0xC000 && (cc->town_or_string & 0xFF) == townidx) + used_checkpoint[(cc->town_or_string >> 8) & 0x3F] = true; + } + + for(i=0; used_checkpoint[i] && i!=lengthof(used_checkpoint)-1; i++) {} + cp->town_or_string = 0xC000 + (i << 8) + townidx; +} + +// find a deleted checkpoint close to a tile. +static Checkpoint *FindDeletedCheckpointCloseTo(uint tile) +{ + Checkpoint *cp,*best = NULL; + uint thres = 8, cur_dist; + + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->deleted && cp->xy) { + cur_dist = GetTileDist(tile, cp->xy); + if (cur_dist < thres) { + thres = cur_dist; + best = cp; + } + } + } + return best; +} + +/* Convert existing rail to checkpoint */ + +int32 CmdBuildTrainCheckpoint(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + Checkpoint *cp; + uint tileh; + uint dir; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + if (!IS_TILETYPE(tile, MP_RAILWAY) || ((dir=0, _map5[tile] != 1) && (dir=1, _map5[tile] != 2))) + return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK); + + if (!CheckTileOwnership(tile)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) return CMD_ERROR; + + tileh = GetTileSlope(tile, NULL); + if (tileh != 0) { + if (!_patches.build_on_slopes || tileh & 0x10 || !(tileh & (0x3 << dir)) || !(tileh & ~(0x3 << dir))) + return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); + } + + // check if there is an already existing, deleted, checkpoint close to us that we can reuse. + cp = FindDeletedCheckpointCloseTo(tile); + if (cp == NULL) { + cp = AllocateCheckpoint(); + if (cp == NULL) return CMD_ERROR; + cp->town_or_string = 0; + } + + if (flags & DC_EXEC) { + ModifyTile(tile, MP_MAP5, RAIL_TYPE_CHECKPOINT | dir); + + cp->deleted = 0; + cp->xy = tile; + + if (cp->town_or_string == 0) MakeDefaultCheckpointName(cp); else RedrawCheckpointSign(cp); + UpdateCheckpointSign(cp); + RedrawCheckpointSign(cp); + SetSignalsOnBothDir(tile, dir ? 2 : 1); + } + + return _price.build_train_depot; +} + +static void DoDeleteCheckpoint(Checkpoint *cp) +{ + cp->xy = 0; + DeleteCommandFromVehicleSchedule(((cp-_checkpoints) << 8) + OT_GOTO_CHECKPOINT); + if (~cp->town_or_string & 0xC000) DeleteName(cp->town_or_string); + RedrawCheckpointSign(cp); +} + +// delete checkpoints after a while +void CheckpointsDailyLoop() +{ + Checkpoint *cp; + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->deleted && !--cp->deleted) { + DoDeleteCheckpoint(cp); + } + } +} + +static int32 RemoveTrainCheckpoint(uint tile, uint32 flags, bool justremove) +{ + Checkpoint *cp; + + // make sure it's a checkpoint + if (!IS_TILETYPE(tile, MP_RAILWAY) || !IS_RAIL_CHECKPOINT(_map5[tile])) + return CMD_ERROR; + + if (!CheckTileOwnership(tile) && !(_current_player==17)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + int direction = _map5[tile] & RAIL_CHECKPOINT_TRACK_MASK; + + // mark the checkpoint deleted + for(cp=_checkpoints; cp->xy != (TileIndex)tile; cp++) {} + cp->deleted = 30; // let it live for this many days before we do the actual deletion. + RedrawCheckpointSign(cp); + + if (justremove) { + ModifyTile(tile, MP_MAP5, 1<town_or_string & 0xC000) DeleteName(cp->town_or_string); + cp->town_or_string = str; + UpdateCheckpointSign(cp); + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + } else { + if (flags & DC_EXEC) { + cp = &_checkpoints[p1]; + if (~cp->town_or_string & 0xC000) DeleteName(cp->town_or_string); + MakeDefaultCheckpointName(cp); + UpdateCheckpointSign(cp); + MarkWholeScreenDirty(); + } + } + return 0; +} + + +/* build signals, p1 = track */ +int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + byte m5; + int32 cost; + int track = p1 & 0x7; + + assert(track >= 0 && track < 6); + assert(p2 == 0); + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; + + // must be railway, and not a depot, and it must have a track in the suggested position. + if (!IS_TILETYPE(tile, MP_RAILWAY) || (m5=_map5[tile], m5&0x80) || !HASBIT(m5, track)) + return CMD_ERROR; + + // check rail combination + { + byte m = m5 & RAIL_BIT_MASK; + if (m != RAIL_BIT_DIAG1 && m != RAIL_BIT_DIAG2 && m != RAIL_BIT_UPPER && m != RAIL_BIT_LOWER && + m != RAIL_BIT_LEFT && m != RAIL_BIT_RIGHT && m != (RAIL_BIT_UPPER|RAIL_BIT_LOWER) && m != (RAIL_BIT_LEFT|RAIL_BIT_RIGHT)) + return CMD_ERROR; + } + + // check ownership + if (!CheckTileOwnership(tile)) + return CMD_ERROR; + + // If it had signals previously it's no cost to build. + cost = 0; + if (!(m5 & RAIL_TYPE_SIGNALS)) { + cost = _price.build_signals; + } + + if (flags & DC_EXEC) { + + + if (!(m5 & RAIL_TYPE_SIGNALS)) { + _map5[tile] |= RAIL_TYPE_SIGNALS; // change into signals + _map2[tile] |= 0xF0; // all signals are on + _map3_lo[tile] &= ~0xF0; // no signals built by default + _map3_hi[tile] = (p1 & 8) ? 4 : 0;// initial presignal state, semaphores depend on ctrl key + goto ignore_presig; + } + + if (!(p1 & 8)) { + byte a,b,c,d; +ignore_presig: + a = _signals_table[track]; // signal for this track in one direction + b = _signals_table[track + 8]; // signal for this track in the other direction + c = a | b; + d = _map3_lo[tile] & c; // mask of built signals. it only affects &0xF0 + + // Alternate between a|b, b, a + if ( d != 0 && d != a) { + c = (d==c)?b:a; + } + + _map3_lo[tile] = (_map3_lo[tile]&~(a|b)) | c; + } else { + // toggle between the signal types. Using low 2 bits of map3_hi. + _map3_hi[tile] = (_map3_hi[tile] & ~3) | ((_map3_hi[tile] + 1) & 3); + } + + MarkTileDirtyByTile(tile); + SetSignalsOnBothDir(tile, track); + } + + return cost; +} + +/* Remove signals + * p1 = unused + * p2 = unused + */ + +int32 CmdRemoveSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + uint tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + tile = ti.tile; + + /* No vehicle behind. */ + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + /* Signals can only exist on railways */ + if (ti.type != MP_RAILWAY) + return CMD_ERROR; + + /* Map5 mode is 0x40 when there's signals */ + if ((ti.map5 & RAIL_TYPE_MASK) != RAIL_TYPE_SIGNALS) + return CMD_ERROR; + + /* Who owns the tile? */ + if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) + return CMD_ERROR; + + /* Do it? */ + if (flags & DC_EXEC) { + byte bits = _map5[tile]; + _map5[tile] &= ~RAIL_TYPE_SIGNALS; + _map2[tile] &= ~0xF0; + + /* TTDBUG: this code contains a bug, if a tile contains 2 signals + * on separate tracks, it won't work properly for the 2nd track */ + SetSignalsOnBothDir(tile, FIND_FIRST_BIT(bits & RAIL_BIT_MASK)); + + MarkTileDirtyByTile(tile); + } + + return _price.remove_signals; +} + +typedef int32 DoConvertRailProc(uint tile, uint totype, bool exec); + +static int32 DoConvertRail(uint tile, uint totype, bool exec) +{ + if (!CheckTileOwnership(tile) || !EnsureNoVehicle(tile)) + return CMD_ERROR; + + // tile is already of requested type? + if ( (uint)(_map3_lo[tile] & 0xF) == totype) + return CMD_ERROR; + + // change type. + if (exec) { + _map3_lo[tile] = (_map3_lo[tile] & 0xF0) + totype; + MarkTileDirtyByTile(tile); + } + + return _price.build_rail >> 1; +} + +extern int32 DoConvertStationRail(uint tile, uint totype, bool exec); +extern int32 DoConvertStreetRail(uint tile, uint totype, bool exec); +extern int32 DoConvertTunnelBridgeRail(uint tile, uint totype, bool exec); + +// p1 = start tile +// p2 = new railtype +int32 CmdConvertRail(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) +{ + int32 ret, cost, money; + int sx,sy,x,y; + + // make sure sx,sy are smaller than ex,ey + sx = GET_TILE_X(p1)*16; + sy = GET_TILE_Y(p1)*16; + if (ex < sx) intswap(ex, sx); + if (ey < sy) intswap(ey, sy); + + money = GetAvailableMoneyForCommand(); + ret = false; + cost = 0; + for(x=sx; x<=ex; x+=16) { + for(y=sy; y<=ey; y+=16) { + uint tile = TILE_FROM_XY(x,y); + DoConvertRailProc *p; + + if (IS_TILETYPE(tile, MP_RAILWAY)) p = DoConvertRail; + else if (IS_TILETYPE(tile, MP_STATION)) p = DoConvertStationRail; + else if (IS_TILETYPE(tile, MP_STREET)) p = DoConvertStreetRail; + else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) p = DoConvertTunnelBridgeRail; + else continue; + + ret = p(tile, p2, false); + if (ret == CMD_ERROR) continue; + cost += ret; + + if (flags & DC_EXEC) { + if ( (money -= ret) < 0) { _additional_cash_required = ret; return cost - ret; } + p(tile, p2, true); + } + } + } + if (cost == 0) cost = CMD_ERROR; + return cost; +} + +static int32 RemoveTrainDepot(uint tile, uint32 flags) +{ + if (!CheckTileOwnership(tile) && !(_current_player==17)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + int track = _map5[tile] & RAIL_DEPOT_TRACK_MASK; + + DoDeleteDepot(tile); + SetSignalsOnBothDir(tile, track); + } + + return _price.remove_train_depot; +} + +static int32 ClearTile_Track(uint tile, byte flags) { + int32 cost,ret; + int i; + byte m5; + + m5 = _map5[tile]; + + if (flags & DC_AUTO) { + if (m5 & RAIL_TYPE_SPECIAL) + return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); + + if (_map_owner[tile] != _current_player) + return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER); + + return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK); + } + + cost = 0; + + + if ( (m5 & RAIL_TYPE_MASK) == RAIL_TYPE_NORMAL) { +regular_track:; + for(i=0; m5; i++, m5>>=1) { + if (m5 & 1) { + ret = DoCommandByTile(tile, 0, i, flags, CMD_REMOVE_SINGLE_RAIL); + if (ret == CMD_ERROR) + return CMD_ERROR; + cost += ret; + } + } + return cost; + + } else if ((m5 & RAIL_TYPE_MASK)==RAIL_TYPE_SIGNALS) { + cost = DoCommandByTile(tile, 0, 0, flags, CMD_REMOVE_SIGNALS); + if (cost == CMD_ERROR) + return CMD_ERROR; + m5 &= RAIL_BIT_MASK; + if (flags & DC_EXEC) + goto regular_track; + return cost + _price.remove_rail; + } else if ( (m5 & (RAIL_TYPE_MASK|RAIL_DEPOT_UNUSED_BITS)) == RAIL_TYPE_DEPOT) { + return RemoveTrainDepot(tile, flags); + } else if ( (m5 & (RAIL_TYPE_MASK|RAIL_CHECKPOINT_UNUSED_BITS)) == RAIL_TYPE_CHECKPOINT) { + return RemoveTrainCheckpoint(tile, flags, false); + } else + return CMD_ERROR; +} + + + +typedef struct DrawTrackSeqStruct { + uint16 image; + byte subcoord_x; + byte subcoord_y; + byte width; + byte height; +} DrawTrackSeqStruct; + +#include "table/track_land.h" + +// used for presignals +static const SpriteID _signal_base_sprites[16] = { + 0x4FB, + 0x1323, + 0x1333, + 0x1343, + + // use semaphores instead of signals? + 0x1353, + 0x1363, + 0x1373, + 0x1383, + + // mirrored versions + 0x4FB, + 0x1323, + 0x1333, + 0x1343, + + 0x13C6, + 0x13D6, + 0x13E6, + 0x13F6, +}; + +// used to determine the side of the road for the signal +static const byte _signal_position[24] = { + /* original: left side position */ + 0x58,0x1E,0xE1,0xB9,0x01,0xA3,0x4B,0xEE,0x3B,0xD4,0x43,0xBD, + /* patch: ride side position */ + 0x1E,0xAC,0x64,0xE1,0x4A,0x10,0xEE,0xC5,0xDB,0x34,0x4D,0xB3 +}; + +static void DrawSignalHelper(TileInfo *ti, byte condition, uint32 image_and_pos) +{ + bool otherside = _opt.road_side & _patches.signal_side; + + uint v = _signal_position[(image_and_pos & 0xF) + (otherside ? 12 : 0)]; + uint x = ti->x | (v&0xF); + uint y = ti->y | (v>>4); + uint sprite = _signal_base_sprites[(_map3_hi[ti->tile] & 7) + (otherside ? 8 : 0)] + (image_and_pos>>4) + ((condition != 0) ? 1 : 0); + AddSortableSpriteToDraw(sprite, x, y, 1, 1, 10, GetSlopeZ(x,y)); +} + +static uint32 _drawtile_track_palette; + + +static void DrawTrackFence_NW(TileInfo *ti) +{ + uint32 image = 0x515; + if (ti->tileh != 0) { + image = 0x519; + if (!(ti->tileh & 2)) { + image = 0x51B; + } + } + AddSortableSpriteToDraw(image | _drawtile_track_palette, + ti->x, ti->y+1, 16, 1, 4, ti->z); +} + +static void DrawTrackFence_SE(TileInfo *ti) +{ + uint32 image = 0x515; + if (ti->tileh != 0) { + image = 0x519; + if (!(ti->tileh & 2)) { + image = 0x51B; + } + } + AddSortableSpriteToDraw(image | _drawtile_track_palette, + ti->x, ti->y+15, 16, 1, 4, ti->z); +} + +static void DrawTrackFence_NW_SE(TileInfo *ti) +{ + DrawTrackFence_NW(ti); + DrawTrackFence_SE(ti); +} + +static void DrawTrackFence_NE(TileInfo *ti) +{ + uint32 image = 0x516; + if (ti->tileh != 0) { + image = 0x51A; + if (!(ti->tileh & 2)) { + image = 0x51C; + } + } + AddSortableSpriteToDraw(image | _drawtile_track_palette, + ti->x+1, ti->y, 1, 16, 4, ti->z); +} + +static void DrawTrackFence_SW(TileInfo *ti) +{ + uint32 image = 0x516; + if (ti->tileh != 0) { + image = 0x51A; + if (!(ti->tileh & 2)) { + image = 0x51C; + } + } + AddSortableSpriteToDraw(image | _drawtile_track_palette, + ti->x+15, ti->y, 1, 16, 4, ti->z); +} + +static void DrawTrackFence_NE_SW(TileInfo *ti) +{ + DrawTrackFence_NE(ti); + DrawTrackFence_SW(ti); +} + +static void DrawTrackFence_NS_1(TileInfo *ti) +{ + int z = ti->z; + if (ti->tileh & 1) + z += 8; + AddSortableSpriteToDraw(0x517 | _drawtile_track_palette, + ti->x + 8, ti->y + 8, 1, 1, 4, z); +} + +static void DrawTrackFence_NS_2(TileInfo *ti) +{ + int z = ti->z; + if (ti->tileh & 4) + z += 8; + AddSortableSpriteToDraw(0x517 | _drawtile_track_palette, + ti->x + 8, ti->y + 8, 1, 1, 4, z); +} + +static void DrawTrackFence_WE_1(TileInfo *ti) +{ + int z = ti->z; + if (ti->tileh & 8) + z += 8; + AddSortableSpriteToDraw(0x518 | _drawtile_track_palette, + ti->x + 8, ti->y + 8, 1, 1, 4, z); +} + +static void DrawTrackFence_WE_2(TileInfo *ti) +{ + int z = ti->z; + if (ti->tileh & 2) + z += 8; + AddSortableSpriteToDraw(0x518 | _drawtile_track_palette, + ti->x + 8, ti->y + 8, 1, 1, 4, z); +} + +static void DetTrackDrawProc_Null(TileInfo *ti) +{ + /* nothing should be here */ +} + +typedef void DetailedTrackProc(TileInfo *ti); +DetailedTrackProc * const _detailed_track_proc[16] = { + DetTrackDrawProc_Null, + DetTrackDrawProc_Null, + + DrawTrackFence_NW, + DrawTrackFence_SE, + DrawTrackFence_NW_SE, + + DrawTrackFence_NE, + DrawTrackFence_SW, + DrawTrackFence_NE_SW, + + DrawTrackFence_NS_1, + DrawTrackFence_NS_2, + + DrawTrackFence_WE_1, + DrawTrackFence_WE_2, + + DetTrackDrawProc_Null, + DetTrackDrawProc_Null, + DetTrackDrawProc_Null, + DetTrackDrawProc_Null, +}; + +static void DrawTile_Track(TileInfo *ti) +{ + uint32 tracktype_offs, image; + byte m5; + + _drawtile_track_palette = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_map_owner[ti->tile])); + + tracktype_offs = (_map3_lo[ti->tile] & 0xF) * TRACKTYPE_SPRITE_PITCH; + + m5 = (byte)ti->map5; + if (!(m5 & RAIL_TYPE_SPECIAL)) { + bool special; + + m5 &= RAIL_BIT_MASK; + + special = false; + + // select the sprite to use based on the map5 byte. + (image = 0x3F3, m5 == RAIL_BIT_DIAG2) || + (image++, m5 == RAIL_BIT_DIAG1) || + (image++, m5 == RAIL_BIT_UPPER) || + (image++, m5 == RAIL_BIT_LOWER) || + (image++, m5 == RAIL_BIT_RIGHT) || + (image++, m5 == RAIL_BIT_LEFT) || + (image++, m5 == (RAIL_BIT_DIAG1|RAIL_BIT_DIAG2)) || + + (image = 0x40B, m5 == (RAIL_BIT_UPPER|RAIL_BIT_LOWER)) || + (image++, m5 == (RAIL_BIT_LEFT|RAIL_BIT_RIGHT)) || + + (special=true, false) || + + (image = 0x3FA, !(m5 & (RAIL_BIT_RIGHT|RAIL_BIT_UPPER|RAIL_BIT_DIAG1))) || + (image++, !(m5 & (RAIL_BIT_LEFT|RAIL_BIT_LOWER|RAIL_BIT_DIAG1))) || + (image++, !(m5 & (RAIL_BIT_LEFT|RAIL_BIT_UPPER|RAIL_BIT_DIAG2))) || + (image++, !(m5 & (RAIL_BIT_RIGHT|RAIL_BIT_LOWER|RAIL_BIT_DIAG2))) || + (image++, true); + + if (ti->tileh != 0) { + int f = GetRailFoundation(ti->tileh, ti->map5 & 0x3F); + if (f) DrawFoundation(ti, f); + + // default sloped sprites.. + if (ti->tileh != 0) image = _track_sloped_sprites[ti->tileh - 1] + 0x3F3; + } + + if ((_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK)==RAIL_GROUND_BROWN) + image = (image & 0xFFFF) | 0x3178000; // use a brown palette + else if ((_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK)==RAIL_GROUND_ICE_DESERT) + image += 26; + + DrawGroundSprite(image + tracktype_offs); + + if (special) { + if (m5 & RAIL_BIT_DIAG1) DrawGroundSprite(0x3ED + tracktype_offs); + if (m5 & RAIL_BIT_DIAG2) DrawGroundSprite(0x3EE + tracktype_offs); + if (m5 & RAIL_BIT_UPPER) DrawGroundSprite(0x3EF + tracktype_offs); + if (m5 & RAIL_BIT_LOWER) DrawGroundSprite(0x3F0 + tracktype_offs); + if (m5 & RAIL_BIT_LEFT) DrawGroundSprite(0x3F2 + tracktype_offs); + if (m5 & RAIL_BIT_RIGHT) DrawGroundSprite(0x3F1 + tracktype_offs); + } + + if (_display_opt & DO_FULL_DETAIL) { + _detailed_track_proc[_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK](ti); + } + + /* draw signals also? */ + if (!(ti->map5 & RAIL_TYPE_SIGNALS)) + return; + + { + byte m23; + + m23 = (_map3_lo[ti->tile] >> 4) | (_map2[ti->tile] & 0xF0); + +#define HAS_SIGNAL(x) (m23 & (byte)(0x1 << (x))) +#define ISON_SIGNAL(x) (m23 & (byte)(0x10 << (x))) +#define MAYBE_DRAW_SIGNAL(x,y,z) if (HAS_SIGNAL(x)) DrawSignalHelper(ti, ISON_SIGNAL(x), ((y-0x4FB) << 4)|(z)) + + if (!(m5 & RAIL_BIT_DIAG2)) { + if (!(m5 & RAIL_BIT_DIAG1)) { + if (m5 & RAIL_BIT_LEFT) { + MAYBE_DRAW_SIGNAL(2, 0x509, 0); + MAYBE_DRAW_SIGNAL(3, 0x507, 1); + } + if (m5 & RAIL_BIT_RIGHT) { + MAYBE_DRAW_SIGNAL(0, 0x509, 2); + MAYBE_DRAW_SIGNAL(1, 0x507, 3); + } + if (m5 & RAIL_BIT_UPPER) { + MAYBE_DRAW_SIGNAL(3, 0x505, 4); + MAYBE_DRAW_SIGNAL(2, 0x503, 5); + } + if (m5 & RAIL_BIT_LOWER) { + MAYBE_DRAW_SIGNAL(1, 0x505, 6); + MAYBE_DRAW_SIGNAL(0, 0x503, 7); + } + } else { + MAYBE_DRAW_SIGNAL(3, 0x4FB, 8); + MAYBE_DRAW_SIGNAL(2, 0x4FD, 9); + } + } else { + MAYBE_DRAW_SIGNAL(3, 0x4FF, 10); + MAYBE_DRAW_SIGNAL(2, 0x501, 11); + } + } + } else { + const byte *s; + const DrawTrackSeqStruct *drss; + + if (!(m5 & (RAIL_TYPE_MASK&~RAIL_TYPE_SPECIAL))) + return; + + if (ti->tileh != 0) { DrawFoundation(ti, ti->tileh); } + + s = _track_depot_layout_table[m5 & 0x3F]; + + image = *(uint16*)s; + if (image & 0x8000) image = (image & 0x7FFF) + tracktype_offs; + + // adjust ground tile for desert + // (don't adjust for arctic, because snow in depots looks weird) + if ((_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK)==RAIL_GROUND_ICE_DESERT && _opt.landscape == LT_DESERT) + { + if(image!=3981) + image += 26; // tile with tracks + else + image = 4550; // flat ground + } + + DrawGroundSprite(image); + + drss = (const DrawTrackSeqStruct*)(s + sizeof(uint16)); + + while ((image=drss->image) != 0) { + if (image & 0x8000) + image |= _drawtile_track_palette; + image += tracktype_offs; + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + AddSortableSpriteToDraw(image, ti->x | drss->subcoord_x, + ti->y | drss->subcoord_y, drss->width, drss->height, 0x17, ti->z); + drss++; + } + } +} + +void DrawTrainDepotSprite(int x, int y, int image, int railtype) +{ + uint32 ormod, img; + const DrawTrackSeqStruct *dtss; + const byte *t; + + /* baseimage */ + railtype *= TRACKTYPE_SPRITE_PITCH; + + ormod = PLAYER_SPRITE_COLOR(_local_player); + + t = _track_depot_layout_table[image]; + + x+=33; + y+=17; + + img = *(uint16*)t; + if (img & 0x8000) img = (img & 0x7FFF) + railtype; + DrawSprite(img, x, y); + + for(dtss = (DrawTrackSeqStruct *)(t + sizeof(uint16)); dtss->image != 0; dtss++) { + Point pt = RemapCoords(dtss->subcoord_x, dtss->subcoord_y, 0); + image = dtss->image; + if (image & 0x8000) image |= ormod; + DrawSprite(image + railtype, x + pt.x, y + pt.y); + } +} + +#define NUM_SSD_ENTRY 256 +#define NUM_SSD_STACK 32 + +typedef struct SetSignalsData { + int cur; + int cur_stack; + bool stop; + bool has_presignal; + + // presignal info + int presignal_exits; + int presignal_exits_free; + + // these are used to keep track of the signals that change. + byte bit[NUM_SSD_ENTRY]; + TileIndex tile[NUM_SSD_ENTRY]; + + // these are used to keep track of the stack that modifies presignals recursively + TileIndex next_tile[NUM_SSD_STACK]; + byte next_dir[NUM_SSD_STACK]; + +} SetSignalsData; + +static bool SetSignalsEnumProc(uint tile, SetSignalsData *ssd, int track, uint length, byte *state) +{ + // the tile has signals? + if (IS_TILETYPE(tile, MP_RAILWAY)) { + if ((_map5[tile]&RAIL_TYPE_MASK) == RAIL_TYPE_SIGNALS) { + if ((_map3_lo[tile] & _signals_table_both[track]) != 0) { + + // is the signal pointing in to the segment existing? + if ((_map3_lo[tile] & _signals_table[track]) != 0) { + // yes, add the signal to the list of signals + if (ssd->cur != NUM_SSD_ENTRY) { + ssd->tile[ssd->cur] = tile; // remember the tile index + ssd->bit[ssd->cur] = track; // and the controlling bit number + ssd->cur++; + } + + // remember if this block has a presignal. + ssd->has_presignal |= (_map3_hi[tile]&1); + } + + // is this an exit signal that points out from the segment? + if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) { + ssd->presignal_exits++; + if ((_map2[tile]&_signals_table_other[track]) != 0) + ssd->presignal_exits_free++; + } + + return true; + } + } else if (IS_RAIL_DEPOT(_map5[tile])) + return true; // don't look further if the tile is a depot + } + return false; +} + +static void SetSignalsAfterProc(TrackPathFinder *tpf) +{ + SetSignalsData *ssd = tpf->userdata; + Vehicle *v; + uint tile, hash, val, offs; + TrackPathFinderLink *link; + + ssd->stop = false; + + // for each train, check if it is in the segment. + // then we know that the signal should be red. + FOR_ALL_VEHICLES(v) { + if (v->type != VEH_Train) + continue; + + tile = v->tile; + if (v->u.rail.track == 0x40) { tile = GetVehicleOutOfTunnelTile(v); } + + hash = PATHFIND_HASH_TILE(tile); + + val = tpf->hash_head[hash]; + if (val == 0) + continue; + + if (!(val & 0x8000)) { + if ((TileIndex)tile == tpf->hash_tile[hash]) + goto check_val; + } else { + offs = tpf->hash_tile[hash]; + do { + link = PATHFIND_GET_LINK_PTR(tpf, offs); + if ( (TileIndex)tile == link->tile) { + val = link->flags; +check_val:; + // the train is on the track, in either direction? + if (val & (v->u.rail.track + (v->u.rail.track<<8))) { + ssd->stop = true; + return; + } + break; + } + } while ((offs=link->next) != 0xFFFF); + } + } +} + +static const byte _dir_from_track[14] = { + 0,1,0,1,2,1, 0,0, + 2,3,3,2,3,0, +}; + + +static void ChangeSignalStates(SetSignalsData *ssd) +{ + int i; + + // thinking about presignals... + // the presignal is green if, + // if no train is in the segment AND + // there is at least one green exit signal OR + // there are no exit signals in the segment + + // then mark the signals in the segment accordingly + for(i=0; i!=ssd->cur; i++) { + uint tile = ssd->tile[i]; + byte bit = _signals_table[ssd->bit[i]]; + byte m2 = _map2[tile]; + + // presignals don't turn green if there is at least one presignal exit and none are free + if (_map3_hi[tile] & 1) { + int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free; + + // subtract for dual combo signals so they don't count themselves + if (_map3_hi[tile]&2 && _map3_lo[tile]&_signals_table_other[ssd->bit[i]]) { + ex--; + if ((_map2[tile]&_signals_table_other[ssd->bit[i]]) != 0) exfree--; + } + + // if we have exits and none are free, make red. + if (ex && !exfree) goto make_red; + } + + // check if the signal is unaffected. + if (ssd->stop) { +make_red: + // turn red + if ( (bit&m2) == 0 ) + continue; + } else { + // turn green + if ( (bit&m2) != 0 ) + continue; + } + + // Update signals on the other side of this exit signal, it changed. + // If this segment has presignals, then we treat exit signals going into the segment as normal signals. + if (_map3_hi[tile]&2 && (_map3_hi[tile]&1 || !ssd->has_presignal)) { + if (ssd->cur_stack != NUM_SSD_STACK) { + ssd->next_tile[ssd->cur_stack] = tile; + ssd->next_dir[ssd->cur_stack] = _dir_from_track[ssd->bit[i]]; + ssd->cur_stack++; + } else { + printf("NUM_SSD_STACK too small\n"); + } + } + + // it changed, so toggle it + _map2[tile] = m2 ^ bit; + MarkTileDirtyByTile(tile); + } +} + + +bool UpdateSignalsOnSegment(uint tile, byte direction) +{ + SetSignalsData ssd; + int result = -1; + + ssd.cur_stack = 0; + direction>>=1; + + for(;;) { + // go through one segment and update all signals pointing into that segment. + ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; + ssd.has_presignal = false; + + FollowTrack(tile, 0xC000, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd); + ChangeSignalStates(&ssd); + + // remember the result only for the first iteration. + if (result < 0) result = ssd.stop; + + // if any exit signals were changed, we need to keep going to modify the stuff behind those. + if(!ssd.cur_stack) + break; + + // one or more exit signals were changed, so we need to update another segment too. + tile = ssd.next_tile[--ssd.cur_stack]; + direction = ssd.next_dir[ssd.cur_stack]; + } + + return (bool)result; +} + +void SetSignalsOnBothDir(uint tile, byte track) +{ + static const byte _search_dir_1[6] = {1, 3, 1, 3, 5, 3}; + static const byte _search_dir_2[6] = {5, 7, 7, 5, 7, 1}; + + UpdateSignalsOnSegment(tile, _search_dir_1[track]); + UpdateSignalsOnSegment(tile, _search_dir_2[track]); +} + +uint GetSlopeZ_Track(TileInfo *ti) +{ + uint z = ti->z; + int th = ti->tileh; + + // check if it's a foundation + if (ti->tileh != 0) { + if ((ti->map5 & 0x80) == 0) { + uint f = GetRailFoundation(ti->tileh, ti->map5 & 0x3F); + if (f != 0) { + if (f < 15) { + // leveled foundation + return z + 8; + } + // inclined foundation + th = _inclined_tileh[f - 15]; + } + } else if ((ti->map5 & 0xC0) == 0xC0) { + // depot or checkpoint + return z + 8; + } + return GetPartialZ(ti->x&0xF, ti->y&0xF, th) + z; + } + return z; +} + +static void GetAcceptedCargo_Track(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void AnimateTile_Track(uint tile) +{ + /* not used */ +} + +static void TileLoop_Track(uint tile) +{ + byte a2; + byte rail; + byte m2; + byte owner; + + m2 = _map2[tile] & 0xF; + + /* special code for alps landscape */ + if (_opt.landscape == LT_HILLY) { + /* convert into snow? */ + if (GetTileZ(tile) > _opt.snow_line) { + a2 = RAIL_GROUND_ICE_DESERT; + goto modify_me; + } + + /* special code for desert landscape */ + } else if (_opt.landscape == LT_DESERT) { + /* convert into desert? */ + if (GetMapExtraBits(tile) == 1) { + a2 = RAIL_GROUND_ICE_DESERT; + goto modify_me; + } + } + + // Don't continue tile loop for depots + if (_map5[tile] & RAIL_TYPE_SPECIAL) + return; + + a2 = RAIL_GROUND_GREEN; + + if (m2 != RAIL_GROUND_BROWN) { /* wait until bottom is green */ + /* determine direction of fence */ + rail = _map5[tile] & RAIL_BIT_MASK; + + if (rail == RAIL_BIT_UPPER) { + a2 = RAIL_GROUND_FENCE_HORIZ1; + } else if (rail == RAIL_BIT_LOWER) { + a2 = RAIL_GROUND_FENCE_HORIZ2; + } else if (rail == RAIL_BIT_LEFT) { + a2 = RAIL_GROUND_FENCE_VERT1; + } else if (rail == RAIL_BIT_RIGHT) { + a2 = RAIL_GROUND_FENCE_VERT2; + } else { + owner = _map_owner[tile]; + + if ( (!(rail&(RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LEFT)) && (rail&RAIL_BIT_DIAG1)) || rail==(RAIL_BIT_LOWER|RAIL_BIT_RIGHT)) { + if (!IS_TILETYPE(tile + TILE_XY(0,-1), MP_RAILWAY) || + owner != _map_owner[tile + TILE_XY(0,-1)] || + (_map5[tile + TILE_XY(0,-1)]==RAIL_BIT_UPPER || _map5[tile + TILE_XY(0,-1)]==RAIL_BIT_LEFT)) + a2 = RAIL_GROUND_FENCE_NW; + } + + if ( (!(rail&(RAIL_BIT_DIAG2|RAIL_BIT_LOWER|RAIL_BIT_RIGHT)) && (rail&RAIL_BIT_DIAG1)) || rail==(RAIL_BIT_UPPER|RAIL_BIT_LEFT)) { + if (!IS_TILETYPE(tile + TILE_XY(0,1), MP_RAILWAY) || + owner != _map_owner[tile + TILE_XY(0,1)] || + (_map5[tile + TILE_XY(0,1)]==RAIL_BIT_LOWER || _map5[tile + TILE_XY(0,1)]==RAIL_BIT_RIGHT)) + a2 = (a2 == RAIL_GROUND_FENCE_NW) ? RAIL_GROUND_FENCE_SENW : RAIL_GROUND_FENCE_SE; + } + + if ( (!(rail&(RAIL_BIT_DIAG1|RAIL_BIT_UPPER|RAIL_BIT_RIGHT)) && (rail&RAIL_BIT_DIAG2)) || rail==(RAIL_BIT_LOWER|RAIL_BIT_LEFT)) { + if (!IS_TILETYPE(tile + TILE_XY(-1,0), MP_RAILWAY) || + owner != _map_owner[tile + TILE_XY(-1,0)] || + (_map5[tile + TILE_XY(-1,0)]==RAIL_BIT_UPPER || _map5[tile + TILE_XY(-1,0)]==RAIL_BIT_RIGHT)) + a2 = RAIL_GROUND_FENCE_NE; + } + + if ( (!(rail&(RAIL_BIT_DIAG1|RAIL_BIT_LOWER|RAIL_BIT_LEFT)) && (rail&RAIL_BIT_DIAG2)) || rail==(RAIL_BIT_UPPER|RAIL_BIT_RIGHT)) { + if (!IS_TILETYPE(tile + TILE_XY(1,0), MP_RAILWAY) || + owner != _map_owner[tile + TILE_XY(1,0)] || + (_map5[tile + TILE_XY(1,0)]==RAIL_BIT_LOWER || _map5[tile + TILE_XY(1,0)]==RAIL_BIT_LEFT)) + a2 = (a2 == RAIL_GROUND_FENCE_NE) ? RAIL_GROUND_FENCE_NESW : RAIL_GROUND_FENCE_SW; + } + } + } + +modify_me:; + /* tile changed? */ + if ( m2 != a2) { + _map2[tile] = (_map2[tile] & ~RAIL_MAP2LO_GROUND_MASK) | a2; + MarkTileDirtyByTile(tile); + } +} + + +static uint32 GetTileTrackStatus_Track(uint tile, int mode) { + byte m5, a, b; + uint32 ret; + + if (mode != 0) + return 0; + + m5 = _map5[tile]; + + if (!(m5 & RAIL_TYPE_SPECIAL)) { + ret = (m5 | (m5 << 8)) & 0x3F3F; + if (!(m5 & RAIL_TYPE_SIGNALS)) { + if ( (ret & 0xFF) == 3) + ret |= 0x40; + } else { + /* has_signals */ + + a = _map3_lo[tile]; + b = _map2[tile]; + + b &= a; + + if ((a & 0xC0) == 0) { b |= 0xC0; } + if ((a & 0x30) == 0) { b |= 0x30; } + + if ( (b & 0x80) == 0) ret |= 0x10070000; + if ( (b & 0x40) == 0) ret |= 0x7100000; + if ( (b & 0x20) == 0) ret |= 0x20080000; + if ( (b & 0x10) == 0) ret |= 0x8200000; + } + } else if (m5 & 0x40) { + static const byte _train_spec_tracks[6] = {1,2,1,2,1,2}; + m5 = _train_spec_tracks[m5 & 0x3F]; + ret = (m5 << 8) + m5; + } else + return 0; + + return ret; +} + +static void ClickTile_Track(uint tile) +{ + if (IS_RAIL_DEPOT(_map5[tile])) + ShowTrainDepotWindow(tile); + else if (IS_RAIL_CHECKPOINT(_map5[tile])) + ShowRenameCheckpointWindow(&_checkpoints[GetCheckpointByTile(tile)]); + +} + +static void GetTileDesc_Track(uint tile, TileDesc *td) +{ + byte m5 = _map5[tile]; + if (!(m5 & 0x80)) { + if(!(m5 & 0x40)) // no signals + td->str = STR_1021_RAILROAD_TRACK; + else + { + switch(_map3_hi[tile] & 0x03) + { + case 0: td->str = STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS; + break; + case 1: td->str = STR_RAILROAD_TRACK_WITH_PRESIGNALS; + break; + case 2: td->str = STR_RAILROAD_TRACK_WITH_EXITSIGNALS; + break; + case 3: td->str = STR_RAILROAD_TRACK_WITH_COMBOSIGNALS; + break; + } + } + } else { + td->str = m5 < 0xC4 ? STR_1023_RAILROAD_TRAIN_DEPOT : STR_LANDINFO_CHECKPOINT; + } + td->owner = _map_owner[tile]; +} + +static void ChangeTileOwner_Track(uint tile, byte old_player, byte new_player) +{ + if (_map_owner[tile] != old_player) + return; + + if (new_player != 255) { + _map_owner[tile] = new_player; + } else { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } +} + +static const byte _fractcoords_behind[4] = { 0x8F, 0x8, 0x80, 0xF8 }; +static const byte _fractcoords_enter[4] = { 0x8A, 0x48, 0x84, 0xA8 }; +static const byte _fractcoords_leave[4] = { 0x81, 0xD8, 0x8D, 0x18 }; +static const byte _enter_directions[4] = {5, 7, 1, 3}; +static const byte _leave_directions[4] = {1, 3, 5, 7}; +static const byte _depot_track_mask[4] = {1, 2, 1, 2}; + +uint32 VehicleEnter_Track(Vehicle *v, uint tile, int x, int y) +{ + byte fract_coord; + int dir; + + // this routine applies only to trains in depot tiles + if (v->type != VEH_Train || !IS_RAIL_DEPOT(_map5[tile])) + return 0; + + /* depot direction */ + dir = _map5[tile] & RAIL_DEPOT_DIR; + + fract_coord = (x & 0xF) + ((y & 0xF) << 4); + if (_fractcoords_behind[dir] == fract_coord) { + /* make sure a train is not entering the tile from behind */ + return 8; + } else if (_fractcoords_enter[dir] == fract_coord) { + if (_enter_directions[dir] == v->direction) { + /* enter the depot */ + v->u.rail.track = 0x80, + v->vehstatus |= VS_HIDDEN; /* hide it */ + v->direction ^= 4; + if (v->next == NULL) + TrainEnterDepot(v, tile); + v->tile = tile; + InvalidateWindow(WC_VEHICLE_DEPOT, tile); + return 4; + } + } else if (_fractcoords_leave[dir] == fract_coord) { + if (_leave_directions[dir] == v->direction) { + /* leave the depot? */ + if ((v=v->next) != NULL) { + v->vehstatus &= ~VS_HIDDEN; + v->u.rail.track = _depot_track_mask[dir]; + } + } + } + + return 0; +} + +void InitializeRail() +{ + _last_built_train_depot_tile = 0; +} + +const TileTypeProcs _tile_type_rail_procs = { + DrawTile_Track, /* draw_tile_proc */ + GetSlopeZ_Track, /* get_slope_z_proc */ + ClearTile_Track, /* clear_tile_proc */ + GetAcceptedCargo_Track, /* get_accepted_cargo_proc */ + GetTileDesc_Track, /* get_tile_desc_proc */ + GetTileTrackStatus_Track, /* get_tile_track_status_proc */ + ClickTile_Track, /* click_tile_proc */ + AnimateTile_Track, /* animate_tile_proc */ + TileLoop_Track, /* tile_loop_clear */ + ChangeTileOwner_Track, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + VehicleEnter_Track, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; diff --git a/rail_gui.c b/rail_gui.c new file mode 100644 --- /dev/null +++ b/rail_gui.c @@ -0,0 +1,1009 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" +#include "vehicle.h" + +static uint _cur_railtype; +static bool _remove_button_clicked; +static byte _build_depot_direction; + +struct { + byte orientation; + byte numtracks; + byte platlength; + bool dragdrop; +} _railstation; + + +static void HandleStationPlacement(uint start, uint end); +static void ShowBuildTrainDepotPicker(); +static void ShowStationBuilder(); + +typedef void OnButtonClick(Window *w); + +static void CcPlaySound1E(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) SndPlayTileFx(0x1E, tile); +} + +static void GenericPlaceRail(uint tile, int cmd) +{ + DoCommandP(tile, _cur_railtype, cmd, CcPlaySound1E, + _remove_button_clicked ? + CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) | CMD_AUTO | CMD_NO_WATER : + CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) | CMD_AUTO | CMD_NO_WATER + ); +} + +static void PlaceRail_N(uint tile) +{ + int cmd = _tile_fract_coords.x > _tile_fract_coords.y ? 4 : 5; + GenericPlaceRail(tile, cmd); +} + +static void PlaceRail_NE(uint tile) +{ + VpStartPlaceSizing(tile, VPM_FIX_Y); +} + +static void PlaceRail_E(uint tile) +{ + int cmd = _tile_fract_coords.x + _tile_fract_coords.y <= 15 ? 2 : 3; + GenericPlaceRail(tile, cmd); +} + +static void PlaceRail_NW(uint tile) +{ + VpStartPlaceSizing(tile, VPM_FIX_X); +} + +static void PlaceRail_AutoRail(uint tile) +{ + VpStartPlaceSizing(tile, VPM_RAILDIRS); +} + +static int16 _place_depot_offs_xy[4] = { -1, 0x100, 1, -0x100}; + +static void PlaceExtraDepotRail(uint tile, uint16 extra) +{ + byte b = _map5[tile]; + + if (b & 0xC0 || !(b & (extra >> 8))) + return; + + DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_AUTO | CMD_NO_WATER); +} + +static const uint16 _place_depot_extra[12] = { + 0x604, 0x2102, 0x1202, 0x505, + 0x2400, 0x2801, 0x1800, 0x1401, + 0x2203, 0x904, 0x0A05, 0x1103, +}; + + +static void CcDepot(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + int dir = p2; + + SndPlayTileFx(0x1E, tile); + ResetObjectToPlace(); + + tile += _place_depot_offs_xy[dir]; + + if (IS_TILETYPE(tile, MP_RAILWAY)) { + PlaceExtraDepotRail(tile, _place_depot_extra[dir]); + PlaceExtraDepotRail(tile, _place_depot_extra[dir + 4]); + PlaceExtraDepotRail(tile, _place_depot_extra[dir + 8]); + } + } +} + +static void PlaceRail_Depot(uint tile) +{ + DoCommandP(tile, _cur_railtype, _build_depot_direction, CcDepot, + CMD_BUILD_TRAIN_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_100E_CAN_T_BUILD_TRAIN_DEPOT)); +} + +static void PlaceRail_Checkpoint(uint tile) +{ + if (!_remove_button_clicked) { + DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_BUILD_TRAIN_CHECKPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_CHECKPOINT)); + } else { + DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_TRAIN_CHECKPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_CHECKPOINT)); + } +} + +static void CcStation(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1E, tile); + ResetObjectToPlace(); + } +} + +static void PlaceRail_Station(uint tile) +{ + if(_remove_button_clicked) + DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION)); + else if (_railstation.dragdrop) { + VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED); + VpSetPlaceSizingLimit(_patches.station_spread); + } else { + DoCommandP(tile, _railstation.orientation | (_railstation.numtracks<<8) | (_railstation.platlength<<16),_cur_railtype, CcStation, + CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_AUTO | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION)); + } +} + +static void PlaceRail_Signals(uint tile) +{ + uint trackstat; + int i; + + trackstat = (byte)GetTileTrackStatus(tile,0); + + if ((trackstat & 0x30) == 0x30) { + trackstat = (_tile_fract_coords.x <= _tile_fract_coords.y) ? 0x20 : 0x10; + } + + if ((trackstat & 0x0C) == 0x0C) { + trackstat = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? 4 : 8; + } + + // Lookup the bit index + i = 0; + if (trackstat != 0) { while (!(trackstat & 1)) { i++; trackstat >>= 1; }} + + if (!_remove_button_clicked) { + DoCommandP(tile, i + (_ctrl_pressed ? 8 : 0), 0, CcPlaySound1E, + CMD_BUILD_SIGNALS | CMD_AUTO | CMD_MSG(STR_1010_CAN_T_BUILD_SIGNALS_HERE)); + } else { + DoCommandP(tile, i, 0, CcPlaySound1E, + CMD_REMOVE_SIGNALS | CMD_AUTO | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM)); + } +} + +static void PlaceRail_Bridge(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_OR_Y); +} + +static void CcBuildTunnel(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1E, tile); + ResetObjectToPlace(); + } else { + SetRedErrorSquare(_build_tunnel_endtile); + } +} + +static void PlaceRail_Tunnel(uint tile) +{ + DoCommandP(tile, _cur_railtype, 0, CcBuildTunnel, + CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE)); +} + +void PlaceProc_BuyLand(uint tile) +{ + DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_PURCHASE_LAND_AREA | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_5806_CAN_T_PURCHASE_THIS_LAND)); +} + +static void PlaceRail_ConvertRail(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_AND_Y | (1<<4)); +} + +static void BuildRailClick_AutoRail(Window *w) +{ + HandlePlacePushButton(w, 3, _cur_railtype + SPR_OPENTTD_BASE + 4, 1, PlaceRail_AutoRail); +} + +static void BuildRailClick_N(Window *w) +{ + HandlePlacePushButton(w, 4, _cur_railtype*4 + 0x4EF, 1, PlaceRail_N); +} + +static void BuildRailClick_NE(Window *w) +{ + HandlePlacePushButton(w, 5, _cur_railtype*4 + 0x4F0, 1, PlaceRail_NE); +} + +static void BuildRailClick_E(Window *w) +{ + HandlePlacePushButton(w, 6, _cur_railtype*4 + 0x4F1, 1, PlaceRail_E); +} + +static void BuildRailClick_NW(Window *w) +{ + HandlePlacePushButton(w, 7, _cur_railtype*4 + 0x4F2, 1, PlaceRail_NW); +} + +static void BuildRailClick_Demolish(Window *w) +{ + HandlePlacePushButton(w, 8, ANIMCURSOR_DEMOLISH, 1, PlaceProc_DemolishArea); +} + +static void BuildRailClick_Lower(Window *w) +{ + HandlePlacePushButton(w, 9, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand); +} + +static void BuildRailClick_Raise(Window *w) +{ + HandlePlacePushButton(w, 10, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand); +} + +static const SpriteID _depot_cursors[] = { + 0x510, + SPR_OPENTTD_BASE + 14, + SPR_OPENTTD_BASE + 15, +}; + +static void BuildRailClick_Depot(Window *w) +{ + if (HandlePlacePushButton(w, 11, _depot_cursors[_cur_railtype], 1, PlaceRail_Depot)) ShowBuildTrainDepotPicker(); +} + +static void BuildRailClick_Station(Window *w) +{ + if (HandlePlacePushButton(w, 12, 0x514, 1, PlaceRail_Station)) ShowStationBuilder(); +} + +static void BuildRailClick_Signals(Window *w) +{ + HandlePlacePushButton(w, 13, ANIMCURSOR_BUILDSIGNALS, 1, PlaceRail_Signals); +} + +static void BuildRailClick_Bridge(Window *w) +{ + HandlePlacePushButton(w, 14, 0xA21, 1, PlaceRail_Bridge); +} + +static void BuildRailClick_Tunnel(Window *w) +{ + HandlePlacePushButton(w, 15, 0x982 + _cur_railtype, 3, PlaceRail_Tunnel); +} + +static void BuildRailClick_Remove(Window *w) +{ + if (w->disabled_state & (1<<16)) + return; + SetWindowDirty(w); + SndPlayFx(0x13); + + _thd.make_square_red = !!((w->click_state ^= (1 << 16)) & (1<<16)); + _remove_button_clicked = (w->click_state & (1 << 16)) != 0; + + // handle station builder + if( w->click_state & (1 << 12) ) + { + if(_remove_button_clicked) + SetTileSelectSize(1, 1); + else + BringWindowToFrontById(WC_BUILD_STATION, 0); + } +} + +static void BuildRailClick_Sign(Window *w) +{ + HandlePlacePushButton(w, 17, 0x12B8, 1, PlaceProc_BuyLand); +} + +static void BuildRailClick_Checkpoint(Window *w) +{ + HandlePlacePushButton(w, 18, SPR_OPENTTD_BASE + 7, 1, PlaceRail_Checkpoint); +} + +static void BuildRailClick_Convert(Window *w) +{ + HandlePlacePushButton(w, 19, (SPR_OPENTTD_BASE + 26) + _cur_railtype * 2, 1, PlaceRail_ConvertRail); +} + + +static void DoRailroadTrack(int mode) +{ + DoCommandP(TILE_FROM_XY(_thd.selstart.x, _thd.selstart.y), PACK_POINT(_thd.selend.x, _thd.selend.y), (mode << 4) | _cur_railtype, NULL, + _remove_button_clicked ? + CMD_REMOVE_RAILROAD_TRACK | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) : + CMD_BUILD_RAILROAD_TRACK | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) + ); +} + +typedef struct { + byte bit, a,b, mouse; +} BestFitStruct; + +#define M(d,m) (d << 6) | (m) +static const BestFitStruct _bestfit[] = { + // both edges have rail + {2, M(0, 1+8), M(3, 2+8), 0}, // upper track + {3, M(2, 1+4), M(1, 2+4), 0}, // lower track + + {4, M(2, 1+32), M(3, 2+32), 1<<2}, // left track + {5, M(0, 1+16), M(1, 2+16), 1<<3}, // right track + + {0, M(0,1+8+16), M(2,1+4+32), 0}, // diag1 track + {1, M(3,2+8+32), M(1,2+4+16), 0}, // diag2 track + + // one edge with rail + {0, M(0,1), 0, 0}, // diag1 track + {0, M(2,1), 0, 0}, // diag1 track + + {1, M(1,2), 0, 0}, // diag2 track + {1, M(3,2), 0, 0}, // diag2 track + + {2, M(0,8), 0, 1<<0}, // upper track + {2, M(3,8), 0, 1<<0}, // upper track + + {3, M(1,4), 0, 1<<1}, // lower track + {3, M(2,4), 0, 1<<1}, // lower track + + {4, M(2,32), 0, 1<<2}, // left track + {4, M(3,32), 0, 1<<2}, // left track + + {5, M(0,16), 0, 1<<3}, // right track + {5, M(1,16), 0, 1<<3}, // right track + + {0xff,0,0}, +}; +#undef M + +static int GetBestArea(int x, int y) +{ + int r = 0; + if (x + y > 0x10) r += 2; + else if (x + y == 0x10) return -1; + if (y - x > 0) r += 1; + else if (y - x == 0) return -1; + return r; +} + +int GetBestFit1x1(int x, int y) +{ + byte m[5]; + const BestFitStruct *bfs; + byte mouse; + uint tile; + int best; + int i; + + // determine the mouse regions + mouse = ((x & 0xF) + (y & 0xF) < 0x10 ? 1 << 0 : 1 << 1) + + ((x & 0xF) > (y & 0xF) ? 1 << 2 : 1 << 3); + + // get the rail in each direction + tile = TILE_FROM_XY(x,y); + for(i=0; i!=5; i++) { + static TileIndexDiff _tile_inc[5] = { + TILE_XY(-1, 0), + TILE_XY(0, 1) - TILE_XY(-1, 0), + TILE_XY(1, 0) - TILE_XY(0, 1), + TILE_XY(0, -1) - TILE_XY(1, 0), + TILE_XY(0, 0) - TILE_XY(0, -1), + }; + tile += _tile_inc[i]; + m[i] = 0; + if (IS_TILETYPE(tile, MP_RAILWAY) && _map5[tile] < 0x80) + m[i] = _map5[tile]&0x3F; + + // handle tracks under bridge + if(IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile]&0xF8)==0xE0) + m[i] = (byte) !(_map5[tile]&0x01) + 1; + + if (_remove_button_clicked) m[i] ^= 0x3F; + } + + // check "mouse gesture"? + { + int a1,a2; + if ((a1 = GetBestArea(x & 0xF, y & 0xF)) != -1 && (a2 = GetBestArea(_tile_fract_coords.x, _tile_fract_coords.y)) != -1 && a1 != a2) { + static const byte _get_dir_by_areas[4][4] = { + {0,2,4,1}, + {2,0,0,5}, + {4,0,0,3}, + {1,5,3,0}, + }; + i = _get_dir_by_areas[a2][a1]; + if (!HASBIT(m[4], i)) + return i; + } + } + // check each bestfit struct + for(bfs = _bestfit, best=-1; bfs->bit != 0xFF; bfs++) { + if ((bfs->a & m[bfs->a >> 6]) && (!bfs->b || bfs->b & m[bfs->b >> 6]) && !HASBIT(m[4], bfs->bit)) { + if ( (byte)(~mouse & bfs->mouse) == 0) + return bfs->bit; + if (best != -1) + return best; + best = bfs->bit; + } + } + + return best; +} + +static void SwapSelection() +{ + TileHighlightData *thd = &_thd; + Point pt = thd->selstart; + thd->selstart.x = thd->selend.x & ~0xF; + thd->selstart.y = thd->selend.y & ~0xF; + thd->selend = pt; +} + +static bool Check2x1AutoRail(int mode) +{ + TileHighlightData *thd = &_thd; + int fxpy = _tile_fract_coords.x + _tile_fract_coords.y; + int sxpy = (thd->selend.x & 0xF) + (thd->selend.y & 0xF); + int fxmy = _tile_fract_coords.x - _tile_fract_coords.y; + int sxmy = (thd->selend.x & 0xF) - (thd->selend.y & 0xF); + + switch(mode) { + case 0: + if (fxpy >= 20 && sxpy <= 12) { SwapSelection(); DoRailroadTrack(0); return true; } + if (fxmy < -3 && sxmy > 3) { DoRailroadTrack(0); return true; } + break; + + case 1: + if (fxmy > 3 && sxmy < -3) { SwapSelection(); DoRailroadTrack(0); return true; } + if (fxpy <= 12 && sxpy >= 20) { DoRailroadTrack(0); return true; } + break; + + case 2: + if (fxmy > 3 && sxmy < -3) { DoRailroadTrack(3); return true; } + if (fxpy >= 20 && sxpy <= 12) { SwapSelection(); DoRailroadTrack(0); return true; } + break; + + case 3: + if (fxmy < -3 && sxmy > 3) { SwapSelection(); DoRailroadTrack(3); return true; } + if (fxpy <= 12 && sxpy >= 20) { DoRailroadTrack(0); return true; } + break; + } + + return false; +} + + +static void HandleAutodirPlacement() +{ + TileHighlightData *thd = &_thd; + int bit; + + if (thd->drawstyle == HT_RECT) { + int dx = thd->selstart.x - (thd->selend.x&~0xF); + int dy = thd->selstart.y - (thd->selend.y&~0xF); + + if (dx == 0 && dy == 0 ) { + // 1x1 tile + bit = GetBestFit1x1(thd->selend.x, thd->selend.y); + if (bit == -1) return; + GenericPlaceRail(TILE_FROM_XY(thd->selend.x, thd->selend.y), bit); + } else if (dx == 0) { + if (dy == -16) { + if (Check2x1AutoRail(0)) return; + } else if (dy == 16) { + if (Check2x1AutoRail(1)) return; + } + // same x coordinate + DoRailroadTrack(VPM_FIX_X); + } else { + // same y coordinate + // check it's it -16 or 16, then we must check if it should be normal tiles or special tiles. + if (dx == -16) { + if (Check2x1AutoRail(2)) return; + } else if (dx == 16) { + if (Check2x1AutoRail(3)) return; + } + DoRailroadTrack(VPM_FIX_Y); + } + } else { + DoRailroadTrack(thd->drawstyle & 1 ? 0 : 3); + } +} + +static OnButtonClick * const _build_railroad_button_proc[] = { + BuildRailClick_AutoRail, + BuildRailClick_N, + BuildRailClick_NE, + BuildRailClick_E, + BuildRailClick_NW, + BuildRailClick_Demolish, + BuildRailClick_Lower, + BuildRailClick_Raise, + BuildRailClick_Depot, + BuildRailClick_Station, + BuildRailClick_Signals, + BuildRailClick_Bridge, + BuildRailClick_Tunnel, + BuildRailClick_Remove, + BuildRailClick_Sign, + BuildRailClick_Checkpoint, + BuildRailClick_Convert, +}; + +static const uint16 _rail_keycodes[] = { + '5', + '1', + '2', + '3', + '4', + '6', + '7', + '8', + 0, // depot + 0, // station + 'S',// signals + 'B',// bridge + 'T',// tunnel + 'R',// remove + 0, // sign + 'C',// checkpoint +}; + + + + +static void BuildRailToolbWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + w->disabled_state &= ~(1 << 16); + if (!(w->click_state & ((1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<12)|(1<<13)|(1<<18)))) { + w->disabled_state |= (1 << 16); + w->click_state &= ~(1<<16); + } + DrawWindowWidgets(w); + break; + + case WE_CLICK: + if (e->click.widget >= 3) { + _remove_button_clicked = false; + _build_railroad_button_proc[e->click.widget - 3](w); + } + break; + + case WE_KEYPRESS: { + int i; + for(i=0; i!=lengthof(_rail_keycodes); i++) + if (e->keypress.keycode == _rail_keycodes[i]) { + e->keypress.cont = false; + _remove_button_clicked = false; + _build_railroad_button_proc[i](w); + break; + } + break; + } + + case WE_PLACE_OBJ: + _place_proc(e->place.tile); + return; + + case WE_PLACE_DRAG: { + VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata & 0xF); + return; + } + + case WE_PLACE_MOUSEUP: + if (e->click.pt.x != -1) { + uint start_tile = e->place.starttile; + uint end_tile = e->place.tile; + + if (e->place.userdata == VPM_X_OR_Y) { + ResetObjectToPlace(); + ShowBuildBridgeWindow(start_tile, end_tile, _cur_railtype); + } else if (e->place.userdata == VPM_RAILDIRS) { + bool old = _remove_button_clicked; + if (_ctrl_pressed) _remove_button_clicked = true; + HandleAutodirPlacement(); + _remove_button_clicked = old; + } else if (e->place.userdata == VPM_X_AND_Y) { + DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + } else if (e->place.userdata == (VPM_X_AND_Y | (1<<4))) { + DoCommandP(end_tile, start_tile, _cur_railtype, CcPlaySound10, CMD_CONVERT_RAIL | CMD_MSG(STR_CANT_CONVERT_RAIL)); + } else if (e->place.userdata == (VPM_X_AND_Y | (2<<4))) { + DoCommandP(end_tile, start_tile, _cur_railtype, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO); + } else if (e->place.userdata == VPM_X_AND_Y_LIMITED) { + HandleStationPlacement(start_tile, end_tile); + } else { + DoRailroadTrack(e->place.userdata); + } + } + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + + w = FindWindowById(WC_BUILD_STATION, 0); + if (w != NULL) WP(w,def_d).close=true; + w = FindWindowById(WC_BUILD_DEPOT, 0); + if (w != NULL) WP(w,def_d).close=true; + break; + + case WE_PLACE_PRESIZE: { + uint tile = e->place.tile; + DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_BUILD_TUNNEL); + VpSetPresizeRange(tile, _build_tunnel_endtile==0?tile:_build_tunnel_endtile); + } break; + } +} + +static const Widget _build_railroad_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 417, 0, 13, STR_100A_RAILROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, + +{ WWT_PANEL, 7, 110, 113, 14, 35, 0x0, 0x0}, +{ WWT_PANEL, 7, 88, 109, 14, 35, SPR_OPENTTD_BASE + 0, STR_BUILD_AUTORAIL_TIP}, + +{ WWT_PANEL, 7, 0, 21, 14, 35, 0x4E3, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 0x4E4, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 0x4E5, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 66, 87, 14, 35, 0x4E6, STR_1018_BUILD_RAILROAD_TRACK}, + +{ WWT_PANEL, 7, 114, 135, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 136, 157, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 158, 179, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 180, 201, 14, 35, 0x50E, STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING}, + +{ WWT_PANEL, 7, 224, 265, 14, 35, 0x512, STR_101A_BUILD_RAILROAD_STATION}, +{ WWT_PANEL, 7, 266, 287, 14, 35, 0x50B, STR_101B_BUILD_RAILROAD_SIGNALS}, +{ WWT_PANEL, 7, 288, 329, 14, 35, 0xA22, STR_101C_BUILD_RAILROAD_BRIDGE}, +{ WWT_PANEL, 7, 330, 351, 14, 35, 0x97E, STR_101D_BUILD_RAILROAD_TUNNEL}, +{ WWT_PANEL, 7, 352, 373, 14, 35, 0x2CA, STR_101E_TOGGLE_BUILD_REMOVE_FOR}, +{ WWT_PANEL, 7, 374, 395, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE}, + +{ WWT_PANEL, 7, 202, 223, 14, 35, SPR_OPENTTD_BASE + 3, STR_CONVERT_RAIL_TO_CHECKPOINT_TIP}, +{ WWT_PANEL, 7, 396, 417, 14, 35, SPR_OPENTTD_BASE + 25, STR_CONVERT_RAIL_TIP}, + +{ WWT_LAST}, +}; + +static const WindowDesc _build_railroad_desc = { + 640-418, 22, 418, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_railroad_widgets, + BuildRailToolbWndProc +}; + +static const Widget _build_monorail_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 417, 0, 13, STR_100B_MONORAIL_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, + +{ WWT_PANEL, 7, 110, 113, 14, 35, 0x0, 0x0}, +{ WWT_PANEL, 7, 88, 109, 14, 35, SPR_OPENTTD_BASE + 1, STR_BUILD_AUTORAIL_TIP}, + +{ WWT_PANEL, 7, 0, 21, 14, 35, 0x4E7, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 0x4E8, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 0x4E9, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 66, 87, 14, 35, 0x4EA, STR_1018_BUILD_RAILROAD_TRACK}, + +{ WWT_PANEL, 7, 114, 135, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 136, 157, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 158, 179, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 180, 201, 14, 35, SPR_OPENTTD_BASE + 12, STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING}, + +{ WWT_PANEL, 7, 224, 265, 14, 35, 0x512, STR_101A_BUILD_RAILROAD_STATION}, +{ WWT_PANEL, 7, 266, 287, 14, 35, 0x50B, STR_101B_BUILD_RAILROAD_SIGNALS}, +{ WWT_PANEL, 7, 288, 329, 14, 35, 0xA22, STR_101C_BUILD_RAILROAD_BRIDGE}, +{ WWT_PANEL, 7, 330, 351, 14, 35, 0x97F, STR_101D_BUILD_RAILROAD_TUNNEL}, +{ WWT_PANEL, 7, 352, 373, 14, 35, 0x2CA, STR_101E_TOGGLE_BUILD_REMOVE_FOR}, +{ WWT_PANEL, 7, 374, 395, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE}, + +{ WWT_PANEL, 7, 202, 223, 14, 35, SPR_OPENTTD_BASE + 3, STR_CONVERT_RAIL_TO_CHECKPOINT_TIP}, +{ WWT_PANEL, 7, 396, 417, 14, 35, SPR_OPENTTD_BASE + 27, STR_CONVERT_RAIL_TIP}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_monorail_desc = { + 640-418, 22, 418, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_monorail_widgets, + BuildRailToolbWndProc +}; + +static const Widget _build_maglev_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 417, 0, 13, STR_100C_MAGLEV_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, + +{ WWT_PANEL, 7, 110, 113, 14, 35, 0x0, 0x0}, +{ WWT_PANEL, 7, 88, 109, 14, 35, SPR_OPENTTD_BASE + 2, STR_BUILD_AUTORAIL_TIP}, + +{ WWT_PANEL, 7, 0, 21, 14, 35, 0x4EB, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 0x4EC, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 0x4EE, STR_1018_BUILD_RAILROAD_TRACK}, +{ WWT_PANEL, 7, 66, 87, 14, 35, 0x4ED, STR_1018_BUILD_RAILROAD_TRACK}, + +{ WWT_PANEL, 7, 114, 135, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 136, 157, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 158, 179, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 180, 201, 14, 35, SPR_OPENTTD_BASE + 13, STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING}, + +{ WWT_PANEL, 7, 224, 265, 14, 35, 0x512, STR_101A_BUILD_RAILROAD_STATION}, +{ WWT_PANEL, 7, 266, 287, 14, 35, 0x50B, STR_101B_BUILD_RAILROAD_SIGNALS}, +{ WWT_PANEL, 7, 288, 329, 14, 35, 0xA22, STR_101C_BUILD_RAILROAD_BRIDGE}, +{ WWT_PANEL, 7, 330, 351, 14, 35, 0x980, STR_101D_BUILD_RAILROAD_TUNNEL}, +{ WWT_PANEL, 7, 352, 373, 14, 35, 0x2CA, STR_101E_TOGGLE_BUILD_REMOVE_FOR}, +{ WWT_PANEL, 7, 374, 395, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE}, + +{ WWT_PANEL, 7, 202, 223, 14, 35, SPR_OPENTTD_BASE + 3, STR_CONVERT_RAIL_TO_CHECKPOINT_TIP}, +{ WWT_PANEL, 7, 396, 417, 14, 35, SPR_OPENTTD_BASE + 29, STR_CONVERT_RAIL_TIP}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_maglev_desc = { + 640-418, 22, 418, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_maglev_widgets, + BuildRailToolbWndProc +}; + + +static const WindowDesc * const _build_rr_desc[] = { + &_build_railroad_desc, + &_build_monorail_desc, + &_build_maglev_desc, +}; + +void ShowBuildRailToolbar(int index, int button) +{ + Window *w; + + // don't recreate the window if we're clicking on a button and the window exists. + if (button < 0 || !(w = FindWindowById(WC_BUILD_TOOLBAR, 0)) || w->wndproc != BuildRailToolbWndProc) { + DeleteWindowById(WC_BUILD_TOOLBAR, 0); + _cur_railtype = (byte)index; + w = AllocateWindowDesc(_build_rr_desc[index]); + } + + if (w != NULL && button >= 0) _build_railroad_button_proc[button](w); +} + +static void HandleStationPlacement(uint start, uint end) +{ + uint sx = GET_TILE_X(start); + uint sy = GET_TILE_Y(start); + uint ex = GET_TILE_X(end); + uint ey = GET_TILE_Y(end); + uint w,h; + + if (sx > ex) intswap(sx,ex); + if (sy > ey) intswap(sy,ey); + w = ex - sx + 1; + h = ey - sy + 1; + if (!_railstation.orientation) intswap(w,h); + + DoCommandP(TILE_XY(sx,sy), _railstation.orientation | (w<<8) | (h<<16),_cur_railtype, CcStation, + CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_AUTO | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION)); +} + +static void StationBuildWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: { + uint bits; + + if (WP(w,def_d).close) + return; + + bits = (1<<3) << ( _railstation.orientation); + if (_railstation.dragdrop) { + bits |= (1<<19); + } else { + bits |= (1<<(5-1)) << (_railstation.numtracks); + bits |= (1<<(12-1)) << (_railstation.platlength); + } + bits |= (1<<20) << (_station_show_coverage); + w->click_state = bits; + + if (_railstation.dragdrop) { + SetTileSelectSize(1, 1); + } else { + int x = _railstation.numtracks; + int y = _railstation.platlength; + if (_railstation.orientation == 0) intswap(x,y); + if(!_remove_button_clicked) + SetTileSelectSize(x, y); + } + + if (_station_show_coverage) + SetTileSelectBigSize(-4, -4, 8, 8); + + DrawWindowWidgets(w); + + StationPickerDrawSprite(39, 42, _cur_railtype, 2); + StationPickerDrawSprite(107, 42, _cur_railtype, 3); + + DrawStringCentered(74, 15, STR_3002_ORIENTATION, 0); + DrawStringCentered(74, 76, STR_3003_NUMBER_OF_TRACKS, 0); + DrawStringCentered(74, 101, STR_3004_PLATFORM_LENGTH, 0); + DrawStringCentered(74, 141, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0); + + DrawStationCoverageAreaText(2, 166, (uint)-1); + } break; + + case WE_CLICK: { + switch(e->click.widget) { + case 0: + ResetObjectToPlace(); + break; + case 3: + case 4: + _railstation.orientation = e->click.widget - 3; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + _railstation.numtracks = (e->click.widget - 5) + 1; + _railstation.dragdrop = false; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + _railstation.platlength = (e->click.widget - 12) + 1; + _railstation.dragdrop = false; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + + case 19: + _railstation.dragdrop ^= true; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + + case 20: + case 21: + _station_show_coverage = e->click.widget - 20; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: { + if (WP(w,def_d).close) { + DeleteWindow(w); + return; + } + CheckRedrawStationCoverage(w); + } break; + } +} + +static const Widget _station_builder_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 147, 0, 13, STR_3000_RAIL_STATION_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 147, 14, 199, 0x0, 0}, +{ WWT_PANEL, 14, 7, 72, 26, 73, 0x0, STR_304E_SELECT_RAILROAD_STATION}, +{ WWT_PANEL, 14, 75, 140, 26, 73, 0x0, STR_304E_SELECT_RAILROAD_STATION}, + +{ WWT_CLOSEBOX, 14, 22, 36, 87, 98, STR_00CB_1, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 37, 51, 87, 98, STR_00CC_2, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 52, 66, 87, 98, STR_00CD_3, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 67, 81, 87, 98, STR_00CE_4, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 82, 96, 87, 98, STR_00CF_5, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 97, 111, 87, 98, STR_0335_6, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, +{ WWT_CLOSEBOX, 14, 112, 126, 87, 98, STR_0336_7, STR_304F_SELECT_NUMBER_OF_PLATFORMS}, + +{ WWT_CLOSEBOX, 14, 22, 36, 112, 123, STR_00CB_1, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 37, 51, 112, 123, STR_00CC_2, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 52, 66, 112, 123, STR_00CD_3, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 67, 81, 112, 123, STR_00CE_4, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 82, 96, 112, 123, STR_00CF_5, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 97, 111, 112, 123, STR_0335_6, STR_3050_SELECT_LENGTH_OF_RAILROAD}, +{ WWT_CLOSEBOX, 14, 112, 126, 112, 123, STR_0336_7, STR_3050_SELECT_LENGTH_OF_RAILROAD}, + +//{ WWT_CLOSEBOX, 14, 14, 73, 137, 148, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, +//{ WWT_CLOSEBOX, 14, 74, 133, 137, 148, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, +{ WWT_CLOSEBOX, 14, 37, 111, 126, 137, STR_DRAG_DROP, STR_STATION_DRAG_DROP}, +{ WWT_CLOSEBOX, 14, 14, 73, 152, 163, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, +{ WWT_CLOSEBOX, 14, 74, 133, 152, 163, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, +{ WWT_LAST}, +}; + +static const WindowDesc _station_builder_desc = { + -1, -1, 148, 200, + WC_BUILD_STATION,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _station_builder_widgets, + StationBuildWndProc +}; + +static void ShowStationBuilder() +{ + AllocateWindowDesc(&_station_builder_desc); +} + +static void BuildTrainDepotWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int r; + + w->click_state = (1 << 3) << _build_depot_direction; + DrawWindowWidgets(w); + + r = _cur_railtype; + DrawTrainDepotSprite(70, 17, 0, r); + DrawTrainDepotSprite(70, 69, 1, r); + DrawTrainDepotSprite(2, 69, 2, r); + DrawTrainDepotSprite(2, 17, 3, r); + break; + } + case WE_CLICK: { + switch(e->click.widget) { + case 0: + ResetObjectToPlace(); + break; + case 3: + case 4: + case 5: + case 6: + _build_depot_direction = e->click.widget - 3; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: + if (WP(w,def_d).close) + DeleteWindow(w); + return; + } +} + +static const Widget _build_depot_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 139, 0, 13, STR_1014_TRAIN_DEPOT_ORIENTATION,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 139, 14, 121, 0x0, 0}, +{ WWT_PANEL, 14, 71, 136, 17, 66, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO}, +{ WWT_PANEL, 14, 71, 136, 69, 118, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO}, +{ WWT_PANEL, 14, 3, 68, 69, 118, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO}, +{ WWT_PANEL, 14, 3, 68, 17, 66, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_depot_desc = { + -1,-1, 140, 122, + WC_BUILD_DEPOT,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_depot_widgets, + BuildTrainDepotWndProc +}; + +static void ShowBuildTrainDepotPicker() +{ + AllocateWindowDesc(&_build_depot_desc); +} + +void InitializeRailGui() +{ + _build_depot_direction = 3; + _railstation.numtracks = 1; + _railstation.platlength = 1; + _railstation.dragdrop = true; +} diff --git a/readme.txt b/readme.txt new file mode 100644 --- /dev/null +++ b/readme.txt @@ -0,0 +1,225 @@ +OpenTTD README +Last updated: $LastChangedDate: 2004-07-25 21:22:11 +0200 (Sun, 25 Jul 2004) $ +Release version: 0.3.3 +------------------------------------------------------------------------ + + +Table of Contents: +------------------ +1.0) About +2.0) Contacting + * 2.1 Reporting Bugs +3.0) Supported Platforms +4.0) Running OpenTTD +5.0) OpenTTD features +6.0) Configuration File +7.0) Compiling +8.0) Translating + * 8.1 Guidelines + * 8.2 Translation + * 8.3 Previewing +X.X) Credits + + +1.0) About: +---- ------ +OpenTTD is a clone of Transport Tycoon Deluxe, a popular game originally +written by Chris Sawyer. It attempts to mimic the original game as closely +as possible while extending it with new features. + + +2.0) Contacting: +---- ---------- +The easiest way to contact the OpenTTD team is by submitting bug reports or +posting comments in our forums. You can also chat with us on IRC (#openttd +on irc.freenode.net). + +The OpenTTD homepage is http://www.openttd.com/. + +You can find a forum for OpenTTD at +http://www.tt-forums.net/index.php?c=20 + + +2.1) Reporting Bugs: +---- --------------- +To report a bug, please create a SourceForge account and follow the bugs +link from our homepage. Please make sure the bug is reproducible and +still occurs in the latest daily build or the current SVN version. Also +please look through the existing bug reports briefly to see whether the bug +is not already known. + +The SourceForge project page URL is: http://sourceforge.net/projects/openttd/ +Click on "Bugs" to see the bug tracker. + +Please include the following information in your bug report: + - OpenTTD version (PLEASE test the latest SVN/daily build) + - Bug details, including instructions how to reproduce it + - Platform and compiler (Win32, Linux, FreeBSD, ...) + - Attach a save game or a screenshot if possible + - If this bug only occurred recently please note the last + version without the bug and the first version including + the bug. That way we can fix it quicker by looking at the + changes made. + + +3.0) Supported Platforms: +---- -------------------- +OpenTTD has been ported to several platforms and operating systems. It shouldn't +be very difficult to port it to a new platform. The currently working platforms +are: + + Windows - Win32 GDI (faster) or SDL + Linux - SDL + FreeBSD - SDL + MacOS - SDL + BeOS - SDL + MorphOS - SDL + + +4.0) Running OpenTTD: +---- ---------------- + +Before you run OpenTTD, you need to put the game's datafiles into the data/ +subdirectory. You need the following files from the original Windows version +of TTD as OpenTTD makes use of the original TTD artwork. + +IMPORTANT! You need the files from the WINDOWS version of TTD. + +List of the required files: +sample.cat +trg1r.grf +trgcr.grf +trghr.grf +trgir.grf +trgtr.grf + +If you want music you need to copy the gm/ folder from Windows TTD into your OpenTTD folder, not your data folder. + +You can change the data path (which contains savegames as well) in Makefile.config by setting DATA_DIR_PREFIX and USE_HOMEDIR. + + +5.0) OpenTTD features: +---- ----------------- + +OpenTTD has a lot of features going beyond the original TTD emulation. +Currently there is unfortunately no comprehensive list of features. You could +check the features list on the web, and some optional features can be +controlled through the Configure patches dialog. We also implement some +features known from TTDPatch (http://www.ttdpatch.net/). + +Several important non-standard controls: + +* Use Ctrl to place presignals +* Ctrl-d toggles double mode on win32 + + +6.0) Configuration File: +---- ------------------- +The configuration file for OpenTTD (openttd.cfg) is in a simple windows-like +.INI format. It's mostly undocumented. + + +7.0) Compiling: +---- ---------- +Windows: + You need Microsoft Visual Studio 6 or .NET. Open the project file + and it should build automatically. In case you don't build with SDL, + you need to remove WITH_SDL from the project settings. + (see also docs/Readme_Windows_MSVC6.0.txt) + + You can also build it using the Makefile with MSys/MingW or Cygwin/MingW. + Please read the Makefile for more information. + +Unix: + OpenTTD can be built either with "make" or with "jam". To build with + "make", just type "make", or "gmake" on non-gnu systems. To build with "jam", + first run "./configure" and then "jam". Note that you need SDL to compile + OpenTTD. + (see also docs/Readme_Mandrake_Linux.txt) + +MacOS: + Use "make". + +BeOS: + Use "jam". + +FreeBSD + Use "gmake". + +MorphOS + Use "make". Note that you need the MorphOS SDK and the + powersdl.library SDK. + +8.0) Translating: +---- ------------------- +See http://www.openttd.com/translating.php for up-to-date information. + +8.1) Guidelines: +---- ------------------- +Here are some translation guidelines which you should follow closely. + + * Please contact the development team before begining the translation process! + This avoids double work, as someone else may have already started translating to the same language. + * Translators must use the charater set "Windows latin-1", also known as ISO 8859-1. + Otherwise, some characters will not display correctly in the game. + +8.2) Translation: +---- ------------------- +So, now that you've notified the development team about your intention to translate +(You did, right? Of course you did.) you can pick up english.txt (found in the SVN repository +under /lang) and translate. + +You must change the first two lines of the file appropriately: + +##name English-Name-Of-Language +##ownname Native-Name-Of-Language + +Note: Do not alter the following parts of the file: + + * String identifiers (the first word on each line) + * Parts of the strings which are in curly braces (such as {STRING}) + * Lines beginning with ## (such as ##id), other than the first two lines of the file + +8.3) Previewing: +---- ------------------- +In order to view the translation in the game, you need to compile your language file +with the strgen utility, which is now bundled with the game. + +strgen is a command-line utility. It takes the language filename as parameter. +Example: + +strgen lang/german.txt + +This results in compiling german.txt and produces another file named german.lng. +Any missing strings are replaced with the english strings. Note that it looks for english.txt +in the lang subdirectory, which is where your language file should also be. + +That's all! You should now be able to select the language in the game options. + + +X.X) Credits: +---- -------- +The OpenTTD team: + Ludvig Strigeus (ludde) - OpenTTD author, main coder. + Serge Paquet (vurlix) - Assistant project manager, coder and webmaster. + Dominik Scherer (dominik81) - Coder + Tamas Farago (Darkvater) - Coder + Owen Rudge (orudge) - Contributor, forum host. + Bjarni Corfitzen (Bjarni) - MacOS port + Cian Duffy (MYOB) - BeOS port / manual writing + Christian Rosentreter (tokaiz) - MorphOS/AmigaOS port + Viktor Strigeus (wiggo) - Web hosting services + +Thanks to: + Bug Reporters - Thanks for all bug reports. + Josef Drexler - For his great work on TTDPatch. + Marcin Grzegorczyk - For his TTDPatch work and documentation of TTD internals and graphics. + Mike Ragsdale - OpenTTD installer + pasky - Many patches, newgrf support, etc. + truesatan - Some patches + TrueLight - Some patches + Michael Polnick - Some patches + Michael Blunck - Nice graphics + George - Canal graphics + Chris Sawyer - For an amazing game. + diff --git a/resource.h b/resource.h new file mode 100644 --- /dev/null +++ b/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ttd.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1005 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/road_cmd.c b/road_cmd.c new file mode 100644 --- /dev/null +++ b/road_cmd.c @@ -0,0 +1,1109 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "viewport.h" +#include "command.h" +#include "player.h" +#include "town.h" +#include "gfx.h" + +static bool _road_special_gettrackstatus; + +void RoadVehEnterDepot(Vehicle *v); + + +static bool HasTileRoadAt(uint tile, int i) +{ + int mask; + byte b; + + switch(GET_TILETYPE(tile)) { + case MP_STREET: + b = _map5[tile]; + + if ((b & 0xF0) == 0) { + } else if ((b & 0xF0) == 0x10) { + b = (b&8)?5:10; + } else if ((b & 0xF0) == 0x20) { + return (~b & 3) == i; + } else + return false; + break; + + case MP_STATION: + b = _map5[tile]; + if (!IS_BYTE_INSIDE(b, 0x43, 0x43+8)) + return false; + return ((~(b - 0x43) & 3) == i); + + case MP_TUNNELBRIDGE: + mask = GetRoadBitsByTile(tile); + b = 10; if (mask & 1) break; + b = 5; if (mask & 2) break; + return false; + + default: + return false; + } + + return HASBIT(b, i); +} + +static bool CheckAllowRemoveRoad(uint tile, uint br, bool *edge_road) +{ + int blocks; + byte owner; + uint n; + *edge_road = true; + + if (_game_mode == GM_EDITOR) + return true; + + blocks = GetRoadBitsByTile(tile); + if (blocks == 0) + return true; + + // Only do the special processing for actual players. + if (_current_player >= MAX_PLAYERS) + return true; + + // A railway crossing has the road owner in the map3_lo byte. + if (IS_TILETYPE(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x10) { + owner = _map3_lo[tile]; + } else { + owner = _map_owner[tile]; + } + // Only do the special processing if the road is owned + // by a town + if (owner != OWNER_TOWN) { + return owner == OWNER_NONE || CheckOwnership(owner); + } + + if (_cheats.magic_bulldozer.value) + return true; + + // Get a bitmask of which neighbouring roads has a tile + n = 0; + if (blocks&0x25 && HasTileRoadAt(TILE_ADDXY(tile,-1, 0), 1)) n |= 8; + if (blocks&0x2A && HasTileRoadAt(TILE_ADDXY(tile, 0, 1), 0)) n |= 4; + if (blocks&0x19 && HasTileRoadAt(TILE_ADDXY(tile, 1, 0), 3)) n |= 2; + if (blocks&0x16 && HasTileRoadAt(TILE_ADDXY(tile, 0,-1), 2)) n |= 1; + + // If 0 or 1 bits are set in n, or if no bits that match the bits to remove, + // then allow it + if ((n & (n-1)) != 0 && (n & br) != 0) { + Town *t; + *edge_road = false; + // you can remove all kind of roads with extra dynamite + if (_patches.extra_dynamite) + return true; + + t = ClosestTownFromTile(tile, (uint)-1); + SET_DPARAM16(0, t->index); + _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; + return false; + } + + return true; +} + +bool IsRoadDepotTile(TileIndex tile) +{ + return IS_TILETYPE(tile, MP_STREET) && + (_map5[tile] & 0xF0) == 0x20; +} + +uint GetRoadBitsByTile(TileIndex tile) +{ + uint32 r = GetTileTrackStatus(tile, 2); + return (byte)(r | (r >> 8)); +} + +// cost for removing inner/edge -roads +static const uint16 _road_remove_cost[2] = {50, 18}; + +/* Delete a piece of road + * p1 = piece type + */ +int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int32 cost; + uint tile; + Town *t; + /* true if the roadpiece was always removeable, + false if it was a center piece. Affects town ratings drop + */ + bool edge_road; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + tile = ti.tile; + t = ClosestTownFromTile(tile, (uint)-1); // needed for town rating penalty + + // allow deleting road under bridge + if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) + return CMD_ERROR; + + { + bool b; + _road_special_gettrackstatus = true; + b = CheckAllowRemoveRoad(tile, p1, &edge_road); + _road_special_gettrackstatus = false; + if (!b) + return CMD_ERROR; + } + + if (ti.type == MP_TUNNELBRIDGE) { + if (!EnsureNoVehicleZ(tile, GET_TILEHEIGHT(tile))) + return CMD_ERROR; + + if ((ti.map5 & 0xE9) == 0xE8) { + if (p1 & 10) goto return_error; + } else if ((ti.map5 & 0xE9) == 0xE9) { + if (p1 & 5) goto return_error; + } else + goto return_error; + + cost = _price.remove_road * 2; + + if (flags & DC_EXEC) { + _map5[tile] = ti.map5 & 0xC7; + _map_owner[tile] = OWNER_NONE; + MarkTileDirtyByTile(tile); + } + return cost; + } else if (ti.type == MP_STREET) { + if (!(ti.map5 & 0xF0)) { + uint c = p1, t2; + + if (ti.tileh != 0 && (ti.map5 == 5 || ti.map5 == 10)) { + c |= (c & 0xC) >> 2; + c |= (c & 0x3) << 2; + } + + // limit the bits to delete to the existing bits. + if ((c &= ti.map5) == 0) goto return_error; + + // calculate the cost + t2 = c; + cost = 0; + do { + if (t2&1) cost += _price.remove_road; + } while(t2>>=1); + + // check if you're allowed to remove the street owned by a town + // removal allowance depends on difficulty setting + if(_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR) { + if (!CheckforTownRating(tile, flags, t, ROAD_REMOVE)) + return CMD_ERROR; + } + + if (flags & DC_EXEC) { + // checks if the owner is town than decrease town rating by 50 until you have + // a "Poor" town rating + if(_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR) + ChangeTownRating(t, -_road_remove_cost[(byte)edge_road], -100); + + _map5[tile] ^= c; + if ((_map5[tile]&0xF) == 0) + DoClearSquare(tile); + else + MarkTileDirtyByTile(tile); + + } + return cost; + } else if (!(ti.map5 & 0xE0)) { + byte c; + + if (!(ti.map5 & 8)) { + c = 2; + if (p1 & 5) goto return_error; + } else { + c = 1; + if (p1 & 10) goto return_error; + } + + cost = _price.remove_road * 2; + if (flags & DC_EXEC) { + ModifyTile(tile, + MP_SETTYPE(MP_RAILWAY) | + MP_MAP2_CLEAR | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5, + _map3_hi[tile] & 0xF, /* map3_lo */ + c /* map5 */ + ); + } + return cost; + } else + goto return_error; + + } else { +return_error:; + return_cmd_error(INVALID_STRING_ID); + } +} + + +enum { + ROAD_NW = 1, // NW road track + ROAD_SW = 2, // SW road track + ROAD_SE = 4, // SE road track + ROAD_NE = 8, // NE road track + ROAD_ALL = (ROAD_NW | ROAD_SW | ROAD_SE | ROAD_NE) +}; + +static const byte _valid_tileh_slopes_road[2][15] = { + // set of normal ones + { + ROAD_ALL, 0, 0, + ROAD_SW | ROAD_NE, 0, 0, // 3, 4, 5 + ROAD_NW | ROAD_SE, 0, 0, + ROAD_NW | ROAD_SE, 0, 0, // 9, 10, 11 + ROAD_SW | ROAD_NE, 0, 0 + }, + // allowed road for an evenly raised platform + { + 0, + ROAD_SW | ROAD_NW, + ROAD_SW | ROAD_SE, + ROAD_NW | ROAD_SE | ROAD_SW, + + ROAD_SE | ROAD_NE, // 4 + ROAD_ALL, + ROAD_SW | ROAD_NE | ROAD_SE, + ROAD_ALL, + + ROAD_NW | ROAD_NE, // 8 + ROAD_SW | ROAD_NE | ROAD_NW, + ROAD_ALL, + ROAD_ALL, + + ROAD_NW | ROAD_SE | ROAD_NE, // 12 + ROAD_ALL, + ROAD_ALL + } +}; + + +static uint32 CheckRoadSlope(int tileh, byte *pieces, byte existing) +{ + if (!(tileh & 0x10)) { + byte road_bits = *pieces | existing; + + // no special foundation + if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) { + // force that all bits are set when we have slopes + if (tileh != 0) *pieces |= _valid_tileh_slopes_road[0][tileh]; + return 0; // no extra cost + } + + // foundation is used. Whole tile is leveled up + if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) { + return existing ? 0 : _price.terraform; + } + + // partly leveled up tile, only if there's no road on that tile + if ( !existing && (tileh == 1 || tileh == 2 || tileh == 4 || tileh == 8) ) { + // force full pieces. + *pieces |= (*pieces & 0xC) >> 2; + *pieces |= (*pieces & 0x3) << 2; + return existing ? 0 : _price.terraform; + } + } + return CMD_ERROR; +} + +/* Build a piece of road + * p1 = piece flags + */ + +int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int32 cost; + byte pieces = (byte)p1, existing = 0; + uint tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + tile = ti.tile; + + // allow building road under bridge + if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (ti.type == MP_STREET) { + if (!(ti.map5 & 0xF0)) { + if ( ((pieces) & (byte)(ti.map5)) == (pieces)) + return_cmd_error(STR_1007_ALREADY_BUILT); + existing = ti.map5; + } else { + if (!(ti.map5 & 0xE0) && pieces != ((ti.map5 & 8) ? 5 : 10)) + return_cmd_error(STR_1007_ALREADY_BUILT); + goto do_clear; + } + } else if (ti.type == MP_RAILWAY) { + byte m5; + + if (ti.tileh != 0) goto do_clear; + + if (ti.map5 == 2) { + if (pieces & 5) goto do_clear; + m5 = 0x10; + } else if (ti.map5 == 1) { + if (pieces & 10) goto do_clear; + m5 = 0x18; + } else + goto do_clear; + + if (flags & DC_EXEC) { + ModifyTile(tile, + MP_SETTYPE(MP_STREET) | + MP_MAP2_CLEAR | MP_MAP3LO | MP_MAP3HI | MP_MAP5, + _current_player, /* map3_lo */ + _map3_lo[tile] & 0xF, /* map3_hi */ + m5 /* map5 */ + ); + } + return _price.build_road * 2; + } else if (ti.type == MP_TUNNELBRIDGE) { + + /* check for flat land */ + if (ti.tileh & 0x10) //goto do_clear; // very steep tile + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + /* is this middle part of a bridge? */ + if ((ti.map5 & 0xC0) != 0xC0) + goto do_clear; + + /* only allow roads pertendicular to bridge */ + if ((pieces & 5) == (ti.map5 & 0x01)) + goto do_clear; + + /* check if clear land under bridge */ + if ((ti.map5 & 0xF8) == 0xE8) /* road under bridge */ + return_cmd_error(STR_1007_ALREADY_BUILT); + else if ((ti.map5 & 0xE0) == 0xE0) /* other transport route under bridge */ + return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK); + else if ((ti.map5 & 0xF8) == 0xC8) /* water under bridge */ + return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); + + /* all checked, can build road now! */ + cost = _price.build_road * 2; + if (flags & DC_EXEC) { + ModifyTile(tile, + MP_MAPOWNER_CURRENT | MP_MAP5, + (ti.map5 & 0xC7) | 0x28 // map5 + ); + } + return cost; + } else { +do_clear:; + if (DoCommandByTile(tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return CMD_ERROR; + } + + cost = CheckRoadSlope(ti.tileh, &pieces, existing); + if (cost == CMD_ERROR) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION); + + // the AI is not allowed to used foundationed tiles. + if (cost && (_is_ai_player || !_patches.build_on_slopes)) + return CMD_ERROR; + + if (!(ti.type == MP_STREET && (ti.map5 & 0xF0) == 0)) { + cost += DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + } else { + // Don't put the pieces that already exist + pieces &= ~ti.map5; + } + + { + byte t = pieces; + while (t) { + if (t & 1) cost += _price.build_road; + t >>= 1; + } + } + + if (flags & DC_EXEC) { + if (ti.type != MP_STREET) { + _map_type_and_height[tile] &= 0xF; + _map_type_and_height[tile] |= MP_STREET << 4; + _map5[tile] = 0; + _map_owner[tile] = _current_player; + } + + _map5[tile] |= (byte)pieces; + + MarkTileDirtyByTile(tile); + } + return cost; +} + +int32 DoConvertStreetRail(uint tile, uint totype, bool exec) +{ + // not a railroad crossing? + if ((_map5[tile] & 0xF0) != 0x10) return CMD_ERROR; + + // not owned by me? + if (!CheckTileOwnership(tile) || !EnsureNoVehicle(tile)) return CMD_ERROR; + + // tile is already of requested type? + if ( (uint)(_map3_hi[tile] & 0xF) == totype) return CMD_ERROR; + + if (exec) { + // change type. + _map3_hi[tile] = (_map3_hi[tile] & 0xF0) + totype; + MarkTileDirtyByTile(tile); + } + + return _price.build_rail >> 1; +} + + +// Build a long piece of road. +// x,y = end tile +// p1 = start tile +// p2&1 = start tile starts in the 2nd half +// p2&2 = end tile starts in the 2nd half +// p2&4 = direction (0 = along x, 1=along y) +int32 CmdBuildLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint start_tile, end_tile, tile; + int mode; + int32 cost,ret; + + start_tile = p1; + end_tile = TILE_FROM_XY(x, y); + + if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) { + uint t = start_tile; start_tile = end_tile; end_tile = t; + p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0; + } + + cost = 0; + tile = start_tile; + // Start tile is the small number. + for(;;) { + mode = (p2&4) ? 5 : 10; + + if (tile == start_tile && (p2&1)) + mode &= (4+2); + else if (tile == end_tile && !(p2&2)) + mode &= (1+8); + + ret = DoCommandByTile(tile, mode, 0, flags, CMD_BUILD_ROAD); + if (ret == CMD_ERROR) { + if (_error_message != STR_1007_ALREADY_BUILT) + return CMD_ERROR; + } else { + cost += ret; + } + + if (tile == end_tile) + break; + + tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0); + } + + // already built? + if (cost == 0) + return CMD_ERROR; + + return cost; +} + +// Remove a long piece of road. +// x,y = end tile +// p1 = start tile +// p2&1 = start tile starts in the 2nd half +// p2&2 = end tile starts in the 2nd half +// p2&4 = direction (0 = along x, 1=along y) +int32 CmdRemoveLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint start_tile, end_tile, tile; + int32 cost,ret; + + start_tile = p1; + end_tile = TILE_FROM_XY(x, y); + + if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) { + uint t = start_tile; start_tile = end_tile; end_tile = t; + p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0; + } + + cost = 0; + tile = start_tile; + // Start tile is the small number. + for(;;) { + uint bits = (p2 & 4) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE; + if (tile == end_tile && !(p2&2)) bits &= ROAD_NW | ROAD_NE; + if (tile == start_tile && (p2&1)) bits &= ROAD_SE | ROAD_SW; + + // try to remove the halves. + if (bits) { + ret = DoCommandByTile(tile, bits, 0, flags, CMD_REMOVE_ROAD); + if (ret != CMD_ERROR) + cost += ret; + } + + if (tile == end_tile) + break; + + tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0); + } + + // already built? + if (cost == 0) + return CMD_ERROR; + + return cost; +} + +/* Build a road depot + * p1 - direction (0-3) + * p2 - unused + */ + +int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int32 cost; + Depot *dep; + uint tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + + tile = ti.tile; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (ti.tileh != 0) { + if (_is_ai_player || !_patches.build_on_slopes || (ti.tileh & 0x10 || !((0x4C >> p1) & ti.tileh) )) + return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); + } + + cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (cost == CMD_ERROR) + return CMD_ERROR; + + dep = AllocateDepot(); + if (dep == NULL) + return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_current_player == _local_player) + _last_built_road_depot_tile = (TileIndex)tile; + + dep->xy = tile; + dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; + + ModifyTile(tile, + MP_SETTYPE(MP_STREET) | + MP_MAPOWNER_CURRENT | MP_MAP5, + (p1 | 0x20) /* map5 */ + ); + + } + return cost + _price.build_road_depot; +} + +static int32 RemoveRoadDepot(uint tile, uint32 flags) +{ + if (!CheckTileOwnership(tile)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoDeleteDepot(tile); + } + + return _price.remove_road_depot; +} + +#define M(x) (1<<(x)) + +static int32 ClearTile_Road(uint tile, byte flags) { + int32 ret; + byte m5 = _map5[tile]; + + if ( (m5 & 0xF0) == 0) { + byte b = m5 & 0xF; + + if (! ((1 << b) & (M(1)|M(2)|M(4)|M(8))) ) { + if ( (!(flags & DC_AI_BUILDING) || _map_owner[tile]!=OWNER_TOWN) && flags&DC_AUTO) + return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); + } + return DoCommandByTile(tile, b, 0, flags, CMD_REMOVE_ROAD); + } else if ( (m5 & 0xE0) == 0) { + if (flags & DC_AUTO) + return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); + + ret = DoCommandByTile(tile, (m5&8)?5:10, 0, flags, CMD_REMOVE_ROAD); + if (ret == CMD_ERROR) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + } + + return ret; + } else { + if (flags & DC_AUTO) + return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); + return RemoveRoadDepot(tile,flags); + } +} + + +typedef struct DrawRoadTileStruct { + uint16 image; + byte subcoord_x; + byte subcoord_y; +} DrawRoadTileStruct; + +typedef struct DrawRoadSeqStruct { + uint32 image; + byte subcoord_x; + byte subcoord_y; + byte width; + byte height; +} DrawRoadSeqStruct; + +#include "table/road_land.h" + + +static uint GetRoadFoundation(uint tileh, uint bits) { + int i; + // normal level sloped building + if ((~_valid_tileh_slopes_road[1][tileh] & bits) == 0) + return tileh; + + // inclined sloped building + if ( ((i=0, tileh == 1) || (i+=2, tileh == 2) || (i+=2, tileh == 4) || (i+=2, tileh == 8)) && + ((bits == (ROAD_SW | ROAD_NE)) || (i++, bits == (ROAD_NW | ROAD_SE)))) + return i + 15; + + return 0; +} + +const byte _road_sloped_sprites[14] = { + 0, 0, 2, 0, + 0, 1, 0, 0, + 3, 0, 0, 0, + 0, 0 +}; + +static void DrawTile_Road(TileInfo *ti) +{ + uint32 image; + byte m2; + const byte *s; + + if ( (ti->map5 & 0xF0) == 0) { // if it is a road the upper 4 bits are 0 + const DrawRoadTileStruct *drts; + + if (ti->tileh != 0) { + int f = GetRoadFoundation(ti->tileh, ti->map5 & 0xF); + if (f) DrawFoundation(ti, f); + + // default sloped sprites.. + if (ti->tileh != 0) { + image = _road_sloped_sprites[ti->tileh - 1] + 0x53F; + } else { + image = _road_tile_sprites_1[ti->map5 & 0xF]; + } + } else { + image = _road_tile_sprites_1[ti->map5 & 0xF]; + } + + m2 = _map2[ti->tile] & 7; + + if (m2 == 0) image |= 0x3178000; + + if (_map3_hi[ti->tile] & 0x80) { + image += 19; + } else if (m2 > 1 && m2 != 6) { + image -= 19; /* pavement along the road? */ + } + + DrawGroundSprite(image); + + if (!(_display_opt & DO_FULL_DETAIL) || _cur_dpi->zoom == 2) + return; + + if (m2 >= 6) { + // roadwork + DrawGroundSprite(0x586 + ((ti->map5&8)!=0 ? 0 : 1)); + return; + } + + drts = (const DrawRoadTileStruct*)_road_display_table[m2][ti->map5 & 0xF]; + + while ((image = drts->image) != 0) { + int x = ti->x | drts->subcoord_x; + int y = ti->y | drts->subcoord_y; + byte z = ti->z; + if (ti->tileh != 0) z = GetSlopeZ(x, y); + AddSortableSpriteToDraw(image, x, y, 2, 2, 0x10, z); + drts++; + } + } else if ( (ti->map5 & 0xE0) == 0) { + image = 0x55B; + + if ( (ti->map5 & 8) != 0) + image--; + + if ( (ti->map5 & 4) != 0) + image += 2; + + if ( _map3_hi[ti->tile] & 0x80) { + image += 8; + } else { + m2 = _map2[ti->tile] & 7; + if (m2 == 0) image |= 0x3178000; + if (m2 > 1) image += 4; + } + + DrawGroundSprite(image + (_map3_hi[ti->tile] & 0xF) * 12); + } else { + uint32 ormod; + int player; + const DrawRoadSeqStruct *drss; + + if (ti->tileh != 0) { DrawFoundation(ti, ti->tileh); } + + ormod = 0x315; + player = _map_owner[ti->tile]; + if (player < MAX_PLAYERS) + ormod = PLAYER_SPRITE_COLOR(player); + + s = _road_display_datas[ti->map5 & 0xF]; + + DrawGroundSprite(*(uint32*)s); + s += sizeof(uint32); + drss = (DrawRoadSeqStruct*)s; + + while ((image=drss->image) != 0) { + if (image & 0x8000) + image |= ormod; + + AddSortableSpriteToDraw(image, ti->x | drss->subcoord_x, + ti->y | drss->subcoord_y, drss->width, drss->height, 0x14, ti->z); + drss++; + } + } +} + +void DrawRoadDepotSprite(int x, int y, int image) +{ + uint32 ormod; + const DrawRoadSeqStruct *dtss; + const byte *t; + + ormod = PLAYER_SPRITE_COLOR(_local_player); + + t = _road_display_datas[image]; + + x+=33; + y+=17; + + DrawSprite(*(uint32*)t, x, y); + t += sizeof(uint32); + + for(dtss = (DrawRoadSeqStruct *)t; dtss->image != 0; dtss++) { + Point pt = RemapCoords(dtss->subcoord_x, dtss->subcoord_y, 0); + + image = dtss->image; + if (image & 0x8000) + image |= ormod; + + DrawSprite(image, x + pt.x, y + pt.y); + } +} + +uint GetSlopeZ_Road(TileInfo *ti) +{ + uint z = ti->z; + int th = ti->tileh; + + // check if it's a foundation + if (ti->tileh != 0) { + if ((ti->map5 & 0xF0) == 0) { + uint f = GetRoadFoundation(ti->tileh, ti->map5 & 0x3F); + if (f != 0) { + if (f < 15) { + // leveled foundation + return z + 8; + } + // inclined foundation + th = _inclined_tileh[f - 15]; + } + } else if ((ti->map5 & 0xF0) == 0x20) { + // depot + return z + 8; + } + return GetPartialZ(ti->x&0xF, ti->y&0xF, th) + z; + } + return z; +} + +static void GetAcceptedCargo_Road(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void AnimateTile_Road(uint tile) +{ + if ((_map5[tile] & 0xF0) == 0x10) { + MarkTileDirtyByTile(tile); + } +} + +static const byte _town_road_types[5][2] = { + {1,1}, + {2,2}, + {2,2}, + {5,5}, + {3,2}, +}; + +static const byte _town_road_types_2[5][2] = { + {1,1}, + {2,2}, + {3,2}, + {3,2}, + {3,2}, +}; + + +static void TileLoop_Road(uint tile) +{ + Town *t; + int grp; + + if (_opt.landscape == LT_HILLY) { + // Fix snow style if the road is above the snowline + if ((_map3_hi[tile] & 0x80) != ((GetTileZ(tile) > _opt.snow_line) ? 0x80 : 0x00)) { + _map3_hi[tile] ^= 0x80; + MarkTileDirtyByTile(tile); + } + } else if (_opt.landscape == LT_DESERT) { + // Fix desert style + if (GetMapExtraBits(tile) == 1 && !(_map3_hi[tile] & 0x80)) { + _map3_hi[tile] |= 0x80; + MarkTileDirtyByTile(tile); + } + } + + if (_map5[tile] & 0xE0) + return; + + if ((_map2[tile] & 7) < 6) { + t = ClosestTownFromTile(tile, (uint)-1); + grp = 0; + if (t != NULL) { + // If in the scenario editor, set the owner to a town. + if (_game_mode == GM_EDITOR) { + _map_owner[tile] = OWNER_TOWN; + } + + grp = GetTownRadiusGroup(t, tile); + + // Show an animation to indicate road work + if (t->road_build_months != 0 && + !(GetTileDist(t->xy, tile) >= 8 && grp==0) && + (_map5[tile]==5 || _map5[tile]==10)) { + if (GetTileSlope(tile, NULL) == 0 && EnsureNoVehicle(tile) && CHANCE16(1,20)) { + _map2[tile] = ((_map2[tile]&7) <= 1) ? 6 : 7; + + SndPlayTileFx(0x1F,tile); + CreateEffectVehicleAbove( + GET_TILE_X(tile) * 16 + 7, + GET_TILE_Y(tile) * 16 + 7, + 0, + EV_ROADWORK); + MarkTileDirtyByTile(tile); + return; + } + } + } + + { + const byte *p = (_opt.landscape == LT_CANDY) ? _town_road_types_2[grp] : _town_road_types[grp]; + byte b = _map2[tile] & 7; + + if (b == p[0]) + return; + + if (b == p[1]) { + b = p[0]; + } else if (b == 0) { + b = p[1]; + } else { + b = 0; + } + _map2[tile] = (_map2[tile] & ~7) | b; + MarkTileDirtyByTile(tile); + } + } else { + // Handle road work + + byte b = _map2[tile]; + if (b < 0x80) { + _map2[tile] = b + 8; + return; + } + _map2[tile] = ((b&7) == 6) ? 1 : 2; + MarkTileDirtyByTile(tile); + } +} + +void ShowRoadDepotWindow(uint tile); + +static void ClickTile_Road(uint tile) +{ + if ((_map5[tile] & 0xF0) == 0x20) { + ShowRoadDepotWindow(tile); + } +} + +static const byte _road_trackbits[16] = { + 0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F, +}; + +static uint32 GetTileTrackStatus_Road(uint tile, int mode) { + if (mode == 0) { + if ((_map5[tile] & 0xF0) != 0x10) + return 0; + return _map5[tile] & 8 ? 0x101 : 0x202; + } else if (mode == 2) { + byte b = _map5[tile]; + if ((b & 0xF0) == 0) { + if (!_road_special_gettrackstatus && (_map2[tile]&7) >= 6) + return 0; + return _road_trackbits[b&0xF] * 0x101; + } else if ((b&0xE0) == 0) { + uint32 r = 0x101; + if (b&8) r <<= 1; + + if (b&4) { + r *= 0x10001; + } + return r; + } + } + return 0; +} + +static const StringID _road_tile_strings[] = { + STR_1818_ROAD_RAIL_LEVEL_CROSSING, + STR_1817_ROAD_VEHICLE_DEPOT, + + STR_1814_ROAD, + STR_1814_ROAD, + STR_1814_ROAD, + STR_1815_ROAD_WITH_STREETLIGHTS, + STR_1814_ROAD, + STR_1816_TREE_LINED_ROAD, + STR_1814_ROAD, + STR_1814_ROAD, +}; + +static void GetTileDesc_Road(uint tile, TileDesc *td) +{ + int i = (_map5[tile] >> 4); + if (i == 0) + i = (_map2[tile] & 7) + 3; + td->str = _road_tile_strings[i - 1]; + td->owner = _map_owner[tile]; +} + +static const byte _roadveh_enter_depot_unk0[4] = { + 8, 9, 0, 1 +}; + +static uint32 VehicleEnter_Road(Vehicle *v, uint tile, int x, int y) +{ + if ((_map5[tile] & 0xF0) == 0x10) { + if (v->type == VEH_Train && (_map5[tile] & 4) == 0) { + /* train crossing a road */ + SndPlayVehicleFx(12, v); + _map5[tile] |= 4; + MarkTileDirtyByTile(tile); + } + } else if ((_map5[tile]&0xF0) == 0x20){ + if (v->type == VEH_Road && v->u.road.frame == 11) { + if (_roadveh_enter_depot_unk0[_map5[tile]&3] == v->u.road.state) { + RoadVehEnterDepot(v); + return 4; + } + } + } + return 0; +} + +static void VehicleLeave_Road(Vehicle *v, uint tile, int x, int y) +{ + if ((_map5[tile] & 0xF0) == 0x10 && v->type == VEH_Train && v->next == NULL) { + _map5[tile] &= ~4; + MarkTileDirtyByTile(tile); + } +} + +static void ChangeTileOwner_Road(uint tile, byte old_player, byte new_player) +{ + byte b; + + // road/rail crossing where the road is owned by the current player? + if (old_player == _map3_lo[tile] && (_map5[tile]&0xF0) == 0x10) { + _map3_lo[tile] = (new_player == 0xFF) ? OWNER_NONE : new_player; + } + + if (_map_owner[tile] != old_player) + return; + + if (new_player != 255) { + _map_owner[tile] = new_player; + } else { + b = _map5[tile]&0xF0; + if (b == 0) { + _map_owner[tile] = OWNER_NONE; + } else if (b == 0x10) { + _map5[tile] = (_map5[tile]&8) ? 0x5 : 0xA; + _map_owner[tile] = _map3_lo[tile]; + _map3_lo[tile] = 0; + _map3_hi[tile] &= 0x80; + } else { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + } +} + +void InitializeRoad() +{ + _last_built_road_depot_tile = 0; +} + +const TileTypeProcs _tile_type_road_procs = { + DrawTile_Road, /* draw_tile_proc */ + GetSlopeZ_Road, /* get_slope_z_proc */ + ClearTile_Road, /* clear_tile_proc */ + GetAcceptedCargo_Road, /* get_accepted_cargo_proc */ + GetTileDesc_Road, /* get_tile_desc_proc */ + GetTileTrackStatus_Road, /* get_tile_track_status_proc */ + ClickTile_Road, /* click_tile_proc */ + AnimateTile_Road, /* animate_tile_proc */ + TileLoop_Road, /* tile_loop_clear */ + ChangeTileOwner_Road, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + VehicleEnter_Road, /* vehicle_enter_tile_proc */ + VehicleLeave_Road, /* vehicle_leave_tile_proc */ +}; diff --git a/road_gui.c b/road_gui.c new file mode 100644 --- /dev/null +++ b/road_gui.c @@ -0,0 +1,515 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" + +static void ShowBusStationPicker(); +static void ShowTruckStationPicker(); +static void ShowRoadDepotPicker(); + +static bool _remove_button_clicked; +static bool _build_road_flag; + +static byte _place_road_flag; + +static byte _road_depot_orientation; +static byte _road_station_picker_orientation; + +static void CcPlaySound1D(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { SndPlayTileFx(0x1D, tile); } +} + +static void PlaceRoad_NE(uint tile) +{ + _place_road_flag = (_tile_fract_coords.y >= 8) + 4; + VpStartPlaceSizing(tile, VPM_FIX_X); +} + +static void PlaceRoad_NW(uint tile) +{ + _place_road_flag = (_tile_fract_coords.x >= 8) + 0; + VpStartPlaceSizing(tile, VPM_FIX_Y); +} + +static void PlaceRoad_Bridge(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_OR_Y); +} + + +static void CcBuildTunnel(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1E, tile); + ResetObjectToPlace(); + } else { + SetRedErrorSquare(_build_tunnel_endtile); + } +} + +static void PlaceRoad_Tunnel(uint tile) +{ + DoCommandP(tile, 0x200, 0, CcBuildTunnel, CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE)); +} + +static void BuildRoadOutsideStation(uint tile, int direction) +{ + static const byte _roadbits_by_dir[4] = {2,1,8,4}; + tile += _tileoffs_by_dir[direction]; + if (IS_TILETYPE(tile, MP_STREET)) { + DoCommandP(tile, _roadbits_by_dir[direction], 0, NULL, CMD_BUILD_ROAD); + } +} + +static void CcDepot(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1D, tile); + ResetObjectToPlace(); + BuildRoadOutsideStation(tile, (int)p1); + } +} + +static void PlaceRoad_Depot(uint tile) +{ + DoCommandP(tile, _road_depot_orientation, 0, CcDepot, CMD_BUILD_ROAD_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1807_CAN_T_BUILD_ROAD_VEHICLE)); +} + +static void PlaceRoad_BusStation(uint tile) +{ + DoCommandP(tile, _road_station_picker_orientation, 0, CcDepot, CMD_BUILD_BUS_STATION | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION)); +} + +static void PlaceRoad_TruckStation(uint tile) +{ + DoCommandP(tile, _road_station_picker_orientation, 0, CcDepot, CMD_BUILD_TRUCK_STATION | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION)); +} + +static void PlaceRoad_DemolishArea(uint tile) +{ + VpStartPlaceSizing(tile, 4); +} + +typedef void OnButtonClick(Window *w); + +static void BuildRoadClick_NE(Window *w) +{ + _build_road_flag = 0; + HandlePlacePushButton(w, 2, 0x51F, 1, PlaceRoad_NE); +} + +static void BuildRoadClick_NW(Window *w) +{ + _build_road_flag = 0; + HandlePlacePushButton(w, 3, 0x520, 1, PlaceRoad_NW); +} + + +static void BuildRoadClick_Demolish(Window *w) +{ + HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceRoad_DemolishArea); +} + +static void BuildRoadClick_Lower(Window *w) +{ + HandlePlacePushButton(w, 5, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand); +} + +static void BuildRoadClick_Raise(Window *w) +{ + HandlePlacePushButton(w, 6, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand); +} + +static void BuildRoadClick_Depot(Window *w) +{ + if (HandlePlacePushButton(w, 7, 0x511, 1, PlaceRoad_Depot)) ShowRoadDepotPicker(); +} + +static void BuildRoadClick_BusStation(Window *w) +{ + if (HandlePlacePushButton(w, 8, 0xAA5, 1, PlaceRoad_BusStation)) ShowBusStationPicker(); +} + +static void BuildRoadClick_TruckStation(Window *w) +{ + if (HandlePlacePushButton(w, 9, 0xAA6, 1, PlaceRoad_TruckStation)) ShowTruckStationPicker(); +} + +static void BuildRoadClick_Bridge(Window *w) +{ + _build_road_flag = 0; + HandlePlacePushButton(w, 10, 0xA21, 1, PlaceRoad_Bridge); +} + +static void BuildRoadClick_Tunnel(Window *w) +{ + _build_road_flag = 0; + HandlePlacePushButton(w, 11, 0x981, 3, PlaceRoad_Tunnel); +} + +static void BuildRoadClick_Remove(Window *w) +{ + if (w->disabled_state & (1<<12)) + return; + SetWindowDirty(w); + SndPlayFx(0x13); + _thd.make_square_red = !!((w->click_state ^= (1 << 12)) & (1<<12)); +} + +static void BuildRoadClick_Purchase(Window *w) +{ + HandlePlacePushButton(w, 13, 0x12B8, 1, PlaceProc_BuyLand); +} + +static OnButtonClick * const _build_road_button_proc[] = { + BuildRoadClick_NE, + BuildRoadClick_NW, + BuildRoadClick_Demolish, + BuildRoadClick_Lower, + BuildRoadClick_Raise, + BuildRoadClick_Depot, + BuildRoadClick_BusStation, + BuildRoadClick_TruckStation, + BuildRoadClick_Bridge, + BuildRoadClick_Tunnel, + BuildRoadClick_Remove, + BuildRoadClick_Purchase, +}; + +static void BuildRoadToolbWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + w->disabled_state &= ~(1 << 12); + if (!(w->click_state & 12)) { + w->disabled_state |= (1 << 12); + w->click_state &= ~(1<<12); + } + DrawWindowWidgets(w); + break; + + case WE_CLICK: { + if (e->click.widget >= 2) + _build_road_button_proc[e->click.widget - 2](w); + } break; + + case WE_KEYPRESS: + switch(e->keypress.keycode) { + case '1': BuildRoadClick_NE(w); break; + case '2': BuildRoadClick_NW(w); break; + case '3': BuildRoadClick_Demolish(w); break; + case '4': BuildRoadClick_Lower(w); break; + case '5': BuildRoadClick_Raise(w); break; + case 'B': BuildRoadClick_Bridge(w); break; + case 'T': BuildRoadClick_Tunnel(w); break; + case 'R': BuildRoadClick_Remove(w); break; + default: + return; + } + e->keypress.cont = false; + break; + + case WE_PLACE_OBJ: + _remove_button_clicked = (w->click_state & (1 << 12)) != 0; + _place_proc(e->place.tile); + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + SetWindowDirty(w); + + w = FindWindowById(WC_BUS_STATION, 0); + if (w != NULL) WP(w,def_d).close=true; + w = FindWindowById(WC_TRUCK_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_DRAG: { + int sel_method; + if (e->place.userdata == 1) { + sel_method = VPM_FIX_X; + _place_road_flag = (_place_road_flag&~2) | ((e->place.pt.y&8)>>2); + } else if (e->place.userdata == 2) { + sel_method = VPM_FIX_Y; + _place_road_flag = (_place_road_flag&~2) | ((e->place.pt.x&8)>>2); + } else if (e->place.userdata == 4) { + sel_method = VPM_X_AND_Y; + } else { + sel_method = VPM_X_OR_Y; + } + + VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, sel_method); + return; + } + + case WE_PLACE_MOUSEUP: + if (e->place.pt.x != -1) { + uint start_tile = e->place.starttile; + uint end_tile = e->place.tile; + if (e->place.userdata == 0) { + ResetObjectToPlace(); + ShowBuildBridgeWindow(start_tile, end_tile, 0x80); + } else if (e->place.userdata != 4) { + DoCommandP(end_tile, start_tile, _place_road_flag, CcPlaySound1D, + _remove_button_clicked ? + CMD_REMOVE_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1805_CAN_T_REMOVE_ROAD_FROM) : + CMD_BUILD_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1804_CAN_T_BUILD_ROAD_HERE)); + } else { + DoCommandP(end_tile, start_tile, _place_road_flag, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + } + } + break; + + case WE_PLACE_PRESIZE: { + uint tile = e->place.tile; + DoCommandByTile(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL); + VpSetPresizeRange(tile, _build_tunnel_endtile==0?tile:_build_tunnel_endtile); + break; + } + } +} + +static const Widget _build_road_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 283, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 21, 14, 35, 0x51D, STR_180B_BUILD_ROAD_SECTION}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 0x51E, STR_180B_BUILD_ROAD_SECTION}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 66, 87, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 88, 109, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 110, 131, 14, 35, 0x50F, STR_180C_BUILD_ROAD_VEHICLE_DEPOT}, +{ WWT_PANEL, 7, 132, 153, 14, 35, 0x2ED, STR_180D_BUILD_BUS_STATION}, +{ WWT_PANEL, 7, 154, 175, 14, 35, 0x2EE, STR_180E_BUILD_TRUCK_LOADING_BAY}, +{ WWT_PANEL, 7, 176, 217, 14, 35, 0xA22, STR_180F_BUILD_ROAD_BRIDGE}, +{ WWT_PANEL, 7, 218, 239, 14, 35, 0x97D, STR_1810_BUILD_ROAD_TUNNEL}, +{ WWT_PANEL, 7, 240, 261, 14, 35, 0x2CA, STR_1811_TOGGLE_BUILD_REMOVE_FOR}, +{ WWT_PANEL, 7, 262, 283, 14, 35, 0x12B7, STR_0329_PURCHASE_LAND_FOR_FUTURE}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_road_desc = { + 356, 22, 284, 36, + WC_BUILD_TOOLBAR,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_road_widgets, + BuildRoadToolbWndProc +}; + +void ShowBuildRoadToolbar() +{ + DeleteWindowById(WC_BUILD_TOOLBAR, 0); + AllocateWindowDesc(&_build_road_desc); +} + +static const Widget _build_road_scen_widgets[] = { +{ WWT_TEXTBTN, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 195, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 7, 0, 21, 14, 35, 0x51D, STR_180B_BUILD_ROAD_SECTION}, +{ WWT_IMGBTN, 7, 22, 43, 14, 35, 0x51E, STR_180B_BUILD_ROAD_SECTION}, +{ WWT_IMGBTN, 7, 44, 65, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_IMGBTN, 7, 66, 87, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_IMGBTN, 7, 88, 109, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_IMGBTN, 7, 110, 151, 14, 35, 0xA22, STR_180F_BUILD_ROAD_BRIDGE}, +{ WWT_IMGBTN, 7, 152, 173, 14, 35, 0x97D, STR_1810_BUILD_ROAD_TUNNEL}, +{ WWT_IMGBTN, 7, 174, 195, 14, 35, 0x2CA, STR_1811_TOGGLE_BUILD_REMOVE_FOR}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_road_scen_desc = { + -1, -1, 196, 36, + WC_SCEN_BUILD_ROAD,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_road_scen_widgets, + BuildRoadToolbWndProc +}; + +void ShowBuildRoadScenToolbar() +{ + AllocateWindowDescFront(&_build_road_scen_desc, 0); +} + +static void BuildRoadDepotWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + w->click_state = (1<<3) << _road_depot_orientation; + DrawWindowWidgets(w); + + DrawRoadDepotSprite(70, 17, 0); + DrawRoadDepotSprite(70, 69, 1); + DrawRoadDepotSprite(2, 69, 2); + DrawRoadDepotSprite(2, 17, 3); + break; + + case WE_CLICK: { + switch(e->click.widget) { + case 0: + ResetObjectToPlace(); + break; + case 3: + case 4: + case 5: + case 6: + _road_depot_orientation = e->click.widget - 3; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: + if (WP(w,def_d).close) + DeleteWindow(w); + break; + } +} + +static const Widget _build_road_depot_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 139, 0, 13, STR_1806_ROAD_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 139, 14, 121, 0x0, 0}, +{ WWT_PANEL, 14, 71, 136, 17, 66, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT}, +{ WWT_PANEL, 14, 71, 136, 69, 118, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT}, +{ WWT_PANEL, 14, 3, 68, 69, 118, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT}, +{ WWT_PANEL, 14, 3, 68, 17, 66, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT}, +{ WWT_LAST}, +}; + +static const WindowDesc _build_road_depot_desc = { + -1,-1, 140, 122, + WC_BUILD_DEPOT,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _build_road_depot_widgets, + BuildRoadDepotWndProc +}; + +static void ShowRoadDepotPicker() +{ + AllocateWindowDesc(&_build_road_depot_desc); +} + +static void RoadStationPickerWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: { + int image; + + w->click_state = ((1<<3) << _road_station_picker_orientation) | + ((1<<7) << _station_show_coverage); + DrawWindowWidgets(w); + + SetTileSelectSize(1, 1); + if (_station_show_coverage) + SetTileSelectBigSize(-4, -4, 8, 8); + + image = (w->window_class == WC_BUS_STATION) ? 0x47 : 0x43; + + StationPickerDrawSprite(103, 35, 0, image); + StationPickerDrawSprite(103, 85, 0, image+1); + StationPickerDrawSprite(35, 85, 0, image+2); + StationPickerDrawSprite(35, 35, 0, image+3); + + DrawStringCentered(70, 120, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0); + DrawStationCoverageAreaText(2, 146, + ((w->window_class == WC_BUS_STATION) ? (1<click.widget) { + case 0: + ResetObjectToPlace(); + break; + case 3: + case 4: + case 5: + case 6: + _road_station_picker_orientation = e->click.widget - 3; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + case 7: + case 8: + _station_show_coverage = e->click.widget - 7; + SndPlayFx(0x13); + SetWindowDirty(w); + break; + } + } break; + + case WE_MOUSELOOP: { + if (WP(w,def_d).close) { + DeleteWindow(w); + return; + } + + CheckRedrawStationCoverage(w); + } break; + } +} + +static const Widget _bus_station_picker_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 139, 0, 13, STR_3042_BUS_STATION_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 139, 14, 176, 0x0, 0}, +{ WWT_PANEL, 14, 71, 136, 17, 66, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION}, +{ WWT_PANEL, 14, 71, 136, 69, 118, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION}, +{ WWT_PANEL, 14, 3, 68, 69, 118, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION}, +{ WWT_PANEL, 14, 3, 68, 17, 66, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION}, +{ WWT_CLOSEBOX, 14, 10, 69, 133, 144, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, +{ WWT_CLOSEBOX, 14, 70, 129, 133, 144, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, +{ WWT_LAST}, +}; + +static const WindowDesc _bus_station_picker_desc = { + -1,-1, 140, 177, + WC_BUS_STATION,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _bus_station_picker_widgets, + RoadStationPickerWndProc +}; + +static void ShowBusStationPicker() +{ + AllocateWindowDesc(&_bus_station_picker_desc); +} + +static const Widget _truck_station_picker_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 139, 0, 13, STR_3043_TRUCK_STATION_ORIENT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 7, 0, 139, 14, 176, 0x0, 0}, +{ WWT_PANEL, 14, 71, 136, 17, 66, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY}, +{ WWT_PANEL, 14, 71, 136, 69, 118, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY}, +{ WWT_PANEL, 14, 3, 68, 69, 118, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY}, +{ WWT_PANEL, 14, 3, 68, 17, 66, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY}, +{ WWT_CLOSEBOX, 14, 10, 69, 133, 144, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, +{ WWT_CLOSEBOX, 14, 70, 129, 133, 144, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, +{ WWT_LAST}, +}; + +static const WindowDesc _truck_station_picker_desc = { + -1,-1, 140, 177, + WC_TRUCK_STATION,WC_BUILD_TOOLBAR, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _truck_station_picker_widgets, + RoadStationPickerWndProc +}; + +static void ShowTruckStationPicker() +{ + AllocateWindowDesc(&_truck_station_picker_desc); +} + +void InitializeRoadGui() +{ + _road_depot_orientation = 3; + _road_station_picker_orientation = 3; +} diff --git a/roadveh_cmd.c b/roadveh_cmd.c new file mode 100644 --- /dev/null +++ b/roadveh_cmd.c @@ -0,0 +1,1578 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "engine.h" +#include "command.h" +#include "station.h" +#include "news.h" +#include "gfx.h" +#include "pathfind.h" +#include "player.h" + +void ShowRoadVehViewWindow(Vehicle *v); + +static const uint16 _roadveh_images[63] = { + 0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14, + 0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74, + 0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C, + 0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC, + 0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC, + 0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4, + 0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C, + 0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4 +}; + + +static const uint16 _roadveh_full_adder[63] = { + 0, 88, 0, 0, 0, 0, 48, 48, + 48, 48, 0, 0, 64, 64, 0, 16, + 16, 0, 88, 0, 0, 0, 0, 48, + 48, 48, 48, 0, 0, 64, 64, 0, + 16, 16, 0, 88, 0, 0, 0, 0, + 48, 48, 48, 48, 0, 0, 64, 64, + 0, 16, 16, 0, 8, 8, 8, 8, + 0, 0, 0, 8, 8, 8, 8 +}; + +static const byte _roadveh_spritenum[88] = { + 0, 17, 17, 34, 51, 51, 51, 1, + 18, 35, 2, 19, 36, 57, 57, 57, + 3, 20, 37, 4, 21, 38, 5, 22, + + 39, 6, 23, 40, 7, 24, 41, 8, + 25, 42, 9, 26, 43, 10, 27, 44, + 11, 28, 45, 12, 29, 46, 13, 30, + 47, 14, 31, 48, 15, 32, 49, 16, + + 33, 50, 52, 52, 52, 53, 53, 53, + 54, 54, 54, 55, 55, 55, 56, 56, + 56, 58, 58, 58, 59, 59, 59, 60, + 60, 60, 61, 61, 61, 62, 62, 62, +}; + +const byte _roadveh_speed[88] = { + 112, 176, 224, 255, 112, 192, 240, 96, + 176, 224, 96, 176, 224, 96, 176, 224, + 96, 176, 224, 96, 176, 224, 96, 176, + 224, 96, 176, 224, 96, 176, 224, 96, + 176, 224, 96, 176, 224, 96, 176, 224, + 96, 176, 224, 96, 176, 224, 96, 176, + 224, 96, 176, 224, 96, 176, 224, 96, + 176, 224, 96, 176, 224, 96, 176, 224, + 96, 176, 224, 96, 176, 224, 96, 176, + 224, 96, 176, 224, 96, 176, 224, 96, + 176, 224, 96, 176, 224, 96, 176, 224, +}; + + +const byte _roadveh_runningcost[88] = { + 91, 128, 178, 240, 91, 171, 240, 90, + 168, 240, 90, 168, 240, 90, 168, 240, + 90, 168, 240, 90, 168, 240, 90, 168, + 240, 90, 168, 240, 90, 168, 240, 90, + 168, 240, 90, 168, 240, 90, 168, 240, + 90, 168, 240, 90, 168, 240, 90, 168, + 240, 90, 168, 240, 90, 168, 240, 90, + 168, 240, 90, 168, 240, 90, 168, 240, + 90, 168, 240, 90, 168, 240, 90, 168, + 240, 90, 168, 240, 90, 168, 240, 90, + 168, 240, 90, 168, 240, 90, 168, 240, +}; + + +const byte _roadveh_capacity[88] = { + 31, 35, 37, 40, 30, 35, 38, 20, + 25, 28, 22, 28, 30, 22, 28, 30, + 21, 25, 27, 14, 16, 18, 14, 16, + 18, 20, 25, 30, 20, 22, 24, 22, + 25, 27, 15, 18, 20, 12, 15, 16, + 17, 20, 22, 15, 18, 20, 22, 25, + 27, 21, 25, 27, 18, 20, 23, 17, + 19, 22, 17, 19, 22, 17, 19, 22, + 17, 19, 22, 17, 19, 22, 17, 19, + 22, 17, 19, 22, 17, 19, 22, 17, + 19, 22, 17, 19, 22, 17, 19, 22, +}; + +const byte _roadveh_cargo_type[88] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 4, 4, 4, 5, 5, + 5, 6, 6, 6, 7, 7, 7, 8, + 8, 8, 9, 9, 9,10,10,10, + 11,11,11, 9, 9, 9, 8, 8, + 8, 9, 9, 9, 4, 4, 4, 1, + 1, 1, 1, 1, 1, 7, 7, 7, + 8, 8, 8, 6, 6, 6, 3, 3, + 3, 5, 5, 5, 4, 4, 4,11, + 11,11,10,10,10, 9, 9, 9, +}; + +const byte _roadveh_price[88] = { + 120,140,150,160,120,140,160,108, + 128,138,115,135,145,115,135,145, + 110,140,150,105,130,140,107,130, + 140,114,133,143,118,137,147,121, + 140,150,112,135,145,145,170,180, + 112,134,144,112,135,145,121,140, + 150,111,141,151,118,148,158,117, + 147,157,117,147,157,117,147,157, + 117,147,157,117,147,157,117,147, + 157,117,147,157,117,147,157,117, + 147,157,117,147,157,117,147,157, +}; + +static const byte _road_engine_sounds[88] = { + 23, 26, 25, 25, 60, 62, 60, 23, + 23, 23, 23, 23, 23, 62, 60, 62, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 63, 64, 63, 64, 63, 64, + 63, 64, 63, 64, 63, 64, 63, 64, + 63, 64, 63, 64, 63, 64, 63, 64, + 63, 64, 63, 64, 63, 64, 63, 64, +}; + +static const uint16 _road_veh_fp_ax_or[4] = { + 0x100,0x200,1,2, +}; + +static const uint16 _road_veh_fp_ax_and[4] = { + 0x1009, 0x16, 0x520, 0x2A00 +}; + +static const byte _road_reverse_table[4] = { + 6, 7, 14, 15 +}; + +static const uint16 _road_pf_table_3[4] = { + 0x910, 0x1600, 0x2005, 0x2A +}; + +int GetRoadVehImage(Vehicle *v, byte direction) +{ + int img = v->spritenum; + int image; + +#ifdef ROADVEH_CUSTOM_SPRITES // TODO --pasky + if (is_custom_sprite(img)) { + image = GetCustomVehicleSprite(v, direction); + if (image) return image; + img = _engine_original_sprites[v->engine_type]; + } +#endif + + image = direction + _roadveh_images[img]; + if (v->cargo_count >= (v->cargo_cap >> 1)) + image += _roadveh_full_adder[img]; + return image; +} + +void DrawRoadVehEngine(int x, int y, int engine, uint32 image_ormod) +{ + DrawSprite((6 + _roadveh_images[_roadveh_spritenum[engine - ROAD_ENGINES_INDEX]]) | image_ormod, x, y); +} + +void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw) +{ + engine -= ROAD_ENGINES_INDEX; + + SET_DPARAM32(0, ((_price.roadveh_base >> 3) * _roadveh_price[engine]) >> 5); + SET_DPARAM16(1, _roadveh_speed[engine] * 10 >> 5); + SET_DPARAM32(2, _roadveh_runningcost[engine] * _price.roadveh_running >> 8); + + SET_DPARAM16(4, _roadveh_capacity[engine]); + SET_DPARAM16(3, _cargoc.names_long_p[_roadveh_cargo_type[engine]]); + + DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw); +} + +static int32 EstimateRoadVehCost(byte engine_type) +{ + return ((_price.roadveh_base >> 3) * _roadveh_price[engine_type - ROAD_ENGINES_INDEX]) >> 5; +} + +int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int32 cost; + Vehicle *v; + byte unit_num; + uint tile = TILE_FROM_XY(x,y); + Engine *e; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + cost = EstimateRoadVehCost(p1); + if (flags & DC_QUERY_COST) + return cost; + + v = AllocateVehicle(); + if (v == NULL || _ptr_to_next_order >= endof(_order_array)) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + /* find the first free roadveh id */ + unit_num = GetFreeUnitNumber(VEH_Road); + if (unit_num > _patches.max_roadveh) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + if (flags & DC_EXEC) { + v->unitnumber = unit_num; + v->direction = 0; + v->owner = _current_player; + + v->tile = tile; + x = GET_TILE_X(tile)*16 + 8; + y = GET_TILE_Y(tile)*16 + 8; + v->x_pos = x; + v->y_pos = y; + v->z_pos = GetSlopeZ(x,y); + v->z_height = 6; + + v->u.road.state = 254; + v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL; + + v->spritenum = _roadveh_spritenum[p1 - ROAD_ENGINES_INDEX]; + v->cargo_type = _roadveh_cargo_type[p1 - ROAD_ENGINES_INDEX]; + v->cargo_cap = _roadveh_capacity[p1 - ROAD_ENGINES_INDEX]; +// v->cargo_count = 0; + v->value = cost; +// v->day_counter = 0; +// v->next_order_param = v->next_order = 0; +// v->load_unload_time_rem = 0; +// v->progress = 0; + +// v->u.road.unk2 = 0; +// v->u.road.overtaking = 0; + + v->last_station_visited = 0xFF; + v->max_speed = _roadveh_speed[p1 - ROAD_ENGINES_INDEX]; + v->engine_type = (byte)p1; + + e = &_engines[p1]; + v->reliability = e->reliability; + v->reliability_spd_dec = e->reliability_spd_dec; + v->max_age = e->lifelength * 366; + _new_roadveh_id = v->index; + + v->string_id = STR_SV_ROADVEH_NAME; + *(v->schedule_ptr = _ptr_to_next_order++) = 0; + + v->service_interval = _patches.servint_roadveh; + + v->date_of_last_service = _date; + v->build_year = _cur_year; + + v->type = VEH_Road; + v->cur_image = 0xC15; + + VehiclePositionChanged(v); + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + InvalidateWindow(WC_ROADVEH_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + } + + return cost; +} + +// p1 = vehicle +int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (v->type != VEH_Road || !CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->vehstatus ^= VS_STOPPED; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + } + + return 0; +} + +int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + v = &_vehicles[p1]; + + if (v->type != VEH_Road || !CheckOwnership(v->owner)) + return CMD_ERROR; + + if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) + return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); + + if (flags & DC_EXEC) { + // Invalidate depot + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + InvalidateWindow(WC_ROADVEH_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + DeleteVehicle(v); + } + + return -(int32)v->value; +} + +typedef struct RoadFindDepotData { + uint best_length; + uint tile; + byte owner; +} RoadFindDepotData; + + +static const TileIndexDiff _road_find_sig_dir_mod[4] = { + TILE_XY(-1,0), + TILE_XY(0,1), + TILE_XY(1,0), + TILE_XY(0,-1), +}; + +static const byte _road_pf_directions[16] = { + 0, 1, 0, 1, 2, 1, 255, 255, + 2, 3, 3, 2, 3, 0, 255, 255, +}; + +static bool EnumRoadSignalFindDepot(uint tile, RoadFindDepotData *rfdd, int track, uint length, byte *state) +{ + tile += _road_find_sig_dir_mod[_road_pf_directions[track]]; + + if (IS_TILETYPE(tile, MP_STREET) && + (_map5[tile] & 0xF0) == 0x20 && + _map_owner[tile] == rfdd->owner) { + + if (length < rfdd->best_length) { + rfdd->best_length = length; + rfdd->tile = tile; + } + } + return false; +} + +static int FindClosestRoadDepot(Vehicle *v) +{ + uint tile = v->tile; + int i; + RoadFindDepotData rfdd; + + if (v->u.road.state == 255) { tile = GetVehicleOutOfTunnelTile(v); } + + rfdd.owner = v->owner; + rfdd.best_length = (uint)-1; + + /* search in all directions */ + for(i=0; i!=4; i++) + FollowTrack(tile, 0x2002, i, (TPFEnumProc*)EnumRoadSignalFindDepot, NULL, &rfdd); + + if (rfdd.best_length == (uint)-1) + return -1; + + return GetDepotByTile(rfdd.tile); +} + +int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1]; + int depot; + + if (v->type != VEH_Road || !CheckOwnership(v->owner)) + return CMD_ERROR; + + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (flags & DC_EXEC) { + if (v->next_order & OF_UNLOAD) + v->cur_order_index++; + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + return 0; + } + + depot = FindClosestRoadDepot(v); + if (depot < 0) + return_cmd_error(STR_9019_UNABLE_TO_FIND_LOCAL_DEPOT); + + if (flags & DC_EXEC) { + v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; + v->next_order_param = (byte)depot; + v->dest_tile = _depots[depot].xy; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + return 0; +} + +int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (v->type != VEH_Road || !CheckOwnership(v->owner)) + return CMD_ERROR; + + if (v->vehstatus & (VS_HIDDEN|VS_STOPPED) || + v->u.road.crashed_ctr != 0 || + v->breakdown_ctr != 0 || + v->u.road.overtaking != 0 || + v->cur_speed < 5) { + _error_message = STR_EMPTY; + return CMD_ERROR; + } + + if (flags & DC_EXEC) { + v->u.road.reverse_ctr = 180; + } + + return 0; +} + +int32 CmdChangeRoadVehServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (v->type != VEH_Road || !CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->service_interval = (uint16)p2; + InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7); + } + + return 0; +} + + +static void MarkRoadVehDirty(Vehicle *v) +{ + v->cur_image = GetRoadVehImage(v, v->direction); + MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); +} + +static void UpdateRoadVehDeltaXY(Vehicle *v) +{ +#define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) + static const uint32 _delta_xy_table[8] = { + MKIT(3, 3, -1, -1), + MKIT(3, 7, -1, -3), + MKIT(3, 3, -1, -1), + MKIT(7, 3, -3, -1), + MKIT(3, 3, -1, -1), + MKIT(3, 7, -1, -3), + MKIT(3, 3, -1, -1), + MKIT(7, 3, -3, -1), + }; +#undef MKIT + uint32 x = _delta_xy_table[v->direction]; + v->x_offs = (byte)x; + v->y_offs = (byte)(x>>=8); + v->sprite_width = (byte)(x>>=8); + v->sprite_height = (byte)(x>>=8); +} + +static void ClearCrashedStation(Vehicle *v) +{ + uint tile = v->tile; + Station *st = DEREF_STATION(_map2[tile]); + byte *b, bb; + + b = (_map5[tile] >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status; + + bb = *b; + + // mark station as not busy + bb &= ~0x80; + + // free parking bay + bb |= (v->u.road.state&0x02)?2:1; + + *b = bb; +} + +static void RoadVehDelete(Vehicle *v) +{ + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + InvalidateWindow(WC_ROADVEH_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + + if(IS_TILETYPE(v->tile, MP_STATION)) + ClearCrashedStation(v); + + BeginVehicleMove(v); + EndVehicleMove(v); + + DeleteVehicle(v); +} + +static byte SetRoadVehPosition(Vehicle *v, int x, int y) +{ + byte new_z, old_z; + + // need this hint so it returns the right z coordinate on bridges. + _get_z_hint = v->z_pos; + new_z = GetSlopeZ(v->x_pos=x, v->y_pos=y); + _get_z_hint = 0; + + old_z = v->z_pos; + v->z_pos = new_z; + + VehiclePositionChanged(v); + EndVehicleMove(v); + return old_z; +} + +static void RoadVehSetRandomDirection(Vehicle *v) +{ + static const int8 _turn_prob[4] = { -1, 0, 0, 1 }; + uint32 r = Random(); + v->direction = (v->direction+_turn_prob[r&3])&7; + BeginVehicleMove(v); + UpdateRoadVehDeltaXY(v); + v->cur_image = GetRoadVehImage(v, v->direction); + SetRoadVehPosition(v, v->x_pos, v->y_pos); +} + +static void RoadVehIsCrashed(Vehicle *v) +{ + v->u.road.crashed_ctr++; + if (v->u.road.crashed_ctr == 2) { + CreateEffectVehicleRel(v,4,4,8,EV_CRASHED_SMOKE); + } else if (v->u.road.crashed_ctr <= 45) { + if ((v->tick_counter&7)==0) + RoadVehSetRandomDirection(v); + } else if (v->u.road.crashed_ctr >= 2220) { + RoadVehDelete(v); + } +} + +static void *EnumCheckRoadVehCrashTrain(Vehicle *v, Vehicle *u) +{ + if (v->type != VEH_Train || + myabs(v->z_pos - u->z_pos) > 6 || + myabs(v->x_pos - u->x_pos) > 4 || + myabs(v->y_pos - u->y_pos) > 4) + return NULL; + return v; +} + +static void RoadVehCrash(Vehicle *v) +{ + uint16 pass; + + v->u.road.crashed_ctr++; + v->vehstatus |= VS_CRASHED; + + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + + pass = 1; + if (v->cargo_type == 0) + pass += v->cargo_count; + v->cargo_count = 0; + SET_DPARAM16(0, pass); + + AddNewsItem(STR_9031_ROAD_VEHICLE_CRASH_DRIVER+(pass!=1), + NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), + v->index, + 0); + + ModifyStationRatingAround(v->tile, v->owner, -160, 22); + SndPlayVehicleFx(16, v); +} + +static void RoadVehCheckTrainCrash(Vehicle *v) +{ + uint tile; + + if (v->u.road.state == 255) + return; + + tile = v->tile; + + // Make sure it's a road/rail crossing + if (!IS_TILETYPE(tile, MP_STREET) || + (_map5[tile] & 0xF0) != 0x10) + return; + + if (VehicleFromPos(tile, v, (VehicleFromPosProc*)EnumCheckRoadVehCrashTrain) != NULL) + RoadVehCrash(v); +} + +static void HandleBrokenRoadVeh(Vehicle *v) +{ + if (v->breakdown_ctr != 1) { + v->breakdown_ctr = 1; + v->cur_speed = 0; + + if (v->breakdowns_since_last_service != 255) + v->breakdowns_since_last_service++; + + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? 0xD : 0x34, v); + + if (!(v->vehstatus & VS_HIDDEN)) { + Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); + if (u) + u->u.special.unk0 = v->breakdown_delay * 2; + } + } + + if (!(v->tick_counter & 1)) { + if (!--v->breakdown_delay) { + v->breakdown_ctr = 0; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + } + } +} + +static void ProcessRoadVehOrder(Vehicle *v) +{ + uint order; + Station *st; + + if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { + // Let a depot order in the schedule interrupt. + if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + return; + } + + if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + v->date_of_last_service+v->service_interval > _date) { + v->cur_order_index++; + } + + if (v->cur_order_index >= v->num_orders) + v->cur_order_index = 0; + + order = v->schedule_ptr[v->cur_order_index]; + + if (order == 0) { + v->next_order = OT_NOTHING; + v->dest_tile = 0; + return; + } + + if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + return; + + v->next_order = (byte)order; + v->next_order_param = (byte)(order >> 8); + + v->dest_tile = 0; + + if ((order & OT_MASK) == OT_GOTO_STATION) { + if ( (byte)(order >> 8) == v->last_station_visited) + v->last_station_visited = 0xFF; + st = DEREF_STATION(order >> 8); + v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile; + } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order >> 8].xy; + } + + InvalidateVehicleOrderWidget(v); +} + +static void HandleRoadVehLoading(Vehicle *v) +{ + if (v->next_order == OT_NOTHING) + return; + + if (v->next_order != OT_DUMMY) { + if ((v->next_order&OT_MASK) != OT_LOADING) + return; + + if (--v->load_unload_time_rem) + return; + + if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); + if (LoadUnloadVehicle(v)) { + InvalidateWindow(WC_ROADVEH_LIST, v->owner); + MarkRoadVehDirty(v); + } + return; + } + + { + byte b = v->next_order; + v->next_order = OT_LEAVESTATION; + if (!(b & OF_NON_STOP)) + return; + } + } + + v->cur_order_index++; + InvalidateVehicleOrderWidget(v); +} + +static void StartRoadVehSound(Vehicle *v) +{ + int s = _road_engine_sounds[v->engine_type - ROAD_ENGINES_INDEX]; + if (s == 23 && (v->tick_counter&3) == 0) s++; + SndPlayVehicleFx(s, v); +} + +typedef struct RoadVehFindData { + int x,y; + Vehicle *veh; + byte dir; +} RoadVehFindData; + +void *EnumCheckRoadVehClose(Vehicle *v, RoadVehFindData *rvf) +{ + static const byte _dists[] = { + 4, 8, 4, 4, 4, 8, 4, 4, + 4, 4, 4, 8, 4, 4, 4, 8, + }; + + if (rvf->veh == v || + v->type != VEH_Road || + v->u.road.state == 254 || + myabs(v->z_pos - rvf->veh->z_pos) > 6 || + v->direction != rvf->dir || + myabs(rvf->x - v->x_pos) >= _dists[v->direction] || + myabs(rvf->y - v->y_pos) >= _dists[v->direction+8]) + return NULL; + + return v; +} + +static Vehicle *RoadVehFindCloseTo(Vehicle *v, int x, int y, byte dir) +{ + RoadVehFindData rvf; + Vehicle *u; + + if (v->u.road.reverse_ctr != 0) + return NULL; + + rvf.x = x; + rvf.y = y; + rvf.dir = dir; + rvf.veh = v; + u = VehicleFromPos(TILE_FROM_XY(x,y), &rvf, (VehicleFromPosProc*)EnumCheckRoadVehClose); + + if (u == NULL) { + v->u.road.unk2 = 0; + return NULL; + } + + if (++v->u.road.unk2 > 1480) + return NULL; + + return u; +} + +static void RoadVehArrivesAt(Vehicle *v, Station *st) +{ + if (v->engine_type < 123) { + /* Check if station was ever visited before */ + if (!(st->had_vehicle_of_type & HVOT_BUS)) { + uint32 flags; + + st->had_vehicle_of_type |= HVOT_BUS; + SET_DPARAM16(0, st->index); + flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); + AddNewsItem( + STR_902F_CITIZENS_CELEBRATE_FIRST, + flags, + v->index, + 0); + } + } else { + /* Check if station was ever visited before */ + if (!(st->had_vehicle_of_type & HVOT_TRUCK)) { + uint32 flags; + + st->had_vehicle_of_type |= HVOT_TRUCK; + SET_DPARAM16(0, st->index); + flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); + AddNewsItem( + STR_9030_CITIZENS_CELEBRATE_FIRST, + flags, + v->index, + 0); + } + } +} + +static bool RoadVehAccelerate(Vehicle *v) +{ + uint spd = v->cur_speed + 1 + ((v->u.road.overtaking != 0)?1:0); + byte t; + + // Clamp + spd = min(spd, v->max_speed); + + //updates statusbar only if speed have changed to save CPU time + if (spd != v->cur_speed) { + v->cur_speed = spd; + if (_patches.vehicle_speed) + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + // Decrease somewhat when turning + if (!(v->direction&1)) + spd = spd * 3 >> 2; + + if (spd == 0) + return false; + + if ((byte)++spd == 0) + return true; + + v->progress = (t = v->progress) - (byte)spd; + + return (t < v->progress); +} + +static byte RoadVehGetNewDirection(Vehicle *v, int x, int y) +{ + static const byte _roadveh_new_dir[11] = { + 0, 7, 6, 0, + 1, 0, 5, 0, + 2, 3, 4 + }; + + x = x - v->x_pos + 1; + y = y - v->y_pos + 1; + + if ((uint)x > 2 || (uint)y > 2) + return v->direction; + return _roadveh_new_dir[y*4+x]; +} + +static byte RoadVehGetSlidingDirection(Vehicle *v, int x, int y) +{ + byte b = RoadVehGetNewDirection(v,x,y); + byte d = v->direction; + if (b == d) return d; + d = (d+1)&7; + if (b==d) return d; + d = (d-2)&7; + if (b==d) return d; + if (b==((d-1)&7)) return d; + if (b==((d-2)&7)) return d; + return (d+2)&7; +} + +typedef struct OvertakeData { + Vehicle *u, *v; + uint tile; + byte tilebits; +} OvertakeData; + +void *EnumFindVehToOvertake(Vehicle *v, OvertakeData *od) +{ + if (v->tile != (TileIndex)od->tile || + v->type != VEH_Road || + v == od->u || + v == od->v) + return NULL; + return v; +} + +static bool FindRoadVehToOvertake(OvertakeData *od) +{ + uint32 bits; + + bits = GetTileTrackStatus(od->tile, 2)&0x3F; + + if (!(od->tilebits & bits) || (bits&0x3C) || (bits & 0x3F3F0000)) + return true; + return VehicleFromPos(od->tile, od, (VehicleFromPosProc*)EnumFindVehToOvertake) != NULL; +} + +static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u) +{ + OvertakeData od; + byte tt; + + od.v = v; + od.u = u; + + if (u->max_speed >= v->max_speed && + !(u->vehstatus&VS_STOPPED) && + u->cur_speed != 0) + return; + + if (v->direction != u->direction || !(v->direction&1)) + return; + + if (v->u.road.state >= 32 || (v->u.road.state&7) > 1 ) + return; + + tt = (byte)(GetTileTrackStatus(v->tile, 2) & 0x3F); + if ((tt & 3) == 0) + return; + if ((tt & 0x3C) != 0) + return; + + if (tt == 3) { + tt = (v->direction&2)?2:1; + } + od.tilebits = tt; + + od.tile = v->tile; + if (FindRoadVehToOvertake(&od)) + return; + + od.tile = v->tile + _tileoffs_by_dir[v->direction>>1]; + if (FindRoadVehToOvertake(&od)) + return; + + if (od.u->cur_speed == 0 || od.u->vehstatus&VS_STOPPED) { + v->u.road.overtaking_ctr = 0x11; + v->u.road.overtaking = 0x10; + } else { +// if (FindRoadVehToOvertake(&od)) +// return; + v->u.road.overtaking_ctr = 0; + v->u.road.overtaking = 0x10; + } +} + +static void RoadZPosAffectSpeed(Vehicle *v, byte old_z) +{ + if (old_z == v->z_pos) + return; + + if (old_z < v->z_pos) { + v->cur_speed = v->cur_speed * 232 >> 8; + } else { + uint16 spd = v->cur_speed + 2; + if (spd <= v->max_speed) + v->cur_speed = spd; + } +} + +static int PickRandomBit(uint bits) +{ + uint num = 0; + uint b = bits; + uint i; + + do { + if (b & 1) + num++; + } while (b >>= 1); + + num = ((uint16)Random() * num >> 16); + + for(i=0; !((bits & 1) && ((int)--num) < 0); bits>>=1,i++); + return i; +} + +typedef struct { + TileIndex dest; + uint maxtracklen; + uint mindist; +} FindRoadToChooseData; + +static bool EnumRoadTrackFindDist(uint tile, FindRoadToChooseData *frd, int track, uint length, byte *state) +{ + uint dist = GetTileDist(tile, frd->dest); + if (dist <= frd->mindist) { + if (dist != frd->mindist || length < frd->maxtracklen) { + frd->maxtracklen = length; + } + frd->mindist = dist; + } + return false; +} + +// Returns direction to choose +// or -1 if the direction is currently blocked +static int RoadFindPathToDest(Vehicle *v, uint tile, int direction) +{ +#define return_track(x) {best_track = x; goto found_best_track; } + + uint16 signal; + uint bitmask; + uint desttile; + FindRoadToChooseData frd; + int best_track; + uint best_dist, best_maxlen; + uint i; + byte m5; + + { + uint32 r; + r = GetTileTrackStatus(tile, 2); + signal = (uint16)(r >> 16); + bitmask = (uint16)r; + } + + if (IS_TILETYPE(tile, MP_STREET)) { + + if ((_map5[tile]&0xF0) == 0x20 && v->owner == _map_owner[tile]) + bitmask |= _road_veh_fp_ax_or[_map5[tile]&3]; + + } else if (IS_TILETYPE(tile, MP_STATION)) { + if (_map_owner[tile] == OWNER_NONE || _map_owner[tile] == v->owner) { + Station *st = DEREF_STATION(_map2[tile]); + byte val = _map5[tile]; + + if (v->cargo_type != CT_PASSENGERS) { + if (IS_BYTE_INSIDE(val, 0x43, 0x47) && (_patches.roadveh_queue || st->truck_stop_status&3)) + bitmask |= _road_veh_fp_ax_or[(val-0x43)&3]; + } else { + if (IS_BYTE_INSIDE(val, 0x47, 0x4B) && (_patches.roadveh_queue || st->bus_stop_status&3)) + bitmask |= _road_veh_fp_ax_or[(val-0x47)&3]; + } + } + } + + bitmask &= _road_veh_fp_ax_and[direction]; + if (bitmask == 0) { + // reverse + return_track(_road_reverse_table[direction]); + } + + if (v->u.road.reverse_ctr != 0) { + v->u.road.reverse_ctr = 0; + if (v->tile != (TileIndex)tile) { + return_track(_road_reverse_table[direction]); + } + } + + desttile = v->dest_tile; + if (desttile == 0) { + // Pick a random direction + return_track(PickRandomBit(bitmask)); + } + + // Only one direction to choose between? + if (!(bitmask & (bitmask - 1))) { + return_track(FindFirstBit2x64(bitmask)); + } + + if (IS_TILETYPE(desttile, MP_STREET)) { + m5 = _map5[desttile]; + if ((m5&0xF0) == 0x20) + goto do_it; + } else if (IS_TILETYPE(desttile, MP_STATION)) { + m5 = _map5[desttile]; + if (IS_BYTE_INSIDE(m5, 0x43, 0x4B)) { + m5 -= 0x43; +do_it:; + desttile += _tileoffs_by_dir[m5&3]; + if (desttile == tile && bitmask&_road_pf_table_3[m5&3]) { + return_track(FindFirstBit2x64(bitmask&_road_pf_table_3[m5&3])); + } + } + } + // do pathfind + frd.dest = desttile; + + best_track = -1; + best_dist = (uint)-1; + best_maxlen = (uint)-1; + i = 0; + do { + if (bitmask & 1) { + if (best_track == -1) best_track = i; // in case we don't find the path, just pick a direction + frd.maxtracklen = (uint)-1; + frd.mindist = (uint)-1; + FollowTrack(tile, 0x3002, _road_pf_directions[i], (TPFEnumProc*)EnumRoadTrackFindDist, NULL, &frd); + + if (frd.mindist < best_dist || (frd.mindist==best_dist && frd.maxtracklen < best_maxlen)) { + best_dist = frd.mindist; + best_maxlen = frd.maxtracklen; + best_track = i; + } + } + } while (++i,(bitmask>>=1) != 0); + +found_best_track:; + + if (HASBIT(signal, best_track)) + return -1; + + return best_track; +} + +typedef struct RoadDriveEntry { + byte x,y; +} RoadDriveEntry; + +#include "table/roadveh.h" + +static const byte _road_veh_data_1[] = { + 20, 20, 16, 16, 0, 0, 0, 0, + 19, 19, 15, 15, 0, 0, 0, 0, + 16, 16, 12, 12, 0, 0, 0, 0, + 15, 15, 11, 11 +}; + +static const byte _roadveh_data_2[4] = { 0,1,8,9 }; + +static void RoadVehEventHandler(Vehicle *v) +{ + GetNewVehiclePosResult gp; + byte new_dir,old_dir,old_order; + RoadDriveEntry rd; + int x,y; + Station *st; + uint32 r; + Vehicle *u; + + // decrease counters + v->tick_counter++; + if (v->u.road.reverse_ctr != 0) + v->u.road.reverse_ctr--; + + // handle crashed + if (v->u.road.crashed_ctr != 0) { + RoadVehIsCrashed(v); + return; + } + + RoadVehCheckTrainCrash(v); + + // road vehicle has broken down? + if (v->breakdown_ctr != 0) { + if (v->breakdown_ctr <= 2) { + HandleBrokenRoadVeh(v); + return; + } + v->breakdown_ctr--; + } + + // exit if vehicle is stopped + if (v->vehstatus & VS_STOPPED) + return; + + ProcessRoadVehOrder(v); + HandleRoadVehLoading(v); + + if ((v->next_order & OT_MASK) == OT_LOADING) + return; + + if (v->u.road.state == 254) { + int dir; + const RoadDriveEntry*rdp; + byte rd2; + + v->cur_speed = 0; + + dir = _map5[v->tile]&3; + v->direction = dir*2+1; + + rd2 = _roadveh_data_2[dir]; + rdp = _road_drive_data[(_opt.road_side<<4) + rd2]; + + x = GET_TILE_X(v->tile)*16 + (rdp[6].x&0xF); + y = GET_TILE_Y(v->tile)*16 + (rdp[6].y&0xF); + + if (RoadVehFindCloseTo(v,x,y,v->direction)) + return; + + StartRoadVehSound(v); + + BeginVehicleMove(v); + + v->vehstatus &= ~VS_HIDDEN; + v->u.road.state = rd2; + v->u.road.frame = 6; + + v->cur_image = GetRoadVehImage(v, v->direction); + UpdateRoadVehDeltaXY(v); + SetRoadVehPosition(v,x,y); + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + return; + } + + if (!RoadVehAccelerate(v)) + return; + + if (v->u.road.overtaking != 0) { + if (++v->u.road.overtaking_ctr >= 35) + v->u.road.overtaking = 0; + } + + BeginVehicleMove(v); + + if (v->u.road.state == 255) { + GetNewVehiclePos(v, &gp); + + if (RoadVehFindCloseTo(v, gp.x, gp.y, v->direction)) { + v->cur_speed = 0; + return; + } + + if (IS_TILETYPE(gp.new_tile, MP_TUNNELBRIDGE) && + (_map5[gp.new_tile]&0xF0) == 0 && + (VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&4)) { + + //new_dir = RoadGetNewDirection(v, gp.x, gp.y) + v->cur_image = GetRoadVehImage(v, v->direction); + UpdateRoadVehDeltaXY(v); + SetRoadVehPosition(v,gp.x,gp.y); + return; + } + + v->x_pos = gp.x; + v->y_pos = gp.y; + VehiclePositionChanged(v); + return; + } + + rd = _road_drive_data[(v->u.road.state + (_opt.road_side<<4)) ^ v->u.road.overtaking][v->u.road.frame+1]; + +// switch to another tile + if (rd.x & 0x80) { + uint tile = v->tile + _tileoffs_by_dir[rd.x&3]; + int dir = RoadFindPathToDest(v, tile, rd.x&3); + int tmp; + uint32 r; + byte newdir; + const RoadDriveEntry *rdp; + + if (dir == -1) { + v->cur_speed = 0; + return; + } + +again: + if ((dir & 7) >= 6) { + tile = v->tile; + } + + tmp = (dir+(_opt.road_side<<4))^v->u.road.overtaking; + rdp = _road_drive_data[tmp]; + + tmp &= ~0x10; + + x = GET_TILE_X(tile)*16 + rdp[0].x; + y = GET_TILE_Y(tile)*16 + rdp[0].y; + + if (RoadVehFindCloseTo(v, x, y, newdir=RoadVehGetSlidingDirection(v, x, y))) + return; + + r = VehicleEnterTile(v, tile, x, y); + if (r & 8) { + if (!IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + v->cur_speed = 0; + return; + } + dir = _road_reverse_table[rd.x&3]; + goto again; + } + + if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IS_TILETYPE(v->tile, MP_STATION)) { + if ((tmp&7) >= 6) { v->cur_speed = 0; return; } + if (IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x4B)) { + Station *st = DEREF_STATION(_map2[v->tile]); + byte *b; + + if (_map5[v->tile] >= 0x47) { + b = &st->bus_stop_status; + } else { + b = &st->truck_stop_status; + } + *b = (*b | ((v->u.road.state&2)?2:1)) & 0x7F; + } + } + + if (!(r & 4)) { + v->tile = tile; + v->u.road.state = (byte)tmp; + v->u.road.frame = 0; + } + if (newdir != v->direction) { + v->direction = newdir; + v->cur_speed -= v->cur_speed >> 2; + } + + v->cur_image = GetRoadVehImage(v, newdir); + UpdateRoadVehDeltaXY(v); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + return; + } + + if (rd.x & 0x40) { + int dir = RoadFindPathToDest(v, v->tile, rd.x&3); + uint32 r; + int tmp; + byte newdir; + const RoadDriveEntry *rdp; + + if (dir == -1) { + v->cur_speed = 0; + return; + } + + tmp = (_opt.road_side<<4) + dir; + rdp = _road_drive_data[tmp]; + + x = GET_TILE_X(v->tile)*16 + rdp[1].x; + y = GET_TILE_Y(v->tile)*16 + rdp[1].y; + + if (RoadVehFindCloseTo(v, x, y, newdir=RoadVehGetSlidingDirection(v, x, y))) + return; + + r = VehicleEnterTile(v, v->tile, x, y); + if (r & 8) { + v->cur_speed = 0; + return; + } + + v->u.road.state = tmp & ~16; + v->u.road.frame = 1; + + if (newdir != v->direction) { + v->direction = newdir; + v->cur_speed -= v->cur_speed >> 2; + } + + v->cur_image = GetRoadVehImage(v, newdir); + UpdateRoadVehDeltaXY(v); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + return; + } + + x = (v->x_pos&~15)+(rd.x&15); + y = (v->y_pos&~15)+(rd.y&15); + + new_dir = RoadVehGetSlidingDirection(v, x, y); + + if (!IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && (u=RoadVehFindCloseTo(v, x, y, new_dir)) != NULL) { + if (v->u.road.overtaking == 0) + RoadVehCheckOvertake(v, u); + return; + } + + old_dir = v->direction; + if (new_dir != old_dir) { + v->direction = new_dir; + v->cur_speed -= (v->cur_speed >> 2); + if (old_dir != v->u.road.state) { + v->cur_image = GetRoadVehImage(v, new_dir); + UpdateRoadVehDeltaXY(v); + SetRoadVehPosition(v, v->x_pos, v->y_pos); + return; + } + } + + if (v->u.road.state >= 0x20 && + _road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) { + byte *b; + + st = DEREF_STATION(_map2[v->tile]); + b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status; + + if ( (v->next_order&OT_MASK) != OT_LEAVESTATION && + (v->next_order&OT_MASK) != OT_GOTO_DEPOT) { + + *b &= ~0x80; + + v->last_station_visited = _map2[v->tile]; + + RoadVehArrivesAt(v, st); + + old_order = v->next_order; + v->next_order = OT_LOADING; + + if ((old_order & OT_MASK) == OT_GOTO_STATION && + v->next_order_param == v->last_station_visited) { + v->next_order = OT_LOADING | OF_NON_STOP | (old_order & (OF_FULL_LOAD|OF_UNLOAD)); + } + + SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); + if (LoadUnloadVehicle(v)) { + InvalidateWindow(WC_ROADVEH_LIST, v->owner); + MarkRoadVehDirty(v); + } + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + return; + } + + if ((v->next_order & OT_MASK) != OT_GOTO_DEPOT) { + if (*b&0x80) { + v->cur_speed = 0; + return; + } + v->next_order = 0; + } + *b |= 0x80; + + StartRoadVehSound(v); + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + r = VehicleEnterTile(v, v->tile, x, y); + if (r & 8) { + v->cur_speed = 0; + return; + } + + if ((r & 4) == 0) { + v->u.road.frame++; + } + + v->cur_image = GetRoadVehImage(v, v->direction); + UpdateRoadVehDeltaXY(v); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); +} + +void RoadVehEnterDepot(Vehicle *v) +{ + byte t; + + v->u.road.state = 254; + v->vehstatus |= VS_HIDDEN; + + v->date_of_last_service = _date; + v->breakdowns_since_last_service = 0; + v->reliability = _engines[v->engine_type].reliability; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + MaybeRenewVehicle(v, EstimateRoadVehCost(v->engine_type)); + + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + + t = v->next_order; + v->next_order = OT_DUMMY; + + // Part of the schedule? + if (t & OF_UNLOAD) { v->cur_order_index++; } + + else if (t & OF_FULL_LOAD) { + v->vehstatus |= VS_STOPPED; + if (v->owner == _local_player) { + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_9016_ROAD_VEHICLE_IS_WAITING, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + } + } + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); +} + +static void AgeRoadVehCargo(Vehicle *v) +{ + if (_age_cargo_skip_counter != 0) + return; + if (v->cargo_days != 255) + v->cargo_days++; +} + +void RoadVeh_Tick(Vehicle *v) +{ + AgeRoadVehCargo(v); + RoadVehEventHandler(v); +} + +static void CheckIfRoadVehNeedsService(Vehicle *v) +{ + int i; + + if (v->date_of_last_service + v->service_interval > _date) + return; + + if (v->vehstatus & VS_STOPPED) + return; + + if (_patches.gotodepot && IS_HUMAN_PLAYER(v->owner) && ScheduleHasDepotOrders(v->schedule_ptr)) + return; + + // Don't interfere with a depot visit scheduled by the user, or a + // depot visit by the order list. + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && + (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) != 0) + return; + + i = FindClosestRoadDepot(v); + + if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + return; + } + + if (v->next_order == (OT_GOTO_DEPOT | OF_NON_STOP) && !CHANCE16(1,20)) + return; + + v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; + v->next_order_param = (byte)i; + v->dest_tile = (&_depots[i])->xy; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); +} + +void OnNewDay_RoadVeh(Vehicle *v) +{ + int32 cost; + Station *st; + uint tile; + + if ((++v->day_counter & 7) == 0) + DecreaseVehicleValue(v); + + if (v->u.road.unk2 == 0) + CheckVehicleBreakdown(v); + + AgeVehicle(v); + CheckIfRoadVehNeedsService(v); + + /* update destination */ + if ((v->next_order & OT_MASK) == OT_GOTO_STATION) { + st = DEREF_STATION(v->next_order_param); + if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0) + v->dest_tile = tile; + } + + if (v->vehstatus & VS_STOPPED) + return; + + cost = _roadveh_runningcost[v->engine_type - ROAD_ENGINES_INDEX] * _price.roadveh_running / 364; + + v->profit_this_year -= cost >> 8; + + SET_EXPENSES_TYPE(EXPENSES_ROADVEH_RUN); + SubtractMoneyFromPlayerFract(v->owner, cost); + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + InvalidateWindow(WC_ROADVEH_LIST, v->owner); +} + +void HandleClickOnRoadVeh(Vehicle *v) +{ + ShowRoadVehViewWindow(v); +} + +void RoadVehiclesYearlyLoop() +{ + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road) { + v->profit_last_year = v->profit_this_year; + v->profit_this_year = 0; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } +} + diff --git a/roadveh_gui.c b/roadveh_gui.c new file mode 100644 --- /dev/null +++ b/roadveh_gui.c @@ -0,0 +1,853 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "vehicle.h" +#include "viewport.h" +#include "station.h" +#include "command.h" +#include "player.h" +//#include "town.h" +#include "engine.h" + +extern const byte _roadveh_price[88]; +extern const byte _roadveh_speed[88]; +extern const byte _roadveh_runningcost[88]; +extern const byte _roadveh_capacity[88]; +extern const byte _roadveh_cargo_type[88]; + +static void DrawRoadVehImage(Vehicle *v, int x, int y, VehicleID selection) +{ + int image = GetRoadVehImage(v, 6); + uint32 ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)); + if (v->vehstatus & VS_CRASHED) ormod = 0x3248000; + DrawSprite(image | ormod, x+14, y+6); + + if (v->index == selection) { + DrawFrameRect(x-1, y-1, x+28, y+12, 15, 0x10); + } +} + +static void RoadVehDetailsWndProc(Window *w, WindowEvent *e) +{ + Vehicle *v = &_vehicles[w->window_number]; + StringID str; + int mod; + + switch(e->event) { + case WE_PAINT: + w->disabled_state = v->owner == _local_player ? 0 : (1 << 2); + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* Draw running cost */ + { + int year = v->age / 366; + StringID str; + + SET_DPARAM16(1, year); + + str = STR_0199_YEAR; + if (year != 1) { + str++; + if (v->max_age - 366 < v->age) + str++; + } + SET_DPARAM16(0, str); + SET_DPARAM16(2, v->max_age / 366); + SET_DPARAM32(3, _roadveh_runningcost[v->engine_type - ROAD_ENGINES_INDEX] * _price.roadveh_running >> 8); + DrawString(2, 15, STR_900D_AGE_RUNNING_COST_YR, 0); + } + + /* Draw max speed */ + { + SET_DPARAM16(0, v->max_speed * 10 >> 5); + DrawString(2, 25, STR_900E_MAX_SPEED, 0); + } + + /* Draw profit */ + { + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(2, 35, STR_900F_PROFIT_THIS_YEAR_LAST_YEAR, 0); + } + + /* Draw breakdown & reliability */ + { + SET_DPARAM8(0, v->reliability * 100 >> 16); + SET_DPARAM16(1, v->breakdowns_since_last_service); + DrawString(2, 45, STR_9010_RELIABILITY_BREAKDOWNS, 0); + } + + /* Draw service interval text */ + { + SET_DPARAM16(0, v->service_interval); + SET_DPARAM16(1, v->date_of_last_service); + DrawString(13, 90, STR_883C_SERVICING_INTERVAL_DAYS, 0); + } + + DrawRoadVehImage(v, 3, 57, INVALID_VEHICLE); + + SET_DPARAM16(0, GetCustomEngineName(v->engine_type)); + SET_DPARAM16(1, 1920 + v->build_year); + SET_DPARAM32(2, v->value); + DrawString(34, 57, STR_9011_BUILT_VALUE, 0); + + SET_DPARAM16(0, _cargoc.names_long_p[v->cargo_type]); + SET_DPARAM16(1, v->cargo_cap); + DrawString(34, 67, STR_9012_CAPACITY, 0); + + str = STR_8812_EMPTY; + if (v->cargo_count != 0) { + SET_DPARAM8(0, v->cargo_type); + SET_DPARAM16(1, v->cargo_count); + SET_DPARAM16(2, v->cargo_source); + str = STR_8813_FROM; + } + DrawString(34, 78, str, 0); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: /* rename */ + SET_DPARAM16(0, v->unitnumber); + ShowQueryString(v->string_id, STR_902C_NAME_ROAD_VEHICLE, 31, 150, w->window_class, w->window_number); + break; + + case 5: /* increase int */ + mod = 10; + goto change_int; + case 6: /* decrease int */ + mod = -10; +change_int: + mod += v->service_interval; + if (!IS_INT_INSIDE(mod, 30, 800+1)) + return; + DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_ROADVEH_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING)); + break; + } + break; + + case WE_4: + if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL) + DeleteWindow(w); + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_902D_CAN_T_NAME_ROAD_VEHICLE)); + } break; + + } +} + +static const Widget _roadveh_details_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 339, 0, 13, STR_900C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 340, 379, 0, 13, STR_01AA_NAME, STR_902E_NAME_ROAD_VEHICLE}, +{ WWT_IMGBTN, 14, 0, 379, 14, 55, 0x0}, +{ WWT_IMGBTN, 14, 0, 379, 56, 88, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 89, 94, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 95, 100, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL}, +{ WWT_IMGBTN, 14, 11, 379, 89, 100, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _roadveh_details_desc = { + -1,-1, 380, 101, + WC_VEHICLE_DETAILS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _roadveh_details_widgets, + RoadVehDetailsWndProc +}; + +static void ShowRoadVehDetailsWindow(Vehicle *v) +{ + Window *w; + VehicleID veh = v->index; + DeleteWindowById(WC_VEHICLE_ORDERS, veh); + DeleteWindowById(WC_VEHICLE_DETAILS, veh); + _alloc_wnd_parent_num = veh; + w = AllocateWindowDesc(&_roadveh_details_desc); + w->window_number = veh; + w->caption_color = v->owner; +} + +static void RoadVehViewWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + StringID str; + + w->disabled_state = (v->owner != _local_player) ? (1<<7 | 1<<6) : 0; + + /* draw widgets & caption */ + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* draw the flag */ + DrawSprite((v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, 2, 105); + + if (v->u.road.crashed_ctr != 0) { + str = STR_8863_CRASHED; + } else if (v->breakdown_ctr == 1) { + str = STR_885C_BROKEN_DOWN; + } else if (v->vehstatus & VS_STOPPED) { + str = STR_8861_STOPPED; + } else { + switch(v->next_order & OT_MASK) { + case OT_GOTO_STATION: { + SET_DPARAM16(0, v->next_order_param); + SET_DPARAM16(1, v->cur_speed * 10 >> 5); + str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; + } break; + + case OT_GOTO_DEPOT: { + Depot *dep = &_depots[v->next_order_param]; + SET_DPARAM16(0, dep->town_index); + SET_DPARAM16(1, v->cur_speed * 10 >> 5); + str = STR_HEADING_FOR_ROAD_DEPOT + _patches.vehicle_speed; + } break; + + case OT_LOADING: + case OT_LEAVESTATION: + str = STR_882F_LOADING_UNLOADING; + break; + + default: + if (v->num_orders == 0) { + str = STR_NO_ORDERS + _patches.vehicle_speed; + SET_DPARAM16(0, v->cur_speed * 10 >> 5); + } else + str = STR_EMPTY; + break; + } + } + + DrawStringCentered(125, 105, str, 0); + DrawWindowViewport(w); + } break; + + case WE_CLICK: { + Vehicle *v = &_vehicles[w->window_number]; + + switch(e->click.widget) { + case 4: /* start stop */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_ROADVEH | CMD_MSG(STR_9015_CAN_T_STOP_START_ROAD_VEHICLE)); + break; + case 5: /* center main view */ + ScrollMainWindowTo(v->x_pos, v->y_pos); + break; + case 6: /* goto hangar */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_SEND_ROADVEH_TO_DEPOT | CMD_MSG(STR_9018_CAN_T_SEND_VEHICLE_TO_DEPOT)); + break; + case 7: /* turn around */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_TURN_ROADVEH | CMD_MSG(STR_9033_CAN_T_MAKE_VEHICLE_TURN)); + break; + case 8: /* show orders */ + ShowOrdersWindow(v); + break; + case 9: /* show details */ + ShowRoadVehDetailsWindow(v); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number); + DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number); + break; + } +} + +static const Widget _roadveh_view_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 249, 0, 13, STR_9002, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 231, 14, 103, 0x0}, +{ WWT_6, 14, 2, 229, 16, 101, 0}, +{ WWT_PUSHIMGBTN, 14, 0, 249, 104, 115, 0x0, STR_901C_CURRENT_VEHICLE_ACTION}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 14, 31, 0x2AB, STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 32, 49, 0x2AE, STR_901F_SEND_VEHICLE_TO_DEPOT}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 50, 67, 0x2CB, STR_9020_FORCE_VEHICLE_TO_TURN_AROUND}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 68, 85, 0x2B2, STR_901D_SHOW_VEHICLE_S_ORDERS}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 86, 103, 0x2B3, STR_9021_SHOW_ROAD_VEHICLE_DETAILS}, +{ WWT_LAST}, +}; + +static const WindowDesc _roadveh_view_desc = { + -1,-1, 250, 116, + WC_VEHICLE_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _roadveh_view_widgets, + RoadVehViewWndProc, +}; + +void ShowRoadVehViewWindow(Vehicle *v) +{ + Window *w; + + w = AllocateWindowDescFront(&_roadveh_view_desc, v->index); + if (w) { + w->caption_color = v->owner; + AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0); + } +} + + +static void DrawNewRoadVehWindow(Window *w) +{ + YearMonthDay ymd; + + if (w->window_number == 0) + w->disabled_state = 1 << 5; + + // setup scroller + { + int count = 0; + int num = NUM_ROAD_ENGINES; + Engine *e = &_engines[ROAD_ENGINES_INDEX]; + do { + if (HASBIT(e->player_avail, _local_player)) + count++; + } while (++e,--num); + SetVScrollCount(w, count); + } + + DrawWindowWidgets(w); + + { + int num = NUM_ROAD_ENGINES; + Engine *e = &_engines[ROAD_ENGINES_INDEX]; + int x = 1; + int y = 15; + int sel = WP(w,buildtrain_d).sel_index; + int pos = w->vscroll.pos; + int engine_id = ROAD_ENGINES_INDEX; + int selected_id = -1; + + do { + if (HASBIT(e->player_avail, _local_player)) { + if (sel==0) selected_id = engine_id; + if (IS_INT_INSIDE(--pos, -8, 0)) { + DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel==0 ? 0xC : 0x10); + DrawRoadVehEngine(x+29, y+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player))); + y += 14; + } + sel--; + } + } while (++engine_id, ++e,--num); + + WP(w,buildtrain_d).sel_engine = selected_id; + if (selected_id != -1) { + Engine *e; + + SET_DPARAM32(0, _roadveh_price[selected_id - ROAD_ENGINES_INDEX] * (_price.roadveh_base>>3)>>5); + SET_DPARAM16(1, _roadveh_speed[selected_id - ROAD_ENGINES_INDEX] * 10 >> 5); + SET_DPARAM32(2, _roadveh_runningcost[selected_id - ROAD_ENGINES_INDEX] * _price.roadveh_running >> 8); + SET_DPARAM16(4, _roadveh_capacity[selected_id - ROAD_ENGINES_INDEX]); + SET_DPARAM16(3, _cargoc.names_long_p[_roadveh_cargo_type[selected_id - ROAD_ENGINES_INDEX]]); + + e = &_engines[selected_id]; + SET_DPARAM16(6, e->lifelength); + SET_DPARAM8(7, e->reliability * 100 >> 16); + ConvertDayToYMD(&ymd, e->intro_date); + SET_DPARAM16(5, ymd.year + 1920); + + DrawString(2, 127, STR_9008_COST_SPEED_RUNNING_COST, 0); + } + } +} + +static void CcBuildRoadVeh(bool success, uint tile, uint32 p1, uint32 p2) +{ + Vehicle *v; + + if (!success) return; + + v = &_vehicles[_new_roadveh_id]; + if (v->tile == _backup_orders_tile) { + _backup_orders_tile = 0; + RestoreVehicleOrders(v, _backup_orders_data); + } + ShowRoadVehViewWindow(v); +} + +static void NewRoadVehWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawNewRoadVehWindow(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + uint i = (e->click.pt.y - 14) / 14; + if (i < 8) { + WP(w,buildtrain_d).sel_index = i + w->vscroll.pos; + SetWindowDirty(w); + } + } break; + + case 5: { /* build */ + int sel_eng = WP(w,buildtrain_d).sel_engine; + if (sel_eng != -1) + DoCommandP(w->window_number, sel_eng, 0, CcBuildRoadVeh, CMD_BUILD_ROAD_VEH | CMD_MSG(STR_9009_CAN_T_BUILD_ROAD_VEHICLE)); + } break; + + case 6: /* rename */ + WP(w,buildtrain_d).rename_engine = WP(w,buildtrain_d).sel_engine; + ShowQueryString( + GetCustomEngineName(WP(w,buildtrain_d).sel_engine), + STR_9036_RENAME_ROAD_VEHICLE_TYPE, + 31, + 160, + w->window_class, + w->window_number); + break; + } + break; + + case WE_4: + if (w->window_number != 0 && !FindWindowById(WC_VEHICLE_DEPOT, w->window_number)) { + DeleteWindow(w); + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_9037_CAN_T_RENAME_ROAD_VEHICLE)); + } break; + + } +} + +static const Widget _new_road_veh_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 247, 0, 13, STR_9006_NEW_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 236, 14, 125, 0x801, STR_9026_ROAD_VEHICLE_SELECTION}, +{ WWT_SCROLLBAR, 14, 237, 247, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 247, 126, 177, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 123, 178, 189, STR_9007_BUILD_VEHICLE, STR_9027_BUILD_THE_HIGHLIGHTED_ROAD}, +{ WWT_PUSHTXTBTN, 14, 124, 247, 178, 189, STR_9034_RENAME, STR_9035_RENAME_ROAD_VEHICLE_TYPE}, +{ WWT_LAST}, +}; + +static const WindowDesc _new_road_veh_desc = { + -1, -1, 248, 190, + WC_BUILD_VEHICLE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _new_road_veh_widgets, + NewRoadVehWndProc +}; + +static void ShowBuildRoadVehWindow(TileIndex tile) +{ + Window *w; + + DeleteWindowById(WC_BUILD_VEHICLE, tile); + + w = AllocateWindowDesc(&_new_road_veh_desc); + w->window_number = tile; + w->vscroll.cap = 8; + + if (tile != 0) { + w->caption_color = _map_owner[tile]; + } else { + w->caption_color = _local_player; + } +} + +static void DrawRoadDepotWindow(Window *w) +{ + uint tile; + Vehicle *v; + int num,x,y; + Depot *d; + + tile = w->window_number; + + /* setup disabled buttons */ + w->disabled_state = (_map_owner[tile]==_local_player) ? 0 : ((1<<3)|(1<<5)); + + /* determine amount of items for scroller */ + num = 0; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && v->u.road.state == 254 && + v->tile == (TileIndex)tile) + num++; + } + SetVScrollCount(w, (num + 4) / 5); + + /* locate the depot struct */ + for(d=_depots; d->xy != (TileIndex)tile; d++) {} + + SET_DPARAM16(0, d->town_index); + DrawWindowWidgets(w); + + x = 2; + y = 15; + num = w->vscroll.pos * 5; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && + v->u.road.state == 254 && + v->tile == (TileIndex)tile && + --num < 0 && num >= -15) { + + DrawRoadVehImage(v, x+24, y, WP(w,traindepot_d).sel); + + SET_DPARAM16(0, v->unitnumber); + DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); + + DrawSprite( (v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, x + 16, y); + + if ((x+=56) == 2+56*5) { + x = 2; + y += 14; + } + } + } +} + +static int GetVehicleFromRoadDepotWndPt(Window *w, int x, int y, Vehicle **veh) +{ + uint xt,yt,xm; + TileIndex tile; + Vehicle *v; + int pos; + + xt = x / 56; + xm = x % 56; + if (xt >= 5) + return 1; + + yt = (y - 14) / 14; + if (yt >= 3) + return 1; + + pos = (yt + w->vscroll.pos) * 5 + xt; + + tile = w->window_number; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && + v->u.road.state == 254 && + v->tile == (TileIndex)tile && + --pos < 0) { + *veh = v; + if (xm >= 24) + return 0; + + if (xm <= 16) + return -1; /* show window */ + + return -2; /* start stop */ + } + } + + return 1; /* outside */ +} + +static void RoadDepotClickVeh(Window *w, int x, int y) +{ + Vehicle *v; + int r; + + r = GetVehicleFromRoadDepotWndPt(w, x, y, &v); + if (r > 0) return; + + if (_thd.place_mode) { _place_clicked_vehicle = v; return; } + switch (r) { + case 0: + if (v != NULL) { + WP(w,traindepot_d).sel = v->index; + SetWindowDirty(w); + SetObjectToPlaceWnd( SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)) + GetRoadVehImage(v, 6), 4, w); + } + break; + + case -1: + ShowRoadVehViewWindow(v); + break; + + case -2: + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_ROADVEH | CMD_MSG(STR_9015_CAN_T_STOP_START_ROAD_VEHICLE)); + break; + + default: + NOT_REACHED(); + } +} + +static void RoadDepotWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawRoadDepotWindow(w); + break; + + case WE_CLICK: { + switch(e->click.widget) { + case 2: + RoadDepotClickVeh(w, e->click.pt.x, e->click.pt.y); + break; + + case 5: + ShowBuildRoadVehWindow(w->window_number); + break; + + case 6: /* scroll to tile */ + ScrollMainWindowToTile(w->window_number); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + break; + + case WE_DRAGDROP: { + switch(e->click.widget) { + case 2: { + Vehicle *v; + VehicleID sel = WP(w,traindepot_d).sel; + + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + + if (GetVehicleFromRoadDepotWndPt(w, e->dragdrop.pt.x, e->dragdrop.pt.y, &v) == 0 && + v != NULL && + sel == v->index) { + ShowRoadVehViewWindow(v); + } + } break; + + case 3: + if (!HASBIT(w->disabled_state, 3) && + WP(w,traindepot_d).sel != INVALID_VEHICLE) { + Vehicle *v; + + HandleButtonClick(w, 3); + + v = &_vehicles[WP(w,traindepot_d).sel]; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + + _backup_orders_tile = v->tile; + BackupVehicleOrders(v, _backup_orders_data); + + if (!DoCommandP(v->tile, v->index, 0, NULL, CMD_SELL_ROAD_VEH | CMD_MSG(STR_9014_CAN_T_SELL_ROAD_VEHICLE))) + _backup_orders_tile = 0; + } + break; + default: + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + } + break; + } + break; + + } + +} + +static const Widget _road_depot_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 314, 0, 13, STR_9003_ROAD_VEHICLE_DEPOT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 279, 14, 55, 0x305, STR_9022_VEHICLES_CLICK_ON_VEHICLE}, +{ WWT_IMGBTN, 14, 280, 303, 14, 55, 0x2A9, STR_9024_DRAG_ROAD_VEHICLE_TO_HERE}, +{ WWT_SCROLLBAR, 14, 304, 314, 14, 55, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 156, 56, 67, STR_9004_NEW_VEHICLES, STR_9023_BUILD_NEW_ROAD_VEHICLE}, +{ WWT_PUSHTXTBTN, 14, 157, 314, 56, 67, STR_00E4_LOCATION, STR_9025_CENTER_MAIN_VIEW_ON_ROAD}, +{ WWT_LAST}, +}; + +static const WindowDesc _road_depot_desc = { + -1, -1, 315, 68, + WC_VEHICLE_DEPOT,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _road_depot_widgets, + RoadDepotWndProc +}; + +void ShowRoadDepotWindow(uint tile) +{ + Window *w; + + w = AllocateWindowDescFront(&_road_depot_desc, tile); + if (w) { + w->caption_color = _map_owner[w->window_number]; + w->vscroll.cap = 3; + WP(w,traindepot_d).sel = -1; + _backup_orders_tile = 0; + } +} + +static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + /* determine amount of items for scroller */ + { + Vehicle *v; + int num = 0; + byte owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && v->owner == owner) + num++; + } + SetVScrollCount(w, num); + } + + /* draw the widgets */ + { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawWindowWidgets(w); + } + + /* draw the road vehicles */ + { + Vehicle *v; + int pos = w->vscroll.pos; + byte owner = (byte)w->window_number; + int x = 2; + int y = 15; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && v->owner == owner && + --pos < 0 && pos >= -7) { + StringID str; + + DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y+13); + + SET_DPARAM16(0, v->unitnumber); + if (IsRoadDepotTile(v->tile)) { + str = STR_021F; + } else { + str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; + } + DrawString(x, y+2, str, 0); + + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + if (v->string_id != STR_SV_ROADVEH_NAME) { + SET_DPARAM16(0, v->string_id); + DrawString(x+24, y, STR_01AB, 0); + } + y += 26; + } + } + } + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { + int idx = (e->click.pt.y - 14) / 26; + Vehicle *v; + byte owner; + + if ((uint)idx >= 7) + break; + + idx += w->vscroll.pos; + + owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Road && v->owner == owner && + --idx < 0) { + ShowRoadVehViewWindow(v); + break; + } + } + } break; + + case 4: { + uint tile; + + tile = _last_built_road_depot_tile; + do { + if (_map_owner[tile] == _local_player && + IsRoadDepotTile(tile)) { + + ShowRoadDepotWindow(tile); + ShowBuildRoadVehWindow(tile); + return; + } + + tile = TILE_MASK(tile + 1); + } while(tile != _last_built_road_depot_tile); + + ShowBuildRoadVehWindow(0); + } break; + } break; + } +} + +static const Widget _player_roadveh_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 195, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 129, 196, 207, STR_9004_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES}, +{ WWT_IMGBTN, 14, 130, 259, 196, 207, 0x0, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _player_roadveh_desc = { + -1, -1, 260, 208, + WC_ROADVEH_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _player_roadveh_widgets, + PlayerRoadVehWndProc +}; + +static const Widget _other_player_roadveh_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 195, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_player_roadveh_desc = { + -1, -1, 260, 196, + WC_ROADVEH_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _other_player_roadveh_widgets, + PlayerRoadVehWndProc +}; + + +void ShowPlayerRoadVehicles(int player) +{ + Window *w; + + if ( player == _local_player) { + w = AllocateWindowDescFront(&_player_roadveh_desc, player); + } else { + w = AllocateWindowDescFront(&_other_player_roadveh_desc, player); + } + if (w) { + w->caption_color = player; + w->vscroll.cap = 7; + } +} diff --git a/saveload.c b/saveload.c new file mode 100644 --- /dev/null +++ b/saveload.c @@ -0,0 +1,1173 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "station.h" +#include "town.h" +#include "player.h" +#include "saveload.h" +#include + +enum { + SAVEGAME_MAJOR_VERSION = 4, + SAVEGAME_MINOR_VERSION = 0, + + SAVEGAME_LOADABLE_VERSION = (SAVEGAME_MAJOR_VERSION << 8) + SAVEGAME_MINOR_VERSION +}; + +/******************************************************/ +/******************************************************/ +/******************************************************/ + +typedef void WriterProc(uint len); +typedef uint ReaderProc(); + +typedef uint ReferenceToIntProc(void *v, uint t); +typedef void *IntToReferenceProc(uint r, uint t); + +typedef struct { + bool save; + byte need_length; + byte block_mode; + bool error; + byte version; + + int obj_len; + int array_index, last_array_index; + + uint32 offs_base; + + WriterProc *write_bytes; + ReaderProc *read_bytes; + + ReferenceToIntProc *ref_to_int_proc; + IntToReferenceProc *int_to_ref_proc; + + const ChunkHandler * const * chs; + const byte * const *includes; + + byte *bufp, *bufe; + + int tmp; + + // these 3 may be used by compressor/decompressors. + byte *buf; // pointer and size to read/write, initialized by init + uint bufsize; + FILE *fh; + + void (*excpt_uninit)(); + const char *excpt_msg; + jmp_buf excpt; // used to jump to "exception handler" +} SaverLoader; + +enum NeedLengthValues { NL_NONE = 0,NL_WANTLENGTH = 1,NL_CALCLENGTH = 2}; + +SaverLoader _sl; + +// fill the input buffer +static void SlReadFill() +{ + uint len = _sl.read_bytes(); + assert(len != 0); + + _sl.bufp = _sl.buf; + _sl.bufe = _sl.buf + len; + _sl.offs_base += len; +} + +static uint32 SlGetOffs() +{ + return _sl.offs_base - (_sl.bufe - _sl.bufp); +} + +// flush the output buffer +static void SlWriteFill() +{ + // flush current buffer? + if (_sl.bufp != NULL) { + uint len = _sl.bufp - _sl.buf; + _sl.offs_base += len; + if (len) _sl.write_bytes(len); + } + + // setup next buffer + _sl.bufp = _sl.buf; + _sl.bufe = _sl.buf + _sl.bufsize; +} + +// error handler, calls longjmp to simulate an exception. +static void NORETURN SlError(const char *msg) +{ + _sl.excpt_msg = msg; + longjmp(_sl.excpt, 0); +} + +int SlReadByte() +{ + if (_sl.bufp == _sl.bufe) SlReadFill(); + return *_sl.bufp++; +} + +void SlWriteByte(byte v) +{ + if (_sl.bufp == _sl.bufe) SlWriteFill(); + *_sl.bufp++ = v; +} + +int SlReadUint16() +{ + int x = SlReadByte() << 8; + return x | SlReadByte(); +} + +uint32 SlReadUint32() +{ + uint32 x = SlReadUint16() << 16; + return x | SlReadUint16(); +} + +uint64 SlReadUint64() +{ + uint32 x = SlReadUint32(); + uint32 y = SlReadUint32(); + return (uint64)x << 32 | y; +} + +void SlWriteUint16(uint16 v) +{ + SlWriteByte((byte)(v >> 8)); + SlWriteByte((byte)v); +} + +void SlWriteUint32(uint32 v) +{ + SlWriteUint16((uint16)(v >> 16)); + SlWriteUint16((uint16)v); +} + +void SlWriteUint64(uint64 x) +{ + SlWriteUint32((uint32)(x >> 32)); + SlWriteUint32((uint32)x); +} + +static int SlReadSimpleGamma() +{ + int x = SlReadByte(); + if (x & 0x80) + x = ((x&0x7F) << 8) + SlReadByte(); + return x; +} + +static void SlWriteSimpleGamma(uint i) +{ + assert(i < (1 << 14)); + if (i >= 0x80) { + SlWriteByte((byte)(0x80|(i >> 8))); + SlWriteByte((byte)i); + } else { + SlWriteByte(i); + } +} + +static uint SlGetGammaLength(uint i) { + return (i>=0x80) ? 2 : 1; +} + +int INLINE SlReadSparseIndex() +{ + return SlReadSimpleGamma(); +} + +void INLINE SlWriteSparseIndex(uint index) +{ + SlWriteSimpleGamma(index); +} + +int INLINE SlReadArrayLength() +{ + return SlReadSimpleGamma(); +} + +void INLINE SlWriteArrayLength(uint length) +{ + SlWriteSimpleGamma(length); +} + +void SlSetArrayIndex(uint index) +{ + _sl.need_length = NL_WANTLENGTH; + _sl.array_index = index; +} + +int SlIterateArray() +{ + int ind; + static uint32 next_offs; + + // Must be at end of current block. + assert(next_offs == 0 || SlGetOffs() == next_offs); + + while(true) { + uint len = SlReadArrayLength(); + if (len == 0) { + next_offs = 0; + return -1; + } + + _sl.obj_len = --len; + next_offs = SlGetOffs() + len; + + switch(_sl.block_mode) { + case CH_SPARSE_ARRAY: ind = SlReadSparseIndex(); break; + case CH_ARRAY: ind = _sl.array_index++; break; + default: + DEBUG(misc, 0) ("SlIterateArray: error\n"); + return -1; // error + } + + if (len != 0) + return ind; + } +} + +// Sets the length of either a RIFF object or the number of items in an array. +void SlSetLength(uint length) +{ + switch(_sl.need_length) { + case NL_WANTLENGTH: + _sl.need_length = NL_NONE; + switch(_sl.block_mode) { + case CH_RIFF: + // Really simple to write a RIFF length :) + SlWriteUint32(length); + break; + case CH_ARRAY: + assert(_sl.array_index >= _sl.last_array_index); + while (++_sl.last_array_index <= _sl.array_index) + SlWriteArrayLength(1); + SlWriteArrayLength(length + 1); + break; + case CH_SPARSE_ARRAY: + SlWriteArrayLength(length + 1 + SlGetGammaLength(_sl.array_index)); // Also include length of sparse index. + SlWriteSparseIndex(_sl.array_index); + break; + default: NOT_REACHED(); + } + break; + case NL_CALCLENGTH: + _sl.obj_len += length; + break; + } +} + +void SlCopyBytes(void *ptr, size_t length) +{ + byte *p = (byte*)ptr; + + if (_sl.save) { + while(length) { + SlWriteByte(*p++); + length--; + } + } else { + while(length) { + // INLINED SlReadByte +#if !defined(_DEBUG) + if (_sl.bufp == _sl.bufe) SlReadFill(); + *p++ = *_sl.bufp++; +#else + *p++ = SlReadByte(); +#endif + length--; + } + } +} + +void SlSkipBytes(size_t length) +{ + while (length) { + SlReadByte(); + length--; + } +} + +uint SlGetFieldLength() +{ + return _sl.obj_len; +} + + +static void SlSaveLoadConv(void *ptr, uint conv) +{ + int64 x = 0; + + if (_sl.save) { + // Read a value from the struct. These ARE endian safe. + switch((conv >> 4)&0xf) { + case SLE_VAR_I8>>4: x = *(int8*)ptr; break; + case SLE_VAR_U8>>4: x = *(byte*)ptr; break; + case SLE_VAR_I16>>4: x = *(int16*)ptr; break; + case SLE_VAR_U16>>4: x = *(uint16*)ptr; break; + case SLE_VAR_I32>>4: x = *(int32*)ptr; break; + case SLE_VAR_U32>>4: x = *(uint32*)ptr; break; + case SLE_VAR_I64>>4: x = *(int64*)ptr; break; + case SLE_VAR_U64>>4: x = *(uint64*)ptr; break; + case SLE_VAR_NULL>>4: x = 0; break; + default: + NOT_REACHED(); + } + + // Write it to the file + switch(conv & 0xF) { + case SLE_FILE_I8: assert(x >= -128 && x <= 127); SlWriteByte(x);break; + case SLE_FILE_U8: assert(x >= 0 && x <= 255); SlWriteByte(x);break; + case SLE_FILE_I16:assert(x >= -32768 && x <= 32767); SlWriteUint16(x);break; + case SLE_FILE_STRINGID: + case SLE_FILE_U16:assert(x >= 0 && x <= 65535); SlWriteUint16(x);break; + case SLE_FILE_I32: + case SLE_FILE_U32:SlWriteUint32((uint32)x);break; + case SLE_FILE_I64: + case SLE_FILE_U64:SlWriteUint64(x);break; + default: + assert(0); + NOT_REACHED(); + } + } else { + + // Read a value from the file + switch(conv & 0xF) { + case SLE_FILE_I8: x = (int8)SlReadByte(); break; + case SLE_FILE_U8: x = (byte)SlReadByte(); break; + case SLE_FILE_I16: x = (int16)SlReadUint16(); break; + case SLE_FILE_U16: x = (uint16)SlReadUint16(); break; + case SLE_FILE_I32: x = (int32)SlReadUint32(); break; + case SLE_FILE_U32: x = (uint32)SlReadUint32(); break; + case SLE_FILE_I64: x = (int64)SlReadUint64(); break; + case SLE_FILE_U64: x = (uint64)SlReadUint64(); break; + case SLE_FILE_STRINGID: x = RemapOldStringID((uint16)SlReadUint16()); break; + default: + assert(0); + NOT_REACHED(); + } + + // Write it to the struct, these ARE endian safe. + switch((conv >> 4)&0xf) { + case SLE_VAR_I8>>4: *(int8*)ptr = x; break; + case SLE_VAR_U8>>4: *(byte*)ptr = x; break; + case SLE_VAR_I16>>4: *(int16*)ptr = x; break; + case SLE_VAR_U16>>4: *(uint16*)ptr = x; break; + case SLE_VAR_I32>>4: *(int32*)ptr = x; break; + case SLE_VAR_U32>>4: *(uint32*)ptr = x; break; + case SLE_VAR_I64>>4: *(int64*)ptr = x; break; + case SLE_VAR_U64>>4: *(uint64*)ptr = x; break; + case SLE_VAR_NULL: break; + default: + NOT_REACHED(); + } + } +} + +static const byte _conv_lengths[] = {1,1,2,2,4,4,8,8,2}; + +static uint SlCalcConvLen(uint conv, void *p) +{ + return _conv_lengths[conv & 0xF]; +} + +static uint SlCalcArrayLen(void *array, uint length, uint conv) +{ + return _conv_lengths[conv & 0xF] * length; +} + +static const byte _conv_mem_size[9] = {1,1,2,2,4,4,8,8,0}; +void SlArray(void *array, uint length, uint conv) +{ + // Automatically calculate the length? + if (_sl.need_length != NL_NONE) { + SlSetLength(SlCalcArrayLen(array, length, conv)); + // Determine length only? + if (_sl.need_length == NL_CALCLENGTH) + return; + } + + // handle buggy stuff + if (!_sl.save && _sl.version == 0) { + if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID) { + length *= 2; + conv = SLE_INT8; + } else if (conv == SLE_INT32 || conv == SLE_UINT32) { + length *= 4; + conv = SLE_INT8; + } + } + + // Optimized cases when input equals output. + switch(conv) { + case SLE_INT8: + case SLE_UINT8:SlCopyBytes(array, length);break; + default: { + // Default "slow" case. + byte *a = (byte*)array; + while (length) { + SlSaveLoadConv(a, conv); + a += _conv_mem_size[(conv >> 4)&0xf]; + length--; + } + } + } +} + +// Calculate the size of an object. +static size_t SlCalcObjLength(void *object, const void *desc) +{ + size_t length = 0; + uint cmd,conv; + byte *d = (byte*)desc; + + // Need to determine the length and write a length tag. + while (true) { + cmd = (d[0] >> 4); + if (cmd < 8) { + conv = d[2]; + d += 3; + if (cmd&4) { + d += 2; + // check if the field is of the right version + if (_sl.version < d[-2] || _sl.version > d[-1]) { + if ((cmd & 3) == 2) d++; + continue; + } + } + + switch(cmd&3) { + // Normal variable + case 0: length += SlCalcConvLen(conv, NULL);break; + // Reference + case 1: length += 2; break; + // Array + case 2: length += SlCalcArrayLen(NULL, *d++, conv); break; + default:NOT_REACHED(); + } + } else if (cmd == 8) { + length++; + d += 4; + } else if (cmd == 9) { + length += SlCalcObjLength(NULL, _sl.includes[d[2]]); + d += 3; + } else if (cmd == 15) + break; + else + assert(0); + } + return length; +} + +void SlObject(void *object, const void *desc) +{ + byte *d = (byte*)desc; + void *ptr; + uint cmd,conv; + + // Automatically calculate the length? + if (_sl.need_length != NL_NONE) { + SlSetLength(SlCalcObjLength(object, d)); + if (_sl.need_length == NL_CALCLENGTH) + return; + } + + while (true) { + // Currently it only supports up to 4096 byte big objects + ptr = (byte*)object + (d[0] & 0xF) + (d[1] << 4); + + cmd = d[0] >> 4; + + if (cmd < 8) { + conv = d[2]; + d += 3; + + if (cmd&4) { + d += 2; + // check if the field is of the right version + if (_sl.version < d[-2] || _sl.version > d[-1]) { + if ((cmd & 3) == 2) d++; + continue; + } + } + + switch(cmd&3) { + // Normal variable + case 0: SlSaveLoadConv(ptr, conv); break; + // Reference + case 1: + if (_sl.save) { + SlWriteUint16(_sl.ref_to_int_proc(*(void**)ptr, conv)); + } else { + *(void**)ptr = _sl.int_to_ref_proc(SlReadUint16(), conv); + } + break; + // Array + case 2: SlArray(ptr, *d++, conv); break; + default:NOT_REACHED(); + } + + // Write byte. + } else if (cmd == 8) { + if (_sl.save) { + SlWriteByte(d[3]); + } else { + *(byte*)ptr = d[2]; + } + d += 4; + + // Include + } else if (cmd == 9) { + SlObject(ptr, _sl.includes[d[2]]); + d += 3; + } else if (cmd == 15) + break; + else + assert(0); + } +} + + +static size_t SlCalcGlobListLength(const SaveLoadGlobVarList *desc) +{ + size_t length = 0; + + while (desc->address) { + length += SlCalcConvLen(desc->conv, NULL); + desc++; + } + return length; +} + +// Save/Load a list of global variables +void SlGlobList(const SaveLoadGlobVarList *desc) +{ + if (_sl.need_length != NL_NONE) { + SlSetLength(SlCalcGlobListLength(desc)); + if (_sl.need_length == NL_CALCLENGTH) + return; + } + while (true) { + void *ptr = desc->address; + if (ptr == NULL) + break; + if(_sl.version >= desc->from_version && _sl.version <= desc->to_version) + SlSaveLoadConv(ptr, desc->conv); + desc++; + } +} + + +void SlAutolength(AutolengthProc *proc, void *arg) +{ + uint32 offs; + + assert(_sl.save); + + // Tell it to calculate the length + _sl.need_length = NL_CALCLENGTH; + _sl.obj_len = 0; + proc(arg); + + // Setup length + _sl.need_length = NL_WANTLENGTH; + SlSetLength(_sl.obj_len); + + offs = SlGetOffs() + _sl.obj_len; + + // And write the stuff + proc(arg); + + assert(offs == SlGetOffs()); +} + +static void SlLoadChunk(const ChunkHandler *ch) +{ + byte m = SlReadByte(); + size_t len; + uint32 endoffs; + + _sl.block_mode = m; + _sl.obj_len = 0; + + switch(m) { + case CH_ARRAY: + _sl.array_index = 0; + ch->load_proc(); + break; + + case CH_SPARSE_ARRAY: + ch->load_proc(); + break; + + case CH_RIFF: + // Read length + len = SlReadByte() << 16; + len += SlReadUint16(); + _sl.obj_len = len; + endoffs = SlGetOffs() + len; + ch->load_proc(); + assert(SlGetOffs() == endoffs); + break; + default: + assert(0); + } +} + +static ChunkSaveLoadProc *_tmp_proc_1; + +static void SlStubSaveProc2(void *arg) +{ + _tmp_proc_1(); +} + +static void SlStubSaveProc() +{ + SlAutolength(SlStubSaveProc2, NULL); +} + +static void SlSaveChunk(const ChunkHandler *ch) +{ + ChunkSaveLoadProc *proc; + + SlWriteUint32(ch->id); + + proc = ch->save_proc; + if (ch->flags & CH_AUTO_LENGTH) { + // Need to calculate the length. Solve that by calling SlAutoLength in the save_proc. + _tmp_proc_1 = proc; + proc = SlStubSaveProc; + } + + _sl.block_mode = ch->flags & CH_TYPE_MASK; + switch(ch->flags & CH_TYPE_MASK) { + case CH_RIFF: + _sl.need_length = NL_WANTLENGTH; + proc(); + break; + case CH_ARRAY: + _sl.last_array_index = 0; + SlWriteByte(CH_ARRAY); + proc(); + SlWriteArrayLength(0); // Terminate arrays + break; + case CH_SPARSE_ARRAY: + SlWriteByte(CH_SPARSE_ARRAY); + proc(); + SlWriteArrayLength(0); // Terminate arrays + break; + default: + NOT_REACHED(); + } +} + +void SlSaveChunks() +{ + const ChunkHandler *ch; + const ChunkHandler * const * chsc; + uint p; + + for(p=0; p!=CH_NUM_PRI_LEVELS; p++) { + for(chsc=_sl.chs;(ch=*chsc++) != NULL;) { + while(true) { + if (((ch->flags >> CH_PRI_SHL) & (CH_NUM_PRI_LEVELS - 1)) == p) + SlSaveChunk(ch); + if (ch->flags & CH_LAST) + break; + ch++; + } + } + } + + // Terminator + SlWriteUint32(0); +} + +static const ChunkHandler *SlFindChunkHandler(uint32 id) +{ + const ChunkHandler *ch; + const ChunkHandler * const * chsc; + for(chsc=_sl.chs;(ch=*chsc++) != NULL;) { + while(true) { + if (ch->id == id) + return ch; + if (ch->flags & CH_LAST) + break; + ch++; + } + } + return NULL; +} + +void SlLoadChunks() +{ + uint32 id; + const ChunkHandler *ch; + + while(true) { + id = SlReadUint32(); + if (id == 0) + return; +#if 0 + printf("Loading chunk %c%c%c%c\n", id >> 24, id>>16, id>>8,id); +#endif + ch = SlFindChunkHandler(id); + if (ch == NULL) SlError("found unknown tag in savegame (sync error)"); + SlLoadChunk(ch); + } +} + +//******************************************* +//********** START OF LZO CODE ************** +//******************************************* +#define LZO_SIZE 8192 + +int CDECL lzo1x_1_compress( const byte *src, uint src_len,byte *dst, uint *dst_len,void *wrkmem ); +uint32 CDECL lzo_adler32(uint32 adler, const byte *buf, uint len); +int CDECL lzo1x_decompress( const byte *src, uint src_len,byte *dst, uint *dst_len,void *wrkmem /* NOT USED */ ); + +static uint ReadLZO() +{ + byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; + uint32 tmp[2]; + uint32 size; + uint len; + + // Read header + if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError("file read failed"); + + // Check if size is bad + ((uint32*)out)[0] = size = tmp[1]; + + if (_sl.version != 0) { + tmp[0] = TO_BE32(tmp[0]); + size = TO_BE32(size); + } + + if (size >= sizeof(out)) SlError("inconsistent size"); + + // Read block + if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError("file read failed"); + + // Verify checksum + if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError("bad checksum"); + + // Decompress + lzo1x_decompress(out + sizeof(uint32)*1, size, _sl.buf, &len, NULL); + return len; +} + +// p contains the pointer to the buffer, len contains the pointer to the length. +// len bytes will be written, p and l will be updated to reflect the next buffer. +static void WriteLZO(uint size) +{ + byte out[LZO_SIZE + LZO_SIZE / 64 + 16 + 3 + 8]; + byte wrkmem[sizeof(byte*)*4096]; + uint outlen; + + lzo1x_1_compress(_sl.buf, size, out + sizeof(uint32)*2, &outlen, wrkmem); + ((uint32*)out)[1] = TO_BE32(outlen); + ((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32))); + if (fwrite(out, outlen + sizeof(uint32)*2, 1, _sl.fh) != 1) SlError("file write failed"); +} + +static bool InitLZO() { + _sl.bufsize = LZO_SIZE; + _sl.buf = (byte*)malloc(LZO_SIZE); + return true; +} + +static void UninitLZO() { + free(_sl.buf); +} + +//******************************************* +//******** START OF NOCOMP CODE ************* +//******************************************* +static uint ReadNoComp() +{ + return fread(_sl.buf, 1, LZO_SIZE, _sl.fh); +} + +static void WriteNoComp(uint size) +{ + fwrite(_sl.buf, 1, size, _sl.fh); +} + +static bool InitNoComp() +{ + _sl.bufsize = LZO_SIZE; + _sl.buf = (byte*)malloc(LZO_SIZE); + return true; +} + +static void UninitNoComp() +{ + free(_sl.buf); +} + +//******************************************** +//********** START OF ZLIB CODE ************** +//******************************************** + +#if defined(WITH_ZLIB) +#include +static z_stream _z; + +static bool InitReadZlib() +{ + memset(&_z, 0, sizeof(_z)); + if (inflateInit(&_z) != Z_OK) return false; + + _sl.bufsize = 4096; + _sl.buf = (byte*)malloc(4096 + 4096); // also contains fread buffer + return true; +} + +static uint ReadZlib() +{ + int r; + + _z.next_out = _sl.buf; + _z.avail_out = 4096; + + do { + // read more bytes from the file? + if (_z.avail_in == 0) { + _z.avail_in = fread(_z.next_in = _sl.buf + 4096, 1, 4096, _sl.fh); + } + + // inflate the data + r = inflate(&_z, 0); + if (r == Z_STREAM_END) + break; + + if (r != Z_OK) + SlError("inflate() failed"); + } while (_z.avail_out); + + return 4096 - _z.avail_out; +} + +static void UninitReadZlib() +{ + inflateEnd(&_z); + free(_sl.buf); +} + +static bool InitWriteZlib() +{ + memset(&_z, 0, sizeof(_z)); + if (deflateInit(&_z, 6) != Z_OK) return false; + + _sl.bufsize = 4096; + _sl.buf = (byte*)malloc(4096); // also contains fread buffer + return true; +} + +static void WriteZlibLoop(z_streamp z, byte *p, uint len, int mode) +{ + char buf[1024]; // output buffer + int r; + uint n; + z->next_in = p; + z->avail_in = len; + do { + z->next_out = buf; + z->avail_out = sizeof(buf); + r = deflate(z, mode); + // bytes were emitted? + if ((n=sizeof(buf) - z->avail_out) != 0) { + if (fwrite(buf, n, 1, _sl.fh) != 1) SlError("file write error"); + } + if (r == Z_STREAM_END) + break; + if (r != Z_OK) SlError("zlib returned error code"); + } while (z->avail_in || !z->avail_out); +} + +static void WriteZlib(uint len) +{ + WriteZlibLoop(&_z, _sl.buf, len, 0); +} + +static void UninitWriteZlib() +{ + // flush any pending output. + if (_sl.fh) WriteZlibLoop(&_z, NULL, 0, Z_FINISH); + deflateEnd(&_z); + free(_sl.buf); +} + +#endif //WITH_ZLIB + +//******************************************* +//************* END OF CODE ***************** +//******************************************* + +// these define the chunks +extern const ChunkHandler _misc_chunk_handlers[]; +extern const ChunkHandler _player_chunk_handlers[]; +extern const ChunkHandler _veh_chunk_handlers[]; +extern const ChunkHandler _town_chunk_handlers[]; +extern const ChunkHandler _sign_chunk_handlers[]; +extern const ChunkHandler _station_chunk_handlers[]; +extern const ChunkHandler _industry_chunk_handlers[]; +extern const ChunkHandler _engine_chunk_handlers[]; +extern const ChunkHandler _economy_chunk_handlers[]; +extern const ChunkHandler _animated_tile_chunk_handlers[]; + +static const ChunkHandler * const _chunk_handlers[] = { + _misc_chunk_handlers, + _veh_chunk_handlers, + _industry_chunk_handlers, + _economy_chunk_handlers, + _engine_chunk_handlers, + _town_chunk_handlers, + _sign_chunk_handlers, + _station_chunk_handlers, + _player_chunk_handlers, + _animated_tile_chunk_handlers, + NULL, +}; + +// used to include a vehicle desc in another desc. +extern const byte _common_veh_desc[]; +static const byte * const _desc_includes[] = { + _common_veh_desc +}; + +typedef struct { + void *base; + size_t size; +} ReferenceSetup; + +// used to translate "pointers" +static const ReferenceSetup _ref_setup[] = { + {_order_array,sizeof(_order_array[0])}, + {_vehicles,sizeof(_vehicles[0])}, + {_stations,sizeof(_stations[0])}, + {_towns,sizeof(_towns[0])}, +}; + +uint ReferenceToInt(void *v, uint t) +{ + if (v == NULL) return 0; + return ((byte*)v - (byte*)_ref_setup[t].base) / _ref_setup[t].size + 1; +} + +void *IntToReference(uint r, uint t) +{ + if (r == 0) return NULL; + return (byte*)_ref_setup[t].base + (r-1) * _ref_setup[t].size; +} + +typedef struct { + const char *name; + uint32 tag; + + bool (*init_read)(); + ReaderProc *reader; + void (*uninit_read)(); + + bool (*init_write)(); + WriterProc *writer; + void (*uninit_write)(); + +} SaveLoadFormat; + +static const SaveLoadFormat _saveload_formats[] = { + {"lzo", TO_BE32X('OTTD'), InitLZO,ReadLZO, UninitLZO, InitLZO, WriteLZO, UninitLZO}, + {"none", TO_BE32X('OTTN'), InitNoComp,ReadNoComp, UninitNoComp, InitNoComp, WriteNoComp, UninitNoComp}, +#if defined(WITH_ZLIB) + {"zlib", TO_BE32X('OTTZ'), InitReadZlib,ReadZlib, UninitReadZlib, InitWriteZlib, WriteZlib, UninitWriteZlib}, +#else + {"zlib", TO_BE32X('OTTZ'), NULL,NULL,NULL,NULL,NULL,NULL} +#endif +}; + +static const SaveLoadFormat *GetSavegameFormat(const char *s) +{ + const SaveLoadFormat *def; + int i; + + // find default savegame format + def = endof(_saveload_formats) - 1; + while (!def->init_write) def--; + + if (_savegame_format[0]) { + for(i = 0; i!=lengthof(_saveload_formats); i++) + if (_saveload_formats[i].init_write && !strcmp(s, _saveload_formats[i].name)) + return _saveload_formats + i; + + ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name); + } + return def; +} + +// actual loader/saver function +extern void InitializeGame(); +extern bool AfterLoadGame(uint version); +extern void BeforeSaveGame(); +extern bool LoadOldSaveGame(const char *file); + +// Save or Load files SL_LOAD, SL_SAVE, SL_OLD_LOAD +int SaveOrLoad(const char *filename, int mode) +{ + uint32 hdr[2]; + const SaveLoadFormat *fmt; + uint version; + + // old style load + if (mode == SL_OLD_LOAD) { + InitializeGame(); + if (!LoadOldSaveGame(filename)) return SL_REINIT; + AfterLoadGame(0); + return SL_OK; + } + + _sl.fh = fopen(filename, mode?"wb":"rb"); + if (_sl.fh == NULL) + return SL_ERROR; + + _sl.bufe = _sl.bufp = NULL; + _sl.offs_base = 0; + _sl.int_to_ref_proc = IntToReference; + _sl.ref_to_int_proc = ReferenceToInt; + _sl.save = mode; + _sl.includes = _desc_includes; + _sl.chs = _chunk_handlers; + + // setup setjmp error handler + if (setjmp(_sl.excpt)) { + // close file handle. + fclose(_sl.fh); _sl.fh = NULL; + + // deinitialize compressor. + _sl.excpt_uninit(); + + // a saver/loader exception!! + // reinitialize all variables to prevent crash! + if (mode == SL_LOAD) { + ShowInfoF("Load game failed: %s.", _sl.excpt_msg); + return SL_REINIT; + } else { + ShowInfoF("Save game failed: %s.", _sl.excpt_msg); + return SL_ERROR; + } + } + + // we first initialize here to avoid: "warning: variable `version' might + // be clobbered by `longjmp' or `vfork'" + version = 0; + + if (mode != SL_LOAD) { + fmt = GetSavegameFormat(_savegame_format); + + _sl.write_bytes = fmt->writer; + _sl.excpt_uninit = fmt->uninit_write; + if (!fmt->init_write()) goto init_err; + + hdr[0] = fmt->tag; + hdr[1] = TO_BE32((SAVEGAME_MAJOR_VERSION<<16) + (SAVEGAME_MINOR_VERSION << 8)); + if (fwrite(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError("file write failed"); + + _sl.version = SAVEGAME_MAJOR_VERSION; + + BeforeSaveGame(); + SlSaveChunks(); + SlWriteFill(); // flush the save buffer + fmt->uninit_write(); + + } else { + if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) { +read_err: + printf("Savegame is obsolete or invalid format.\n"); +init_err: + fclose(_sl.fh); + return SL_ERROR; + } + + // see if we have any loader for this type. + for(fmt = _saveload_formats; ; fmt++) { + if (fmt == endof(_saveload_formats)) { + printf("Unknown savegame type, trying to load it as the buggy format.\n"); + rewind(_sl.fh); + _sl.version = 0; + version = 0; + fmt = _saveload_formats + 0; // lzo + break; + } + if (fmt->tag == hdr[0]) { + // check version number + version = TO_BE32(hdr[1]) >> 8; + + // incompatible version? + if (version > SAVEGAME_LOADABLE_VERSION) goto read_err; + _sl.version = (version>>8); + break; + } + } + + _sl.read_bytes = fmt->reader; + _sl.excpt_uninit = fmt->uninit_read; + + // loader for this savegame type is not implemented? + if (fmt->init_read == NULL) { + ShowInfoF("Loader for '%s' is not available.", fmt->name); + fclose(_sl.fh); + return SL_ERROR; + } + + if (!fmt->init_read()) goto init_err; + // Clear everything + InitializeGame(); + SlLoadChunks(); + fmt->uninit_read(); + } + + fclose(_sl.fh); + + if (mode == SL_LOAD) { + if (!AfterLoadGame(version)) + return SL_REINIT; + } + + return SL_OK; +} + +bool EmergencySave() +{ + SaveOrLoad("crash.sav", SL_SAVE); + return true; +} + +// not used right now, but could be used if extensions of savegames are garbled +/*int GetSavegameType(char *file) +{ + const SaveLoadFormat *fmt; + uint32 hdr; + FILE *f; + int mode = SL_OLD_LOAD; + + f = fopen(file, "rb"); + if (fread(&hdr, sizeof(hdr), 1, f) != 1) { + printf("Savegame is obsolete or invalid format.\n"); + mode = SL_LOAD; // don't try to get filename, just show name as it is written + } + else { + // see if we have any loader for this type. + for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) { + if (fmt->tag == hdr) { + mode = SL_LOAD; // new type of savegame + break; + } + } + } + + fclose(f); + return mode; +}*/ diff --git a/saveload.h b/saveload.h new file mode 100644 --- /dev/null +++ b/saveload.h @@ -0,0 +1,127 @@ +#ifndef SAVELOAD_H +#define SAVELOAD_H + +typedef void ChunkSaveLoadProc(); +typedef void AutolengthProc(void *arg); + +typedef struct SaveLoadGlobVarList { + void *address; + byte conv; + byte from_version; + byte to_version; +} SaveLoadGlobVarList; + + +typedef struct { + uint32 id; + ChunkSaveLoadProc *save_proc; + ChunkSaveLoadProc *load_proc; + uint32 flags; +} ChunkHandler; + +typedef struct { + byte null; +} NullStruct; + +enum { + REF_SCHEDULE = 0, + REF_VEHICLE = 1, + REF_STATION = 2, + REF_TOWN = 3, +}; + + +enum { + INC_VEHICLE_COMMON = 0, +}; + + +enum { + CH_RIFF = 0, + CH_ARRAY = 1, + CH_SPARSE_ARRAY = 2, + CH_TYPE_MASK = 3, + CH_LAST = 8, + CH_AUTO_LENGTH = 16, + CH_PRI_0 = 0 << 4, + CH_PRI_1 = 1 << 4, + CH_PRI_2 = 2 << 4, + CH_PRI_3 = 3 << 4, + CH_PRI_SHL = 4, + CH_NUM_PRI_LEVELS = 4, +}; + +enum { + SLE_FILE_I8 = 0, + SLE_FILE_U8 = 1, + SLE_FILE_I16 = 2, + SLE_FILE_U16 = 3, + SLE_FILE_I32 = 4, + SLE_FILE_U32 = 5, + SLE_FILE_I64 = 6, + SLE_FILE_U64 = 7, + + SLE_FILE_STRINGID = 8, +// SLE_FILE_IVAR = 8, +// SLE_FILE_UVAR = 9, + + SLE_VAR_I8 = 0 << 4, + SLE_VAR_U8 = 1 << 4, + SLE_VAR_I16 = 2 << 4, + SLE_VAR_U16 = 3 << 4, + SLE_VAR_I32 = 4 << 4, + SLE_VAR_U32 = 5 << 4, + SLE_VAR_I64 = 6 << 4, + SLE_VAR_U64 = 7 << 4, + + SLE_VAR_NULL = 8 << 4, // useful to write zeros in savegame. + + SLE_VAR_INT = SLE_VAR_I32, + SLE_VAR_UINT = SLE_VAR_U32, + + SLE_INT8 = SLE_FILE_I8 | SLE_VAR_I8, + SLE_UINT8 = SLE_FILE_U8 | SLE_VAR_U8, + SLE_INT16 = SLE_FILE_I16 | SLE_VAR_I16, + SLE_UINT16 = SLE_FILE_U16 | SLE_VAR_U16, + SLE_INT32 = SLE_FILE_I32 | SLE_VAR_I32, + SLE_UINT32 = SLE_FILE_U32 | SLE_VAR_U32, + SLE_INT64 = SLE_FILE_I64 | SLE_VAR_I64, + SLE_UINT64 = SLE_FILE_U64 | SLE_VAR_U64, + + SLE_STRINGID = SLE_FILE_STRINGID | SLE_VAR_U16, +}; + +#define SLE_VAR(t,i,c) 0 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c +#define SLE_REF(t,i,c) 0x10 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c +#define SLE_ARR(t,i,c,l) 0x20 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c, l +#define SLE_CONDVAR(t,i,c,from,to) 0x40 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c, from, to +#define SLE_CONDREF(t,i,c,from,to) 0x50 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c, from, to +#define SLE_CONDARR(t,i,c,l,from,to) 0x60 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c, from,to, l +#define SLE_WRITEBYTE(t,i,b,c) 0x80 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, b, c +#define SLE_INCLUDE(t,i,c) 0x90 | (offsetof(t,i) & 0xF), offsetof(t,i) >> 4, c + + +#define SLE_VARX(t,c) 0x00 | ((t) & 0xF), (t) >> 4, c +#define SLE_REFX(t,c) 0x10 | ((t) & 0xF), (t) >> 4, c +#define SLE_CONDVARX(t,c,from,to) 0x40 | ((t) & 0xF), (t) >> 4, c, from, to +#define SLE_CONDREFX(t,c,co) 0x50 | ((t) & 0xF), (t) >> 4, c, co +#define SLE_WRITEBYTEX(t,b) 0x80 | ((t) & 0xF), (t) >> 4, b +#define SLE_INCLUDEX(t,c) 0x90 | ((t) & 0xF), (t) >> 4, c + +#define SLE_END() 0xF0 + + +void SlSetArrayIndex(uint index); +int SlIterateArray(); +void SlArray(void *array, uint length, uint conv); +void SlObject(void *object, const void *desc); +void SlAutolength(AutolengthProc *proc, void *arg); +uint SlGetFieldLength(); +int SlReadByte(); +void SlSetLength(uint length); +void SlWriteByte(byte v); +void SlGlobList(const SaveLoadGlobVarList *desc); + +//int GetSavegameType(char *file); + +#endif /* SAVELOAD_H */ diff --git a/screenshot.c b/screenshot.c new file mode 100644 --- /dev/null +++ b/screenshot.c @@ -0,0 +1,474 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gfx.h" +#include "viewport.h" +#include "player.h" +#include "gui.h" + +// called by the ScreenShot proc to generate screenshot lines. +typedef void ScreenshotCallback(void *userdata, byte *buf, uint y, uint pitch, uint n); +typedef bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const byte *palette); + +typedef struct { + const char *name; + const char *extension; + ScreenshotHandlerProc *proc; + byte id; +} ScreenshotFormat; + +//************************************************ +//*** SCREENSHOT CODE FOR WINDOWS BITMAP (.BMP) +//************************************************ +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif + +typedef struct BitmapFileHeader { + uint16 type; + uint32 size; + uint32 reserved; + uint32 off_bits; +} GCC_PACK BitmapFileHeader; +assert_compile(sizeof(BitmapFileHeader) == 14); + +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +typedef struct BitmapInfoHeader { + uint32 size; + int32 width, height; + uint16 planes, bitcount; + uint32 compression, sizeimage, xpels, ypels, clrused, clrimp; +} BitmapInfoHeader; +assert_compile(sizeof(BitmapInfoHeader) == 40); + +typedef struct RgbQuad { + byte blue, green, red, reserved; +} RgbQuad; +assert_compile(sizeof(RgbQuad) == 4); + +// generic .BMP writer +static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const byte *palette) +{ + BitmapFileHeader bfh; + BitmapInfoHeader bih; + RgbQuad *rq = alloca(sizeof(RgbQuad) * 256); + byte *buff; + FILE *f; + uint i, padw; + uint n, maxlines; + + // only implemented for 8bit images so far. + if (pixelformat != 8) + return false; + + f = fopen(name, "wb"); + if (f == NULL) return false; + + // each scanline must be aligned on a 32bit boundary + padw = (w + 3) & ~3; + + // setup the file header + bfh.type = TO_LE16('MB'); + bfh.size = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256 + padw * h); + bfh.reserved = 0; + bfh.off_bits = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256); + + // setup the info header + bih.size = TO_LE32(sizeof(BitmapInfoHeader)); + bih.width = TO_LE32(w); + bih.height = TO_LE32(h); + bih.planes = TO_LE16(1); + bih.bitcount = TO_LE16(8); + bih.compression = 0; + bih.sizeimage = 0; + bih.xpels = 0; + bih.ypels = 0; + bih.clrused = 0; + bih.clrimp = 0; + + // convert the palette to the windows format + for(i=0; i!=256; i++) { + rq[i].red = *palette++; + rq[i].green = *palette++; + rq[i].blue = *palette++; + rq[i].reserved = 0; + } + + // write file header and info header and palette + fwrite(&bfh, 1, sizeof(bfh), f); + fwrite(&bih, 1, sizeof(bih), f); + fwrite(rq, 1, sizeof(RgbQuad) * 256, f); + + // use by default 64k temp memory + maxlines = clamp(65536 / padw, 16, 128); + + // now generate the bitmap bits + buff = (byte*)alloca(padw * maxlines); // by default generate 128 lines at a time. + memset(buff, 0, padw * maxlines); // zero the buffer to have the padding bytes set to 0 + + // start at the bottom, since bitmaps are stored bottom up. + do { + // determine # lines + n = min(h, maxlines); + h -= n; + + // render the pixels + callb(userdata, buff, h, padw, n); + + // write each line + while (n) + fwrite(buff + (--n) * padw, 1, padw, f); + } while (h); + + fclose(f); + + return true; +} + +//******************************************************** +//*** SCREENSHOT CODE FOR PORTABLE NETWORK GRAPHICS (.PNG) +//******************************************************** +#if defined(WITH_PNG) +#include + +static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message) +{ + DEBUG(misc, 0) ("ERROR(libpng): %s - %s\n", message,(char *)png_get_error_ptr(png_ptr)); + longjmp(png_ptr->jmpbuf, 1); +} + +static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message) +{ + DEBUG(misc, 0) ("WARNING(libpng): %s - %s\n", message, (char *)png_get_error_ptr(png_ptr)); +} + +static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const byte *palette) +{ + png_colorp rq = alloca(sizeof(png_color) * 256); + byte *buff; + FILE *f; + uint i, y, n; + uint maxlines; + png_structp png_ptr; + png_infop info_ptr; + + // only implemented for 8bit images so far. + if (pixelformat != 8) + return false; + + f = fopen(name, "wb"); + if (f == NULL) return false; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (char *) name, png_my_error, png_my_warning); + + if (!png_ptr) { + fclose(f); + return false; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(f); + return false; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(f); + return false; + } + + png_init_io(png_ptr, f); + + png_set_filter(png_ptr, 0, PNG_FILTER_NONE); + + png_set_IHDR(png_ptr, info_ptr, w, h, pixelformat, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // convert the palette to the .PNG format. + { + // avoids "might be clobbered" warning of argument "palette" + const byte *pal = palette; + + for(i=0; i!=256; i++) { + rq[i].red = *pal++; + rq[i].green = *pal++; + rq[i].blue = *pal++; + } + } + + png_set_PLTE(png_ptr, info_ptr, rq, 256); + png_write_info(png_ptr, info_ptr); + png_set_flush(png_ptr, 512); + + // use by default 64k temp memory + maxlines = clamp(65536 / w, 16, 128); + + // now generate the bitmap bits + buff = (byte*)alloca(w * maxlines); // by default generate 128 lines at a time. + memset(buff, 0, w * maxlines); // zero the buffer to have the padding bytes set to 0 + + y = 0; + do { + // determine # lines to write + n = min(h - y, maxlines); + + // render the pixels into the buffer + callb(userdata, buff, y, w, n); + y += n; + + // write them to png + for(i=0; i!=n; i++) + png_write_row(png_ptr, buff + i * w); + } while (y != h); + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + fclose(f); + return true; +} +#endif // WITH_PNG + + +//************************************************ +//*** SCREENSHOT CODE FOR ZSOFT PAINTBRUSH (.PCX) +//************************************************ + +typedef struct { + byte manufacturer; + byte version; + byte rle; + byte bpp; + uint32 unused; + uint16 xmax, ymax; + uint16 hdpi, vdpi; + byte pal_small[16*3]; + byte reserved; + byte planes; + uint16 pitch; + uint16 cpal; + uint16 width; + uint16 height; + byte filler[54]; +} PcxHeader; +assert_compile(sizeof(PcxHeader) == 128); + +static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const byte *palette) +{ + byte *buff; + FILE *f; + uint maxlines; + uint y; + PcxHeader pcx; + + if (pixelformat != 8 || w == 0) + return false; + + f = fopen(name, "wb"); + if (f == NULL) return false; + + memset(&pcx, 0, sizeof(pcx)); + + // setup pcx header + pcx.manufacturer = 10; + pcx.version = 5; + pcx.rle = 1; + pcx.bpp = 8; + pcx.xmax = TO_LE16(w-1); + pcx.ymax = TO_LE16(h-1); + pcx.hdpi = TO_LE16(320); + pcx.vdpi = TO_LE16(320); + + pcx.planes = 1; + pcx.cpal = TO_LE16(1); + pcx.width = pcx.pitch = TO_LE16(w); + pcx.height = TO_LE16(h); + + // write pcx header + fwrite(&pcx, sizeof(pcx), 1, f); + + // use by default 64k temp memory + maxlines = clamp(65536 / w, 16, 128); + + // now generate the bitmap bits + buff = (byte*)alloca(w * maxlines); // by default generate 128 lines at a time. + memset(buff, 0, w * maxlines); // zero the buffer to have the padding bytes set to 0 + + y = 0; + do { + // determine # lines to write + uint n = min(h - y, maxlines), i; + + // render the pixels into the buffer + callb(userdata, buff, y, w, n); + y += n; + + // write them to pcx + for(i=0; i!=n; i++) { + int runcount = 1; + byte *bufp = buff + i * w; + byte runchar = buff[0]; + uint left = w - 1; + + // for each pixel... + while (left) { + byte ch = *bufp++; + if (ch != runchar || runcount >= 0x3f) { + if (runcount > 1 || (runchar & 0xC0) == 0xC0) fputc(0xC0 | runcount, f); + fputc(runchar,f); + runcount = 0; + runchar = ch; + } + runcount++; + left--; + } + + // write remaining bytes.. + if (runcount > 1 || (runchar & 0xC0) == 0xC0) fputc(0xC0 | runcount, f); + fputc(runchar,f); + } + } while (y != h); + + // write 8-bit color palette + fputc(12, f); + fwrite(palette, 256*3, 1, f); + fclose(f); + + return true; +} + +//************************************************ +//*** GENERIC SCREENSHOT CODE +//************************************************ + +static const ScreenshotFormat _screenshot_formats[] = { + {"BMP", "bmp", &MakeBmpImage}, +#if defined(WITH_PNG) + {"PNG", "png", &MakePNGImage}, +#endif + {"PCX", "pcx", &MakePCXImage}, +}; + +void InitializeScreenshotFormats() +{ + int i,j; + for (i=0,j=0; i!=lengthof(_screenshot_formats); i++) + if (!strcmp(_screenshot_format_name, _screenshot_formats[i].extension)) { j=i; break; } + _cur_screenshot_format = j; + _num_screenshot_formats = lengthof(_screenshot_formats); +} + +const char *GetScreenshotFormatDesc(int i) +{ + return _screenshot_formats[i].name; +} + +void SetScreenshotFormat(int i) +{ + _cur_screenshot_format = i; + strcpy(_screenshot_format_name, _screenshot_formats[i].extension); +} + +// screenshot generator that dumps the current video buffer +void CurrentScreenCallback(void *userdata, byte *buf, uint y, uint pitch, uint n) +{ + assert(_screen.pitch == (int)pitch); + memcpy(buf, _screen.dst_ptr + y * _screen.pitch, n * _screen.pitch); +} + +extern void ViewportDoDraw(ViewPort *vp, int left, int top, int right, int bottom); + +// generate a large piece of the world +void LargeWorldCallback(void *userdata, byte *buf, uint y, uint pitch, uint n) +{ + ViewPort *vp = (ViewPort *)userdata; + DrawPixelInfo dpi, *old_dpi; + int wx, left; + + old_dpi = _cur_dpi; + _cur_dpi = &dpi; + + dpi.dst_ptr = buf; + dpi.height = n; + dpi.width = vp->width; + dpi.pitch = pitch; + dpi.zoom = 0; + dpi.left = 0; + dpi.top = y; + + left = 0; + while (vp->width - left != 0) { + wx = min(vp->width - left, 1600); + left += wx; + + ViewportDoDraw(vp, + ((left - wx - vp->left) << vp->zoom) + vp->virtual_left, + ((y - vp->top) << vp->zoom) + vp->virtual_top, + ((left - vp->left) << vp->zoom) + vp->virtual_left, + (((y+n) - vp->top) << vp->zoom) + vp->virtual_top + ); + } + + _cur_dpi = old_dpi; +} + +static char *MakeScreenshotName(const char *ext) +{ + static char filename[256]; + char *base; + int serial; + + if (_game_mode == GM_EDITOR || _local_player == 0xff) { + sprintf(_screenshot_name, "screenshot"); + } else { + Player *p = &_players[_local_player]; + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, _date); + GetString(_screenshot_name, STR_4004); + } + + base = strchr(_screenshot_name, 0); + base[0] = '.'; strcpy(base + 1, ext); + + serial = 0; + for(;;) { + snprintf(filename, sizeof(filename), "%s%s", _path.personal_dir, _screenshot_name); + if (!FileExists(filename)) + break; + sprintf(base, " #%d.%s", ++serial, ext); + } + + return filename; +} + +extern byte _cur_palette[768]; + +bool MakeScreenshot() +{ + const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format; + return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, 8, _cur_palette); +} + +bool MakeWorldScreenshot(int left, int top, int width, int height, int zoom) +{ + ViewPort vp; + const ScreenshotFormat *sf; + + vp.zoom = zoom; + vp.left = 0; + vp.top = 0; + vp.virtual_width = width; + vp.width = width >> zoom; + vp.virtual_height = height; + vp.height = height >> zoom; + vp.virtual_left = left; + vp.virtual_top = top; + + sf = _screenshot_formats + _cur_screenshot_format; + return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, 8, _cur_palette); +} diff --git a/sdl.c b/sdl.c new file mode 100644 --- /dev/null +++ b/sdl.c @@ -0,0 +1,628 @@ +#include "stdafx.h" + +#if defined(WITH_SDL) +#include "ttd.h" +#include "gfx.h" +#include "sound.h" +#include "window.h" +#include +#include "player.h" +#include "hal.h" + +#ifdef UNIX +#include +#endif + +#define DYNAMICALLY_LOADED_SDL + +static SDL_Surface *_sdl_screen; +static int _sdl_usage; +static bool _all_modes; + +#define MAX_DIRTY_RECTS 100 +static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; +static int _num_dirty_rects; + +#define SDL_CALL + +#if defined(DYNAMICALLY_LOADED_SDL) && defined(WIN32) + +bool LoadLibraryList(void **proc, const char *dll); + +typedef struct { + int (SDLCALL *SDL_Init)(Uint32); + int (SDLCALL *SDL_InitSubSystem)(Uint32); + char *(SDLCALL *SDL_GetError)(); + void (SDLCALL *SDL_QuitSubSystem)(Uint32); + void (SDLCALL *SDL_UpdateRect)(SDL_Surface *, Sint32, Sint32, Uint32, Uint32); + void (SDLCALL *SDL_UpdateRects)(SDL_Surface *, int, SDL_Rect *); + int (SDLCALL *SDL_SetColors)(SDL_Surface *, SDL_Color *, int, int); + void (SDLCALL *SDL_WM_SetCaption)(const char *, const char *); + int (SDLCALL *SDL_ShowCursor)(int); + void (SDLCALL *SDL_FreeSurface)(SDL_Surface *); + int (SDLCALL *SDL_PollEvent)(SDL_Event *); + void (SDLCALL *SDL_WarpMouse)(Uint16, Uint16); + uint32 (SDLCALL *SDL_GetTicks)(); + int (SDLCALL *SDL_OpenAudio)(SDL_AudioSpec *, SDL_AudioSpec*); + void (SDLCALL *SDL_PauseAudio)(int); + void (SDLCALL *SDL_CloseAudio)(); + int (SDLCALL *SDL_LockSurface)(SDL_Surface*); + void (SDLCALL *SDL_UnlockSurface)(SDL_Surface*); + SDLMod (SDLCALL *SDL_GetModState)(); + void (SDLCALL *SDL_Delay)(Uint32); + void (SDLCALL *SDL_Quit)(); + SDL_Surface *(SDLCALL *SDL_SetVideoMode)(int,int,int,Uint32); + int (SDLCALL *SDL_EnableKeyRepeat)(int,int); + void (SDLCALL *SDL_EnableUNICODE)(int); + void (SDLCALL *SDL_VideoDriverName)(char *, int); + SDL_Rect **(SDLCALL *SDL_ListModes)(void *, int); + Uint8 *(SDLCALL *SDL_GetKeyState)(int *); +} SDLProcs; + +#define M(x) x "\0" +static const char sdl_files[] = + M("sdl.dll") + M("SDL_Init") + M("SDL_InitSubSystem") + M("SDL_GetError") + M("SDL_QuitSubSystem") + M("SDL_UpdateRect") + M("SDL_UpdateRects") + M("SDL_SetColors") + M("SDL_WM_SetCaption") + M("SDL_ShowCursor") + M("SDL_FreeSurface") + M("SDL_PollEvent") + M("SDL_WarpMouse") + M("SDL_GetTicks") + M("SDL_OpenAudio") + M("SDL_PauseAudio") + M("SDL_CloseAudio") + M("SDL_LockSurface") + M("SDL_UnlockSurface") + M("SDL_GetModState") + M("SDL_Delay") + M("SDL_Quit") + M("SDL_SetVideoMode") + M("SDL_EnableKeyRepeat") + M("SDL_EnableUNICODE") + M("SDL_VideoDriverName") + M("SDL_ListModes") + M("SDL_GetKeyState") + M("") +; +#undef M + +static SDLProcs _proc; + +static char *LoadSdlDLL() +{ + if (_proc.SDL_Init != NULL) + return NULL; + if (!LoadLibraryList((void**)&_proc, sdl_files)) + return "Unable to load sdl.dll"; + return NULL; +} + +#undef SDL_CALL +#define SDL_CALL _proc. + +#endif + + +#ifdef UNIX +static void SdlAbort(int sig) +{ + /* Own hand-made parachute for the cases of failed assertions. */ + SDL_CALL SDL_Quit(); +} +#endif + + +static char *SdlOpen(uint32 x) +{ +#if defined(DYNAMICALLY_LOADED_SDL) && defined(WIN32) + { char *s = LoadSdlDLL(); if (s) return s; } +#endif + if (_sdl_usage++ == 0) { + if (SDL_CALL SDL_Init(x) == -1) + return SDL_CALL SDL_GetError(); + } else if (x) { + if (SDL_CALL SDL_InitSubSystem(x) == -1) + return SDL_CALL SDL_GetError(); + } + +#ifdef UNIX + signal(SIGABRT, SdlAbort); +#endif + + return NULL; +} + +static void SdlClose(uint32 x) +{ + if (x) + SDL_CALL SDL_QuitSubSystem(x); + if (--_sdl_usage == 0) { + SDL_CALL SDL_Quit(); +#ifdef UNIX +#ifndef __MORPHOS__ + signal(SIGABRT, SIG_DFL); +#else + signal(SIGABRT, (void (*)(int))0 ); +#endif +#endif + } +} + +static void SdlVideoMakeDirty(int left, int top, int width, int height) +{ +// printf("(%d,%d)-(%d,%d)\n", left, top, width, height); +// _pixels_redrawn += width*height; + if (_num_dirty_rects < MAX_DIRTY_RECTS) { + _dirty_rects[_num_dirty_rects].x = left; + _dirty_rects[_num_dirty_rects].y = top; + _dirty_rects[_num_dirty_rects].w = width; + _dirty_rects[_num_dirty_rects].h = height; + } + _num_dirty_rects++; +} + +static SDL_Color pal[256]; + +static void UpdatePalette(uint start, uint end) { + uint i; + byte *b; + + for(i = start, b = _cur_palette + start * 3; i != end; i++, b += 3) { + pal[i].r = b[0]; + pal[i].g = b[1]; + pal[i].b = b[2]; + pal[i].unused = b[3]; + } + + SDL_CALL SDL_SetColors(_sdl_screen, pal, start, end); +} + +static void InitPalette(void) { + UpdatePalette(0, 256); +} + +static void DrawSurfaceToScreen() +{ + int n; + + if(_pal_last_dirty != -1) { + UpdatePalette(_pal_first_dirty, _pal_last_dirty + 1); + _pal_last_dirty = -1; + } + + if ((n=_num_dirty_rects) != 0) { + _num_dirty_rects = 0; + if (n > MAX_DIRTY_RECTS) + SDL_CALL SDL_UpdateRect(_sdl_screen, 0, 0, 0, 0); + else { + SDL_CALL SDL_UpdateRects(_sdl_screen, n, _dirty_rects); + } + } +} + +static int CDECL compare_res(const void *pa, const void *pb) +{ + int x = ((uint16*)pa)[0] - ((uint16*)pb)[0]; + if (x) return x; + return ((uint16*)pa)[1] - ((uint16*)pb)[1]; +} + +static const uint16 default_resolutions[][2] = { + {640,480}, + {800,600}, + {1024,768}, + {1152,864}, + {1280,960}, + {1280,1024}, + {1400,1050}, + {1600,1200}, +}; + +static void GetVideoModes(void) { + int i; + SDL_Rect **modes; + + modes = SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE + (_fullscreen ? SDL_FULLSCREEN : 0)); + + _all_modes = (int)modes == -1; + + if(modes == NULL) { + error("sdl: no modes available"); + } else if((int) modes == -1) { + // all modes available, put some default ones here + memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); + _num_resolutions = sizeof(default_resolutions) / (sizeof(uint16)*2); + } else { + int n = 0; + + for(i = 0; modes[i] != NULL; i++) { + int w = modes[i]->w; + int h = modes[i]->h; + if (IS_INT_INSIDE(w, 640, MAX_SCREEN_WIDTH+1) && + IS_INT_INSIDE(h, 480, MAX_SCREEN_HEIGHT+1) && + w%8 == 0 && h%8 == 0) { // disable screen resolutions which are not multiples of 8 + _resolutions[n][0] = w; + _resolutions[n][1] = h; + if (++n == sizeof(_resolutions) / (sizeof(uint16)*2)) break; + } + } + _num_resolutions = n; + qsort(_resolutions, n, sizeof(uint16)*2, compare_res); + } +} + +static int GetAvailableVideoMode(int *w, int *h) +{ + int i; + + + // all modes available? + if (_all_modes) + return 1; + + // is the wanted mode among the available modes? + for(i = 0; i != _num_resolutions; i++) { + if(*w == _resolutions[i][0] && *h == _resolutions[i][1]) + return 1; + } + + // use the default mode + *w = _resolutions[0][0]; + *h = _resolutions[0][1]; + return 2; +} + +static bool CreateMainSurface(int w, int h) +{ + SDL_Surface *newscreen; + bool sizechange; + + GetAvailableVideoMode(&w, &h); + + sizechange = (_screen.width != w || _screen.height != h); + _screen.pitch = _screen.width = w; + _screen.height = h; + + DEBUG(misc, 0) ("sdl: using mode %dx%d", w, h); + + newscreen = SDL_CALL SDL_SetVideoMode(w, h, 8, SDL_SWSURFACE + SDL_HWPALETTE + (_fullscreen?SDL_FULLSCREEN:SDL_RESIZABLE)); + if(newscreen == NULL) + return false; + + _sdl_screen = newscreen; + InitPalette(); + + SDL_CALL SDL_WM_SetCaption("OpenTTD", "OpenTTD"); + SDL_CALL SDL_ShowCursor(0); + +// if(sizechange) + GameSizeChanged(); + + return true; +} + +typedef struct { + uint16 vk_from; + byte vk_count; + byte map_to; +} VkMapping; + +#define AS(x,z) {x,0,z} +#define AM(x,y,z,w) {x,y-x,z} + +static const VkMapping _vk_mapping[] = { + // Pageup stuff + up/down + AM(SDLK_PAGEUP,SDLK_PAGEDOWN, WKC_PAGEUP, WKC_PAGEDOWN), + AS(SDLK_UP, WKC_UP), + AS(SDLK_DOWN, WKC_DOWN), + AS(SDLK_LEFT, WKC_LEFT), + AS(SDLK_RIGHT, WKC_RIGHT), + + AS(SDLK_HOME, WKC_HOME), + AS(SDLK_END, WKC_END), + + AS(SDLK_INSERT, WKC_INSERT), + AS(SDLK_DELETE, WKC_DELETE), + + // Map letters & digits + AM(SDLK_a,SDLK_z,'A','Z'), + AM(SDLK_0,SDLK_9,'0','9'), + + AS(SDLK_AMPERSAND, WKC_AMPERSAND), // mainly for french keyboards + + AS(SDLK_ESCAPE, WKC_ESC), + AS(SDLK_BACKSPACE, WKC_BACKSPACE), + + AS(SDLK_SPACE, WKC_SPACE), + AS(SDLK_RETURN, WKC_RETURN), + AS(SDLK_TAB, WKC_TAB), + + // Function keys + AM(SDLK_F1, SDLK_F12, WKC_F1, WKC_F12), + + // Numeric part. + // What is the virtual keycode for numeric enter?? + AM(SDLK_KP0,SDLK_KP9, WKC_NUM_0, WKC_NUM_9), + AS(SDLK_KP_DIVIDE, WKC_NUM_DIV), + AS(SDLK_KP_MULTIPLY, WKC_NUM_MUL), + AS(SDLK_KP_MINUS, WKC_NUM_MINUS), + AS(SDLK_KP_PLUS, WKC_NUM_PLUS), + AS(SDLK_KP_ENTER, WKC_NUM_ENTER), + AS(SDLK_KP_PERIOD, WKC_NUM_DECIMAL), + {0} +}; + +static uint32 ConvertSdlKeyIntoMy(SDL_keysym *sym) +{ + const VkMapping *map = _vk_mapping - 1; + uint from; + uint key = sym->sym; + for(;;) { + map++; + from = map->vk_from; + if (from == 0) { + key = 0; + break; + } + if ((uint)(key - from) <= map->vk_count) { + key = key - from + map->map_to; + break; + } + } + + // META are the command keys on mac + if (sym->mod & KMOD_META) key |= WKC_META; + if (sym->mod & KMOD_SHIFT) key |= WKC_SHIFT; + if (sym->mod & KMOD_CTRL) key |= WKC_CTRL; + if (sym->mod & KMOD_ALT) key |= WKC_ALT; + return (key << 16) + sym->unicode; +} + +static int PollEvent() { + SDL_Event ev; + + if (!SDL_CALL SDL_PollEvent(&ev)) + return -2; + + switch(ev.type) { + case SDL_MOUSEMOTION: + if (_cursor.fix_at) { + int dx = ev.motion.x - _cursor.pos.x; + int dy = ev.motion.y - _cursor.pos.y; + if (dx != 0 || dy != 0) { + _cursor.delta.x += dx; + _cursor.delta.y += dy; + SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); + } + } else { + _cursor.delta.x = ev.motion.x - _cursor.pos.x; + _cursor.delta.y = ev.motion.y - _cursor.pos.y; + _cursor.pos.x = ev.motion.x; + _cursor.pos.y = ev.motion.y; + _cursor.dirty = true; + } + break; + + case SDL_MOUSEBUTTONDOWN: + if (_rightclick_emulate && (SDL_CALL SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))) + ev.button.button = SDL_BUTTON_RIGHT; + + if (ev.button.button == SDL_BUTTON_LEFT) { + _left_button_down = true; + } else if (ev.button.button == SDL_BUTTON_RIGHT) { + _right_button_down = true; + _right_button_clicked = true; + } +#if !defined(WIN32) + else if (ev.button.button == SDL_BUTTON_WHEELUP) { + _cursor.wheel--; + } else if (ev.button.button == SDL_BUTTON_WHEELDOWN) { + _cursor.wheel++; + } +#endif + break; + + case SDL_MOUSEBUTTONUP: + if (_rightclick_emulate) { + _right_button_down = false; + _left_button_down = false; + _left_button_clicked = false; + } else if (ev.button.button == SDL_BUTTON_LEFT) { + _left_button_down = false; + _left_button_clicked = false; + } else if (ev.button.button == SDL_BUTTON_RIGHT) { + _right_button_down = false; + } + break; + + case SDL_QUIT: + return ML_QUIT; + + case SDL_KEYDOWN: + if ((((ev.key.keysym.sym == SDLK_RETURN) || (ev.key.keysym.sym == SDLK_f)) && (ev.key.keysym.mod & KMOD_ALT)) || (((ev.key.keysym.sym == SDLK_RETURN) || (ev.key.keysym.sym == SDLK_f)) && (ev.key.keysym.mod & KMOD_META))) { + _fullscreen ^= true; + GetVideoModes(); + CreateMainSurface(_screen.width, _screen.height); + MarkWholeScreenDirty(); + } else { + _pressed_key = ConvertSdlKeyIntoMy(&ev.key.keysym); + } + break; + + case SDL_VIDEORESIZE: { + int w, h; + w = ev.resize.w; + h = ev.resize.h; + + w = clamp(w & ~0x7, 64, MAX_SCREEN_WIDTH); + h = clamp(h & ~0x7, 64, MAX_SCREEN_HEIGHT); + + ChangeResInGame(w, h); + + break; + } + } + return -1; +} + +static const char *SdlVideoStart(char **parm) +{ + char buf[30]; + + {char *s;if ((s = SdlOpen(SDL_INIT_VIDEO)) != NULL) return s;} + + SDL_CALL SDL_VideoDriverName(buf, 30); + DEBUG(misc, 0) ("sdl: using driver '%s'", buf); + + GetVideoModes(); + CreateMainSurface(_cur_resolution[0], _cur_resolution[1]); + MarkWholeScreenDirty(); + + SDL_CALL SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + SDL_CALL SDL_EnableUNICODE(1); + return NULL; +} + +static void SdlVideoStop() +{ + SdlClose(SDL_INIT_VIDEO); +} + +static int SdlVideoMainLoop() +{ + uint32 next_tick = SDL_CALL SDL_GetTicks() + 30, cur_ticks; + int i; + uint32 mod; + int numkeys; + Uint8 *keys; + + while (true) { + InteractiveRandom(); // randomness + + while ((i=PollEvent()) == -1) {} + if (i>=0) return i; + + mod = SDL_CALL SDL_GetModState(); + _ctrl_pressed = !!(mod & (KMOD_LCTRL | KMOD_RCTRL)); + _shift_pressed = !!(mod & (KMOD_LSHIFT | KMOD_RSHIFT)); + + + keys = SDL_CALL SDL_GetKeyState(&numkeys); + + _dirkeys = + (keys[SDLK_LEFT] ? 1 : 0) + + (keys[SDLK_UP] ? 2 : 0) + + (keys[SDLK_RIGHT] ? 4 : 0) + + (keys[SDLK_DOWN] ? 8 : 0); + + GameLoop(); + + _screen.dst_ptr = _sdl_screen->pixels; + UpdateWindows(); + + if ((cur_ticks=SDL_CALL SDL_GetTicks()) > next_tick) { + next_tick = cur_ticks; + } else { + DrawSurfaceToScreen(); + } + +#if defined(_DEBUG) + if (_shift_pressed) { +#else + if (keys[SDLK_TAB]) { +#endif + _fast_forward |= 2; + } else if (_fast_forward&2) { + _fast_forward = 0; + } + + if (!_fast_forward || _pause) { + int d = next_tick - SDL_CALL SDL_GetTicks(); + if (d > 0) { + SDL_CALL SDL_Delay(d); + } + } else { + next_tick = SDL_CALL SDL_GetTicks(); + } + next_tick += 30; + + if (_exit_game) + return ML_QUIT; + } +} + +static bool SdlVideoChangeRes(int w, int h) +{ + // see if the mode is available + if (GetAvailableVideoMode(&w, &h) != 1) + return false; + + CreateMainSurface(w, h); + return true; +} + +const HalVideoDriver _sdl_video_driver = { + SdlVideoStart, + SdlVideoStop, + SdlVideoMakeDirty, + SdlVideoMainLoop, + SdlVideoChangeRes, +}; + +static void CDECL fill_sound_buffer(void *userdata, Uint8 *stream, int len) +{ + MxMixSamples(_mixer, stream, len >> 2); +} + +static char *SdlSoundStart(char **parm) +{ + SDL_AudioSpec spec; + + {char *s;if ((s = SdlOpen(SDL_INIT_AUDIO)) != NULL) return s;} + spec.freq = GetDriverParamInt(parm, "hz", 11025); + spec.format = AUDIO_S16SYS; + spec.channels = 2; + spec.samples = 512; + *(void**)&spec.callback = fill_sound_buffer; + SDL_CALL SDL_OpenAudio(&spec, &spec); + SDL_CALL SDL_PauseAudio(0); + return NULL; +} + +static void SdlSoundStop() +{ + SDL_CALL SDL_CloseAudio(); + SdlClose(SDL_INIT_AUDIO); +} + +const HalSoundDriver _sdl_sound_driver = { + SdlSoundStart, + SdlSoundStop, +}; + + +#include "viewport.h" +void redsq_debug(int tile) +{ + _thd.redsq = tile; + MarkWholeScreenDirty(); + _screen.dst_ptr = _sdl_screen->pixels; + UpdateWindows(); + + SdlVideoMakeDirty(0,0,_screen.width,_screen.height); + DrawSurfaceToScreen(); +} + +void DbgRedraw() +{ + SdlVideoMakeDirty(0,0,_screen.width,_screen.height); + DrawSurfaceToScreen(); +} +#endif // WITH_SDL diff --git a/settings.c b/settings.c new file mode 100644 --- /dev/null +++ b/settings.c @@ -0,0 +1,922 @@ +#include "stdafx.h" +#include "ttd.h" +#include "sound.h" + +enum SettingDescType { + SDT_INTX, // must be 0 + SDT_ONEOFMANY, + SDT_MANYOFMANY, + SDT_BOOLX, + SDT_STRING, + SDT_STRINGBUF, + SDT_INTLIST, + + SDT_INT8 = 0 << 4, + SDT_UINT8 = 1 << 4, + SDT_INT16 = 2 << 4, + SDT_UINT16 = 3 << 4, + SDT_INT32 = 4 << 4, + SDT_UINT32 = 5 << 4, + SDT_CALLBX = 6 << 4, + + SDT_UINT = SDT_UINT32, + SDT_INT = SDT_INT32, + + SDT_NOSAVE = 1 << 8, + + SDT_CALLB = SDT_INTX | SDT_CALLBX, + + SDT_BOOL = SDT_BOOLX | SDT_UINT8, +}; + +typedef struct IniFile IniFile; +typedef struct IniItem IniItem; +typedef struct IniGroup IniGroup; +typedef struct SettingDesc SettingDesc; +typedef struct MemoryPool MemoryPool; + +static void pool_init(MemoryPool **pool); +static void *pool_alloc(MemoryPool **pool, uint size); +static void *pool_strdup(MemoryPool **pool, const char *mem, uint size); +static void pool_free(MemoryPool **pool); + +struct MemoryPool { + uint pos,size; + MemoryPool *next; + byte mem[1]; +}; + +static MemoryPool *pool_new(uint minsize) +{ + MemoryPool *p; + if (minsize < 4096 - 12) minsize = 4096 - 12; + + p = malloc(sizeof(MemoryPool) - 1 + minsize); + p->pos = 0; + p->size = minsize; + p->next = NULL; + return p; +} + +static void pool_init(MemoryPool **pool) +{ + *pool = pool_new(0); +} + +static void *pool_alloc(MemoryPool **pool, uint size) +{ + uint pos; + MemoryPool *p = *pool; + + size = (size + 3) & ~3; // align everything to a 32 bit boundary + + // first check if there's memory in the next pool + if (p->next && p->next->pos + size <= p->next->size) { + p = p->next; + // then check if there's not memory in the cur pool + } else if (p->pos + size > p->size) { + MemoryPool *n = pool_new(size); + *pool = n; + n->next = p; + p = n; + } + + pos = p->pos; + p->pos += size; + return p->mem + pos; +} + +static void *pool_strdup(MemoryPool **pool, const char *mem, uint size) +{ + byte *p = pool_alloc(pool, size + 1); + p[size] = 0; + memcpy(p, mem, size); + return p; +} + +static void pool_free(MemoryPool **pool) +{ + MemoryPool *p = *pool, *n; + *pool = NULL; + while (p) { + n = p->next; + free(p); + p = n; + } +} + +// structs describing the ini format. +struct IniItem { + char *name; + char *value; + char *comment; + IniItem *next; +}; + +struct IniGroup { + char *name; // name of group + char *comment; //comment for group + IniItem *item, **last_item; + IniGroup *next; + IniFile *ini; +}; + +struct IniFile { + MemoryPool *pool; + IniGroup *group, **last_group; + char *comment; // last comment in file +}; + +// allocate an inifile object +static IniFile *ini_alloc() +{ + IniFile *ini; + MemoryPool *pool; + pool_init(&pool); + ini = (IniFile*)pool_alloc(&pool, sizeof(IniFile)); + ini->pool = pool; + ini->group = NULL; + ini->last_group = &ini->group; + ini->comment = NULL; + return ini; +} + +// allocate an ini group object +static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len) +{ + IniGroup *grp = pool_alloc(&ini->pool, sizeof(IniGroup)); + grp->ini = ini; + grp->name = pool_strdup(&ini->pool, grpt, len); + grp->next = NULL; + grp->item = NULL; + grp->comment = NULL; + grp->last_item = &grp->item; + *ini->last_group = grp; + ini->last_group = &grp->next; + return grp; +} + +static IniItem *ini_item_alloc(IniGroup *group, const char *name, int len) +{ + IniItem *item = pool_alloc(&group->ini->pool, sizeof(IniItem)); + item->name = pool_strdup(&group->ini->pool, name, len); + item->next = NULL; + item->comment = NULL; + item->value = NULL; + *group->last_item = item; + group->last_item = &item->next; + return item; +} + +// load an ini file into the "abstract" format +static IniFile *ini_load(const char *filename) +{ + char buffer[1024], c, *s, *t, *e; + FILE *in; + IniFile *ini; + IniGroup *group = NULL; + IniItem *item; + + byte *comment = NULL; + uint comment_size = 0; + uint comment_alloc = 0; + + ini = ini_alloc(); + + in = fopen(filename, "r"); + if (in == NULL) return ini; + + // for each line in the file + while (fgets(buffer, sizeof(buffer), in)) { + + // trim whitespace from the left side + for(s=buffer; *s == ' ' || *s == '\t'; s++); + + // trim whitespace from right side. + e = s + strlen(s); + while (e > s && ((c=e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; + *e = 0; + + // skip comments and empty lines + if (*s == '#' || *s == 0) { + uint ns = comment_size + (e - s + 1); + uint a = comment_alloc; + uint pos; + // add to comment + if (ns > a) { + a = max(a, 128); + do a*=2; while (a < ns); + comment = realloc(comment, comment_alloc = a); + } + pos = comment_size; + comment_size += (e - s + 1); + comment[pos + e - s] = '\n'; // comment newline + memcpy(comment + pos, s, e - s); // copy comment contents + continue; + } + + // it's a group? + if (s[0] == '[') { + if (e[-1] != ']') + ShowInfoF("ini: invalid group name '%s'\n", buffer); + else + e--; + s++; // skip [ + group = ini_group_alloc(ini, s, e - s); + if (comment_size) { + group->comment = pool_strdup(&ini->pool, comment, comment_size); + comment_size = 0; + } + } else if (group) { + // find end of keyname + for(t=s; *t != 0 && *t != '=' && *t != '\t' && *t != ' '; t++) {} + + // it's an item in an existing group + item = ini_item_alloc(group, s, t-s); + if (comment_size) { + item->comment = pool_strdup(&ini->pool, comment, comment_size); + comment_size = 0; + } + + // find start of parameter + while (*t == '=' || *t == ' ' || *t == '\t') t++; + item->value = pool_strdup(&ini->pool, t, e - t); + } else { + // it's an orphan item + ShowInfoF("ini: '%s' outside of group\n", buffer); + } + } + + if (comment_size) { + ini->comment = pool_strdup(&ini->pool, comment, comment_size); + comment_size = 0; + } + + free(comment); + fclose(in); + + return ini; +} + +// lookup a group or make a new one +static IniGroup *ini_getgroup(IniFile *ini, const char *name, int len) +{ + IniGroup *group; + + if (len == -1) len = strlen(name); + + // does it exist already? + for(group = ini->group; group; group = group->next) + if (!memcmp(group->name, name, len) && group->name[len] == 0) + return group; + + // otherwise make a new one + group = ini_group_alloc(ini, name, len); + group->comment = pool_strdup(&ini->pool, "\n", 1); + return group; +} + +// lookup an item or make a new one +static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) +{ + IniItem *item; + uint len = strlen(name); + + for(item = group->item; item; item = item->next) + if (!strcmp(item->name, name)) + return item; + + if (!create) return NULL; + + // otherwise make a new one + item = ini_item_alloc(group, name, len); + return item; +} + +// save ini file from the "abstract" format. +static bool ini_save(const char *filename, IniFile *ini) +{ + FILE *f; + IniGroup *group; + IniItem *item; + + f = fopen(filename, "w"); + if (f == NULL) return false; + + for(group = ini->group; group; group = group->next) { + if (group->comment) fputs(group->comment, f); + fprintf(f, "[%s]\n", group->name); + for(item = group->item; item; item = item->next) { + if (item->comment) fputs(item->comment, f); + fprintf(f, "%s = %s\n", item->name, item->value ? item->value : ""); + } + } + if (ini->comment) fputs(ini->comment, f); + + fclose(f); + return true; +} + +static void ini_free(IniFile *ini) +{ + pool_free(&ini->pool); +} + +struct SettingDesc { + const char *name; + int flags; + void *def; + void *ptr; + void *b; + +}; + +static int lookup_oneofmany(const char *many, const char *one, int onelen) +{ + const char *s; + int idx; + + if (onelen == -1) onelen = strlen(one); + + // check if it's an integer + if (*one >= '0' && *one <= '9') + return strtoul(one, NULL, 0); + + idx = 0; + for(;;) { + // find end of item + s = many; + while (*s != '|' && *s != 0) s++; + if (s - many == onelen && !memcmp(one, many, onelen)) return idx; + if (*s == 0) return -1; + many = s + 1; + idx++; + } +} + +static uint32 lookup_manyofmany(const char *many, const char *str) +{ + const char *s; + int r; + uint32 res = 0; + + for(;;) { + // skip "whitespace" + while (*str == ' ' || *str == '\t' || *str == '|') str++; + if (*str == 0) break; + + s = str; + while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++; + + r = lookup_oneofmany(many, str, s - str); + if (r == -1) return (uint32)-1; + + res |= (1 << r); + if (*s == 0) break; + str = s + 1; + } + return res; +} + +static int parse_intlist(const char *p, int *items, int maxitems) +{ + int n = 0, v; + char *end; + + for(;;) { + v = strtol(p, &end, 0); + if (p == end || n == maxitems) return -1; + p = end; + items[n++] = v; + if (*p == 0) break; + if (*p != ',') return -1; + p++; + } + + return n; +} + +static bool load_intlist(const char *str, void *array, int nelems, int type) +{ + int items[64]; + int i,nitems; + + if (str == NULL) { + memset(items, 0, sizeof(items)); + nitems = nelems; + } else { + nitems = parse_intlist(str, items, lengthof(items)); + if (nitems != nelems) + return false; + } + + switch(type) { + case SDT_INT8 >> 4: + case SDT_UINT8 >> 4: + for(i=0; i!=nitems; i++) ((byte*)array)[i] = items[i]; + break; + case SDT_INT16 >> 4: + case SDT_UINT16 >> 4: + for(i=0; i!=nitems; i++) ((uint16*)array)[i] = items[i]; + break; + case SDT_INT32 >> 4: + case SDT_UINT32 >> 4: + for(i=0; i!=nitems; i++) ((uint32*)array)[i] = items[i]; + break; + default: + NOT_REACHED(); + } + + return true; +} + +static void make_intlist(char *buf, void *array, int nelems, int type) +{ + int i, v = 0; + byte *p = (byte*)array; + for(i=0; i!=nelems; i++) { + switch(type) { + case SDT_INT8 >> 4: v = *(int8*)p; p += 1; break; + case SDT_UINT8 >> 4:v = *(byte*)p; p += 1; break; + case SDT_INT16 >> 4:v = *(int16*)p; p += 2; break; + case SDT_UINT16 >> 4:v = *(uint16*)p; p += 2; break; + case SDT_INT32 >> 4:v = *(int32*)p; p += 4; break; + case SDT_UINT32 >> 4:v = *(uint32*)p; p += 4; break; + default: NOT_REACHED(); + } + buf += sprintf(buf, i ? ",%d" : "%d", v); + } +} + +static void make_oneofmany(char *buf, const char *many, int i) +{ + int orig_i = i; + char c; + + while (--i >= 0) { + do { + many++; + if (many[-1] == 0) { + sprintf(buf, "%d", orig_i); + return; + } + } while (many[-1] != '|'); + } + + // copy until | or 0 + while ((c=*many++) != 0 && c != '|') + *buf++ = c; + *buf = 0; +} + +static void make_manyofmany(char *buf, const char *many, uint32 x) +{ + const char *start; + int i = 0; + bool init = true; + + do { + start = many; + while (*many != 0 && *many != '|') many++; + if (x & 1) { + if (!init) *buf++ = '|'; + init = false; + if (start == many) { + buf += sprintf(buf, "%d", i); + } else { + memcpy(buf, start, many - start); + buf += many - start; + } + } + if (*many == '|') many++; + } while (++i, x>>=1); + *buf = 0; +} + +static void *string_to_val(const SettingDesc *desc, const char *str) +{ + unsigned long val; + char *end; + + switch(desc->flags & 0xF) { + case SDT_INTX: + val = strtol(str, &end, 0); + if (*end != 0) ShowInfoF("ini: trailing characters at end of setting '%s'", desc->name); + return (void*)val; + case SDT_ONEOFMANY: { + int r = lookup_oneofmany((char*)desc->b, str, -1); + if (r != -1) return (void*)r; + ShowInfoF("ini: invalid value '%s' for '%s'", str, desc->name); + return 0; + } + case SDT_MANYOFMANY: { + uint32 r = lookup_manyofmany(desc->b, str); + if (r != (uint32)-1) return (void*)r; + ShowInfoF("ini: invalid value '%s' for '%s'", str, desc->name); + return 0; + } + case SDT_BOOLX: + if (!strcmp(str, "true") || !strcmp(str, "on") || !strcmp(str, "1")) + return (void*)true; + if (!strcmp(str, "false") || !strcmp(str, "off") || !strcmp(str, "0")) + return (void*)false; + ShowInfoF("ini: invalid setting value '%s' for '%s'", str, desc->name); + break; + + case SDT_STRING: + case SDT_STRINGBUF: + case SDT_INTLIST: + return (void*)str; + } + + return NULL; +} + +static void load_setting_desc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base) +{ + IniGroup *group_def = ini_getgroup(ini, grpname, -1), *group; + IniItem *item; + void *p; + void *ptr; + + for (;desc->name;desc++) { + // group override? + const char *s = strchr(desc->name, '.'); + if (s) { + group = ini_getgroup(ini, desc->name, s - desc->name); + s++; + } else { + s = desc->name; + group = group_def; + } + + item = ini_getitem(group, s, false); + if (!item) { + p = desc->def; + } else { + p = string_to_val(desc, item->value); + } + + // get ptr to array + ptr = desc->ptr; + if ( (uint32)ptr < 0x10000) + ptr = (byte*)base + (uint32)ptr; + + switch(desc->flags & 0xF) { + // all these are stored in the same way + case SDT_INTX: + case SDT_ONEOFMANY: + case SDT_MANYOFMANY: + case SDT_BOOLX: + switch(desc->flags >> 4 & 7) { + case SDT_INT8 >> 4: + case SDT_UINT8 >> 4: + *(byte*)ptr = (byte)(uint)p; + break; + case SDT_INT16 >> 4: + case SDT_UINT16 >> 4: + *(uint16*)ptr = (uint16)(uint)p; + break; + case SDT_INT32 >> 4: + case SDT_UINT32 >> 4: + *(uint32*)ptr = (uint32)p; + break; + default: + NOT_REACHED(); + } + break; + case SDT_STRING: + if (*(char**)ptr) free(*(char**)ptr); + *(char**)ptr = strdup((char*)p); + break; + case SDT_STRINGBUF: + if (p) ttd_strlcpy((char*)ptr, p, desc->flags >> 16); + break; + case SDT_INTLIST: { + if (!load_intlist(p, ptr, desc->flags >> 16, desc->flags >> 4 & 7)) + ShowInfoF("ini: error in array '%s'", desc->name); + break; + } + default: + NOT_REACHED(); + } + } +} + +static void save_setting_desc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base) +{ + IniGroup *group_def = NULL, *group; + IniItem *item; + void *p, *ptr; + int i = 0; + char buf[512]; // setting buffer + const char *s; + + for (;desc->name;desc++) { + if (desc->flags & SDT_NOSAVE) + continue; + + // group override? + s = strchr(desc->name, '.'); + if (s) { + group = ini_getgroup(ini, desc->name, s - desc->name); + s++; + } else { + if (group_def == NULL) + group_def = ini_getgroup(ini, grpname, -1); + s = desc->name; + group = group_def; + } + + item = ini_getitem(group, s, true); + + // get ptr to array + ptr = desc->ptr; + if ( (uint32)ptr < 0x10000) + ptr = (byte*)base + (uint32)ptr; + + if (item->value != NULL) { + // check if the value is the same as the old value + p = string_to_val(desc, item->value); + + switch(desc->flags & 0xF) { + case SDT_INTX: + case SDT_ONEOFMANY: + case SDT_MANYOFMANY: + case SDT_BOOLX: + switch(desc->flags >> 4 & 7) { + case SDT_INT8 >> 4: + case SDT_UINT8 >> 4: + if (*(byte*)ptr == (byte)(uint)p) + continue; + break; + case SDT_INT16 >> 4: + case SDT_UINT16 >> 4: + if (*(uint16*)ptr == (uint16)(uint)p) + continue; + break; + case SDT_INT32 >> 4: + case SDT_UINT32 >> 4: + if (*(uint32*)ptr == (uint32)p) + continue; + break; + default: + NOT_REACHED(); + } + break; + case SDT_STRING: + assert(0); + break; + case SDT_INTLIST: + // assume intlist is always changed. + break; + } + } + + switch(desc->flags & 0xF) { + case SDT_INTX: + case SDT_ONEOFMANY: + case SDT_MANYOFMANY: + case SDT_BOOLX: + switch(desc->flags >> 4 & 7) { + case SDT_INT8 >> 4: i = *(int8*)ptr; break; + case SDT_UINT8 >> 4:i = *(byte*)ptr; break; + case SDT_INT16 >> 4:i = *(int16*)ptr; break; + case SDT_UINT16 >> 4:i = *(uint16*)ptr; break; + case SDT_INT32 >> 4:i = *(int32*)ptr; break; + case SDT_UINT32 >> 4:i = *(uint32*)ptr; break; + default: + NOT_REACHED(); + } + switch(desc->flags & 0xF) { + case SDT_INTX: + sprintf(buf, "%d", i); + break; + case SDT_ONEOFMANY: + make_oneofmany(buf, (char*)desc->b, i); + break; + case SDT_MANYOFMANY: + make_manyofmany(buf, (char*)desc->b, i); + break; + case SDT_BOOLX: + strcpy(buf, i ? "true" : "false"); + break; + default: + NOT_REACHED(); + } + break; + case SDT_STRINGBUF: + strcpy(buf, (char*)ptr); + break; + case SDT_STRING: + strcpy(buf, *(char**)ptr); + break; + case SDT_INTLIST: + make_intlist(buf, ptr, desc->flags >> 16, desc->flags >> 4 & 7); + break; + } + // the value is different, that means we have to write it to the ini + item->value = pool_strdup(&ini->pool, buf, strlen(buf)); + } +} + +//*************************** +// TTD specific INI stuff +//*************************** + +static const SettingDesc music_settings[] = { + {"playlist", SDT_UINT8, (void*)0, (void*)offsetof(MusicFileSettings, playlist) }, + {"music_vol", SDT_UINT8, (void*)128, (void*)offsetof(MusicFileSettings, music_vol) }, + {"effect_vol", SDT_UINT8, (void*)128, (void*)offsetof(MusicFileSettings, effect_vol) }, + {"custom_1", SDT_INTLIST | SDT_UINT8 | lengthof(msf.custom_1) << 16, NULL, (void*)offsetof(MusicFileSettings, custom_1) }, + {"custom_2", SDT_INTLIST | SDT_UINT8 | lengthof(msf.custom_2) << 16, NULL, (void*)offsetof(MusicFileSettings, custom_2) }, + {"playing", SDT_BOOL, (void*)true, (void*)offsetof(MusicFileSettings, btn_down) }, + {"shuffle", SDT_BOOL, (void*)false, (void*)offsetof(MusicFileSettings, shuffle) }, + {NULL} +}; + +static const SettingDesc win32_settings[] = { + {"display_hz", SDT_UINT, (void*)0, &_display_hz}, + {"force_full_redraw", SDT_BOOL, (void*)false, &_force_full_redraw}, + {"fullscreen_bpp", SDT_UINT, (void*)8, &_fullscreen_bpp}, + {"double_size", SDT_BOOL, (void*)false, &_double_size}, + {NULL} +}; + +static const SettingDesc misc_settings[] = { + {"display_opt", SDT_MANYOFMANY | SDT_UINT8, (void*)(DO_SHOW_TOWN_NAMES|DO_SHOW_STATION_NAMES|DO_SHOW_SIGNS|DO_FULL_ANIMATION|DO_FULL_DETAIL|DO_TRANS_BUILDINGS|DO_CHECKPOINTS), &_display_opt, "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|TRANS_BUILDINGS|FULL_DETAIL|CHECKPOINTS"}, + {"news_display_opt", SDT_UINT16, (void*)-1, &_news_display_opt}, + {"fullscreen", SDT_BOOL, (void*)false, &_fullscreen}, + {"videodriver", SDT_STRINGBUF | (lengthof(_ini_videodriver)<<16) | SDT_NOSAVE, NULL, _ini_videodriver}, + {"musicdriver", SDT_STRINGBUF | (lengthof(_ini_musicdriver)<<16) | SDT_NOSAVE, NULL, _ini_musicdriver}, + {"sounddriver", SDT_STRINGBUF | (lengthof(_ini_sounddriver)<<16) | SDT_NOSAVE, NULL, _ini_sounddriver}, + {"language", SDT_STRINGBUF | lengthof(_dynlang.curr_file)<<16, NULL, _dynlang.curr_file }, + {"resolution", SDT_UINT16 | SDT_INTLIST | lengthof(_cur_resolution) << 16, "640,480", _cur_resolution}, + {"cache_sprites", SDT_BOOL, (void*)false, &_cache_sprites}, + {"screenshot_format", SDT_STRINGBUF | (lengthof(_screenshot_format_name)<<16), NULL, _screenshot_format_name}, + {"savegame_format", SDT_STRINGBUF | (lengthof(_savegame_format)<<16), NULL, _savegame_format}, + {"rightclick_emulate", SDT_BOOL, (void*)false, &_rightclick_emulate}, + {NULL} +}; + +static const SettingDesc network_settings[] = { + {"port", SDT_UINT | SDT_NOSAVE, (void*)3979, &_network_port}, + {"sync_freq", SDT_UINT | SDT_NOSAVE, (void*)4, &_network_sync_freq}, + {"ahead_frames", SDT_UINT | SDT_NOSAVE, (void*)5, &_network_ahead_frames}, + {NULL} +}; + +static const SettingDesc debug_settings[] = { + {"savedump_path", SDT_STRINGBUF | (lengthof(_savedump_path)<<16) | SDT_NOSAVE, NULL, _savedump_path}, + {"savedump_first", SDT_UINT | SDT_NOSAVE, 0, &_savedump_first}, + {"savedump_freq", SDT_UINT | SDT_NOSAVE, (void*)1, &_savedump_freq}, + {"savedump_last", SDT_UINT | SDT_NOSAVE, 0, &_savedump_last}, + {NULL} +}; + + +static const SettingDesc gameopt_settings[] = { + {"diff_level", SDT_UINT8, (void*)9, (void*)offsetof(GameOptions, diff_level) }, + {"diff_custom", SDT_INTLIST | SDT_UINT32 | (sizeof(GameDifficulty)/4) << 16, NULL, (void*)offsetof(GameOptions, diff) }, + {"currency", SDT_UINT8 | SDT_ONEOFMANY, (void*)0, (void*)offsetof(GameOptions, currency), "GBP|USD|FF|DM|YEN|PT|FT|ZL|ATS|BEF|DKK|FIM|GRD|CHF|NLG|ITL|SEK|RUR|CZK|ISK|NOK|EUR" }, + {"distances", SDT_UINT8 | SDT_ONEOFMANY, (void*)0, (void*)offsetof(GameOptions, kilometers), "imperial|metric" }, + {"town_names", SDT_UINT8 | SDT_ONEOFMANY, (void*)0, (void*)offsetof(GameOptions, town_name), "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|hungarian" }, + {"landscape", SDT_UINT8 | SDT_ONEOFMANY, (void*)0, (void*)offsetof(GameOptions, landscape), "normal|hilly|desert|candy" }, + {"autosave", SDT_UINT8 | SDT_ONEOFMANY, (void*)1, (void*)offsetof(GameOptions, autosave), "off|monthly|quarterly|half year|yearly" }, + {"road_side", SDT_UINT8 | SDT_ONEOFMANY, (void*)0, (void*)offsetof(GameOptions, road_side), "left|right" }, + + {NULL} +}; + +static const SettingDesc patch_settings[] = { + {"vehicle_speed", SDT_BOOL, (void*)true, (void*)offsetof(Patches, vehicle_speed) }, + {"build_on_slopes", SDT_BOOL, (void*)true, (void*)offsetof(Patches, build_on_slopes) }, + {"mammoth_trains", SDT_BOOL, (void*)true, (void*)offsetof(Patches, mammoth_trains) }, + {"join_stations", SDT_BOOL, (void*)true, (void*)offsetof(Patches, join_stations) }, + {"station_spread", SDT_UINT8, (void*)12, (void*)offsetof(Patches, station_spread) }, + {"full_load_any", SDT_BOOL, (void*)true, (void*)offsetof(Patches, full_load_any)}, + + {"inflation", SDT_BOOL, (void*)true, (void*)offsetof(Patches, inflation)}, + {"no_train_service", SDT_BOOL, (void*)false, (void*)offsetof(Patches, no_train_service)}, + {"selectgoods", SDT_BOOL, (void*)true, (void*)offsetof(Patches, selectgoods)}, + {"longbridges", SDT_BOOL, (void*)false, (void*)offsetof(Patches, longbridges)}, + {"gotodepot", SDT_BOOL, (void*)true, (void*)offsetof(Patches, gotodepot)}, + + {"build_rawmaterial_ind", SDT_BOOL, (void*)false, (void*)offsetof(Patches, build_rawmaterial_ind)}, + {"multiple_industry_per_town", SDT_BOOL, (void*)false, (void*)offsetof(Patches, multiple_industry_per_town)}, + {"same_industry_close", SDT_BOOL, (void*)false, (void*)offsetof(Patches, same_industry_close)}, + + {"lost_train_days", SDT_UINT16, (void*)180, (void*)offsetof(Patches, lost_train_days)}, + {"train_income_warn", SDT_BOOL, (void*)true, (void*)offsetof(Patches, train_income_warn)}, + + {"status_long_date", SDT_BOOL, (void*)true, (void*)offsetof(Patches, status_long_date)}, + {"signal_side", SDT_BOOL, (void*)true, (void*)offsetof(Patches, signal_side)}, + {"show_finances", SDT_BOOL, (void*)true, (void*)offsetof(Patches, show_finances)}, + + {"new_nonstop", SDT_BOOL, (void*)false, (void*)offsetof(Patches, new_nonstop)}, + {"roadveh_queue", SDT_BOOL, (void*)false, (void*)offsetof(Patches, roadveh_queue)}, + + {"autoscroll", SDT_BOOL, (void*)false, (void*)offsetof(Patches, autoscroll)}, + {"errmsg_duration", SDT_UINT8, (void*)5, (void*)offsetof(Patches, errmsg_duration)}, + {"snow_line_height", SDT_UINT8, (void*)7, (void*)offsetof(Patches, snow_line_height)}, + + {"bribe", SDT_BOOL, (void*)false, (void*)offsetof(Patches, bribe)}, + {"new_depot_finding", SDT_BOOL, (void*)false, (void*)offsetof(Patches, new_depot_finding)}, + + {"nonuniform_stations", SDT_BOOL, (void*)false, (void*)offsetof(Patches, nonuniform_stations)}, + {"always_small_airport", SDT_BOOL, (void*)false, (void*)offsetof(Patches, always_small_airport)}, + {"realistic_acceleration", SDT_BOOL, (void*)false, (void*)offsetof(Patches, realistic_acceleration)}, + + {"max_trains", SDT_UINT8, (void*)80,(void*)offsetof(Patches, max_trains)}, + {"max_roadveh", SDT_UINT8, (void*)80,(void*)offsetof(Patches, max_roadveh)}, + {"max_aircraft", SDT_UINT8, (void*)40,(void*)offsetof(Patches, max_aircraft)}, + {"max_ships", SDT_UINT8, (void*)50,(void*)offsetof(Patches, max_ships)}, + + {"servint_trains", SDT_UINT16, (void*)150,(void*)offsetof(Patches, servint_trains)}, + {"servint_roadveh", SDT_UINT16, (void*)150,(void*)offsetof(Patches, servint_roadveh)}, + {"servint_ships", SDT_UINT16, (void*)360,(void*)offsetof(Patches, servint_ships)}, + {"servint_aircraft", SDT_UINT16, (void*)100,(void*)offsetof(Patches, servint_aircraft)}, + + {"autorenew", SDT_BOOL, (void*)false,(void*)offsetof(Patches, autorenew)}, + {"autorenew_months", SDT_UINT16, (void*)-12, (void*)offsetof(Patches, autorenew_months)}, + + {"new_pathfinding", SDT_BOOL, (void*)false, (void*)offsetof(Patches, new_pathfinding)}, + {"pf_maxlength", SDT_UINT16, (void*)512, (void*)offsetof(Patches, pf_maxlength)}, + {"pf_maxdepth", SDT_UINT8, (void*)16, (void*)offsetof(Patches, pf_maxdepth)}, + + {"build_in_pause", SDT_BOOL, (void*)false, (void*)offsetof(Patches, build_in_pause)}, + + {"ai_disable_veh", SDT_UINT8, (void*)0, (void*)offsetof(Patches, ai_disable_veh)}, + {"starting_date", SDT_UINT32, (void*)1950, (void*)offsetof(Patches, starting_date)}, + + {"colored_news_date", SDT_UINT32, (void*)2000, (void*)offsetof(Patches, colored_news_date)}, + + {"bridge_pillars", SDT_BOOL, (void*)true, (void*)offsetof(Patches, bridge_pillars)}, + + {"keep_all_autosave", SDT_BOOL, (void*)false, (void*)offsetof(Patches, keep_all_autosave)}, + + {"extra_dynamite", SDT_BOOL, (void*)false, (void*)offsetof(Patches, extra_dynamite)}, + + {"never_expire_vehicles", SDT_BOOL, (void*)false, (void*)offsetof(Patches, never_expire_vehicles)}, + {"extend_vehicle_life", SDT_UINT8, (void*)0, (void*)offsetof(Patches, extend_vehicle_life)}, + + {"auto_euro", SDT_BOOL, (void*)true, (void*)offsetof(Patches, auto_euro)}, + + {"serviceathelipad", SDT_BOOL, (void*)true, (void*)offsetof(Patches, serviceathelipad)}, + {"smooth_economy", SDT_BOOL, (void*)false, (void*)offsetof(Patches, smooth_economy)}, + {"dist_local_authority", SDT_UINT8, (void*)20, (void*)offsetof(Patches, dist_local_authority)}, + + {"wait_oneway_signal", SDT_UINT8, (void*)15, (void*)offsetof(Patches, wait_oneway_signal)}, + {"wait_twoway_signal", SDT_UINT8, (void*)41, (void*)offsetof(Patches, wait_twoway_signal)}, + + {NULL} +}; + +typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base); + +static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc) +{ + proc(ini, misc_settings, "misc", NULL); + proc(ini, win32_settings, "win32", NULL); + proc(ini, network_settings, "network", NULL); + proc(ini, music_settings, "music", &msf); + proc(ini, gameopt_settings, "gameopt", &_new_opt); + proc(ini, patch_settings, "patches", &_patches); + + proc(ini, debug_settings, "debug", NULL); +} + +void LoadGrfSettings(IniFile *ini) +{ + IniGroup *group = ini_getgroup(ini, "newgrf", -1); + IniItem *item; + int i; + + if (!group) + return; + + for(i=0; i!=lengthof(_newgrf_files); i++) { + char buf[3]; + sprintf(buf, "%d", i); + item = ini_getitem(group, buf, false); + if (!item) + break; + _newgrf_files[i] = strdup(item->value); + } +} + +void LoadFromConfig() +{ + IniFile *ini = ini_load(_config_file); + HandleSettingDescs(ini, load_setting_desc); + LoadGrfSettings(ini); + ini_free(ini); +} + +void SaveToConfig() +{ + IniFile *ini = ini_load(_config_file); + HandleSettingDescs(ini, save_setting_desc); + ini_save(_config_file, ini); + ini_free(ini); +} diff --git a/settings_gui.c b/settings_gui.c new file mode 100644 --- /dev/null +++ b/settings_gui.c @@ -0,0 +1,979 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" +#include "engine.h" + +static uint32 _dropdown_disabled; +static const StringID *_dropdown_items; +static int _dropdown_selindex; +static uint _dropdown_item_count; +static byte _dropdown_button; +static WindowClass _dropdown_windowclass; +static WindowNumber _dropdown_windownum; +static byte _dropdown_var1; +static byte _dropdown_var2; + +static uint32 _difficulty_click_a; +static uint32 _difficulty_click_b; +static byte _difficulty_timeout; + +static Widget _dropdown_menu_widgets[] = { +{ WWT_IMGBTN, 0, 0, 0, 0, 0, 0x0}, +{ WWT_LAST}, +}; + +static int GetDropdownItem(Window *w) +{ + uint item; + int y; + + if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0) + return -1; + + y = _cursor.pos.y - w->top - 2; + + if (y < 0) + return - 1; + + item = y / 10; + if (item >= _dropdown_item_count || HASBIT(_dropdown_disabled,item) || _dropdown_items[item] == 0) + return - 1; + + return item; +} + +void DropdownMenuWndProc(Window *w, WindowEvent *e) +{ + int item; + + switch(e->event) { + case WE_PAINT: { + int x,y,i,sel; + uint32 dis; + + DrawWindowWidgets(w); + + x = 1; + y = 2; + sel = _dropdown_selindex; + dis = _dropdown_disabled; + + for(i=0; _dropdown_items[i] != INVALID_STRING_ID; i++) { + if (_dropdown_items[i] != 0) { + if (sel == 0) { + GfxFillRect(x+1, y, x+w->width-4, y + 9, 0); + } + DrawString(x+2, y, _dropdown_items[i], sel==0 ? 12 : 16); + + if (dis & 1) { + GfxFillRect(x, y, x+w->width-3, y + 9, 0x8000 + + _color_list[_dropdown_menu_widgets[0].color].window_color_bga); + } + } else { + int color_1 = _color_list[_dropdown_menu_widgets[0].color].window_color_1a; + int color_2 = _color_list[_dropdown_menu_widgets[0].color].window_color_2; + GfxFillRect(x+1, y+3, x+w->width-5, y+3, color_1); + GfxFillRect(x+1, y+4, x+w->width-5, y+4, color_2); + } + y += 10; + sel--; + dis>>=1; + } + } break; + + case WE_CLICK: { + item = GetDropdownItem(w); + if (item >= 0) { + _dropdown_var1 = 4; + _dropdown_selindex = item; + SetWindowDirty(w); + } + } break; + + case WE_MOUSELOOP: { + Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum); + if (w2 == NULL) { + DeleteWindow(w); + return; + } + + if (_dropdown_var1 != 0 && --_dropdown_var1 == 0) { + WindowEvent e; + e.event = WE_DROPDOWN_SELECT; + e.dropdown.button = _dropdown_button; + e.dropdown.index = _dropdown_selindex; + w2->wndproc(w2, &e); + DeleteWindow(w); + return; + } + + if (_dropdown_var2 != 0) { + item = GetDropdownItem(w); + + if (!_left_button_clicked) { + _dropdown_var2 = 0; + if (item < 0) + return; + _dropdown_var1 = 2; + } else { + if (item < 0) + return; + } + + _dropdown_selindex = item; + SetWindowDirty(w); + } + } break; + + case WE_DESTROY: { + Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum); + if (w2 != NULL) { + CLRBIT(w2->click_state, _dropdown_button); + InvalidateWidget(w2, _dropdown_button); + } + } break; + } +} + +void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask) +{ + WindowNumber num; + WindowClass cls; + int i,t1,t2; + const Widget *wi; + Window *w2; + uint32 old_click_state = w->click_state; + + _dropdown_disabled = disabled_mask; + + cls = w->window_class; + num = w->window_number; + DeleteWindowById(WC_DROPDOWN_MENU, 0); + w = FindWindowById(cls, num); + + if (HASBIT(old_click_state, button)) + return; + + SETBIT(w->click_state, button); + + InvalidateWidget(w, button); + + for(i=0;strings[i] != INVALID_STRING_ID;i++); + if (i == 0) + return; + + _dropdown_items = strings; + _dropdown_item_count = i; + _dropdown_selindex = selected; + + _dropdown_windowclass = w->window_class; + _dropdown_windownum = w->window_number; + _dropdown_button = button; + + _dropdown_var1 = 0; + _dropdown_var2 = 1; + + wi = &w->widget[button]; + + _dropdown_menu_widgets[0].color = wi->color; + + w2 = AllocateWindow( + w->left + wi[-1].left + 1, + w->top + wi->bottom + 2, + (_dropdown_menu_widgets[0].right=t1=wi->right - wi[-1].left, t1 + 1), + (_dropdown_menu_widgets[0].bottom=t2=i*10+3, t2+1), + DropdownMenuWndProc, + 0x3F, + _dropdown_menu_widgets); + + + w2->flags4 &= ~WF_WHITE_BORDER_MASK; +} + +extern const StringID _currency_string_list[]; +extern uint GetMaskOfAllowedCurrencies(); + +static const StringID _distances_dropdown[] = { + STR_0139_IMPERIAL_MILES, + STR_013A_METRIC_KILOMETERS, + INVALID_STRING_ID +}; + +static const StringID _driveside_dropdown[] = { + STR_02E9_DRIVE_ON_LEFT, + STR_02EA_DRIVE_ON_RIGHT, + INVALID_STRING_ID +}; + +static const StringID _autosave_dropdown[] = { + STR_02F7_OFF, + STR_AUTOSAVE_1_MONTH, + STR_02F8_EVERY_3_MONTHS, + STR_02F9_EVERY_6_MONTHS, + STR_02FA_EVERY_12_MONTHS, + INVALID_STRING_ID, +}; + +static const StringID _designnames_dropdown[] = { + STR_02BE_DEFAULT, + STR_02BF_CUSTOM, + INVALID_STRING_ID +}; + +static StringID *BuildDynamicDropdown(StringID base, int num) +{ + static StringID buf[32 + 1]; + StringID *p = buf; + while (--num>=0) *p++ = base++; + *p = INVALID_STRING_ID; + return buf; +} + +static int GetCurRes() +{ + int i; + for(i=0; i!=_num_resolutions; i++) + if (_resolutions[i][0] == _cur_resolution[0] && _resolutions[i][1] == _cur_resolution[1]) + break; + return i; +} + +static void GameOptionsWndProc(Window *w, WindowEvent *e) +{ + int i; + + switch(e->event) { + case WE_PAINT: { + StringID str = STR_02BE_DEFAULT; + w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21); + SET_DPARAM16(0, str); + SET_DPARAM16(1, _currency_string_list[_opt_mod_ptr->currency]); + SET_DPARAM16(2, _opt_mod_ptr->kilometers + STR_0139_IMPERIAL_MILES); + SET_DPARAM16(3, STR_02E9_DRIVE_ON_LEFT + _opt_mod_ptr->road_side); + SET_DPARAM16(4, STR_TOWNNAME_ENGLISH + _opt_mod_ptr->town_name); + SET_DPARAM16(5, _autosave_dropdown[_opt_mod_ptr->autosave]); + SET_DPARAM16(6, SPECSTR_LANGUAGE_START + _dynlang.curr); + i = GetCurRes(); + SET_DPARAM16(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i); + SET_DPARAM16(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format); + DrawWindowWidgets(w); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 5: + ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies()); + return; + case 8: + ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0); + return; + case 11: { + int i = _opt_mod_ptr->road_side; + ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i)); + return; + } + case 14: { + int i = _opt_mod_ptr->town_name; + ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i)); + return; + } + case 17: + ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0); + return; + case 20: + ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2); + return; + case 21: + return; + case 24: + ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0); + return; + case 27: + // setup resolution dropdown + ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0); + return; + case 30: + // setup screenshot format dropdown + ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0); + return; + + } + break; + + case WE_DROPDOWN_SELECT: + switch(e->dropdown.button) { + case 20: + if (e->dropdown.index == 0) { + DeleteCustomEngineNames(); + MarkWholeScreenDirty(); + } else if (!(_vehicle_design_names&1)) { + LoadCustomEngineNames(); + MarkWholeScreenDirty(); + } + break; + case 5: + _opt_mod_ptr->currency = _opt.currency = e->dropdown.index; + MarkWholeScreenDirty(); + break; + case 8: + _opt_mod_ptr->kilometers = e->dropdown.index; + MarkWholeScreenDirty(); + break; + case 11: + if (_game_mode == GM_MENU) + DoCommandP(0, e->dropdown.index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_EMPTY)); + break; + case 14: + if (_game_mode == GM_MENU) + DoCommandP(0, e->dropdown.index, 0, NULL, CMD_SET_TOWN_NAME_TYPE | CMD_MSG(STR_EMPTY)); + break; + case 17: + _opt_mod_ptr->autosave = e->dropdown.index; + SetWindowDirty(w); + break; + + // change interface language + case 24: + ReadLanguagePack(e->dropdown.index); + MarkWholeScreenDirty(); + break; + + // change resolution + case 27: + if (e->dropdown.index < _num_resolutions && ChangeResInGame(_resolutions[e->dropdown.index][0],_resolutions[e->dropdown.index][1])) + SetWindowDirty(w); + break; + + // change screenshot format + case 30: + SetScreenshotFormat(e->dropdown.index); + SetWindowDirty(w); + break; + } + break; + } +} + +int32 CmdSetRoadDriveSide(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + _opt_mod_ptr->road_side = p1; + InvalidateWindow(WC_GAME_OPTIONS,0); + } + return 0; +} + +int32 CmdSetTownNameType(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + if (flags & DC_EXEC) { + _opt_mod_ptr->town_name = p1; + InvalidateWindow(WC_GAME_OPTIONS,0); + } + return 0; +} + + +static const Widget _game_options_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 369, 0, 13, STR_00B1_GAME_OPTIONS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 369, 14, 233, 0x0}, +{ WWT_FRAME, 14, 10, 179, 20, 55, STR_02E0_CURRENCY_UNITS}, +{ WWT_6, 14, 20, 169, 34, 45, STR_02E1, STR_02E2_CURRENCY_UNITS_SELECTION}, +{ WWT_CLOSEBOX, 14, 158, 168, 35, 44, STR_0225, STR_02E2_CURRENCY_UNITS_SELECTION}, +{ WWT_FRAME, 14, 190, 359, 20, 55, STR_02E3_DISTANCE_UNITS}, +{ WWT_6, 14, 200, 349, 34, 45, STR_02E4, STR_02E5_DISTANCE_UNITS_SELECTION}, +{ WWT_CLOSEBOX, 14, 338, 348, 35, 44, STR_0225, STR_02E5_DISTANCE_UNITS_SELECTION}, +{ WWT_FRAME, 14, 10, 179, 62, 97, STR_02E6_ROAD_VEHICLES}, +{ WWT_6, 14, 20, 169, 76, 87, STR_02E7, STR_02E8_SELECT_SIDE_OF_ROAD_FOR}, +{ WWT_CLOSEBOX, 14, 158, 168, 77, 86, STR_0225, STR_02E8_SELECT_SIDE_OF_ROAD_FOR}, +{ WWT_FRAME, 14, 190, 359, 62, 97, STR_02EB_TOWN_NAMES}, +{ WWT_6, 14, 200, 349, 76, 87, STR_02EC, STR_02ED_SELECT_STYLE_OF_TOWN_NAMES}, +{ WWT_CLOSEBOX, 14, 338, 348, 77, 86, STR_0225, STR_02ED_SELECT_STYLE_OF_TOWN_NAMES}, +{ WWT_FRAME, 14, 10, 179, 104, 139, STR_02F4_AUTOSAVE}, +{ WWT_6, 14, 20, 169, 118, 129, STR_02F5, STR_02F6_SELECT_INTERVAL_BETWEEN}, +{ WWT_CLOSEBOX, 14, 158, 168, 119, 128, STR_0225, STR_02F6_SELECT_INTERVAL_BETWEEN}, + +{ WWT_FRAME, 14, 10, 359, 188, 223, STR_02BC_VEHICLE_DESIGN_NAMES}, +{ WWT_6, 14, 20, 119, 202, 213, STR_02BD, STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION}, +{ WWT_CLOSEBOX, 14, 108, 118, 203, 212, STR_0225, STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION}, +{ WWT_CLOSEBOX, 14, 130, 349, 202, 213, STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK, STR_02C2_SAVE_CUSTOMIZED_VEHICLE}, + +{ WWT_FRAME, 14, 190, 359, 104, 139, STR_OPTIONS_LANG}, +{ WWT_6, 14, 200, 349, 118, 129, STR_OPTIONS_LANG_CBO, STR_OPTIONS_LANG_TIP}, +{ WWT_CLOSEBOX, 14, 338, 348, 119, 128, STR_0225, STR_OPTIONS_LANG_TIP}, +{ WWT_FRAME, 14, 10, 179, 146, 181, STR_OPTIONS_RES}, +{ WWT_6, 14, 20, 169, 160, 171, STR_OPTIONS_RES_CBO, STR_OPTIONS_RES_TIP}, +{ WWT_CLOSEBOX, 14, 158, 168, 161, 170, STR_0225, STR_OPTIONS_RES_TIP}, + +{ WWT_FRAME, 14, 190, 359, 146, 181, STR_OPTIONS_SCREENSHOT_FORMAT}, +{ WWT_6, 14, 200, 349, 160, 171, STR_OPTIONS_SCREENSHOT_FORMAT_CBO, STR_OPTIONS_SCREENSHOT_FORMAT_TIP}, +{ WWT_CLOSEBOX, 14, 338, 348, 161, 170, STR_0225, STR_OPTIONS_SCREENSHOT_FORMAT_TIP}, + +{ WWT_LAST}, +}; + +static const WindowDesc _game_options_desc = { + WDP_CENTER, WDP_CENTER, 370, 234, + WC_GAME_OPTIONS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESTORE_DPARAM | WDF_UNCLICK_BUTTONS, + _game_options_widgets, + GameOptionsWndProc +}; + + +void ShowGameOptions() +{ + DeleteWindowById(WC_GAME_OPTIONS, 0); + AllocateWindowDesc(&_game_options_desc); +} + +typedef struct { + int16 min; + int16 max; + int16 step; + StringID str; +} GameSettingData; + +static const GameSettingData _game_setting_info[] = { + {0,7,1,0}, + {0,3,1,STR_6830_IMMEDIATE}, + {0,2,1,STR_6816_LOW}, + {0,2,1,STR_6816_LOW}, + {100,500,50,0}, + {2,4,1,0}, + {0,2,1,STR_6820_LOW}, + {0,4,1,STR_681B_VERY_SLOW}, + {0,2,1,STR_6820_LOW}, + {0,2,1,STR_6823_NONE}, + {0,3,1,STR_6826_X1_5}, + {0,2,1,STR_6820_LOW}, + {0,3,1,STR_682A_VERY_FLAT}, + {0,3,1,STR_VERY_LOW}, + {0,1,1,STR_682E_STEADY}, + {0,1,1,STR_6834_AT_END_OF_LINE_AND_AT_STATIONS}, + {0,1,1,STR_6836_OFF}, + {0,2,1,STR_6839_PERMISSIVE}, +}; + +static bool FORCEINLINE GetBitAndShift(uint32 *b) +{ + uint32 x = *b; + *b >>= 1; + return (x&1) != 0; +} + +static GameOptions _opt_mod_temp; + +static const int16 _default_game_diff[3][GAME_DIFFICULTY_NUM] = { + {2, 2, 1, 2, 300, 2, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0}, + {4, 1, 1, 1, 150, 3, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1}, + {7, 0, 2, 1, 100, 4, 1, 3, 2, 2, 0, 2, 3, 2, 1, 1, 1, 2}, +}; + +void SetDifficultyLevel(int mode, GameOptions *gm_opt) +{ + int i; + assert(mode <= 3); + + gm_opt->diff_level = mode; + if (mode != 3) { // not custom + for(i = 0; i != GAME_DIFFICULTY_NUM; i++) + ((int*)&gm_opt->diff)[i] = _default_game_diff[mode][i]; + } +} + +static void GameDifficultyWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + uint32 click_a, click_b, disabled; + int i; + int x,y,value; + + w->click_state = (1 << 4) << _opt_mod_temp.diff_level; + w->disabled_state = (_game_mode != GM_NORMAL) ? 0 : (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); + DrawWindowWidgets(w); + + click_a = _difficulty_click_a; + click_b = _difficulty_click_b; + + disabled = _game_mode == GM_NORMAL ? 0x383E : 0; + // XXX + + x = 0; + y = 32; + for (i = 0; i != GAME_DIFFICULTY_NUM; i++) { + DrawFrameRect(x+5, y+1, x+5+9, y+9, 3, GetBitAndShift(&click_a)?0x20:0); + DrawFrameRect(x+15, y+1, x+15+9, y+9, 3, GetBitAndShift(&click_b)?0x20:0); + if (GetBitAndShift(&disabled)) { + int color = 0x8000 | _color_list[3].unk2; + GfxFillRect(x+6, y+2, x+6+8, y+9, color); + GfxFillRect(x+16, y+2, x+16+8, y+9, color); + } + + DrawStringCentered(x+10, y+1, STR_6819, 0); + DrawStringCentered(x+20, y+1, STR_681A, 0); + + + value = _game_setting_info[i].str + ((int*)&_opt_mod_temp.diff)[i]; + if (i == 4) value *= 1000; // handle currency option + SET_DPARAM32(0, value); + DrawString(x+30, y+1, STR_6805_MAXIMUM_NO_COMPETITORS + i, 0); + + y += 11; + } + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: { + int x,y; + uint btn, dis; + int val; + const GameSettingData *info; + + x = e->click.pt.x - 5; + if (!IS_INT_INSIDE(x, 0, 21)) + return; + + y = e->click.pt.y - 33; + if (y < 0) + return; + + // Get button from Y coord. + btn = y / 11; + if (btn >= GAME_DIFFICULTY_NUM || y % 11 > 9) + return; + + // Clicked disabled button? + dis = 0; + if (_game_mode == GM_NORMAL) + dis |= 0x383E; + if (HASBIT(dis, btn)) + return; + + _difficulty_timeout = 5; + + val = ((int*)&_opt_mod_temp.diff)[btn]; + + info = &_game_setting_info[btn]; + if (x >= 10) { + // Increase button clicked + val = min(val + info->step, info->max); + SETBIT(_difficulty_click_b, btn); + } else { + // Decrease button clicked + val = max(val - info->step, info->min); + SETBIT(_difficulty_click_a, btn); + } + + // save value in temporary variable + ((int*)&_opt_mod_temp.diff)[btn] = val; + SetDifficultyLevel(3, &_opt_mod_temp); // set difficulty level to custom + SetWindowDirty(w); + break; + } + case 4: case 5: case 6: case 7: // easy/medium/hard/custom + // temporarily change difficulty level + SetDifficultyLevel(e->click.widget - 4, &_opt_mod_temp); + SetWindowDirty(w); + break; + case 8: + ShowHighscoreTable(_opt_mod_ptr->diff_level); + break; + case 10: { // Save button - save changes + int btn, val; + for (btn = 0; btn != GAME_DIFFICULTY_NUM; btn++) { + val = ((int*)&_opt_mod_temp.diff)[btn]; + // if setting has changed, change it + if (val != ((int*)&_opt_mod_ptr->diff)[btn]) + DoCommandP(0, btn, val, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + } + DoCommandP(0, -1, _opt_mod_temp.diff_level, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + DeleteWindow(w); + break; + } + case 11: // Cancel button - close window + DeleteWindow(w); + break; + } + break; + + case WE_MOUSELOOP: + if (_difficulty_timeout != 0 && !--_difficulty_timeout) { + _difficulty_click_a = 0; + _difficulty_click_b = 0; + SetWindowDirty(w); + } + break; + } +} + +static const Widget _game_difficulty_widgets[] = { +{ WWT_CLOSEBOX, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 10, 11, 369, 0, 13, STR_6800_DIFFICULTY_LEVEL, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 10, 0, 369, 14, 29, 0x0, 0}, +{ WWT_PANEL, 10, 0, 369, 30, 276, 0x0, 0}, +{ WWT_PUSHTXTBTN, 3, 10, 96, 16, 27, STR_6801_EASY, 0}, +{ WWT_PUSHTXTBTN, 3, 97, 183, 16, 27, STR_6802_MEDIUM, 0}, +{ WWT_PUSHTXTBTN, 3, 184, 270, 16, 27, STR_6803_HARD, 0}, +{ WWT_PUSHTXTBTN, 3, 271, 357, 16, 27, STR_6804_CUSTOM, 0}, +{ WWT_EMPTY, 10, 0, 369, 251, 262, 0x0, 0}, +//{ WWT_CLOSEBOX, 10, 0, 369, 251, 262, STR_6838_SHOW_HI_SCORE_CHART, 0}, +{ WWT_PANEL, 10, 0, 369, 263, 278, 0x0, 0}, +{ WWT_PUSHTXTBTN, 3, 105, 185, 265, 276, STR_OPTIONS_SAVE_CHANGES, 0}, +{ WWT_PUSHTXTBTN, 3, 186, 266, 265, 276, STR_012E_CANCEL, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _game_difficulty_desc = { + WDP_CENTER, WDP_CENTER, 370, 279, + WC_GAME_OPTIONS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _game_difficulty_widgets, + GameDifficultyWndProc +}; + +void ShowGameDifficulty() +{ + DeleteWindowById(WC_GAME_OPTIONS, 0); + /* copy current settings to temporary holding place + * change that when setting stuff, copy back on clicking 'OK' + */ + memcpy(&_opt_mod_temp, _opt_mod_ptr, sizeof(GameOptions)); + AllocateWindowDesc(&_game_difficulty_desc); +} + +void ShowHighscoreTable(int tbl) +{ + ShowInfoF("ShowHighscoreTable(%d) not implemented", tbl); +} + +typedef struct PatchEntry { + byte type; // type of selector + byte flags; // selector flags + StringID str; // string with descriptive text + void *variable; // pointer to the variable + int16 min,max; // range for spinbox setting + uint16 step; // step for spinbox +} PatchEntry; + +enum { + PE_BOOL = 0, + PE_UINT8 = 1, + PE_INT16 = 2, + PE_UINT16 = 3, + PE_INT32 = 4, + PE_BYTE = 5, + + PF_0ISDIS = 1, + PF_NOCOMMA = 2, +}; + +static const PatchEntry _patches_ui[] = { + {PE_BOOL, 0, STR_CONFIG_PATCHES_VEHICLESPEED, &_patches.vehicle_speed}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_LONGDATE, &_patches.status_long_date}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SHOWFINANCES, &_patches.show_finances}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_AUTOSCROLL, &_patches.autoscroll}, + + {PE_UINT8, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, &_patches.errmsg_duration, 0, 20, 1}, + +}; + +static const PatchEntry _patches_construction[] = { + {PE_BOOL, 0, STR_CONFIG_PATCHES_BUILDONSLOPES, &_patches.build_on_slopes}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_EXTRADYNAMITE, &_patches.extra_dynamite}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_LONGBRIDGES, &_patches.longbridges}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SIGNALSIDE, &_patches.signal_side}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_BUILD_IN_PAUSE, &_patches.build_in_pause}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SMALL_AIRPORTS, &_patches.always_small_airport}, + +}; + +static const PatchEntry _patches_vehicles[] = { + {PE_BOOL, 0, STR_CONFIG_PATCHES_REALISTICACCEL, &_patches.realistic_acceleration}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_MAMMOTHTRAINS, &_patches.mammoth_trains}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NOTRAINSERVICE, &_patches.no_train_service}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_GOTODEPOT, &_patches.gotodepot}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_ROADVEH_QUEUE, &_patches.roadveh_queue}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NEW_DEPOT_FINDING, &_patches.new_depot_finding}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NEW_TRAIN_PATHFIND, &_patches.new_pathfinding}, + + {PE_BOOL, 0, STR_CONFIG_PATCHES_WARN_INCOME_LESS, &_patches.train_income_warn}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES, &_patches.never_expire_vehicles}, + + {PE_UINT16, PF_0ISDIS, STR_CONFIG_PATCHES_LOST_TRAIN_DAYS, &_patches.lost_train_days, 180, 720, 60}, + {PE_BOOL, 0, STR_CONFIG_AUTORENEW_VEHICLE, &_patches.autorenew}, + + {PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_TRAINS, &_patches.max_trains, 0, 240, 10}, + {PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_ROADVEH, &_patches.max_roadveh, 0, 240, 10}, + {PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_AIRCRAFT, &_patches.max_aircraft, 0, 240, 10}, + {PE_UINT8, 0, STR_CONFIG_PATCHES_MAX_SHIPS, &_patches.max_ships, 0, 240, 10}, + + {PE_UINT16, 0, STR_CONFIG_PATCHES_SERVINT_TRAINS, &_patches.servint_trains, 0, 1200, 10}, + {PE_UINT16, 0, STR_CONFIG_PATCHES_SERVINT_ROADVEH, &_patches.servint_roadveh, 0, 1200, 10}, + {PE_UINT16, 0, STR_CONFIG_PATCHES_SERVINT_AIRCRAFT, &_patches.servint_aircraft, 0, 1200, 10}, + {PE_UINT16, 0, STR_CONFIG_PATCHES_SERVINT_SHIPS, &_patches.servint_ships, 0, 1200, 10}, + + {PE_BYTE, 0, STR_CONFIG_PATCHES_AI_BUILDS_TRAINS, &_patches.ai_disable_veh, 0x01}, + {PE_BYTE, 0, STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH, &_patches.ai_disable_veh, 0x02}, + {PE_BYTE, 0, STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT, &_patches.ai_disable_veh, 0x04}, + {PE_BYTE, 0, STR_CONFIG_PATCHES_AI_BUILDS_SHIPS, &_patches.ai_disable_veh, 0x08}, +}; + +static const PatchEntry _patches_stations[] = { + {PE_BOOL, 0, STR_CONFIG_PATCHES_JOINSTATIONS, &_patches.join_stations}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_FULLLOADANY, &_patches.full_load_any}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SELECTGOODS, &_patches.selectgoods}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NEW_NONSTOP, &_patches.new_nonstop}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_NONUNIFORM_STATIONS, &_patches.nonuniform_stations}, + {PE_UINT8, 0, STR_CONFIG_PATCHES_STATION_SPREAD, &_patches.station_spread, 4, 64, 1}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SERVICEATHELIPAD, &_patches.serviceathelipad}, +}; + +static const PatchEntry _patches_economy[] = { + {PE_BOOL, 0, STR_CONFIG_PATCHES_INFLATION, &_patches.inflation}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_BUILDXTRAIND, &_patches.build_rawmaterial_ind}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_MULTIPINDTOWN, &_patches.multiple_industry_per_town}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_SAMEINDCLOSE, &_patches.same_industry_close}, + {PE_BOOL, 0, STR_CONFIG_PATCHES_BRIBE, &_patches.bribe}, + {PE_UINT8, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT, &_patches.snow_line_height, 2, 13, 1}, + + {PE_INT32, PF_NOCOMMA, STR_CONFIG_PATCHES_COLORED_NEWS_DATE, &_patches.colored_news_date, 1900, 2200, 5}, + {PE_INT32, PF_NOCOMMA, STR_CONFIG_PATCHES_STARTING_DATE, &_patches.starting_date, 1920, 2100, 1}, + + {PE_BOOL, 0, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, &_patches.smooth_economy}, +}; + +typedef struct PatchPage { + const PatchEntry *entries; + uint num; +} PatchPage; + +static const PatchPage _patches_page[] = { + {_patches_ui, lengthof(_patches_ui) }, + {_patches_construction, lengthof(_patches_construction) }, + {_patches_vehicles, lengthof(_patches_vehicles) }, + {_patches_stations, lengthof(_patches_stations) }, + {_patches_economy, lengthof(_patches_economy) }, +}; + +static int32 ReadPE(const PatchEntry*pe) +{ + switch(pe->type) { + case PE_BOOL: return *(bool*)pe->variable; + case PE_UINT8: return *(uint8*)pe->variable; + case PE_INT16: return *(int16*)pe->variable; + case PE_UINT16: return *(uint16*)pe->variable; + case PE_INT32: return *(int32*)pe->variable; + case PE_BYTE: return *(byte*)pe->variable; + default: + NOT_REACHED(); + } + + /* useless, but avoids compiler warning this way */ + return 0; +} + +static void WritePE(const PatchEntry *pe, int32 val) +{ + switch(pe->type) { + case PE_BOOL: *(bool*)pe->variable = (bool)val; break; + case PE_BYTE: *(byte*)pe->variable = (byte)val; break; + case PE_UINT8: *(uint8*)pe->variable = (uint8)val; break; + case PE_INT16: *(int16*)pe->variable = (int16)val; break; + case PE_UINT16: *(uint16*)pe->variable = (uint16)val; break; + case PE_INT32: *(int32*)pe->variable = val; break; + default: + NOT_REACHED(); + } +} + +static void PatchesSelectionWndProc(Window *w, WindowEvent *e) +{ + uint i; + switch(e->event) { + case WE_PAINT: { + int x,y; + const PatchEntry *pe; + const PatchPage *page; + uint clk; + int32 val; + + w->click_state = 1 << (WP(w,def_d).data_1 + 4); + + DrawWindowWidgets(w); + + x = 0; + y = 46; + clk = WP(w,def_d).data_2; + page = &_patches_page[WP(w,def_d).data_1]; + for(i=0,pe=page->entries; i!=page->num; i++,pe++) { + if (pe->type == PE_BOOL) { + DrawFrameRect(x+5, y+1, x+15+9, y+9, (*(bool*)pe->variable)?6:4, (*(bool*)pe->variable)?0x20:0); + SET_DPARAM16(0, *(bool*)pe->variable ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); + } else if (pe->type == PE_BYTE) { + bool enabled; + val = ReadPE(pe); + enabled = (byte)val & (byte)pe->min; + DrawFrameRect(x+5, y+1, x+15+9, y+9, enabled?6:4, enabled?0x20:0); + SET_DPARAM16(0, enabled ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); + } else { + DrawFrameRect(x+5, y+1, x+5+9, y+9, 3, clk == i*2+1 ? 0x20 : 0); + DrawFrameRect(x+15, y+1, x+15+9, y+9, 3, clk == i*2+2 ? 0x20 : 0); + DrawStringCentered(x+10, y+1, STR_6819, 0); + DrawStringCentered(x+20, y+1, STR_681A, 0); + + val = ReadPE(pe); + if (val == 0 && pe->flags & PF_0ISDIS) { + SET_DPARAM16(0, STR_CONFIG_PATCHES_DISABLED); + } else { + SET_DPARAM32(1, val); + SET_DPARAM16(0, pe->flags & PF_NOCOMMA ? STR_CONFIG_PATCHES_INT32 : STR_7024); + } + } + DrawString(30, y+1, pe->str, 0); + y += 11; + } + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 3: { + int x,y; + uint btn; + const PatchPage *page; + const PatchEntry *pe; + + y = e->click.pt.y - 46 - 1; + if (y < 0) return; + + btn = y / 11; + if (y % 11 > 9) return; + + page = &_patches_page[WP(w,def_d).data_1]; + if (btn >= page->num) return; + pe = &page->entries[btn]; + + x = e->click.pt.x - 5; + if (x < 0) return; + + if (x < 21) { + int32 val = ReadPE(pe), oval = val; + + switch(pe->type) { + case PE_BOOL: + val ^= 1; + break; + case PE_BYTE: + val ^= pe->min; + break; + case PE_UINT8: + case PE_INT16: + case PE_UINT16: + case PE_INT32: + // don't allow too fast scrolling + if ((w->flags4 & WF_TIMEOUT_MASK) > 2 << WF_TIMEOUT_SHL) { + _left_button_clicked = false; + return; + } + + if (x >= 10) { + //increase + if (pe->flags & PF_0ISDIS && val == 0) + val = pe->min; + else + val += pe->step; + if (val > pe->max) val = pe->max; + } else { + if (val <= pe->min && pe->flags & PF_0ISDIS) { + val = 0; + } else { + // decrease + val -= pe->step; + if (val < pe->min) val = pe->min; + } + } + + if (val != oval) { + WP(w,def_d).data_2 = btn * 2 + 1 + ((x>=10) ? 1 : 0); + w->flags4 |= 5 << WF_TIMEOUT_SHL; + _left_button_clicked = false; + } + break; + } + if (val != oval) { + WritePE(pe, val); + SetWindowDirty(w); + } + } else { + if (pe->type != PE_BOOL) { + WP(w,def_d).data_3 = btn; + SET_DPARAM32(0, ReadPE(pe)); + ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_PATCHES_QUERY_CAPT, 10, 100, WC_GAME_OPTIONS, 0); + } + } + + break; + } + case 4: case 5: case 6: case 7: case 8: + WP(w,def_d).data_1 = e->click.widget - 4; + DeleteWindowById(WC_QUERY_STRING, 0); + SetWindowDirty(w); + break; + } + break; + + case WE_TIMEOUT: + WP(w,def_d).data_2 = 0; + SetWindowDirty(w); + break; + + case WE_ON_EDIT_TEXT: { + if (*e->edittext.str) { + const PatchPage *page = &_patches_page[WP(w,def_d).data_1]; + WritePE(&page->entries[WP(w,def_d).data_3], atoi(e->edittext.str)); + SetWindowDirty(w); + } + break; + } + + case WE_DESTROY: + DeleteWindowById(WC_QUERY_STRING, 0); + break; + } +} + +static const Widget _patches_selection_widgets[] = { +{ WWT_CLOSEBOX, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 10, 11, 369, 0, 13, STR_CONFIG_PATCHES_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 10, 0, 369, 14, 41, 0x0, 0}, +{ WWT_PANEL, 10, 0, 369, 42, 320, 0x0, 0}, + +{ WWT_CLOSEBOX, 3, 10, 96, 16, 27, STR_CONFIG_PATCHES_GUI, 0}, +{ WWT_CLOSEBOX, 3, 97, 183, 16, 27, STR_CONFIG_PATCHES_CONSTRUCTION, 0}, +{ WWT_CLOSEBOX, 3, 184, 270, 16, 27, STR_CONFIG_PATCHES_VEHICLES, 0}, +{ WWT_CLOSEBOX, 3, 271, 357, 16, 27, STR_CONFIG_PATCHES_STATIONS, 0}, +{ WWT_CLOSEBOX, 3, 10, 96, 28, 39, STR_CONFIG_PATCHES_ECONOMY, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _patches_selection_desc = { + WDP_CENTER, WDP_CENTER, 370, 321, + WC_GAME_OPTIONS,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _patches_selection_widgets, + PatchesSelectionWndProc, +}; + +void ShowPatchesSelection() +{ + DeleteWindowById(WC_GAME_OPTIONS, 0); + AllocateWindowDesc(&_patches_selection_desc); +} diff --git a/ship_cmd.c b/ship_cmd.c new file mode 100644 --- /dev/null +++ b/ship_cmd.c @@ -0,0 +1,982 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "command.h" +#include "pathfind.h" +#include "station.h" +#include "gfx.h" +#include "news.h" +#include "engine.h" +#include "gui.h" +#include "player.h" + + +static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D}; +static const byte _ship_sometracks[4] = {0x19, 0x16, 0x25, 0x2A}; + +static byte GetTileShipTrackStatus(uint tile) { + uint32 r = GetTileTrackStatus(tile, 4); + return r | r >> 8; +} + +void DrawShipEngine(int x, int y, int engine, uint32 image_ormod) +{ + int spritenum = ship_vehicle_info(engine).image_index; + + if (is_custom_sprite(spritenum)) { + int sprite = GetCustomEngineSprite(engine, 0xffff, CID_PURCHASE, 0, 0, 6); + + if (sprite) { + DrawSprite(sprite | image_ormod, x, y); + return; + } + spritenum = _engine_original_sprites[engine]; + } + DrawSprite((6 + _ship_sprites[spritenum]) | image_ormod, x, y); +} + +void DrawShipEngineInfo(int engine, int x, int y, int maxw) +{ + ShipVehicleInfo *svi = &ship_vehicle_info(engine); + SET_DPARAM32(0, svi->base_cost * (_price.ship_base>>3)>>5); + SET_DPARAM16(1, svi->max_speed * 10 >> 5); + SET_DPARAM16(2, _cargoc.names_long_p[svi->cargo_type]); + SET_DPARAM16(3, svi->capacity); + SET_DPARAM32(4, svi->running_cost * _price.ship_running >> 8); + DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw); +} + +int GetShipImage(Vehicle *v, byte direction) +{ + int spritenum = v->spritenum; + + if (is_custom_sprite(spritenum)) { + int sprite = GetCustomVehicleSprite(v, direction); + + if (sprite) return sprite; + spritenum = _engine_original_sprites[v->engine_type]; + } + return _ship_sprites[spritenum] + direction; +} + +static int FindClosestShipDepot(Vehicle *v) +{ + uint tile, dist, best_dist = (uint)-1; + int best_depot = -1; + int i; + byte owner = v->owner; + uint tile2 = v->tile; + + for(i=0; i!=lengthof(_depots); i++) { + tile = _depots[i].xy; + if (IS_TILETYPE(tile, MP_WATER) && _map_owner[tile] == owner) { + dist = GetTileDist(tile, tile2); + if (dist < best_dist) { + best_dist = dist; + best_depot = i; + } + } + } + + return best_depot; +} + +static void CheckIfShipNeedsService(Vehicle *v) +{ + int i; + + if (v->date_of_last_service + v->service_interval > _date) + return; + + if (v->vehstatus & VS_STOPPED) + return; + + if ((v->next_order & (OT_MASK | OF_FULL_LOAD)) == (OT_GOTO_DEPOT | OF_FULL_LOAD)) + return; + + if (_patches.gotodepot && IS_HUMAN_PLAYER(v->owner) && ScheduleHasDepotOrders(v->schedule_ptr)) + return; + + i = FindClosestShipDepot(v); + + if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + return; + } + + v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; + v->next_order_param = (byte)i; + v->dest_tile = (&_depots[i])->xy; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); +} + +void OnNewDay_Ship(Vehicle *v) +{ + int32 cost; + + if ((++v->day_counter & 7) == 0) + DecreaseVehicleValue(v); + + CheckVehicleBreakdown(v); + AgeVehicle(v); + CheckIfShipNeedsService(v); + + if (v->vehstatus & VS_STOPPED) + return; + + cost = ship_vehicle_info(v->engine_type).running_cost * _price.ship_running / 364; + v->profit_this_year -= cost >> 8; + + SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); + SubtractMoneyFromPlayerFract(v->owner, cost); + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + InvalidateWindow(WC_SHIPS_LIST, v->owner); +} + +static void HandleBrokenShip(Vehicle *v) +{ + if (v->breakdown_ctr != 1) { + v->breakdown_ctr = 1; + v->cur_speed = 0; + + if (v->breakdowns_since_last_service != 255) + v->breakdowns_since_last_service++; + + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? 0xE : 0x3A, v); + + if (!(v->vehstatus & VS_HIDDEN)) { + Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); + if (u) + u->u.special.unk0 = v->breakdown_delay * 2; + } + } + + if (!(v->tick_counter & 1)) { + if (!--v->breakdown_delay) { + v->breakdown_ctr = 0; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + } + } +} + +static void MarkShipDirty(Vehicle *v) +{ + v->cur_image = GetShipImage(v, v->direction); + MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); +} + +static void PlayShipSound(Vehicle *v) +{ + SndPlayVehicleFx(ship_vehicle_info(v->engine_type).sfx, v); +} + +static const TileIndexDiff _dock_offs[] = { + TILE_XY(2, 0), + TILE_XY(-2, 0), + TILE_XY(0, 2), + TILE_XY(2, 0), + TILE_XY(0, -2), + TILE_XY(0,0), + TILE_XY(0,0), + TILE_XY(0,0), +}; + +static void ProcessShipOrder(Vehicle *v) +{ + uint order; + Station *st; + + if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { + if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + return; + } + + if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + v->date_of_last_service+v->service_interval > _date) { + v->cur_order_index++; + } + + + if (v->cur_order_index >= v->num_orders) + v->cur_order_index = 0; + + order = v->schedule_ptr[v->cur_order_index]; + + if (order == 0) { + v->next_order = OT_NOTHING; + v->dest_tile = 0; + return; + } + + if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + return; + + v->next_order = (byte)order; + v->next_order_param = (byte)(order >> 8); + + if ((order & OT_MASK) == OT_GOTO_STATION) { + if ( (byte)(order >> 8) == v->last_station_visited) + v->last_station_visited = 0xFF; + + st = DEREF_STATION(order >> 8); + if (st->dock_tile != 0) { + v->dest_tile = TILE_ADD(st->dock_tile, _dock_offs[_map5[st->dock_tile]-0x4B]); + } + } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order >> 8].xy; + } else { + v->dest_tile = 0; + } + InvalidateVehicleOrderWidget(v); +} + +static void HandleShipLoading(Vehicle *v) +{ + if (v->next_order == OT_NOTHING) + return; + + if (v->next_order != OT_DUMMY) { + if ((v->next_order&OT_MASK) != OT_LOADING) + return; + + if (--v->load_unload_time_rem) + return; + + if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); + if (LoadUnloadVehicle(v)) { + InvalidateWindow(WC_SHIPS_LIST, v->owner); + MarkShipDirty(v); + } + return; + } + PlayShipSound(v); + + { + byte b = v->next_order; + v->next_order = OT_LEAVESTATION; + if (!(b & OF_NON_STOP)) + return; + } + } + + v->cur_order_index++; + InvalidateVehicleOrderWidget(v); +} + +static void UpdateShipDeltaXY(Vehicle *v, int dir) +{ +#define MKIT(d,c,b,a) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) + static const uint32 _delta_xy_table[8] = { + MKIT( -3, -3, 6, 6), + MKIT(-16, -3, 32, 6), + MKIT( -3, -3, 6, 6), + MKIT( -3,-16, 6, 32), + MKIT( -3, -3, 6, 6), + MKIT(-16, -3, 32, 6), + MKIT( -3, -3, 6, 6), + MKIT( -3,-16, 6, 32), + }; +#undef MKIT + uint32 x = _delta_xy_table[dir]; + v->x_offs = (byte)x; + v->y_offs = (byte)(x>>=8); + v->sprite_width = (byte)(x>>=8); + v->sprite_height = (byte)(x>>=8); +} + +static void RecalcShipStuff(Vehicle *v) +{ + UpdateShipDeltaXY(v, v->direction); + v->cur_image = GetShipImage(v, v->direction); + MarkShipDirty(v); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); +} + +static const TileIndexDiff _ship_leave_depot_offs[] = { + TILE_XY(-1,0), + TILE_XY(0,-1), +}; + +static void CheckShipLeaveDepot(Vehicle *v) +{ + uint tile; + int d; + uint m; + + if (v->u.ship.state != 0x80) + return; + + tile = v->tile; + d = (_map5[tile]&2) ? 1 : 0; + + // Check first side + if (_ship_sometracks[d] & GetTileShipTrackStatus(TILE_ADD(tile,_ship_leave_depot_offs[d]))) { + m = (d==0) ? 0x101 : 0x207; + // Check second side + } else if (_ship_sometracks[d+2] & GetTileShipTrackStatus(TILE_ADD(tile, -2*_ship_leave_depot_offs[d]))) { + m = (d==0) ? 0x105 : 0x203; + } else { + return; + } + v->direction = (byte)m; + v->u.ship.state = (byte)(m >> 8); + v->vehstatus &= ~VS_HIDDEN; + + v->cur_speed = 0; + RecalcShipStuff(v); + + PlayShipSound(v); +} + +static bool ShipAccelerate(Vehicle *v) +{ + uint spd; + byte t; + + spd = min(v->cur_speed + 1, v->max_speed); + + //updates statusbar only if speed have changed to save CPU time + if (spd != v->cur_speed) { + v->cur_speed = spd; + if (_patches.vehicle_speed) + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + // Decrease somewhat when turning + if (!(v->direction&1)) { + spd = spd * 3 >> 2; + } + + if (spd == 0) + return false; + + if ((byte)++spd == 0) + return true; + + v->progress = (t = v->progress) - (byte)spd; + + return (t < v->progress); +} + + +static int32 EstimateShipCost(uint16 engine_type); + +static void ShipEnterDepot(Vehicle *v) +{ + byte t; + + v->u.ship.state = 0x80; + v->vehstatus |= VS_HIDDEN; + v->cur_speed = 0; + RecalcShipStuff(v); + + v->date_of_last_service = _date; + v->breakdowns_since_last_service = 0; + v->reliability = _engines[v->engine_type].reliability; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + MaybeRenewVehicle(v, EstimateShipCost(v->engine_type)); + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + + t = v->next_order; + v->next_order = OT_DUMMY; + + if (t&OF_UNLOAD) { v->cur_order_index++; } + + else if (t & 0x40) { + v->vehstatus |= VS_STOPPED; + if (v->owner == _local_player) { + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_981C_SHIP_IS_WAITING_IN_DEPOT, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + } + } +} + +static void ShipArrivesAt(Vehicle *v, Station *st) +{ + /* Check if station was ever visited before */ + if (!(st->had_vehicle_of_type & HVOT_SHIP)) { + uint32 flags; + st->had_vehicle_of_type |= HVOT_SHIP; + SET_DPARAM16(0, st->index); + flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); + AddNewsItem( + STR_9833_CITIZENS_CELEBRATE_FIRST, + flags, + v->index, + 0); + } +} + +typedef struct { + uint skiptile; + uint dest_coords; + uint best_bird_dist; + uint best_length; +} PathFindShip; + +//extern void dbg_store_path(); + +static bool ShipTrackFollower(uint tile, PathFindShip *pfs, int track, uint length, byte *state) +{ + // Found dest? + if (tile == pfs->dest_coords) { + pfs->best_bird_dist = 0; + +// if (length < pfs->best_length) +// dbg_store_path(); + + pfs->best_length = minu(pfs->best_length, length); + return true; + } + + // Skip this tile in the calculation + if (tile != pfs->skiptile) { + pfs->best_bird_dist = minu(pfs->best_bird_dist, GetTileDist1Db(pfs->dest_coords, tile)); + } + + return false; +} + +static const byte _ship_search_directions[6][4] = { + { 0, 9, 2, 9 }, + { 9, 1, 9, 3 }, + { 9, 0, 3, 9 }, + { 1, 9, 9, 2 }, + { 3, 2, 9, 9 }, + { 9, 9, 1, 0 }, +}; + +static const byte _pick_shiptrack_table[6] = {1, 3, 2, 2, 0, 0}; + +static uint FindShipTrack(Vehicle *v, uint tile, int dir, uint bits, uint skiptile, int *track) +{ + PathFindShip pfs; + int i, best_track; + uint best_bird_dist = 0; + uint best_length = 0; + uint r; + byte ship_dir = v->direction & 3; + + pfs.dest_coords = v->dest_tile; + pfs.skiptile = skiptile; + + best_track = -1; + + do { + i = FIND_FIRST_BIT(bits); + bits = KILL_FIRST_BIT(bits); + + pfs.best_bird_dist = (uint)-1; + pfs.best_length = (uint)-1; + + FollowTrack(tile, 0x3804, _ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs); + + if (best_track >= 0) { + if (pfs.best_bird_dist != 0) { + /* neither reached the destination, pick the one with the smallest bird dist */ + if (pfs.best_bird_dist > best_bird_dist) goto bad; + if (pfs.best_bird_dist < best_bird_dist) goto good; + } else { + if (pfs.best_length > best_length) goto bad; + if (pfs.best_length < best_length) goto good; + } + + /* if we reach this position, there's two paths of equal value so far. + * pick one randomly. */ + r = (byte)Random(); + if (_pick_shiptrack_table[i] == ship_dir) r += 80; + if (_pick_shiptrack_table[best_track] == ship_dir) r -= 80; + if (r <= 127) goto bad; + } +good:; + best_track = i; + best_bird_dist = pfs.best_bird_dist; + best_length = pfs.best_length; +bad:; + + } while (bits != 0); + + *track = best_track; + return best_bird_dist; +} + +static int ChooseShipTrack(Vehicle *v, uint tile, int dir, uint tracks) +{ + uint b; + uint tot_dist, dist; + int track; + uint tile2; + + assert(dir>=0 && dir<=3); + tile2 = TILE_ADD(tile, -_tileoffs_by_dir[dir]); + dir ^= 2; + tot_dist = (uint)-1; + b = GetTileShipTrackStatus(tile2) & _ship_sometracks[dir] & v->u.ship.state; + if (b != 0) { + dist = FindShipTrack(v, tile2, dir, b, tile, &track); + if (dist != (uint)-1) + tot_dist = dist + 1; + } + dist = FindShipTrack(v, tile, dir^2, tracks, 0, &track); + if (dist > tot_dist) + return -1; + return track; +} + +static const byte _new_vehicle_direction_table[11] = { + 0, 7, 6, 0, + 1, 0, 5, 0, + 2, 3, 4, +}; + +static int ShipGetNewDirectionFromTiles(uint new_tile, uint old_tile) +{ + uint offs = (GET_TILE_Y(new_tile) - GET_TILE_Y(old_tile) + 1) * 4 + + GET_TILE_X(new_tile) - GET_TILE_X(old_tile) + 1; + assert(offs < 11 && offs != 3 && offs != 7); + return _new_vehicle_direction_table[offs]; +} + +static int ShipGetNewDirection(Vehicle *v, int x, int y) +{ + uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1); + assert(offs < 11 && offs != 3 && offs != 7); + return _new_vehicle_direction_table[offs]; +} + +static int GetAvailShipTracks(uint tile, int dir) +{ + uint32 r = GetTileTrackStatus(tile, 4); + return (byte) ((r | r >> 8)) & _ship_sometracks[dir]; +} + +static const byte _ship_subcoord[4][6][3] = { + { + {15, 8, 1}, + { 0, 0, 0}, + { 0, 0, 0}, + {15, 8, 2}, + {15, 7, 0}, + { 0, 0, 0}, + }, + { + { 0, 0, 0}, + { 8, 0, 3}, + { 7, 0, 2}, + { 0, 0, 0}, + { 8, 0, 4}, + { 0, 0, 0}, + }, + { + { 0, 8, 5}, + { 0, 0, 0}, + { 0, 7, 6}, + { 0, 0, 0}, + { 0, 0, 0}, + { 0, 8, 4}, + }, + { + { 0, 0, 0}, + { 8,15, 7}, + { 0, 0, 0}, + { 8,15, 6}, + { 0, 0, 0}, + { 7,15, 0}, + } +}; + + +static void ShipController(Vehicle *v) +{ + GetNewVehiclePosResult gp; + uint32 r; + const byte *b; + int dir,track,tracks; + + v->tick_counter++; + + if (v->breakdown_ctr != 0) { + if (v->breakdown_ctr <= 2) { + HandleBrokenShip(v); + return; + } + v->breakdown_ctr--; + } + + if (v->vehstatus & VS_STOPPED) + return; + + ProcessShipOrder(v); + HandleShipLoading(v); + + if ((v->next_order & OT_MASK) == OT_LOADING) + return; + + CheckShipLeaveDepot(v); + + if (!ShipAccelerate(v)) + return; + + BeginVehicleMove(v); + + if (GetNewVehiclePos(v, &gp)) { + // staying in tile + if (v->u.ship.state == 0x80) { + gp.x = v->x_pos; + gp.y = v->y_pos; + } else { + /* isnot inside depot */ + r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); + if (r & 0x8) goto reverse_direction; + + if (v->dest_tile != 0 && v->dest_tile == gp.new_tile) { + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if ((gp.x&0xF)==8 && (gp.y&0xF)==8) { + ShipEnterDepot(v); + return; + } + } else if ((v->next_order & OT_MASK) == OT_GOTO_STATION) { + Station *st; + + v->last_station_visited = v->next_order_param; + + st = DEREF_STATION(v->next_order_param); + if (!(st->had_vehicle_of_type & HVOT_BUOY)) { + v->next_order = (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) | OF_NON_STOP | OT_LOADING; + ShipArrivesAt(v, st); + + SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); + if (LoadUnloadVehicle(v)) { + InvalidateWindow(WC_SHIPS_LIST, v->owner); + MarkShipDirty(v); + } + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } else { + v->next_order = OT_LEAVESTATION; + v->cur_order_index++; + InvalidateVehicleOrderWidget(v); + } + goto else_end; + } + } + + if (v->next_order == OT_LEAVESTATION) { + v->next_order = OT_NOTHING; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } + } else { + // new tile + if (GET_TILE_X(gp.new_tile) == 0xFF || + (byte)GET_TILE_Y(gp.new_tile) == 0xFF) + goto reverse_direction; + + dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile); + assert(dir == 1 || dir == 3 || dir == 5 || dir == 7); + dir>>=1; + tracks = GetAvailShipTracks(gp.new_tile, dir); + if (tracks == 0) + goto reverse_direction; + + // Choose a direction, and continue if we find one + track = ChooseShipTrack(v, gp.new_tile, dir, tracks); + if (track < 0) + goto reverse_direction; + + b = _ship_subcoord[dir][track]; + + gp.x = (gp.x&~0xF) | b[0]; + gp.y = (gp.y&~0xF) | b[1]; + + /* Call the landscape function and tell it that the vehicle entered the tile */ + r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); + if (r&0x8) goto reverse_direction; + + if (!(r&0x4)) { + v->tile = gp.new_tile; + v->u.ship.state = 1 << track; + } + + v->direction = b[2]; + } +else_end:; + + /* update image of ship, as well as delta XY */ + dir = ShipGetNewDirection(v, gp.x, gp.y); + v->x_pos = gp.x; + v->y_pos = gp.y; + v->z_pos = GetSlopeZ(gp.x, gp.y); + +getout: + UpdateShipDeltaXY(v, dir); + v->cur_image = GetShipImage(v, dir); + VehiclePositionChanged(v); + EndVehicleMove(v); + return; + +reverse_direction: + dir = v->direction ^ 4; + v->direction = dir; + goto getout; +} + +static void AgeShipCargo(Vehicle *v) +{ + if (_age_cargo_skip_counter != 0) + return; + if (v->cargo_days != 255) + v->cargo_days++; +} + +void Ship_Tick(Vehicle *v) +{ + AgeShipCargo(v); + ShipController(v); +} + +void OnTick_Ship() +{ + // unused +} + + +void HandleClickOnShip(Vehicle *v) +{ + ShowShipViewWindow(v); +} + +void ShipsYearlyLoop() +{ + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship) { + v->profit_last_year = v->profit_this_year; + v->profit_this_year = 0; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } +} + +static int32 EstimateShipCost(uint16 engine_type) +{ + return ship_vehicle_info(engine_type).base_cost * (_price.ship_base>>3)>>5; +} + +// p1 = type to build +int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int32 value; + Vehicle *v; + uint unit_num; + uint tile = TILE_FROM_XY(x,y); + Engine *e; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + value = EstimateShipCost(p1); + if (flags & DC_QUERY_COST) + return value; + + v = AllocateVehicle(); + if (v == NULL || _ptr_to_next_order >= endof(_order_array) || + (unit_num = GetFreeUnitNumber(VEH_Ship)) > _patches.max_ships) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + if (flags & DC_EXEC) { + v->unitnumber = unit_num; + + v->owner = _current_player; + v->tile = tile; + x = GET_TILE_X(tile)*16 + 8; + y = GET_TILE_Y(tile)*16 + 8; + v->x_pos = x; + v->y_pos = y; + v->z_pos = GetSlopeZ(x,y); + + v->z_height = 6; + v->sprite_width = 6; + v->sprite_height = 6; + v->x_offs = -3; + v->y_offs = -3; + v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; + + v->spritenum = ship_vehicle_info(p1).image_index; + v->cargo_type = ship_vehicle_info(p1).cargo_type; + v->cargo_cap = ship_vehicle_info(p1).capacity; + v->value = value; + + v->last_station_visited = 255; + v->max_speed = ship_vehicle_info(p1).max_speed; + v->engine_type = (byte)p1; + + e = &_engines[p1]; + v->reliability = e->reliability; + v->reliability_spd_dec = e->reliability_spd_dec; + v->max_age = e->lifelength * 366; + _new_ship_id = v->index; + + v->string_id = STR_SV_SHIP_NAME; + v->u.ship.state = 0x80; + *(v->schedule_ptr = _ptr_to_next_order++) = 0; + + v->service_interval = _patches.servint_ships; + v->date_of_last_service = _date; + v->build_year = _cur_year; + v->cur_image = 0x0E5E; + v->type = VEH_Ship; + + VehiclePositionChanged(v); + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + InvalidateWindow(WC_SHIPS_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + } + + return value; +} + +int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (!IsShipDepotTile(v->tile) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED)) + return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); + + if (flags & DC_EXEC) { + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + InvalidateWindow(WC_SHIPS_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + DeleteVehicle(v); + } + + return -(int32)v->value; +} + +// p1 = vehicle +int32 CmdStartStopShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->vehstatus ^= VS_STOPPED; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + } + + return 0; +} + +int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + int depot; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + if (flags & DC_EXEC) { + if (v->next_order&OF_UNLOAD) {v->cur_order_index++;} + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } else { + depot = FindClosestShipDepot(v); + if (depot < 0) + return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT); + + if (flags & DC_EXEC) { + v->dest_tile = _depots[depot].xy; + v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; + v->next_order_param = depot; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } + + return 0; +} + +int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->service_interval = (uint16)p2; + InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7); + } + + return 0; +} + + +// p1 = vehicle +// p2 = new cargo +int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + int32 cost; + + SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); + + v = &_vehicles[p1]; + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (!IsShipDepotTile(v->tile) || + !(v->vehstatus&VS_STOPPED) || + v->u.ship.state != 0x80) + return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); + + cost = 0; + if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) { + cost = _price.ship_base >> 7; + } + + if (flags & DC_EXEC) { + v->cargo_count = 0; + v->cargo_type = (byte)p2; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + + return cost; + +} + + diff --git a/ship_gui.c b/ship_gui.c new file mode 100644 --- /dev/null +++ b/ship_gui.c @@ -0,0 +1,1014 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "vehicle.h" +#include "viewport.h" +#include "station.h" +#include "command.h" +#include "player.h" +//#include "town.h" +#include "engine.h" + + +static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection); + + +const byte _ship_refit_types[4][16] = { + {CT_MAIL, CT_COAL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_IRON_ORE, CT_STEEL, CT_VALUABLES, 255}, + {CT_MAIL, CT_COAL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_PAPER, CT_FOOD, CT_VALUABLES, 255}, + {CT_MAIL, CT_FRUIT, CT_GOODS, CT_COPPER_ORE, CT_GRAIN, CT_WOOD, CT_WATER, CT_VALUABLES, 255}, + {CT_MAIL, CT_SUGAR, CT_TOYS, CT_CANDY, CT_COLA, CT_COTTON_CANDY, CT_BUBBLES, CT_TOFFEE, CT_BATTERIES, CT_PLASTIC, CT_FIZZY_DRINKS, 255}, +}; + +static void ShipRefitWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + const byte *b; + int sel; + int x,y; + byte color; + int cargo; + + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + DrawString(1, 15, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, 0); + + cargo = -1; + x = 6; + y = 25; + sel = WP(w,refit_d).sel; + +#define show_cargo(ctype) { \ + color = 16; \ + if (sel == 0) { \ + cargo = ctype; \ + color = 12; \ + } \ + sel--; \ + DrawString(x, y, _cargoc.names_s[ctype], color); \ + y += 10; \ + } + + if (_engine_refit_masks[v->engine_type]) { + uint32 mask = _engine_refit_masks[v->engine_type]; + int cid = 0; + + for (; mask; mask >>= 1, cid++) { + if (!(mask & 1)) // not this cid + continue; + if (!(_local_cargo_id_landscape[cid] & (1 << _opt.landscape))) // not in this landscape + continue; + + show_cargo(_local_cargo_id_ctype[cid]); + } + + } else { // generic refit list + b = _ship_refit_types[_opt.landscape]; + do { + show_cargo(*b); + } while (*++b != 255); + } + +#undef show_cargo + + WP(w,refit_d).cargo = cargo; + + if (cargo != -1) { + int32 cost = DoCommandByTile(v->tile, v->index, cargo, 0, CMD_REFIT_SHIP); + if (cost != CMD_ERROR) { + SET_DPARAM32(2, cost); + SET_DPARAM16(0, _cargoc.names_long_p[cargo]); + SET_DPARAM16(1, v->cargo_cap); + DrawString(1, 137, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); + } + } + + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + int y = e->click.pt.y - 25; + if (y >= 0) { + WP(w,refit_d).sel = y / 10; + SetWindowDirty(w); + } + } break; + case 4: /* refit button */ + if (WP(w,refit_d).cargo != 0xFF) { + Vehicle *v = &_vehicles[w->window_number]; + if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP))) + DeleteWindow(w); + } + break; + } + break; + } +} + + +static const Widget _ship_refit_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 239, 0, 13, STR_983B_REFIT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 239, 14, 135, 0x0, STR_983D_SELECT_TYPE_OF_CARGO_FOR}, +{ WWT_IMGBTN, 14, 0, 239, 136, 157, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 239, 158, 169, STR_983C_REFIT_SHIP, STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED}, +{ WWT_LAST}, +}; + +static const WindowDesc _ship_refit_desc = { + -1,-1, 240, 170, + WC_VEHICLE_REFIT,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _ship_refit_widgets, + ShipRefitWndProc, +}; + +static void ShowShipRefitWindow(Vehicle *v) +{ + Window *w; + + DeleteWindowById(WC_VEHICLE_REFIT, v->index); + + _alloc_wnd_parent_num = v->index; + w = AllocateWindowDesc(&_ship_refit_desc); + w->window_number = v->index; + w->caption_color = v->owner; + WP(w,refit_d).sel = -1; +} + +static void ShipDetailsWndProc(Window *w, WindowEvent *e) +{ + Vehicle *v = &_vehicles[w->window_number]; + StringID str; + int mod; + + switch(e->event) { + case WE_PAINT: + w->disabled_state = v->owner == _local_player ? 0 : (1 << 2); + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* Draw running cost */ + { + int year = v->age / 366; + StringID str; + + SET_DPARAM16(1, year); + + str = STR_0199_YEAR; + if (year != 1) { + str++; + if (v->max_age - 366 < v->age) + str++; + } + SET_DPARAM16(0, str); + SET_DPARAM16(2, v->max_age / 366); + SET_DPARAM32(3, ship_vehicle_info(v->engine_type).running_cost * _price.ship_running >> 8); + DrawString(2, 15, STR_9812_AGE_RUNNING_COST_YR, 0); + } + + /* Draw max speed */ + { + SET_DPARAM16(0, v->max_speed * 10 >> 5); + DrawString(2, 25, STR_9813_MAX_SPEED, 0); + } + + /* Draw profit */ + { + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(2, 35, STR_9814_PROFIT_THIS_YEAR_LAST_YEAR, 0); + } + + /* Draw breakdown & reliability */ + { + SET_DPARAM8(0, v->reliability * 100 >> 16); + SET_DPARAM16(1, v->breakdowns_since_last_service); + DrawString(2, 45, STR_9815_RELIABILITY_BREAKDOWNS, 0); + } + + /* Draw service interval text */ + { + SET_DPARAM16(0, v->service_interval); + SET_DPARAM16(1, v->date_of_last_service); + DrawString(13, 90, STR_883C_SERVICING_INTERVAL_DAYS, 0); + } + + DrawShipImage(v, 3, 57, INVALID_VEHICLE); + + SET_DPARAM16(1, 1920 + v->build_year); + SET_DPARAM16(0, GetCustomEngineName(v->engine_type)); + SET_DPARAM32(2, v->value); + DrawString(74, 57, STR_9816_BUILT_VALUE, 0); + + SET_DPARAM16(0, _cargoc.names_long_p[v->cargo_type]); + SET_DPARAM16(1, v->cargo_cap); + DrawString(74, 67, STR_9817_CAPACITY, 0); + + str = STR_8812_EMPTY; + if (v->cargo_count != 0) { + SET_DPARAM8(0, v->cargo_type); + SET_DPARAM16(1, v->cargo_count); + SET_DPARAM16(2, v->cargo_source); + str = STR_8813_FROM; + } + DrawString(74, 78, str, 0); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: /* rename */ + SET_DPARAM16(0, v->unitnumber); + ShowQueryString(v->string_id, STR_9831_NAME_SHIP, 31, 150, w->window_class, w->window_number); + break; + case 5: /* increase int */ + mod = 10; + goto change_int; + case 6: /* decrease int */ + mod = -10; +change_int: + mod += v->service_interval; + if (!IS_INT_INSIDE(mod, 30, 800+1)) + return; + DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SHIP_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING)); + break; + } + break; + + case WE_4: + if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL) + DeleteWindow(w); + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_9832_CAN_T_NAME_SHIP)); + } break; + + } +} + + +static const Widget _ship_details_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 364, 0, 13, STR_9811_DETAILS,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 365, 404, 0, 13, STR_01AA_NAME, STR_982F_NAME_SHIP}, +{ WWT_IMGBTN, 14, 0, 404, 14, 55, 0x0}, +{ WWT_IMGBTN, 14, 0, 404, 56, 88, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 89, 94, STR_0188,STR_884D_INCREASE_SERVICING_INTERVAL}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 95, 100, STR_0189,STR_884E_DECREASE_SERVICING_INTERVAL}, +{ WWT_IMGBTN, 14, 11, 404, 89, 100, 0x0}, +{ WWT_LAST}, +}; + +static const WindowDesc _ship_details_desc = { + -1,-1, 405, 101, + WC_VEHICLE_DETAILS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _ship_details_widgets, + ShipDetailsWndProc +}; + +static void ShowShipDetailsWindow(Vehicle *v) +{ + Window *w; + VehicleID veh = v->index; + DeleteWindowById(WC_VEHICLE_ORDERS, veh); + DeleteWindowById(WC_VEHICLE_DETAILS, veh); + _alloc_wnd_parent_num = veh; + w = AllocateWindowDesc(&_ship_details_desc); + w->window_number = veh; + w->caption_color = v->owner; +} + +static void CcBuildShip(bool success, uint tile, uint32 p1, uint32 p2) +{ + Vehicle *v; + if (!success) return; + + v = &_vehicles[_new_ship_id]; + if (v->tile == _backup_orders_tile) { + _backup_orders_tile = 0; + RestoreVehicleOrders(v, _backup_orders_data); + } + ShowShipViewWindow(v); +} + +static void NewShipWndProc(Window *w, WindowEvent *e) +{ + YearMonthDay ymd; + switch(e->event) { + case WE_PAINT: + if (w->window_number == 0) + w->disabled_state = 1 << 5; + + // Setup scroll count + { + int count = 0; + int num = NUM_SHIP_ENGINES; + Engine *e = &_engines[SHIP_ENGINES_INDEX]; + do { + if (HASBIT(e->player_avail, _local_player)) + count++; + } while (++e,--num); + SetVScrollCount(w, count); + } + + DrawWindowWidgets(w); + + { + int num = NUM_SHIP_ENGINES; + Engine *e = &_engines[SHIP_ENGINES_INDEX]; + int x = 2; + int y = 15; + int sel = WP(w,buildtrain_d).sel_index; + int pos = w->vscroll.pos; + int engine_id = SHIP_ENGINES_INDEX; + int selected_id = -1; + + do { + if (HASBIT(e->player_avail, _local_player)) { + if (sel==0) selected_id = engine_id; + if (IS_INT_INSIDE(--pos, -4, 0)) { + DrawString(x+75, y+7, GetCustomEngineName(engine_id), sel==0 ? 0xC : 0x10); + DrawShipEngine(x+35, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player))); + y += 24; + } + sel--; + } + } while (++engine_id, ++e,--num); + + WP(w,buildtrain_d).sel_engine = selected_id; + + if (selected_id != -1) { + Engine *e; + + SET_DPARAM32(0, ship_vehicle_info(selected_id).base_cost * (_price.ship_base>>3)>>5); + SET_DPARAM16(1, ship_vehicle_info(selected_id).max_speed * 10 >> 5); + SET_DPARAM16(2, _cargoc.names_long_p[ship_vehicle_info(selected_id).cargo_type]); + SET_DPARAM16(3, ship_vehicle_info(selected_id).capacity); + SET_DPARAM16(4, ship_vehicle_info(selected_id).refittable ? STR_9842_REFITTABLE : STR_EMPTY); + SET_DPARAM32(5, ship_vehicle_info(selected_id).running_cost * _price.ship_running >> 8); + + e = &_engines[selected_id]; + SET_DPARAM16(7, e->lifelength); + SET_DPARAM8(8, e->reliability * 100 >> 16); + ConvertDayToYMD(&ymd, e->intro_date); + SET_DPARAM16(6, ymd.year + 1920); + + DrawString(2, 111, STR_980A_COST_SPEED_CAPACITY_RUNNING, 0); + } + } + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + uint i = (e->click.pt.y - 14) / 24; + if (i < 4) { + WP(w,buildtrain_d).sel_index = i + w->vscroll.pos; + SetWindowDirty(w); + } + } break; + case 5: { /* build */ + int sel_eng = WP(w,buildtrain_d).sel_engine; + if (sel_eng != -1) + DoCommandP(w->window_number, sel_eng, 0, CcBuildShip, CMD_BUILD_SHIP | CMD_MSG(STR_980D_CAN_T_BUILD_SHIP)); + } break; + + case 6: /* rename */ + WP(w,buildtrain_d).rename_engine = WP(w,buildtrain_d).sel_engine; + ShowQueryString( + GetCustomEngineName(WP(w,buildtrain_d).sel_engine), + STR_9838_RENAME_SHIP_TYPE, + 31, + 160, + w->window_class, + w->window_number); + break; + + } + break; + + case WE_4: + if (w->window_number != 0 && !FindWindowById(WC_VEHICLE_DEPOT, w->window_number)) { + DeleteWindow(w); + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_9839_CAN_T_RENAME_SHIP_TYPE)); + } break; + + } +} + +static const Widget _new_ship_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 254, 0, 13, STR_9808_NEW_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 243, 14, 109, 0x401, STR_9825_SHIP_SELECTION_LIST_CLICK}, +{ WWT_SCROLLBAR, 14, 244, 254, 14, 109, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 254, 110, 161, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 126, 162, 173, STR_9809_BUILD_SHIP, STR_9826_BUILD_THE_HIGHLIGHTED_SHIP}, +{ WWT_PUSHTXTBTN, 14, 127, 254, 162, 173, STR_9836_RENAME, STR_9837_RENAME_SHIP_TYPE}, +{ WWT_LAST}, +}; + +static const WindowDesc _new_ship_desc = { + -1, -1, 255, 174, + WC_BUILD_VEHICLE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _new_ship_widgets, + NewShipWndProc +}; + + +static void ShowBuildShipWindow(TileIndex tile) +{ + Window *w; + + DeleteWindowById(WC_BUILD_VEHICLE, tile); + + w = AllocateWindowDesc(&_new_ship_desc); + w->window_number = tile; + w->vscroll.cap = 4; + + if (tile != 0) { + w->caption_color = _map_owner[tile]; + } else { + w->caption_color = _local_player; + } + +} + + +static void ShipViewWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + uint32 disabled = 1<<7; + StringID str; + + // Possible to refit? + if (ship_vehicle_info(v->engine_type).refittable && + v->vehstatus&VS_STOPPED && + v->u.ship.state == 0x80 && + IsShipDepotTile(v->tile)) + disabled = 0; + + if (v->owner != _local_player) + disabled |= 1<<7 | 1<<6; + w->disabled_state = disabled; + + /* draw widgets & caption */ + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* draw the flag */ + DrawSprite((v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, 2, 105); + + if (v->breakdown_ctr == 1) { + str = STR_885C_BROKEN_DOWN; + } else if (v->vehstatus & VS_STOPPED) { + str = STR_8861_STOPPED; + } else { + switch(v->next_order & OT_MASK) { + case OT_GOTO_STATION: { + SET_DPARAM16(0, v->next_order_param); + SET_DPARAM16(1, v->cur_speed * 10 >> 5); + str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; + } break; + + case OT_GOTO_DEPOT: { + Depot *dep = &_depots[v->next_order_param]; + SET_DPARAM16(0, dep->town_index); + SET_DPARAM16(1, v->cur_speed * 10 >> 5); + str = STR_HEADING_FOR_SHIP_DEPOT + _patches.vehicle_speed; + } break; + + case OT_LOADING: + case OT_LEAVESTATION: + str = STR_882F_LOADING_UNLOADING; + break; + + default: + if (v->num_orders == 0) { + str = STR_NO_ORDERS + _patches.vehicle_speed; + SET_DPARAM16(0, v->cur_speed * 10 >> 5); + } else + str = STR_EMPTY; + break; + } + } + + DrawStringCentered(125, 105, str, 0); + DrawWindowViewport(w); + } break; + + case WE_CLICK: { + Vehicle *v = &_vehicles[w->window_number]; + + switch(e->click.widget) { + case 4: /* start stop */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_SHIP | CMD_MSG(STR_9818_CAN_T_STOP_START_SHIP)); + break; + case 5: /* center main view */ + ScrollMainWindowTo(v->x_pos, v->y_pos); + break; + case 6: /* goto hangar */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_SEND_SHIP_TO_DEPOT | CMD_MSG(STR_9819_CAN_T_SEND_SHIP_TO_DEPOT)); + break; + case 7: /* refit */ + ShowShipRefitWindow(v); + break; + case 8: /* show orders */ + ShowOrdersWindow(v); + break; + case 9: /* show details */ + ShowShipDetailsWindow(v); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number); + DeleteWindowById(WC_VEHICLE_REFIT, w->window_number); + DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number); + break; + } +} + +static const Widget _ship_view_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 249, 0, 13, STR_980F, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 231, 14, 103, 0x0}, +{ WWT_6, 14, 2, 229, 16, 101, 0}, +{ WWT_PUSHIMGBTN, 14, 0, 249, 104, 115, 0x0, STR_9827_CURRENT_SHIP_ACTION_CLICK}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 14, 31, 0x2AB, STR_9829_CENTER_MAIN_VIEW_ON_SHIP}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 32, 49, 0x2B0, STR_982A_SEND_SHIP_TO_DEPOT}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 50, 67, 0x2B4, STR_983A_REFIT_CARGO_SHIP_TO_CARRY}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 68, 85, 0x2B2, STR_9828_SHOW_SHIP_S_ORDERS}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 86, 103, 0x2B3, STR_982B_SHOW_SHIP_DETAILS}, +{ WWT_LAST}, +}; + +static const WindowDesc _ship_view_desc = { + -1,-1, 250, 116, + WC_VEHICLE_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _ship_view_widgets, + ShipViewWndProc +}; + +void ShowShipViewWindow(Vehicle *v) +{ + Window *w; + + w = AllocateWindowDescFront(&_ship_view_desc, v->index); + if (w) { + w->caption_color = v->owner; + AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0); + } +} + + +static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection) +{ + int image = GetShipImage(v, 6); + uint32 ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)); + DrawSprite(image | ormod, x+32, y+10); + + if (v->index == selection) { + DrawFrameRect(x-5, y-1, x+67, y+21, 15, 0x10); + } +} + +static void DrawShipDepotWindow(Window *w) +{ + uint tile; + Vehicle *v; + int num,x,y; + Depot *d; + + tile = w->window_number; + + /* setup disabled buttons */ + w->disabled_state = (_map_owner[tile]==_local_player) ? 0 : ((1<<3)|(1<<5)); + + /* determine amount of items for scroller */ + num = 0; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && v->u.ship.state == 0x80 && + v->tile == (TileIndex)tile) + num++; + } + SetVScrollCount(w, (num+2) / 3); + + /* locate the depot struct */ + for(d=_depots; d->xy != (TileIndex)tile; d++) {} + + SET_DPARAM16(0, d->town_index); + DrawWindowWidgets(w); + + x = 2; + y = 15; + num = w->vscroll.pos * 3; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && + v->u.ship.state == 0x80 && + v->tile == (TileIndex)tile && + --num < 0 && num >= -6) { + + DrawShipImage(v, x+19, y, WP(w,traindepot_d).sel); + + SET_DPARAM16(0, v->unitnumber); + DrawString(x, y, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); + + DrawSprite( (v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, x, y + 9); + + if ((x+=90) == 2+90*3) { + x = 2; + y += 24; + } + } + } +} + +static int GetVehicleFromShipDepotWndPt(Window *w, int x, int y, Vehicle **veh) +{ + uint xt,yt,xm,ym; + TileIndex tile; + Vehicle *v; + int pos; + + xt = x / 90; + xm = x % 90; + if (xt >= 5) + return 1; + + yt = (y - 14) / 24; + ym = (y - 14) % 24; + if (yt >= 2) + return 1; + + pos = (yt + w->vscroll.pos) * 3 + xt; + + tile = w->window_number; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && + v->vehstatus&VS_HIDDEN && + v->tile == (TileIndex)tile && + --pos < 0) { + *veh = v; + if (xm >= 19) + return 0; + if (ym <= 10) + return -1; /* show window */ + return -2; /* start stop */ + } + } + + return 1; /* outside */ + +} + +static void ShipDepotClick(Window *w, int x, int y) +{ + Vehicle *v; + + switch (GetVehicleFromShipDepotWndPt(w, x, y, &v)) { + case 1: + return; + + case 0: + if (v != NULL) { + WP(w,traindepot_d).sel = v->index; + SetWindowDirty(w); + SetObjectToPlaceWnd( SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)) + + GetShipImage(v, 6), 4, w); + } + break; + + case -1: + ShowShipViewWindow(v); + break; + + case -2: + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_SHIP | CMD_MSG(STR_9818_CAN_T_STOP_START_SHIP)); + break; + + default: + NOT_REACHED(); + } +} + +static void ShipDepotWndProc(Window *w, WindowEvent *e) { + switch(e->event) { + case WE_PAINT: + DrawShipDepotWindow(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: + ShipDepotClick(w, e->click.pt.x, e->click.pt.y); + break; + + case 5: + ShowBuildShipWindow(w->window_number); + break; + + case 6: /* scroll to tile */ + ScrollMainWindowToTile(w->window_number); + break; + } + break; + + case WE_DESTROY: + DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + break; + + case WE_DRAGDROP: { + switch(e->click.widget) { + case 2: { + Vehicle *v; + VehicleID sel = WP(w,traindepot_d).sel; + + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + + if (GetVehicleFromShipDepotWndPt(w, e->dragdrop.pt.x, e->dragdrop.pt.y, &v) == 0 && + v != NULL && + sel == v->index) { + ShowShipViewWindow(v); + } + } break; + + case 3: + if (!HASBIT(w->disabled_state, 3) && + WP(w,traindepot_d).sel != INVALID_VEHICLE) { + Vehicle *v; + + HandleButtonClick(w, 3); + + v = &_vehicles[WP(w,traindepot_d).sel]; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + + _backup_orders_tile = v->tile; + BackupVehicleOrders(v, _backup_orders_data); + + if (!DoCommandP(v->tile, v->index, 0, NULL, CMD_SELL_SHIP | CMD_MSG(STR_980C_CAN_T_SELL_SHIP))) + _backup_orders_tile = 0; + } + break; + default: + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + } + break; + } + break; + } +} + +static const Widget _ship_depot_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 304, 0, 13, STR_9803_SHIP_DEPOT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 269, 14, 61, 0x203, STR_981F_SHIPS_CLICK_ON_SHIP_FOR}, +{ WWT_IMGBTN, 14, 270, 293, 14, 61, 0x2A9, STR_9821_DRAG_SHIP_TO_HERE_TO_SELL}, +{ WWT_SCROLLBAR, 14, 294, 304, 14, 61, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 151, 62, 73, STR_9804_NEW_SHIPS, STR_9820_BUILD_NEW_SHIP}, +{ WWT_PUSHTXTBTN, 14, 152, 304, 62, 73, STR_00E4_LOCATION, STR_9822_CENTER_MAIN_VIEW_ON_SHIP}, +{ WWT_LAST}, +}; + +static const WindowDesc _ship_depot_desc = { + -1, -1, 305, 74, + WC_VEHICLE_DEPOT,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _ship_depot_widgets, + ShipDepotWndProc +}; + +void ShowShipDepotWindow(uint tile) +{ + Window *w; + + w = AllocateWindowDescFront(&_ship_depot_desc,tile); + if (w) { + w->caption_color = _map_owner[w->window_number]; + w->vscroll.cap = 2; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + _backup_orders_tile = 0; + } +} + + +static void DrawSmallShipSchedule(Vehicle *v, int x, int y) { + uint16 *sched; + int sel; + uint ord; + Station *st; + int i = 0; + + sched = v->schedule_ptr; + sel = v->cur_order_index; + + while ((ord=*sched++) != 0) { + if (sel == 0) { + _stringwidth_base = 0xE0; + DoDrawString( "\xAF", x-6, y, 16); + _stringwidth_base = 0; + } + sel--; + + if ((ord & OT_MASK) == OT_GOTO_STATION) { + st = DEREF_STATION(ord >> 8); + + if (!(st->had_vehicle_of_type & HVOT_BUOY)) { + SET_DPARAM16(0, ord >> 8); + DrawString(x, y, STR_A036, 0); + + y += 6; + if (++i == 4) + break; + } + } + } +} + +static void PlayerShipsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + /* determine amount of items for scroller */ + { + Vehicle *v; + int num = 0; + byte owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && v->owner == owner) + num++; + } + SetVScrollCount(w, num); + } + + /* draw the widgets */ + { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawWindowWidgets(w); + } + + /* draw the ships vehicles */ + { + Vehicle *v; + int pos = w->vscroll.pos; + byte owner = (byte)w->window_number; + int x = 2; + int y = 15; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && v->owner == owner && + --pos < 0 && pos >= -4) { + StringID str; + + DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y+13); + + SET_DPARAM16(0, v->unitnumber); + if (IsShipDepotTile(v->tile)) { + str = STR_021F; + } else { + str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; + } + DrawString(x, y+2, str, 0); + + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + if (v->string_id != STR_SV_SHIP_NAME) { + SET_DPARAM16(0, v->string_id); + DrawString(x+12, y, STR_01AB, 0); + } + + DrawSmallShipSchedule(v, x+138, y); + + y += 36; + } + } + } + break; + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* click ship */ + int sel; + Vehicle *v; + byte owner; + + sel = (e->click.pt.y - 14) / 36; + + if ((uint)sel >= 4) + break; + sel += w->vscroll.pos; + owner = (byte)w->window_number; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Ship && v->owner == owner && --sel < 0) { + ShowShipViewWindow(v); + break; + } + } + break; + } + case 4: {/* click buy */ + uint tile; + + tile = _last_built_ship_depot_tile; + do { + if (_map_owner[tile] == _local_player && + IsShipDepotTile(tile)) { + + ShowShipDepotWindow(tile); + ShowBuildShipWindow(tile); + return; + } + + tile = TILE_MASK(tile + 1); + } while(tile != _last_built_ship_depot_tile); + + ShowBuildShipWindow(0); + } break; + } + break; + } +} + +static const Widget _player_ships_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 129, 158, 169, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES}, +{ WWT_IMGBTN, 14, 130, 259, 158, 169, 0x0}, +{ WWT_LAST}, +}; +static const WindowDesc _player_ships_desc = { + -1, -1, 260, 170, + WC_SHIPS_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _player_ships_widgets, + PlayerShipsWndProc +}; + +static const Widget _other_player_ships_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, +{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; +static const WindowDesc _other_player_ships_desc = { + -1, -1, 260, 158, + WC_SHIPS_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _other_player_ships_widgets, + PlayerShipsWndProc +}; + + +void ShowPlayerShips(int player) +{ + Window *w; + + if ( player == _local_player) { + w = AllocateWindowDescFront(&_player_ships_desc, player); + } else { + w = AllocateWindowDescFront(&_other_player_ships_desc, player); + } + if (w) { + w->caption_color = w->window_number; + w->vscroll.cap = 4; + } +} diff --git a/smallmap_gui.c b/smallmap_gui.c new file mode 100644 --- /dev/null +++ b/smallmap_gui.c @@ -0,0 +1,997 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gfx.h" +#include "viewport.h" +#include "player.h" +#include "vehicle.h" +#include "town.h" + +static const Widget _smallmap_megabig_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 592, 0, 13, STR_00B0_MAP,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 593, 606, 0, 13, 0x2AA,STR_01CC_TOGGLE_LARGE_SMALL_MAP}, +{ WWT_IMGBTN, 13, 0, 606, 14, 407, 0x0, 0}, +{ WWT_6, 13, 2, 604, 16, 405, 0x0, 0}, +{ WWT_IMGBTN, 13, 541, 562, 408, 429, 0x2E2,STR_0191_SHOW_LAND_CONTOURS_ON_MAP}, +{ WWT_IMGBTN, 13, 563, 584, 408, 429, 0x2E3,STR_0192_SHOW_VEHICLES_ON_MAP}, +{ WWT_IMGBTN, 13, 585, 606, 408, 429, 0x2E5,STR_0193_SHOW_INDUSTRIES_ON_MAP}, +{ WWT_IMGBTN, 13, 519, 540, 430, 451, 0x2E4,STR_0194_SHOW_TRANSPORT_ROUTES_ON}, +{ WWT_IMGBTN, 13, 541, 562, 430, 451, 0x2E6,STR_0195_SHOW_VEGETATION_ON_MAP}, +{ WWT_IMGBTN, 13, 563, 584, 430, 451, 0x2E7,STR_0196_SHOW_LAND_OWNERS_ON_MAP}, +{ WWT_IMGBTN, 13, 585, 606, 430, 451, 0xFED,STR_0197_TOGGLE_TOWN_NAMES_ON_OFF}, +{ WWT_IMGBTN, 13, 0, 518, 408, 451, 0x0,STR_0197_TOGGLE_TOWN_NAMES_ON_OFF}, +{ WWT_IMGBTN, 13, 519, 540, 408, 429, 0x0,0}, +{ WWT_LAST}, +}; + +static const Widget _smallmap_big_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 431, 0, 13, STR_00B0_MAP,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 432, 445, 0, 13, 0x2AA,STR_01CC_TOGGLE_LARGE_SMALL_MAP}, +{ WWT_IMGBTN, 13, 0, 445, 14, 257, 0x0, 0}, +{ WWT_6, 13, 2, 443, 16, 255, 0x0, 0}, +{ WWT_IMGBTN, 13, 380, 401, 258, 279, 0x2E2,STR_0191_SHOW_LAND_CONTOURS_ON_MAP}, +{ WWT_IMGBTN, 13, 402, 423, 258, 279, 0x2E3,STR_0192_SHOW_VEHICLES_ON_MAP}, +{ WWT_IMGBTN, 13, 424, 445, 258, 279, 0x2E5,STR_0193_SHOW_INDUSTRIES_ON_MAP}, +{ WWT_IMGBTN, 13, 380, 401, 280, 301, 0x2E4,STR_0194_SHOW_TRANSPORT_ROUTES_ON}, +{ WWT_IMGBTN, 13, 402, 423, 280, 301, 0x2E6,STR_0195_SHOW_VEGETATION_ON_MAP}, +{ WWT_IMGBTN, 13, 424, 445, 280, 301, 0x2E7,STR_0196_SHOW_LAND_OWNERS_ON_MAP}, +{ WWT_IMGBTN, 13, 358, 379, 280, 301, 0xFED,STR_0197_TOGGLE_TOWN_NAMES_ON_OFF}, +{ WWT_IMGBTN, 13, 0, 357, 258, 301, 0x0,STR_0197_TOGGLE_TOWN_NAMES_ON_OFF}, +{ WWT_IMGBTN, 13, 358, 379, 258, 279, 0x0,0}, +{ WWT_LAST}, +}; + + +static const Widget _smallmap_small_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 233, 0, 13, STR_00B0_MAP,STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 234, 247, 0, 13, 0x2AA,STR_01CC_TOGGLE_LARGE_SMALL_MAP}, +{ WWT_IMGBTN, 13, 0, 225, 14, 167, 0x0, 0}, +{ WWT_6, 13, 2, 223, 16, 165, 0x0, 0}, +{ WWT_IMGBTN, 13, 226, 247, 14, 35, 0x2E2,STR_0191_SHOW_LAND_CONTOURS_ON_MAP}, +{ WWT_IMGBTN, 13, 226, 247, 36, 57, 0x2E3,STR_0192_SHOW_VEHICLES_ON_MAP}, +{ WWT_IMGBTN, 13, 226, 247, 58, 79, 0x2E5,STR_0193_SHOW_INDUSTRIES_ON_MAP}, +{ WWT_IMGBTN, 13, 226, 247, 80, 101, 0x2E4,STR_0194_SHOW_TRANSPORT_ROUTES_ON}, +{ WWT_IMGBTN, 13, 226, 247, 102, 123, 0x2E6,STR_0195_SHOW_VEGETATION_ON_MAP}, +{ WWT_IMGBTN, 13, 226, 247, 124, 145, 0x2E7,STR_0196_SHOW_LAND_OWNERS_ON_MAP}, +{ WWT_IMGBTN, 13, 226, 247, 146, 167, 0xFED,STR_0197_TOGGLE_TOWN_NAMES_ON_OFF}, +{ WWT_IMGBTN, 13, 0, 247, 168, 211, 0x0,0}, +{ WWT_LAST}, +}; + +static int _smallmap_type; +static byte _smallmap_size; +static bool _smallmap_show_towns = true; + +static void DoShowSmallMap(int big); + +#define MK(a,b) a,b +#define MKEND() 0xffff +#define MS(a,b) (a|0x100),b + +static const uint16 _legend_land_contours[] = { + MK(0x5A,STR_00F0_100M), + MK(0x5C,STR_00F1_200M), + MK(0x5E,STR_00F2_300M), + MK(0x1F,STR_00F3_400M), + MK(0x27,STR_00F4_500M), + + MS(0xD7,STR_00EB_ROADS), + MK(0x0A,STR_00EC_RAILROADS), + MK(0x98,STR_00ED_STATIONS_AIRPORTS_DOCKS), + MK(0xB5,STR_00EE_BUILDINGS_INDUSTRIES), + MK(0x0F,STR_00EF_VEHICLES), + MKEND() +}; + +static const uint16 _legend_vehicles[] = { + MK(0xB8,STR_00F5_TRAINS), + MK(0xBF,STR_00F6_ROAD_VEHICLES), + MK(0x98,STR_00F7_SHIPS), + MK(0x0F,STR_00F8_AIRCRAFT), + MS(0xD7,STR_00F9_TRANSPORT_ROUTES), + MK(0xB5,STR_00EE_BUILDINGS_INDUSTRIES), + MKEND() +}; + +static const uint16 _legend_industries_normal[] = { + MK(0xD7,STR_00FA_COAL_MINE), + MK(0xB8,STR_00FB_POWER_STATION), + MK(0x56,STR_00FC_FOREST), + MK(0xC2,STR_00FD_SAWMILL), + MK(0xBF,STR_00FE_OIL_REFINERY), + MK(0x0F,STR_0105_BANK), + + MS(0x30,STR_00FF_FARM), + MK(0xAE,STR_0100_FACTORY), + MK(0x98,STR_0102_OIL_WELLS), + MK(0x37,STR_0103_IRON_ORE_MINE), + MK(0x0A,STR_0104_STEEL_MILL), + MKEND() +}; + +static const uint16 _legend_industries_hilly[] = { + MK(0xD7,STR_00FA_COAL_MINE), + MK(0xB8,STR_00FB_POWER_STATION), + MK(0x56,STR_00FC_FOREST), + MK(0x0A,STR_0106_PAPER_MILL), + MK(0xBF,STR_00FE_OIL_REFINERY), + MK(0x37,STR_0108_FOOD_PROCESSING_PLANT), + MS(0x30,STR_00FF_FARM), + + MK(0xAE,STR_0101_PRINTING_WORKS), + MK(0x98,STR_0102_OIL_WELLS), + MK(0xC2,STR_0107_GOLD_MINE), + MK(0x0F,STR_0105_BANK), + MKEND() +}; + +static const uint16 _legend_industries_desert[] = { + MK(0xBF,STR_00FE_OIL_REFINERY), + MK(0x98,STR_0102_OIL_WELLS), + MK(0x0F,STR_0105_BANK), + MK(0xB8,STR_0109_DIAMOND_MINE), + MK(0x37,STR_0108_FOOD_PROCESSING_PLANT), + MK(0x0A,STR_010A_COPPER_ORE_MINE), + MK(0x30,STR_00FF_FARM), + MS(0x56,STR_010B_FRUIT_PLANTATION), + + MK(0x27,STR_010C_RUBBER_PLANTATION), + MK(0x25,STR_010D_WATER_SUPPLY), + MK(0xD0,STR_010E_WATER_TOWER), + MK(0xAE,STR_0100_FACTORY), + MK(0xC2,STR_010F_LUMBER_MILL), + MKEND() +}; + +static const uint16 _legend_industries_candy[] = { + MK(0x30,STR_0110_COTTON_CANDY_FOREST), + MK(0xAE,STR_0111_CANDY_FACTORY), + MK(0x27,STR_0112_BATTERY_FARM), + MK(0x37,STR_0113_COLA_WELLS), + MK(0xD0,STR_0114_TOY_SHOP), + MK(0x0A,STR_0115_TOY_FACTORY), + MS(0x25,STR_0116_PLASTIC_FOUNTAINS), + + MK(0xB8,STR_0117_FIZZY_DRINK_FACTORY), + MK(0x98,STR_0118_BUBBLE_GENERATOR), + MK(0xC2,STR_0119_TOFFEE_QUARRY), + MK(0x0F,STR_011A_SUGAR_MINE), + MKEND() +}; + +static const uint16 _legend_routes[] = { + MK(0xD7,STR_00EB_ROADS), + MK(0x0A,STR_00EC_RAILROADS), + MK(0xB5,STR_00EE_BUILDINGS_INDUSTRIES), + MS(0x56,STR_011B_RAILROAD_STATION), + + MK(0xC2,STR_011C_TRUCK_LOADING_BAY), + MK(0xBF,STR_011D_BUS_STATION), + MK(0xB8,STR_011E_AIRPORT_HELIPORT), + MK(0x98,STR_011F_DOCK), + MKEND() +}; + +static const uint16 _legend_vegetation[] = { + MK(0x52,STR_0120_ROUGH_LAND), + MK(0x54,STR_0121_GRASS_LAND), + MK(0x37,STR_0122_BARE_LAND), + MK(0x25,STR_0123_FIELDS), + MK(0x57,STR_0124_TREES), + MK(0xD0,STR_00FC_FOREST), + MS(0x0A,STR_0125_ROCKS), + + MK(0xC2,STR_012A_DESERT), + MK(0x98,STR_012B_SNOW), + MK(0xD7,STR_00F9_TRANSPORT_ROUTES), + MK(0xB5,STR_00EE_BUILDINGS_INDUSTRIES), + MKEND() +}; + +static const uint16 _legend_land_owners[] = { + MK(0xCA,STR_0126_WATER), + MK(0x54,STR_0127_NO_OWNER), + MK(0xB4,STR_0128_TOWNS), + MK(0x20,STR_0129_INDUSTRIES), + MKEND() +}; +#undef MK +#undef MS +#undef MKEND + + +enum { IND_OFFS = 6 }; +static const uint16 * const _legend_table[] = { + _legend_land_contours, + _legend_vehicles, + NULL, + _legend_routes, + _legend_vegetation, + _legend_land_owners, + + _legend_industries_normal, + _legend_industries_hilly, + _legend_industries_desert, + _legend_industries_candy, +}; + +#if defined(TTD_ALIGNMENT_4) + static INLINE void WRITE_PIXELS(void *dst, uint32 val) + { + byte *d = (byte*)dst; +# if defined(TTD_BIG_ENDIAN) + d[0] = (byte)(val >> 24); + d[1] = (byte)(val >> 16); + d[2] = (byte)(val >> 8); + d[3] = (byte)(val >> 0); +# elif defined(TTD_LITTLE_ENDIAN) + d[0] = (byte)(val >> 0); + d[1] = (byte)(val >> 8); + d[2] = (byte)(val >> 16); + d[3] = (byte)(val >> 24); +# endif + } + +/* need to use OR, otherwise we will overwrite the wrong pixels at the edges :( */ + static INLINE void WRITE_PIXELS_OR(void *dst, uint32 val) + { + byte *d = (byte*)dst; +# if defined(TTD_BIG_ENDIAN) + d[0] |= (byte)(val >> 24); + d[1] |= (byte)(val >> 16); + d[2] |= (byte)(val >> 8); + d[3] |= (byte)(val >> 0); +# elif defined(TTD_LITTLE_ENDIAN) + d[0] |= (byte)(val >> 0); + d[1] |= (byte)(val >> 8); + d[2] |= (byte)(val >> 16); + d[3] |= (byte)(val >> 24); +# endif + } +#else +# define WRITE_PIXELS(dst, val) *(uint32*)(dst) = (val); +# define WRITE_PIXELS_OR(dst,val) *(uint32*)(dst) |= (val); +#endif + +#if defined(TTD_BIG_ENDIAN) +# define MKCOLOR(x) BSWAP32(x) +#elif defined(TTD_LITTLE_ENDIAN) +# define MKCOLOR(x) (x) +#endif + +static const uint32 _map_height_bits[16] = { + MKCOLOR(0x5A5A5A5A), + MKCOLOR(0x5A5B5A5B), + MKCOLOR(0x5B5B5B5B), + MKCOLOR(0x5B5C5B5C), + MKCOLOR(0x5C5C5C5C), + MKCOLOR(0x5C5D5C5D), + MKCOLOR(0x5D5D5D5D), + MKCOLOR(0x5D5E5D5E), + MKCOLOR(0x5E5E5E5E), + MKCOLOR(0x5E5F5E5F), + MKCOLOR(0x5F5F5F5F), + MKCOLOR(0x5F1F5F1F), + MKCOLOR(0x1F1F1F1F), + MKCOLOR(0x1F271F27), + MKCOLOR(0x27272727), + MKCOLOR(0x27272727), +}; + +static const uint32 _smallmap_contours_andor[12][2] = { + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x000A0A00),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x98989898),MKCOLOR(0x00000000)}, + {MKCOLOR(0xCACACACA),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0xB5B5B5B5),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x000A0A00),MKCOLOR(0xFF0000FF)}, +}; + +static const uint32 _smallmap_vehicles_andor[12][2] = { + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0xCACACACA),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0xB5B5B5B5),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, +}; + +static const uint32 _smallmap_vegetation_andor[12][2] = { + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00575700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0xCACACACA),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0xB5B5B5B5),MKCOLOR(0x00000000)}, + {MKCOLOR(0x00000000),MKCOLOR(0xFFFFFFFF)}, + {MKCOLOR(0x00B5B500),MKCOLOR(0xFF0000FF)}, + {MKCOLOR(0x00D7D700),MKCOLOR(0xFF0000FF)}, +}; + +static uint32 INLINE GetSmallMapCountoursPixels(uint tile) +{ + uint t; + + t = GET_TILETYPE(tile); + if (t == MP_TUNNELBRIDGE) { + t = _map5[tile]; + if ((t & 0x80) == 0) t>>=1; + if ((t & 6) == 0) { + t = MP_RAILWAY; + } else if ((t & 6) == 2) { + t = MP_STREET; + } else { + t = MP_WATER; + } + } + + return (_map_height_bits[_map_type_and_height[tile] & 0xF] & _smallmap_contours_andor[t][1]) | _smallmap_contours_andor[t][0]; +} + +static void DrawSmallMapContours(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR( dst, GetSmallMapCountoursPixels(TILE_XY(xc,yc)) & mask ); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + + +static uint32 INLINE GetSmallMapVehiclesPixels(uint tile) +{ + uint t; + + t = GET_TILETYPE(tile); + if (t == MP_TUNNELBRIDGE) { + t = _map5[tile]; + if ((t & 0x80) == 0) t>>=1; + if ((t & 6) == 0) { + t = MP_RAILWAY; + } else if ((t & 6) == 2) { + t = MP_STREET; + } else { + t = MP_WATER; + } + } + return (MKCOLOR(0x54545454) & _smallmap_vehicles_andor[t][1]) | _smallmap_vehicles_andor[t][0]; +} + + +static void DrawSmallMapVehicles(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR( dst, GetSmallMapVehiclesPixels(TILE_XY(xc,yc)) & mask ); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + +static const byte _industry_smallmap_colors[175] = { + 215,215,215,215,215,215,215,184, + 184,184,184,194,194,194,194,194, + 86, 86,191,191,191,191,191,191, + 152,152,152,152,152,152,152,152, + 152, 48, 48, 48, 48, 48, 48,174, + 174,174,174,174,174,174,174, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 15, 15, 55, 55, 55, 55, + 10, 10, 10, 10, 10, 10, 10, 10, + 194,194,194,194,194,194,194,194, + 194,194,194,194,194,194,194,194, + 194, 15, 15,184,184,184,184,184, + 184,184,184,184, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 86, 39, 37, 37, + 208,174,174,174,174,194,194,194, + 194, 48, 48,174,174,174,174, 39, + 39, 55,208,208,208,208, 10, 10, + 10, 10, 10, 10, 37, 37, 37, 37, + 37, 37, 37, 37,184,184,184,184, + 152,152,152,152,194,194,194, 15, + 15, 15, 15, 15, 15, 15, 15, +}; + +static uint32 INLINE GetSmallMapIndustriesPixels(uint tile) +{ + int t; + + t = GET_TILETYPE(tile); + if (t == MP_INDUSTRY) { + byte color = _industry_smallmap_colors[_map5[tile]]; + return color + (color << 8) + (color << 16) + (color << 24); + } else { + if (t == MP_TUNNELBRIDGE) { + t = _map5[tile]; + if ((t & 0x80) == 0) t>>=1; + if ((t & 6) == 0) { + t = MP_RAILWAY; + } else if ((t & 6) == 2) { + t = MP_STREET; + } else { + t = MP_WATER; + } + } + return ((MKCOLOR(0x54545454) & _smallmap_vehicles_andor[t][1]) | _smallmap_vehicles_andor[t][0]); + } +} + +static void DrawSmallMapIndustries(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR(dst, GetSmallMapIndustriesPixels(TILE_XY(xc,yc)) & mask); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + +static uint32 INLINE GetSmallMapRoutesPixels(uint tile) +{ + int t; + uint32 bits; + + t = GET_TILETYPE(tile); + if (t == MP_STATION) { + byte m5 = _map5[tile]; + (bits = MKCOLOR(0x56565656), m5 < 8) || // 8 - railroad station (green) + (bits = MKCOLOR(0xB8B8B8B8), m5 < 0x43) || // 67 - airport (red) + (bits = MKCOLOR(0xC2C2C2C2), m5 < 0x47) || // 71 - truck loading bay (orange) + (bits = MKCOLOR(0xBFBFBFBF), m5 < 0x4B) || // 75 - bus station (yellow) + (bits = MKCOLOR(0x98989898), m5 < 0x53) || // 83 - docks (blue) + (bits = MKCOLOR(0xB8B8B8B8), m5 < 0x73) || // 115 - airport (red) (new airports) + (bits = MKCOLOR(0xFFFFFFFF), true); // all others + } else { + if (t == MP_TUNNELBRIDGE) { + t = _map5[tile]; + if ((t & 0x80) == 0) t>>=1; + if ((t & 6) == 0) { + t = MP_RAILWAY; + } else if ((t & 6) == 2) { + t = MP_STREET; + } else { + t = MP_WATER; + } + } + // ground color + bits = ((MKCOLOR(0x54545454) & _smallmap_contours_andor[t][1]) | _smallmap_contours_andor[t][0]); + } + return bits; +} + +static void DrawSmallMapRoutes(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR(dst, GetSmallMapRoutesPixels(TILE_XY(xc,yc)) & mask); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + +static const uint32 _vegetation_clear_bits[4 + 7] = { + MKCOLOR(0x37373737), + MKCOLOR(0x37373737), + MKCOLOR(0x37373737), + MKCOLOR(0x54545454), + + MKCOLOR(0x52525252), + MKCOLOR(0x0A0A0A0A), + MKCOLOR(0x25252525), + MKCOLOR(0x98989898), + MKCOLOR(0xC2C2C2C2), + MKCOLOR(0x54545454), + MKCOLOR(0x54545454), +}; + +static uint32 INLINE GetSmallMapVegetationPixels(uint tile) +{ + int i,t; + uint32 bits; + + t = GET_TILETYPE(tile); + if (t == MP_CLEAR) { + i = (_map5[tile] & 0x1F) - 4; + if (i >= 0) i = (i >> 2); + bits = _vegetation_clear_bits[i + 4]; + } else if (t == MP_INDUSTRY) { + bits = IS_BYTE_INSIDE(_map5[tile], 0x10, 0x12) ? MKCOLOR(0xD0D0D0D0) : MKCOLOR(0xB5B5B5B5); + } else if (t == MP_TREES) { + bits = MKCOLOR(0x54575754); + if ((_map2[tile] & 0x30) == 0x20) + bits = (_opt.landscape == LT_HILLY) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2); + } else { + if (t == MP_TUNNELBRIDGE) { + t = _map5[tile]; + if ((t & 0x80) == 0) t>>=1; + if ((t & 6) == 0) { + t = MP_RAILWAY; + } else if ((t & 6) == 2) { + t = MP_STREET; + } else { + t = MP_WATER; + } + } + bits = ((MKCOLOR(0x54545454) & _smallmap_vehicles_andor[t][1]) | _smallmap_vehicles_andor[t][0]); + } + + return bits; +} + + +static void DrawSmallMapVegetation(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR(dst, GetSmallMapVegetationPixels(TILE_XY(xc,yc)) & mask); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + + +static uint32 *_owner_colors; + +static uint32 INLINE GetSmallMapOwnerPixels(uint tile) +{ + int t; + + t = GET_TILETYPE(tile); + if (t == MP_HOUSE || _map_owner[tile] == OWNER_TOWN) { + t = 0x80; + } else if (t == MP_INDUSTRY) { + t = 0xff; + } else { + t = _map_owner[tile]; + } + + return _owner_colors[t]; +} + + +static void DrawSmallMapOwners(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask) +{ + do { + if (xc < TILE_X_MAX && yc < TILE_Y_MAX) + WRITE_PIXELS_OR(dst, GetSmallMapOwnerPixels(TILE_XY(xc,yc)) & mask); + } while (xc++,yc++,dst+=pitch,--reps != 0); +} + + +static const uint32 _smallmap_mask_left[3] = { + MKCOLOR(0xFF000000), + MKCOLOR(0xFFFF0000), + MKCOLOR(0xFFFFFF00), +}; + +static const uint32 _smallmap_mask_right[4] = { + MKCOLOR(0x00000000), + MKCOLOR(0x000000FF), + MKCOLOR(0x0000FFFF), + MKCOLOR(0x00FFFFFF), +}; + +/* each tile has 4 x pixels and 1 y pixel */ + +typedef void SmallmapDrawProc(byte *dst, uint xc, uint yc, int pitch, int reps, uint32 mask); + +static SmallmapDrawProc *_smallmap_draw_procs[] = { + DrawSmallMapContours, + DrawSmallMapVehicles, + DrawSmallMapIndustries, + DrawSmallMapRoutes, + DrawSmallMapVegetation, + DrawSmallMapOwners, +}; + +static const byte _vehicle_type_colors[6] = { + 184, 191, 152, 15, 215, 184 +}; + +static INLINE uint32 dup_byte32(byte b) { + return b + (b << 8) + (b << 16) + (b << 24); +} + +static void DrawVertMapIndicator(int x, int y, int x2, int y2) +{ + GfxFillRect(x, y, x2, y + 3, 69); + GfxFillRect(x, y2 - 3, x2, y2, 69); +} + +static void DrawHorizMapIndicator(int x, int y, int x2, int y2) +{ + GfxFillRect(x, y, x + 3, y2, 69); + GfxFillRect(x2 - 3, y, x2, y2, 69); +} + +static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_towns) +{ + DrawPixelInfo *old_dpi; + int dx,dy, x, y, x2, y2; + byte *ptr; + uint tile_x, tile_y; + uint32 mask; + int t; + int reps; + SmallmapDrawProc *proc; + ViewPort *vp; + + old_dpi = _cur_dpi; + _cur_dpi = dpi; + + /* clear it */ + GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0); + + /* setup owner table */ + if (type == 5) { + Player *p; + uint32 *tbl; + + /* setup owners ptr */ + _owner_colors = tbl = alloca(256 * sizeof(*_owner_colors)); + + /* clear the town colors */ + memset(tbl + 128, 0xB4, 128 * sizeof(*_owner_colors)); + + /* fill with some special colors */ + tbl[0x10] = MKCOLOR(0x54545454); + tbl[0x11] = MKCOLOR(0xCACACACA); + tbl[0xff] = MKCOLOR(0x20202020); /* industry */ + + /* now fill with the player colors */ + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + tbl[p->index] = dup_byte32(GetSpritePtr(0x307 + p->player_color)[0xCB]); + } + } + } + + tile_x = (int)WP(w,smallmap_d).scroll_x >> 4; + tile_y = (int)WP(w,smallmap_d).scroll_y >> 4; + + dx = dpi->left + WP(w,smallmap_d).subscroll; + tile_x -= (dx >> 2); + tile_y += (dx >> 2); + dx &= 3; + + dy = dpi->top; + tile_x += (dy >> 1); + tile_y += (dy >> 1); + + if (dy & 1) { + tile_x++; + dx += 2; + if (dx > 3) { + dx -= 4; + tile_x--; + tile_y++; + } + } + + proc = _smallmap_draw_procs[type]; + + ptr = dpi->dst_ptr - dx - 4; + x = - dx - 4; + y = 0; + + for(;;) { + mask = (uint32)-1; + + /* distance from left edge */ + if (x < 0) { + if (x < -3) goto skip_column; + /* mask to use at the left edge */ + mask = _smallmap_mask_left[x + 3]; + } + + /* distance from right edge */ + t = dpi->width - x; + if (t < 4) { + if (t < 0) + break; /* exit loop */ + /* mask to use at the right edge */ + mask &= _smallmap_mask_right[t]; + } + + /* number of lines */ + reps = ((dpi->height - y + 1) >> 1); + if (reps > 0) { +// assert(ptr >= dpi->dst_ptr); + proc(ptr, tile_x, tile_y, dpi->pitch*2, reps, mask); + } + +skip_column: + if (y == 0) { + tile_y++; + y++; + ptr += dpi->pitch; + } else { + tile_x--; + y--; + ptr -= dpi->pitch; + } + ptr += 2; + x += 2; + } + + /* draw vehicles? */ + if (type == 0 || type == 1) { + Vehicle *v; + bool skip; + byte color; + + FOR_ALL_VEHICLES(v) { + if (v->type != 0 && v->type != 0x14 && (v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0) { + // Remap into flat coordinates. + Point pt = RemapCoords( + (int)(v->x_pos - WP(w,smallmap_d).scroll_x) >> 4, + (int)(v->y_pos - WP(w,smallmap_d).scroll_y) >> 4, + 0); + x = pt.x; + y = pt.y; + + // Check if y is out of bounds? + y -= dpi->top; + if ((uint)y >= (uint)dpi->height) + continue; + + // Default is to draw both pixels. + skip = false; + + // Offset X coordinate + x -= WP(w,smallmap_d).subscroll + 3 + dpi->left; + + if (x < 0) { + // if x+1 is 0, that means we're on the very left edge, + // and should thus only draw a single pixel + if (++x != 0) + continue; + skip = true; + } else if (x >= dpi->width - 1) { + // Check if we're at the very right edge, and if so draw only a single pixel + if (x != dpi->width - 1) + continue; + skip = true; + } + + // Calculate pointer to pixel and the color + ptr = dpi->dst_ptr + y * dpi->pitch + x; + color = (type == 1) ? _vehicle_type_colors[v->type-0x10] : 0xF; + + // And draw either one or two pixels depending on clipping + ptr[0] = color; + if (!skip) + ptr[1] = color; + } + } + } + + if (show_towns) { + Town *t; + FOR_ALL_TOWNS(t) { + if (t->xy != 0) { + // Remap the town coordinate + Point pt = RemapCoords( + (int)(GET_TILE_X(t->xy)*16 - WP(w,smallmap_d).scroll_x) >> 4, + (int)(GET_TILE_Y(t->xy)*16 - WP(w,smallmap_d).scroll_y) >> 4, + 0); + x = pt.x - WP(w,smallmap_d).subscroll + 3 - (t->sign.width_2 >> 1); + y = pt.y; + + // Check if the town sign is within bounds + if (x + t->sign.width_2 > dpi->left && + x < dpi->left + dpi->width && + y + 6 > dpi->top && + y < dpi->top + dpi->height) { + // And draw it. + SET_DPARAM16(0, t->index); + DrawString(x, y, STR_2056, 12); + } + } + } + } + + // Draw map indicators + { + Point pt; + + // Find main viewport. + vp = FindWindowById(WC_MAIN_WINDOW,0)->viewport; + + pt = RemapCoords( + WP(w,smallmap_d).scroll_x, + WP(w,smallmap_d).scroll_y, + 0); + + x = vp->virtual_left - pt.x; + y = vp->virtual_top - pt.y; + x2 = (x + vp->virtual_width) >> 4; + y2 = (y + vp->virtual_height) >> 4; + x >>= 4; + y >>= 4; + + x -= WP(w,smallmap_d).subscroll; + x2 -= WP(w,smallmap_d).subscroll; + + DrawVertMapIndicator(x, y, x, y2); + DrawVertMapIndicator(x2, y, x2, y2); + + DrawHorizMapIndicator(x, y, x2, y); + DrawHorizMapIndicator(x, y2, x2, y2); + } + _cur_dpi = old_dpi; +} + +static void SmallMapWindowProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + const uint16 *tbl; + int x,y,y_org; + DrawPixelInfo new_dpi; + + + /* draw the window */ + SET_DPARAM16(0, STR_00E5_CONTOURS + _smallmap_type); + DrawWindowWidgets(w); + + /* draw the legend */ + tbl = _legend_table[(_smallmap_type != 2) ? _smallmap_type : (_opt.landscape + IND_OFFS)]; + x = 4; + y_org = w->height - 43; + y = y_org; + while(1) { + GfxFillRect(x, y+1, x+8, y + 5, 0); + GfxFillRect(x+1, y+2, x+7, y + 4, (byte)tbl[0]); + DrawString(x+11, y, tbl[1], 0); + + tbl += 2; + y += 6; + + if (tbl[0] == 0xFFFF) { + break; + } else if (tbl[0] & 0x100) { + x += 123; + y = y_org; + } + } + + if (!FillDrawPixelInfo(&new_dpi, NULL, 3, 17, w->width - 28 + (w->widget == _smallmap_small_widgets ? 0 : 22), w->height - 64)) + return; + + DrawSmallMap(&new_dpi, w, _smallmap_type, _smallmap_show_towns); + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: {/* big/small size */ + // const Widget *wi = w->widget; + DeleteWindow(w); + SndPlayFx(0x13); + { + int i = _smallmap_size + 1; + if (i == 3) i = 0; + DoShowSmallMap(i); + } + } break; + + case 4: {/* main wnd */ + Window *w2; + Point pt; + + _left_button_clicked = false; + + w2 = FindWindowById(WC_MAIN_WINDOW, 0); + + pt = RemapCoords(WP(w,smallmap_d).scroll_x, WP(w,smallmap_d).scroll_y, 0); + WP(w2,vp_d).scrollpos_x = pt.x + ((_cursor.pos.x - w->left + 2) << 4) - (w2->viewport->virtual_width >> 1); + WP(w2,vp_d).scrollpos_y = pt.y + ((_cursor.pos.y - w->top - 16) << 4) - (w2->viewport->virtual_height >> 1); + } break; + + case 5: /* show land contours */ + case 6: /* show vehicles */ + case 7: /* show industries */ + case 8: /* show transport routes */ + case 9: /* show vegetation */ + case 10: /* show land owners */ + w->click_state &= ~(1<<5|1<<6|1<<7|1<<8|1<<9|1<<10); + w->click_state |= 1 << e->click.widget; + _smallmap_type = e->click.widget - 5; + + SetWindowDirty(w); + SndPlayFx(0x13); + break; + + case 11: /* toggle town names */ + w->click_state ^= (1 << 11); + _smallmap_show_towns = (w->click_state >> 11) & 1; + SetWindowDirty(w); + SndPlayFx(0x13); + break; + } + break; + + case WE_RCLICK: + if (e->click.widget == 4) { + if (_scrolling_viewport) + return; + _scrolling_viewport = true; + _cursor.delta.x = 0; + _cursor.delta.y = 0; + } + break; + + case WE_MOUSELOOP: + /* update the window every now and then */ + if ((++w->vscroll.pos & 0x1F) == 0) + SetWindowDirty(w); + break; + } +} + +static const WindowDesc _smallmap_small_desc = { + -1,-1, 248, 212, + WC_SMALLMAP,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _smallmap_small_widgets, + SmallMapWindowProc +}; + +static const WindowDesc _smallmap_big_desc = { + -1,-1, 446, 302, + WC_SMALLMAP,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _smallmap_big_widgets, + SmallMapWindowProc +}; + +static const WindowDesc _smallmap_megabig_desc = { + -1,-1, 607, 452, + WC_SMALLMAP,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _smallmap_megabig_widgets, + SmallMapWindowProc +}; + +static const WindowDesc * const _smallmap_descs[3] = { + &_smallmap_small_desc, + &_smallmap_big_desc, + &_smallmap_megabig_desc +}; + +static void DoShowSmallMap(int big) +{ + Window *w; + ViewPort *vp; + int x,y; + + _smallmap_size = big; + + w = AllocateWindowDescFront(_smallmap_descs[big], 0); + if (w) { + w->click_state = (1<<5) << _smallmap_type | _smallmap_show_towns << 11; + vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport; + + x = (((vp->virtual_width - (big?220*32:110*32)) >> 1) + vp->virtual_left) >> 2; + y = ((((vp->virtual_height- (big?120*32:75*32)) >> 1) + vp->virtual_top) >> 1) - 32; + WP(w,smallmap_d).scroll_x = (y-x) & ~0xF; + WP(w,smallmap_d).scroll_y = (x+y) & ~0xF; + WP(w,smallmap_d).subscroll = 0; + } +} + +void ShowSmallMap() +{ + DoShowSmallMap(_smallmap_size); +} diff --git a/sound.c b/sound.c new file mode 100644 --- /dev/null +++ b/sound.c @@ -0,0 +1,341 @@ +#include "stdafx.h" +#include "ttd.h" +#include "sound.h" +#include "vehicle.h" +#include "window.h" +#include "viewport.h" +#include "fileio.h" + +typedef struct { + // Mixer + Mixer *mx; + bool active; + + // pointer to allocated buffer memory + void *memory; + + // current position in memory + uint32 pos; + uint32 frac_pos; + uint32 frac_speed; + uint32 samples_left; + + // Mixing volume + uint volume_left; + uint volume_right; + + uint flags; +} MixerChannel; + +typedef struct FileEntry FileEntry; +struct FileEntry { + uint32 file_offset; + uint32 file_size; + uint16 rate; + uint8 bits_per_sample; + uint8 channels; +}; + +struct Mixer { + uint32 play_rate; + FileEntry *files; + uint32 file_count; + MixerChannel channels[8]; +}; + +enum { + MX_AUTOFREE = 1, +// MX_8BIT = 2, +// MX_STEREO = 4, + MX_UNSIGNED = 8, +}; + +#define SOUND_SLOT 31 + + +FILE *out; + +static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples) +{ + int8 *b; + uint32 frac_pos; + uint32 frac_speed; + uint volume_left; + uint volume_right; + + if (samples > sc->samples_left) samples = sc->samples_left; + sc->samples_left -= samples; + assert(samples > 0); + + b = (int8*)sc->memory + sc->pos; + frac_pos = sc->frac_pos; + frac_speed = sc->frac_speed; + volume_left = sc->volume_left; + volume_right = sc->volume_right; + + if (frac_speed == 0x10000) { + // Special case when frac_speed is 0x10000 + do { + buffer[0]+= *b * volume_left >> 8; + buffer[1]+= *b * volume_right >> 8; + b++; + buffer += 2; + } while (--samples); + } else { + do { + buffer[0] += *b * volume_left >> 8; + buffer[1] += *b * volume_right >> 8; + buffer += 2; + frac_pos += frac_speed; + b += frac_pos >> 16; + frac_pos &= 0xffff; + } while (--samples); + } + + sc->frac_pos = frac_pos; + sc->pos = b - (int8*)sc->memory; +} + +static void MxCloseChannel(MixerChannel *mc) +{ + void *mem = mc->memory; + mc->memory = NULL; + mc->active = false; + + if (mc->flags & MX_AUTOFREE) + free(mem); +} + +void MxMixSamples(Mixer *mx, void *buffer, uint samples) +{ + int i; + MixerChannel *mc; + + // Clear the buffer + memset(buffer, 0, sizeof(int16)*2*samples); + + // Mix each channel + for(i=0,mc=mx->channels; i!=lengthof(mx->channels); i++,mc++) { + if (mc->active) { + mix_int8_to_int16(mc, (int16*)buffer, samples); + if (mc->samples_left == 0) { + MxCloseChannel(mc); + } + } + } + +// if (out == NULL) +// out = fopen("d:\\dump.raw", "wb"); +// fwrite(buffer, samples*4, 1, out); +} + +static MixerChannel *MxAllocateChannel(Mixer *mx) +{ + int i; + MixerChannel *mc; + for(i=0,mc=mx->channels; i!=lengthof(mx->channels); i++,mc++) + if (!mc->memory) { + mc->active = false; + mc->mx = mx; + return mc; + } + return NULL; +} + +static void MxSetChannelRawSrc(MixerChannel *mc, void *mem, uint size, uint rate, uint flags) +{ + mc->memory = mem; + mc->flags = flags; + mc->frac_pos = 0; + mc->pos = 0; + + mc->frac_speed = (rate<<16) / mc->mx->play_rate; + + // adjust the magnitude to prevent overflow + while (size & 0xFFFF0000) + size >>= 1, rate = (rate >> 1) + 1; + + mc->samples_left = size * mc->mx->play_rate / rate; +} + +static void MxSetChannelVolume(MixerChannel *mc, uint left, uint right) +{ + mc->volume_left = left; + mc->volume_right = right; +} + +static void MxOpenBankFile(Mixer *mx, const char *filename) +{ + uint count, i; + uint32 size, tag; + FileEntry *fe; + + FioOpenFile(SOUND_SLOT, filename); + mx->file_count = count = FioReadDword() >> 3; + fe = mx->files = calloc(sizeof(FileEntry), count); + + FioSeekTo(0, SEEK_SET); + + for(i=0; i!=count; i++,fe++) { + fe->file_offset = FioReadDword(); + fe->file_size = FioReadDword(); + } + + fe = mx->files; + for(i=0; i!=count; i++,fe++) { + FioSeekTo(fe->file_offset, SEEK_SET); + // Skip past string and the name. + FioSeekTo(FioReadByte() + 12, SEEK_CUR); + + // Read riff tags + while(true) { + tag = FioReadDword(); + size = FioReadDword(); + + if (tag == ' tmf') { + FioReadWord(); // wFormatTag + fe->channels = FioReadWord(); // wChannels + FioReadDword(); // samples per second + fe->rate = 11025; // seems like all samples should be played at this rate. + FioReadDword(); // avg bytes per second + FioReadWord(); // alignment + fe->bits_per_sample = FioReadByte(); // bits per sample + FioSeekTo(size - (2+2+4+4+2+1), SEEK_CUR); + } else if (tag == 'atad') { + fe->file_size = size; + fe->file_offset = FioGetPos() | (SOUND_SLOT << 24); + break; + } else { + fe->file_size = 0; + break; + } + } + } +} + +static bool MxSetBankSource(MixerChannel *mc, uint bank) +{ + FileEntry *fe = &mc->mx->files[bank]; + void *mem; + uint i; + + if (fe->file_size == 0) + return false; + + mem = malloc(fe->file_size); + FioSeekToFile(fe->file_offset); + FioReadBlock(mem, fe->file_size); + + for(i=0; i!=fe->file_size; i++) { + ((byte*)mem)[i] ^= 0x80; + } + + assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0); + + MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE | MX_UNSIGNED); + + return true; +} + +bool MxInitialize(uint rate, const char *filename) +{ + static Mixer mx; + _mixer = &mx; + mx.play_rate = rate; + MxOpenBankFile(&mx, filename); + return true; +} + +// Low level sound player +static void StartSound(uint sound, uint panning, uint volume) +{ + if (volume != 0) { + MixerChannel *mc = MxAllocateChannel(_mixer); + if (mc == NULL) + return; + if (MxSetBankSource(mc, sound)) { + MxSetChannelVolume(mc, volume << 8, volume << 8); + mc->active = true; + } + } +} + + +static const byte _vol_factor_by_zoom[] = {255, 190, 134}; + +static const byte _sound_base_vol[] = { + 128, 90, 128, 128, 128, 128, 128, 128, + 128, 90, 90, 128, 128, 128, 128, 128, + 128, 128, 128, 80, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 90, 90, 90, 128, 90, 128, + 128, 90, 128, 128, 128, 90, 128, 128, + 128, 128, 128, 128, 90, 128, 128, 128, + 128, 90, 128, 128, 128, 128, 128, 128, + 128, 128, 90, 90, 90, 128, 128, 128, + 90, +}; + +static const byte _sound_idx[] = { + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 0, + 1, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, +}; + +void SndPlayScreenCoordFx(int sound, int x, int y) +{ + Window *w; + ViewPort *vp; + int left; + + if (msf.effect_vol == 0) + return; + + for(w=_windows; w!=_last_window; w++) { + if ((vp=w->viewport) && + IS_INSIDE_1D(x, vp->virtual_left, vp->virtual_width) && + IS_INSIDE_1D(y, vp->virtual_top, vp->virtual_height)) { + + left = ((x - vp->virtual_left) >> vp->zoom) + vp->left; + StartSound( + _sound_idx[sound], + clamp(left / 71, 0, 8), + (_sound_base_vol[sound] * msf.effect_vol * _vol_factor_by_zoom[vp->zoom]) >> 15 + ); + return; + } + } + +} + +void SndPlayTileFx(int sound, TileIndex tile) +{ + int x = GET_TILE_X(tile)*16; + int y = GET_TILE_Y(tile)*16; + Point pt = RemapCoords(x,y, GetSlopeZ(x+8, y+8)); + SndPlayScreenCoordFx(sound, pt.x, pt.y); +} + +void SndPlayVehicleFx(int sound, Vehicle *v) +{ + SndPlayScreenCoordFx(sound, + (v->left_coord + v->right_coord) >> 1, + (v->top_coord + v->bottom_coord) >> 1 + ); +} + +void SndPlayFx(int sound) +{ + StartSound( + _sound_idx[sound], + 4, + (_sound_base_vol[sound] * msf.effect_vol) >> 7 + ); +} diff --git a/sound.h b/sound.h new file mode 100644 --- /dev/null +++ b/sound.h @@ -0,0 +1,25 @@ +#ifndef SOUND_H +#define SOUND_H + +typedef struct Mixer Mixer; + +typedef struct MusicFileSettings { + byte playlist; + byte music_vol; + byte effect_vol; + byte custom_1[33]; + byte custom_2[33]; + bool btn_down; + bool shuffle; +} MusicFileSettings; + +VARDEF byte _music_wnd_cursong; +VARDEF bool _song_is_active; +VARDEF byte _cur_playlist[33]; +VARDEF MusicFileSettings msf; +VARDEF Mixer *_mixer; + +bool MxInitialize(uint rate, const char *filename); +void MxMixSamples(Mixer *mx, void *buffer, uint samples); + +#endif /* SOUND_H */ diff --git a/spritecache.c b/spritecache.c new file mode 100644 --- /dev/null +++ b/spritecache.c @@ -0,0 +1,766 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gfx.h" +#include "fileio.h" +#include + +#define SPRITECACHE_ID 0xF00F0006 +#define SPRITE_CACHE_SIZE 1024*1024 + + +//#define WANT_SPRITESIZES +#define WANT_NEW_LRU +//#define WANT_LOCKED + + +int _skip_sprites = 0; + +static const char *_cur_grffile; +static int _skip_specials; +static SpriteHdr _cur_sprite; + +static byte *_sprite_ptr[NUM_SPRITES]; +static uint16 _sprite_size[NUM_SPRITES]; +static uint32 _sprite_file_pos[NUM_SPRITES]; + +// This one is probably not needed. +#if defined(WANT_LOCKED) +static bool _sprite_locked[NUM_SPRITES]; +#endif + +#if defined(WANT_NEW_LRU) +static int16 _sprite_lru_new[NUM_SPRITES]; +#else +static uint16 _sprite_lru[NUM_SPRITES]; +static uint16 _sprite_lru_cur[NUM_SPRITES]; +#endif + +#ifdef WANT_SPRITESIZES +static int8 _sprite_xoffs[NUM_SPRITES]; +static int8 _sprite_yoffs[NUM_SPRITES]; +static uint16 _sprite_xsize[NUM_SPRITES]; +static uint8 _sprite_ysize[NUM_SPRITES]; +#endif + +static uint _sprite_lru_counter; +static byte *_spritecache_ptr; +static uint32 _spritecache_size; +static int _compact_cache_counter; + + +static const char * const _filename_list[] = { + "TRG1R.GRF", + "TRGIR.GRF", + "signalsw.grf", //0x1320 - 0x1405 inclusive +// "openttd.grf", //0x1406 - + NULL +}; + +static const char * const _landscape_filenames[] = { + "TRGCR.GRF", + "TRGHR.GRF", + "TRGTR.GRF" +}; + + +#include "table/landscape_sprite.h" + +static const uint16 * const _landscape_spriteindexes[] = { + _landscape_spriteindexes_1, + _landscape_spriteindexes_2, + _landscape_spriteindexes_3, +}; + +static void CompactSpriteCache(); + +void DecodeSpecialSprite(const char *filename, int num, int load_index); + +static void ReadSpriteHeaderSkipData(int num, int load_index) +{ + byte type; + int8 i; + int deaf = 0; + + if (_skip_sprites) { + if (_skip_sprites > 0) + _skip_sprites--; + deaf = 1; + } + + type = FioReadByte(); + if (type == 0xFF) { + /* We need to really skip only special sprites in the deaf + * mode. It won't hurt to proceed regular sprites as usual + * because if no special sprite referencing to them is + * processed, they themselves are never referenced and loaded + * on their own. */ + if (_skip_specials || deaf) { + FioSkipBytes(num); + } else { + DecodeSpecialSprite(_cur_grffile, num, load_index); + } + return; + } + + _cur_sprite.info = type; +#ifdef WANT_SPRITESIZES + _cur_sprite.height = FioReadByte(); + _cur_sprite.width = FioReadWord(); + _cur_sprite.x_offs = FioReadWord(); + _cur_sprite.y_offs = FioReadWord(); +#else + FioSkipBytes(7); +#endif + num -= 8; + if (num == 0) + return; + + if (type & 2) { + FioSkipBytes(num); + return; + } + + while (num) { + i = FioReadByte(); + if (i>=0) { + num -= i; + FioSkipBytes(i); + } else { + i = -(i >> 3); + num -= i; + FioReadByte(); + } + } +} + +static void ReadSprite(int num, byte *dest) +{ + byte type; + byte *rel; + int8 i; + int j, dist; + + type = FioReadByte(); + /* We've decoded special sprites when reading headers. */ + if (type != 0xFF) { + /* read sprite hdr */ + *dest++ = type; + for(j=0; j!=7; j++) + *dest++ = FioReadByte(); + num -= 8; + } + + if (type & 2) { + while (num--) + *dest++ = FioReadByte(); + return; + } + + while (num) { + i = FioReadByte(); + if (i>=0) { + num -= i; + while (i--) + *dest++ = FioReadByte(); + } else { + dist = -(((i&7)<<8)|FioReadByte()); + i = -(i >> 3); + num -= i; + + rel = &dest[dist]; + while (i--) + *dest++ = *rel++; + } + } +} + + +static bool LoadNextSprite(int load_index, byte file_index) +{ + uint16 size; + + if ( (size = FioReadWord()) == 0) + return false; + + _sprite_size[load_index] = size; + _sprite_file_pos[load_index] = FioGetPos() | (file_index << 24); + + ReadSpriteHeaderSkipData(size, load_index); + +#ifdef WANT_SPRITESIZES + _sprite_xsize[load_index] = _cur_sprite.width; + _sprite_ysize[load_index] = _cur_sprite.height; + + _sprite_xoffs[load_index] = _cur_sprite.x_offs; + _sprite_yoffs[load_index] = _cur_sprite.y_offs; +#endif + + _sprite_ptr[load_index] = NULL; +#if defined(WANT_LOCKED) + _sprite_locked[load_index] = false; +#endif + +#if defined(WANT_NEW_LRU) + _sprite_lru_new[load_index] = 0; +#else + _sprite_lru[load_index] = 0xFFFF; + _sprite_lru_cur[load_index] = 0; +#endif + + return true; +} + +// Checks, if trg1r.grf is the Windows version +static bool CheckGrfFile() +{ + byte check; + FioSeekToFile(38); // Byte 38 has the value 0x21 in Windows version, 0x07 in DOS + check = FioReadWord(); + FioSeekToFile(0); + return (check==0x21); +} + +static int LoadGrfFile(const char *filename, int load_index, int file_index) +{ + int load_index_org = load_index; + + FioOpenFile(file_index, filename); + _cur_grffile = filename; + _skip_specials = !strncmp(filename, "TRG", 3); + + if(file_index==0 && !_ignore_wrong_grf) + if(!CheckGrfFile()) + error("Wrong version of grf files!\nThe Windows 95 edition of Transport Tycoon Deluxe is required to play OTTD!\n(you can disable this message by starting with the \"-i\" switch."); + + while (LoadNextSprite(load_index, file_index)) { + load_index++; + if (load_index >= NUM_SPRITES) { + error("Too many sprites. Recompile with higher NUM_SPRITES value or remove some custom GRF files."); + } + } + + _skip_sprites = 0; // clean up + + return load_index - load_index_org; +} + +static void LoadGrfIndexed(const char *filename, const uint16 *index_tbl, int file_index) +{ + int start, end; + + FioOpenFile(file_index, filename); + + for(;(start=*index_tbl++) != 0xffff;) { + end = *index_tbl++; + do { + bool b = LoadNextSprite(start, file_index); + assert(b); + } while (++start <= end); + } +} + +typedef size_t CDECL fread_t(void*,size_t,size_t,FILE*); + +static bool HandleCachedSpriteHeaders(const char *filename, bool read) +{ + FILE *f; + fread_t *proc; + uint32 hdr; + + if (!_cache_sprites) + return false; + + if (read) { + f = fopen(filename, "rb"); + proc = fread; + + if (f == NULL) + return false; + + proc(&hdr, sizeof(hdr), 1, f); + if (hdr != SPRITECACHE_ID) { + fclose(f); + return false; + } + } else { + f = fopen(filename, "wb"); + proc = (fread_t*) fwrite; + + if (f == NULL) + return false; + + hdr = SPRITECACHE_ID; + proc(&hdr, sizeof(hdr), 1, f); + } + + proc(_sprite_size, 1, sizeof(_sprite_size), f); + proc(_sprite_file_pos, 1, sizeof(_sprite_file_pos), f); + +#if 0 + proc(_sprite_xsize, 1, sizeof(_sprite_xsize), f); + proc(_sprite_ysize, 1, sizeof(_sprite_ysize), f); + proc(_sprite_xoffs, 1, sizeof(_sprite_xoffs), f); + proc(_sprite_yoffs, 1, sizeof(_sprite_yoffs), f); +#endif + +#if !defined(WANT_NEW_LRU) + if (read) + memset(_sprite_lru, 0xFF, sizeof(_sprite_lru)); +#endif + + fclose(f); + return true; +} + +#define S_DATA(x) (*(uint32*)(x)) +#define S_FREE_MASK 1 +#define S_HDRSIZE sizeof(uint32) + +static uint32 GetSpriteCacheUsage() +{ + byte *s = _spritecache_ptr; + size_t cur_size, tot_size = 0; + for(; (cur_size=S_DATA(s)) != 0; s+=cur_size) { + if ( cur_size & S_FREE_MASK ) { + cur_size--; + } else { + tot_size += cur_size; + } + } + + return tot_size; +} + + +void IncreaseSpriteLRU() +{ + int i; + + // Increase all LRU values +#if defined(WANT_NEW_LRU) + if (_sprite_lru_counter > 16384) { + DEBUG(spritecache, 2) ("fixing lru %d, inuse=%d", _sprite_lru_counter, GetSpriteCacheUsage()); + + for(i=0; i!=NUM_SPRITES; i++) + if (_sprite_ptr[i] != NULL) { + if (_sprite_lru_new[i] >= 0) { + _sprite_lru_new[i] = -1; + } else if (_sprite_lru_new[i] != -32768) { + _sprite_lru_new[i]--; + } + } + _sprite_lru_counter = 0; + } +#else + for(i=0; i!=NUM_SPRITES; i++) + if (_sprite_ptr[i] != NULL && _sprite_lru[i] != 65535) + _sprite_lru[i]++; + // Reset the lru counter. + _sprite_lru_counter = 0; +#endif + + // Compact sprite cache every now and then. + if (++_compact_cache_counter >= 740) { + CompactSpriteCache(); + _compact_cache_counter = 0; + } +} + +// Called when holes in the sprite cache should be removed. +// That is accomplished by moving the cached data. +static void CompactSpriteCache() +{ + byte *s, *t; + size_t size, sizeb, cur_size; + int i; + + DEBUG(spritecache, 2) ("compacting sprite cache, inuse=%d", GetSpriteCacheUsage()); + + s = _spritecache_ptr; + + while (true) { + size = S_DATA(s); + + // Only look for free blocks. + if (size & S_FREE_MASK) { + size -= S_FREE_MASK; + // Since free blocks are automatically coalesced, this should hold true. + assert(!(S_DATA(s+size) & S_FREE_MASK)); + + // If the next block is the sentinel block, we can safely return + if ( (sizeb=S_DATA(s + size)) == 0) + break; + + // Locate the sprite number belonging to the next pointer. + for(i=0,t=s+size+S_HDRSIZE; _sprite_ptr[i] != t; i++) {assert(i < NUM_SPRITES);} + + // If it's locked, we must not move it. +#if defined(WANT_LOCKED) + if (!_sprite_locked[i]) { +#endif + + // Offset the sprite pointer by the size of the free block + _sprite_ptr[i] -= size; + + // Move the memory + memcpy_overlapping(s+S_HDRSIZE, s+S_HDRSIZE+size, sizeb - S_HDRSIZE ); + + // What we just did had the effect of swapping the allocated block with the free block, so we need to update + // the block pointers. First update the allocated one. It is in use. + S_DATA(s) = sizeb; + + // Then coalesce the free ones that follow. + s += sizeb; + while ((cur_size = S_DATA(s+size)) & S_FREE_MASK) + size += cur_size - S_FREE_MASK; + S_DATA(s) = size + S_FREE_MASK; + continue; +#if defined(WANT_LOCKED) + } +#endif + } + // Continue with next block until the sentinel is reached. + s += size; + if (size == 0) + break; + } +} + +static void DeleteEntryFromSpriteCache() +{ + int i; + int best = -1; + byte *s; + size_t cur_size, cur; + int cur_lru; + + DEBUG(spritecache, 2) ("DeleteEntryFromSpriteCache, inuse=%d", GetSpriteCacheUsage()); + +#if defined(WANT_NEW_LRU) + cur_lru = 0xffff; + for(i=0; i!=NUM_SPRITES; i++) { + if (_sprite_ptr[i] != 0 && + _sprite_lru_new[i] < cur_lru +#if defined(WANT_LOCKED) + && !_sprite_locked[i]) { +#else + ) { +#endif + cur_lru = _sprite_lru_new[i]; + best = i; + } + } +#else + { + uint16 cur_lru = 0, cur_lru_cur = 0xffff; + for(i=0; i!=NUM_SPRITES; i++) { + if (_sprite_ptr[i] == 0 || +#if defined(WANT_LOCKED) + _sprite_locked[i] || +#endif + _sprite_lru[i] < cur_lru) + continue; + + // Found a sprite with a higher LRU value, then remember it. + if (_sprite_lru[i] != cur_lru) { + cur_lru = _sprite_lru[i]; + best = i; + + // Else if both sprites were very recently referenced, compare by the cur value instead. + } else if (cur_lru == 0 && _sprite_lru_cur[i] <= cur_lru_cur) { + cur_lru_cur = _sprite_lru_cur[i]; + cur_lru = _sprite_lru[i]; + best = i; + } + } + } +#endif + + // Display an error message and die, in case we found no sprite at all. + // This shouldn't really happen, unless all sprites are locked. + if (best == -1) + error("Out of sprite memory"); + + // Mark the block as free (the block must be in use) + s = _sprite_ptr[best]; + assert(!(S_DATA(s - S_HDRSIZE) & S_FREE_MASK)); + S_DATA(s - S_HDRSIZE) += S_FREE_MASK; + _sprite_ptr[best] = NULL; + + // And coalesce adjacent free blocks + s = _spritecache_ptr; + for(; (cur_size=S_DATA(s)) != 0; s+=cur_size) { + if ( cur_size & S_FREE_MASK ) { + while ((cur=S_DATA(s+cur_size-S_FREE_MASK)) & S_FREE_MASK) { + cur_size += cur - S_FREE_MASK; + S_DATA(s) = cur_size; + } + cur_size--; + } + } +} + +static byte *LoadSpriteToMem(int sprite) +{ + byte *s; + size_t mem_req, cur_size; + + DEBUG(spritecache, 9) ("load sprite %d", sprite); + +restart: + // Number of needed bytes + mem_req = _sprite_size[sprite] + S_HDRSIZE; + + // Align this to an uint32 boundary. This also makes sure that the 2 least bit are not used, + // so we could use those for other things. + mem_req = (mem_req + sizeof(uint32) - 1) & ~(sizeof(uint32) - 1); + + s = _spritecache_ptr; + for(;;) { + for(;;) { + cur_size = S_DATA(s); + if (! (cur_size & S_FREE_MASK) ) break; + + cur_size -= S_FREE_MASK; + + // Now s points at a free block. + // The block is exactly the size we need? + if (cur_size != mem_req) { + + // No.. is it too small? + if (cur_size < mem_req + S_HDRSIZE) + break; + + // Block was big enough, and we need to inject a free block too. + S_DATA(s + mem_req) = cur_size - mem_req + S_FREE_MASK; + + } + // Set size and in use + S_DATA(s) = mem_req; + + _sprite_ptr[sprite] = (s += S_HDRSIZE); + + FioSeekToFile(_sprite_file_pos[sprite]); + ReadSprite(_sprite_size[sprite], s); + + // Patch the height to compensate for a TTD bug? + if (sprite == 142) { s[1] = 10; } + + // Return sprite ptr + return s; + } + + // Reached sentinel, but no block found yet. Need to delete some old entries. + if (cur_size == 0) { + DeleteEntryFromSpriteCache(); + goto restart; + } + + s += cur_size; + } +} + +#if defined(NEW_ROTATION) +#define X15(x) else if (s >= x && s < (x+15)) { s = _rotate_tile_sprite[s - x] + x; } +#define X19(x) else if (s >= x && s < (x+19)) { s = _rotate_tile_sprite[s - x] + x; } +#define MAP(from,to,map) else if (s >= from && s <= to) { s = map[s - from] + from; } + + +uint RotateSprite(uint s) +{ + static const byte _rotate_tile_sprite[19] = { 0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,17,18,16,15 }; + static const byte _coast_map[9] = {0, 4, 3, 1, 2, 6, 8, 5, 7}; + static const byte _fence_map[6] = {1, 0, 5, 4, 3, 2}; + + if (0); + X19(752) + X15(990-1) + X19(3924) + X19(3943) + X19(3962) + X19(3981) + X19(4000) + X19(4023) + X19(4042) + MAP(4061,4069,_coast_map) + X19(4126) + X19(4145) + X19(4164) + X19(4183) + X19(4202) + X19(4221) + X19(4240) + X19(4259) + X19(4259) + X19(4278) + MAP(4090, 4095, _fence_map) + MAP(4096, 4101, _fence_map) + MAP(4102, 4107, _fence_map) + MAP(4108, 4113, _fence_map) + MAP(4114, 4119, _fence_map) + MAP(4120, 4125, _fence_map) + return s; +} +#endif + +byte *GetSpritePtr(uint sprite) +{ + byte *p; + + assert(sprite < NUM_SPRITES); + +#if defined(NEW_ROTATION) + sprite = RotateSprite(sprite); +#endif + + // Update LRU +#if defined(WANT_NEW_LRU) + _sprite_lru_new[sprite] = ++_sprite_lru_counter; +#else + _sprite_lru_cur[sprite] = ++_sprite_lru_counter; + _sprite_lru[sprite] = 0; +#endif + + // Check if the sprite is loaded already? + p = _sprite_ptr[sprite]; + if (p == NULL) + p = LoadSpriteToMem(sprite); // No, need to load it. + return p; +} + +byte _sprite_page_to_load = 0xFF; + +static const char * const _cached_filenames[4] = { + "cached_sprites.xxx", + "cached_sprites.xx1", + "cached_sprites.xx2", + "cached_sprites.xx3", +}; + +static const uint16 _openttd_grf_indexes[] = { + SPR_OPENTTD_BASE+0, SPR_OPENTTD_BASE+7, // icons etc + 98,98, // euro symbol medium size + 546,546, // euro symbol large size + SPR_OPENTTD_BASE+10, SPR_OPENTTD_BASE+57, // more icons + 648, 648, // nordic char: æ + 616, 616, // nordic char: Æ + 666, 666, // nordic char: Ø + 634, 634, // nordic char: Ø + SPR_OPENTTD_BASE+62, SPR_OPENTTD_BASE+70, // more icons + 0xffff, +}; + +static void LoadSpriteTables() +{ + int i,j; + + /* load initial sprites */ + if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) { + + int load_index = 0; + for(i=0; _filename_list[i] != NULL; i++) { + load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i); + } + + LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++); + + { + int l; + if ((l=_sprite_page_to_load) != 0) + LoadGrfIndexed(_landscape_filenames[l-1], _landscape_spriteindexes[l-1], i++); + } + + load_index = SPR_CANALS_BASE; + load_index += LoadGrfFile("canalsw.grf", load_index, i++); + /* XXX: Only for debugging. Will be more generic. */ + + for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) + load_index += LoadGrfFile(_newgrf_files[j], load_index, i++); + +// load_index += LoadGrfFile("arcticseto.grf", load_index, i++); +// load_index += LoadGrfFile("tempsetpo.grf", load_index, i++); +// load_index += LoadGrfFile("newshipso.grf", load_index, i++); + //load_index += LoadGrfFile("brseto.grf", load_index, i++); + + HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false); + } else { + for(i=0; _filename_list[i] != NULL; i++) + FioOpenFile(i,_filename_list[i]); + + FioOpenFile(i, "openttd.grf"); + FioOpenFile(i+1, "canalsw.grf"); + + if (_sprite_page_to_load != 0) + FioOpenFile(i+2, _landscape_filenames[_sprite_page_to_load-1]); + } + + _compact_cache_counter = 0; +} + +void GfxInitSpriteMem(byte *ptr, uint32 size) +{ + // initialize sprite cache heap + _spritecache_ptr = ptr; + _spritecache_size = size; + + // Sentinel block (identified by size=0) + S_DATA(ptr + size - S_HDRSIZE) = 0; + // A big free block + S_DATA(ptr) = size - S_HDRSIZE + S_FREE_MASK; + + memset(_sprite_ptr, 0, sizeof(_sprite_ptr)); +} + + +void GfxLoadSprites() { + static byte *_sprite_mem; + + // Need to reload the sprites only if the landscape changed + if (_sprite_page_to_load != _opt.landscape) { + _sprite_page_to_load = _opt.landscape; + + // Sprite cache + DEBUG(spritecache, 1) ("Loading sprite set %d.", _sprite_page_to_load); + + // Reuse existing memory? + if (_sprite_mem == NULL) _sprite_mem = malloc(SPRITE_CACHE_SIZE); + GfxInitSpriteMem(_sprite_mem, SPRITE_CACHE_SIZE); + LoadSpriteTables(); + GfxInitPalettes(); + } +} + + +const SpriteDimension *GetSpriteDimension(uint sprite) +{ + static SpriteDimension sd_static; + SpriteDimension *sd; + +#ifndef WANT_SPRITESIZES + byte *p; + + p = _sprite_ptr[sprite]; + if (p == NULL) + p = GetSpritePtr(sprite); + + /* decode sprite header */ + sd = &sd_static; + sd->xoffs = (int16)READ_LE_UINT16(&((SpriteHdr*)p)->x_offs); + sd->yoffs = (int16)READ_LE_UINT16(&((SpriteHdr*)p)->y_offs); + sd->xsize = READ_LE_UINT16(&((SpriteHdr*)p)->width); + sd->ysize = ((SpriteHdr*)p)->height; +#else + sd = &sd_static; + sd->xoffs = _sprite_xoffs[sprite]; + sd->yoffs = _sprite_yoffs[sprite]; + sd->xsize = _sprite_xsize[sprite]; + sd->ysize = _sprite_ysize[sprite]; +#endif +/* sd->xoffs = _sprite_xoffs[sprite]; + sd->yoffs = _sprite_yoffs[sprite]; + sd->xsize = _sprite_xsize[sprite]; + sd->ysize = _sprite_ysize[sprite]; +*/ + return sd; +} + diff --git a/station.h b/station.h new file mode 100644 --- /dev/null +++ b/station.h @@ -0,0 +1,89 @@ +#ifndef STATION_H +#define STATION_H + +#include "vehicle.h" + +typedef struct GoodsEntry { + uint16 waiting_acceptance; + byte days_since_pickup; + byte rating; + byte enroute_from; + byte enroute_time; + byte last_speed; + byte last_age; +} GoodsEntry; + +struct Station { + TileIndex xy; + TileIndex bus_tile; + TileIndex lorry_tile; + TileIndex train_tile; + TileIndex airport_tile; + TileIndex dock_tile; + Town *town; + // alpha_order is obsolete since savegame format 4 + byte alpha_order_obsolete; + uint16 string_id; + + ViewportSign sign; + + uint16 had_vehicle_of_type; + + byte time_since_load; + byte time_since_unload; + byte delete_ctr; + byte owner; + byte facilities; + byte airport_type; + byte truck_stop_status; + byte bus_stop_status; + byte blocked_months; + + // trainstation width/height + byte trainst_w, trainst_h; + + byte stat_id, class_id; + uint16 build_date; + + //uint16 airport_flags; + uint32 airport_flags; + uint16 index; + + VehicleID last_vehicle; + GoodsEntry goods[NUM_CARGO]; +}; + +enum { + FACIL_TRAIN = 1, + FACIL_TRUCK_STOP = 2, + FACIL_BUS_STOP = 4, + FACIL_AIRPORT = 8, + FACIL_DOCK = 0x10, +}; + +enum { +// HVOT_PENDING_DELETE = 1<<0, // not needed anymore + HVOT_TRAIN = 1<<1, + HVOT_BUS = 1 << 2, + HVOT_TRUCK = 1 << 3, + HVOT_AIRCRAFT = 1<<4, + HVOT_SHIP = 1 << 5, + HVOT_BUOY = 1 << 6 +}; + +void ModifyStationRatingAround(TileIndex tile, byte owner, int amount, uint radius); + +void ShowStationViewWindow(int station); +void UpdateAllStationVirtCoord(); + +VARDEF Station _stations[250]; +VARDEF bool _station_sort_dirty; + +#define DEREF_STATION(i) (&_stations[i]) +#define FOR_ALL_STATIONS(st) for(st=_stations; st != endof(_stations); st++) + + +void GetProductionAroundTiles(uint *produced, uint tile, int w, int h); +void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h); +uint GetStationPlatforms(Station *st, uint tile); +#endif /* STATION_H */ diff --git a/station_cmd.c b/station_cmd.c new file mode 100644 --- /dev/null +++ b/station_cmd.c @@ -0,0 +1,2546 @@ +#include "stdafx.h" +#include "ttd.h" +#include "station.h" +#include "gfx.h" +#include "window.h" +#include "viewport.h" +#include "command.h" +#include "town.h" +#include "vehicle.h" +#include "news.h" +#include "saveload.h" +#include "economy.h" +#include "player.h" +#include "airport.h" + +// FIXME -- need to be embedded into Airport variable. Is dynamically +// deducteable from graphics-tile array, so will not be needed +const byte _airport_size_x[5] = {4, 6, 1, 6, 7 }; +const byte _airport_size_y[5] = {3, 6, 1, 6, 7 }; + +void ShowAircraftDepotWindow(uint tile); +extern void UpdateAirplanesOnNewStation(Station *st); + +static void MarkStationDirty(Station *st) +{ + if (st->sign.width_1 != 0) { + InvalidateWindowWidget(WC_STATION_VIEW, st->index, 1); + + MarkAllViewportsDirty( + st->sign.left - 6, + st->sign.top, + st->sign.left + (st->sign.width_1 << 2) + 12, + st->sign.top + 48); + } +} + +#define CHECK_STATIONS_ERR ((Station*)-1) + +static Station *GetStationAround(uint tile, int w, int h, int closest_station) +{ + // check around to see if there's any stations there + BEGIN_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TILE_XY(1,1)) + if (IS_TILETYPE(tile_cur, MP_STATION)) { + int t; + t = _map2[tile_cur]; + if (closest_station == -1) { + closest_station = t; + } else if (closest_station != t) { + _error_message = STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING; + return CHECK_STATIONS_ERR; + } + } + END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TILE_XY(1,1)) + return (closest_station == -1) ? NULL : DEREF_STATION(closest_station); +} + + +static bool CheckStationSpreadOut(Station *st, uint tile, int w, int h) +{ + byte station_index = st->index; + uint i; + uint x1 = GET_TILE_X(tile); + uint y1 = GET_TILE_Y(tile); + uint x2 = x1 + w - 1; + uint y2 = y1 + h - 1; + uint t; + + for(i=0; i!=TILES_X*TILES_Y; i++) { + if (IS_TILETYPE(i, MP_STATION) && _map2[i] == station_index) { + t = GET_TILE_X(i); + if (t < x1) x1 = t; + if (t > x2) x2 = t; + + t = GET_TILE_Y(i); + if (t < y1) y1 = t; + if (t > y2) y2 = t; + } + } + + if (y2-y1 >= _patches.station_spread || x2-x1 >= _patches.station_spread) { + _error_message = STR_306C_STATION_TOO_SPREAD_OUT; + return false; + } + + return true; +} + +static Station *AllocateStation() +{ + Station *st, *a_free = NULL; + int count; + int num_free = 0; + int i; + + for(st = _stations, count = lengthof(_stations); count != 0; count--, st++) { + if (st->xy == 0) { + num_free++; + if (a_free==NULL) + a_free = st; + } + } + + if (a_free == NULL || + (num_free < 30 && IS_HUMAN_PLAYER(_current_player))) { + _error_message = STR_3008_TOO_MANY_STATIONS_LOADING; + return NULL; + } + + i = a_free->index; + memset(a_free, 0, sizeof(Station)); + a_free->index = i; + return a_free; +} + + +static int CountMapSquareAround(uint tile, byte type, byte min, byte max) { + static const TileIndexDiff _count_square_table[7*7+1] = { + TILE_XY(-3,-3), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + TILE_XY(-6,1), 1, 1, 1, 1, 1, 1, + 0, + }; + int j; + const TileIndexDiff *p = _count_square_table; + int num = 0; + + while ( (j=*p++) != 0 ) { + tile = TILE_MASK(tile + j); + + if (IS_TILETYPE(tile, type) && _map5[tile] >= min && _map5[tile] <= max) + num++; + } + + return num; +} + +#define M(x) ((x) - STR_SV_STNAME) + +static bool GenerateStationName(Station *st, uint tile, int flag) +{ + static const uint32 _gen_station_name_bits[] = { + 0, /* 0 */ + 1 << M(STR_SV_STNAME_AIRPORT), /* 1 */ + 1 << M(STR_SV_STNAME_OILFIELD), /* 2 */ + 1 << M(STR_SV_STNAME_DOCKS), /* 3 */ + 0x1FF << M(STR_SV_STNAME_BUOY_1), /* 4 */ + 1 << M(STR_SV_STNAME_HELIPORT), /* 5 */ + }; + + Town *t = st->town; + uint32 free_names = (uint32)-1; + int found; + uint z,z2; + unsigned long tmp; + + { + Station *s; + + FOR_ALL_STATIONS(s) { + if (s != st && s->xy != 0 && s->town==t) { + uint str = M(s->string_id); + if (str <= 0x20) { + if (str == M(STR_SV_STNAME_FOREST)) + str = M(STR_SV_STNAME_WOODS); + CLRBIT(free_names, str); + } + } + } + } + + /* check default names */ + tmp = free_names & _gen_station_name_bits[flag]; + if (tmp != 0) { + found = FindFirstBit(tmp); + goto done; + } + + /* check mine? */ + if (HASBIT(free_names, M(STR_SV_STNAME_MINES))) { + if (CountMapSquareAround(tile, MP_INDUSTRY, 0, 6) >= 2 || + CountMapSquareAround(tile, MP_INDUSTRY, 0x64, 0x73) >= 2 || + CountMapSquareAround(tile, MP_INDUSTRY, 0x2F, 0x33) >= 2 || + CountMapSquareAround(tile, MP_INDUSTRY, 0x48, 0x58) >= 2 || + CountMapSquareAround(tile, MP_INDUSTRY, 0x5B, 0x63) >= 2) { + found = M(STR_SV_STNAME_MINES); + goto done; + } + } + + /* check close enough to town to get central as name? */ + if (GetTileDist1D(tile,t->xy) < 8) { + found = M(STR_SV_STNAME); + if (HASBIT(free_names, M(STR_SV_STNAME))) goto done; + + found = M(STR_SV_STNAME_CENTRAL); + if (HASBIT(free_names, M(STR_SV_STNAME_CENTRAL))) goto done; + } + + /* Check lakeside */ + if (HASBIT(free_names, M(STR_SV_STNAME_LAKESIDE)) && + !CheckDistanceFromEdge(tile, 20) && + CountMapSquareAround(tile, MP_WATER, 0, 0) >= 5) { + found = M(STR_SV_STNAME_LAKESIDE); + goto done; + } + + /* Check woods */ + if (HASBIT(free_names, M(STR_SV_STNAME_WOODS)) && ( + CountMapSquareAround(tile, MP_TREES, 0, 255) >= 8 || + CountMapSquareAround(tile, MP_INDUSTRY, 0x10, 0x11) >= 2 )) { + found = (_opt.landscape==LT_DESERT) ? M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS); + goto done; + } + + /* check elevation compared to town */ + z = GetTileZ(tile); + z2 = GetTileZ(t->xy); + if (z < z2) { + found = M(STR_SV_STNAME_VALLEY); + if (HASBIT(free_names, M(STR_SV_STNAME_VALLEY))) goto done; + } else if (z > z2) { + found = M(STR_SV_STNAME_HEIGHTS); + if (HASBIT(free_names, M(STR_SV_STNAME_HEIGHTS))) goto done; + } + + /* check direction compared to town */ + { + static const int8 _direction_and_table[] = { + ~( (1<xy)) + + (GET_TILE_Y(tile) < GET_TILE_Y(t->xy))*2]; + } + + tmp = free_names & ((1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<6)|(1<<7)|(1<<12)|(1<<26)|(1<<27)|(1<<28)|(1<<29)|(1<<30)); + if (tmp == 0) { + _error_message = STR_3007_TOO_MANY_STATIONS_LOADING; + return false; + } + found = FindFirstBit(tmp); + +done: + st->string_id = found + STR_SV_STNAME; + return true; +} +#undef M + +static Station *GetClosestStationFromTile(uint tile, uint threshold, byte owner) +{ + Station *st, *best_station = NULL; + uint cur_dist; + + FOR_ALL_STATIONS(st) { + cur_dist = GetTileDist(tile, st->xy); + if (cur_dist < threshold && (owner == 0xFF || st->owner == owner)) { + threshold = cur_dist; + best_station = st; + } + } + + return best_station; +} + +static void StationInitialize(Station *st, TileIndex tile) +{ + int i; + GoodsEntry *ge; + + st->xy = tile; + st->bus_tile = st->lorry_tile = st->airport_tile = st->dock_tile = st->train_tile = 0; + st->had_vehicle_of_type = 0; + st->time_since_load = 255; + st->time_since_unload = 255; + st->delete_ctr = 0; + st->facilities = 0; + + st->blocked_months = 0; + st->last_vehicle = INVALID_VEHICLE; + + for(i=0,ge=st->goods; i!=NUM_CARGO; i++, ge++) { + ge->waiting_acceptance = 0; + ge->days_since_pickup = 0; + ge->enroute_from = 0xFF; + ge->rating = 175; + ge->last_speed = 0; + ge->last_age = 0xFF; + } + _station_sort_dirty = true; +} + +// Update the virtual coords needed to draw the station sign. +// st = Station to update for. +static void UpdateStationVirtCoord(Station *st) +{ + Point pt = RemapCoords2(GET_TILE_X(st->xy) * 16, GET_TILE_Y(st->xy) * 16); + pt.y -= 32; + if (st->facilities&FACIL_AIRPORT && st->airport_type==AT_OILRIG) pt.y -= 16; + + SET_DPARAM16(0, st->index); + SET_DPARAM8(1, st->facilities); + UpdateViewportSignPos(&st->sign, pt.x, pt.y, STR_305C_0); +} + +// Update the virtual coords needed to draw the station sign for all stations. +void UpdateAllStationVirtCoord() +{ + Station *st; + FOR_ALL_STATIONS(st) { + if (st->xy != 0) + UpdateStationVirtCoord(st); + } +} + +// Update the station virt coords while making the modified parts dirty. +static void UpdateStationVirtCoordDirty(Station *st) +{ + MarkStationDirty(st); + UpdateStationVirtCoord(st); + MarkStationDirty(st); +} + +// Get a mask of the cargo types that the station accepts. +static uint GetAcceptanceMask(Station *st) +{ + uint mask = 0; + uint cur_mask = 1; + int i; + for(i=0; i!=NUM_CARGO; i++,cur_mask*=2) { + if (st->goods[i].waiting_acceptance & 0x8000) + mask |= cur_mask; + } + return mask; +} + +// Items contains the two cargo names that are to be accepted or rejected. +// msg is the string id of the message to display. +static void ShowRejectOrAcceptNews(Station *st, uint32 items, StringID msg) +{ + if (items) { + SET_DPARAM32(2, items >> 16); + SET_DPARAM32(1, items & 0xFFFF); + SET_DPARAM16(0, st->index); + AddNewsItem(msg + ((items >> 16)?1:0), NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0); + } +} + +// Get a list of the cargo types being produced around the tile. +void GetProductionAroundTiles(uint *produced, uint tile, int w, int h) +{ + int x,y; + int x1,y1,x2,y2; + int xc,yc; + byte cargos[2]; + + memset(produced, 0, NUM_CARGO * sizeof(uint)); + + x = GET_TILE_X(tile); + y = GET_TILE_Y(tile); + + // expand the region by 4 tiles on each side + // while making sure that we remain inside the board. + x2 = min(x + w+4, TILE_X_MAX+1); + x1 = max(x-4, 0); + + y2 = min(y + h+4, TILE_Y_MAX+1); + y1 = max(y-4, 0); + + assert(x1 < x2); + assert(y1 < y2); + assert(w > 0); + assert(h > 0); + + yc = y1; + do { + xc = x1; + do { + if (!(IS_INSIDE_1D(xc, x, w) && IS_INSIDE_1D(yc, y, h))) { + GetProducedCargoProc *gpc; + uint tile = TILE_XY(xc, yc); + gpc = _tile_type_procs[GET_TILETYPE(tile)]->get_produced_cargo_proc; + if (gpc != NULL) { + cargos[0] = cargos[1] = 0xFF; + gpc(tile, cargos); + if (cargos[0] != 0xFF) { + produced[cargos[0]]++; + if (cargos[1] != 0xFF) { + produced[cargos[1]]++; + } + } + } + } + } while (++xc != x2); + } while (++yc != y2); +} + +// Get a list of the cargo types that are accepted around the tile. +void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h) +{ + int x,y; + int x1,y1,x2,y2; + int xc,yc; + AcceptedCargo ac; + + memset(accepts, 0, NUM_CARGO * sizeof(uint)); + + x = GET_TILE_X(tile); + y = GET_TILE_Y(tile); + + // expand the region by 4 tiles on each side + // while making sure that we remain inside the board. + x2 = min(x + w + 4, TILE_X_MAX+1); + y2 = min(y + h + 4, TILE_Y_MAX+1); + x1 = max(x-4, 0); + y1 = max(y-4, 0); + + assert(x1 < x2); + assert(y1 < y2); + assert(w > 0); + assert(h > 0); + + yc = y1; + do { + xc = x1; + do { + uint tile = TILE_XY(xc, yc); + if (!IS_TILETYPE(tile, MP_STATION)) { + GetAcceptedCargo(tile, &ac); + accepts[ac.type_1] += ac.amount_1; + accepts[ac.type_2] += ac.amount_2; + accepts[ac.type_3] += ac.amount_3; + } + } while (++xc != x2); + } while (++yc != y2); +} + +// Update the acceptance for a station. +// show_msg controls whether to display a message that acceptance was changed. +static void UpdateStationAcceptance(Station *st, bool show_msg) +{ + uint old_acc, new_acc; + TileIndex span[1+1+2+2+1]; + int i; + int min_x, min_y, max_x, max_y; + uint accepts[NUM_CARGO]; + + // Don't update acceptance for a buoy + if (st->had_vehicle_of_type & HVOT_BUOY) + return; + + /* old accepted goods types */ + old_acc = GetAcceptanceMask(st); + + // Put all the tiles that span an area in the table. + span[3] = span[5] = 0; + span[0] = st->bus_tile; + span[1] = st->lorry_tile; + span[2] = st->train_tile; + if (st->train_tile != 0) { + span[3] = st->train_tile + TILE_XY(st->trainst_w-1, st->trainst_h-1); + } + span[4] = st->airport_tile; + if (st->airport_tile != 0) { + span[5] = st->airport_tile + TILE_XY(_airport_size_x[st->airport_type]-1, _airport_size_y[st->airport_type]-1); + } + span[6] = st->dock_tile; + + // Construct a rectangle from those points + min_x = min_y = 0x7FFFFFFF; + max_x = max_y = 0; + + for(i=0; i!=7; i++) { + uint tile = span[i]; + if (tile) { + min_x = min(min_x,GET_TILE_X(tile)); + max_x = max(max_x,GET_TILE_X(tile)); + min_y = min(min_y,GET_TILE_Y(tile)); + max_y = max(max_y,GET_TILE_Y(tile)); + } + } + + // And retrieve the acceptance. + if (max_x != 0) { + GetAcceptanceAroundTiles(accepts, TILE_XY(min_x, min_y), max_x - min_x + 1, max_y-min_y+1); + } else { + memset(accepts, 0, sizeof(accepts)); + } + + // Adjust in case our station only accepts fewer kinds of goods + for(i=0; i!=NUM_CARGO; i++) { + uint amt = min(accepts[i], 15); + + // Make sure the station can accept the goods type. + if ((i != CT_PASSENGERS && !(st->facilities & (byte)~FACIL_BUS_STOP)) || + (i == CT_PASSENGERS && !(st->facilities & (byte)~FACIL_TRUCK_STOP))) + amt = 0; + + st->goods[i].waiting_acceptance = (st->goods[i].waiting_acceptance & ~0xF000) + (amt << 12); + } + + // Only show a message in case the acceptance was actually changed. + new_acc = GetAcceptanceMask(st); + if (old_acc == new_acc) + return; + + // show a message to report that the acceptance was changed? + if (show_msg && st->owner == _local_player && st->facilities) { + uint32 accept=0, reject=0; /* these contain two string ids each */ + const StringID *str = _cargoc.names_s; + + do { + if (new_acc & 1) { + if (!(old_acc & 1)) accept = (accept << 16) | *str; + } else { + if (old_acc & 1) reject = (reject << 16) | *str; + } + } while (str++,(new_acc>>=1) != (old_acc>>=1)); + + ShowRejectOrAcceptNews(st, accept, STR_3040_NOW_ACCEPTS); + ShowRejectOrAcceptNews(st, reject, STR_303E_NO_LONGER_ACCEPTS); + } + + // redraw the station view since acceptance changed + InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4); +} + +// This is called right after a station was deleted. +// It checks if the whole station is free of substations, and if so, the station will be +// deleted after a little while. +static void DeleteStationIfEmpty(Station *st) { + if (st->facilities == 0) { + st->delete_ctr = 0; + InvalidateWindow(WC_STATION_LIST, st->owner); + } +} + +// Tries to clear the given area. Returns the cost in case of success. +// Or an error code if it failed. +int32 CheckFlatLandBelow(uint tile, uint w, uint h, uint flags, uint invalid_dirs, int *station) +{ + int32 cost = 0, ret; + + uint tileh; + int z, allowed_z = -1, flat_z; + + BEGIN_TILE_LOOP(tile_cur, w, h, tile) + if (!EnsureNoVehicle(tile_cur)) + return CMD_ERROR; + + tileh = GetTileSlope(tile_cur, &z); + + // steep slopes are completely prohibited + if (tileh & 0x10 || ((_is_ai_player || !_patches.build_on_slopes) && tileh != 0)) { + _error_message = STR_0007_FLAT_LAND_REQUIRED; + return CMD_ERROR; + } + + flat_z = z; + if (tileh) { + // need to check so the entrance to the station is not pointing at a slope. + if ((invalid_dirs&1 && !(tileh & 0xC) && (uint)w_cur == w) || + (invalid_dirs&2 && !(tileh & 6) && h_cur == 1) || + (invalid_dirs&4 && !(tileh & 3) && w_cur == 1) || + (invalid_dirs&8 && !(tileh & 9) && (uint)h_cur == h)) { + _error_message = STR_0007_FLAT_LAND_REQUIRED; + return CMD_ERROR; + } + cost += _price.terraform; + flat_z += 8; + } + + // get corresponding flat level and make sure that all parts of the station have the same level. + if (allowed_z == -1) { + // first tile + allowed_z = flat_z; + } else if (allowed_z != flat_z) { + _error_message = STR_0007_FLAT_LAND_REQUIRED; + return CMD_ERROR; + } + + // if station is set, then we have special handling to allow building on top of already existing stations. + // so station points to -1 if we can build on any station. or it points to a station if we're only allowed to build + // on exactly that station. + if (station && IS_TILETYPE(tile_cur, MP_STATION)) { + if (_map5[tile] >= 8) { + _error_message = STR_0007_FLAT_LAND_REQUIRED; + return CMD_ERROR; + } else { + int st = _map2[tile_cur]; + if (*station == -1) + *station = st; + else if (*station != st) { + _error_message = STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING; + return CMD_ERROR; + } + } + } else { + ret = DoCommandByTile(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + cost += ret; + } + END_TILE_LOOP(tile_cur, w, h, tile) + + return cost; +} + +static bool CanExpandRailroadStation(Station *st, uint *fin, int direction) +{ + uint curw = st->trainst_w, curh = st->trainst_h; + uint tile = fin[0]; + uint w = fin[1]; + uint h = fin[2]; + + if (_patches.nonuniform_stations) { + // determine new size of train station region.. + int x = min(GET_TILE_X(st->train_tile), GET_TILE_X(tile)); + int y = min(GET_TILE_Y(st->train_tile), GET_TILE_Y(tile)); + curw = max(GET_TILE_X(st->train_tile) + curw, GET_TILE_X(tile) + w) - x; + curh = max(GET_TILE_Y(st->train_tile) + curh, GET_TILE_Y(tile) + h) - y; + tile = TILE_XY(x,y); + } else { + // check so the direction is the same + if ((_map5[st->train_tile] & 1) != direction) return false; + + // check if the new station adjoins the old station in either direction + if (curw == w && st->train_tile == tile + TILE_XY(0, h)) { + // above + curh += h; + } else if (curw == w && st->train_tile == tile - TILE_XY(0, curh)) { + // below + tile -= TILE_XY(0, curh); + curh += h; + } else if (curh == h && st->train_tile == tile + TILE_XY(w, 0)) { + // to the left + curw += w; + } else if (curh == h && st->train_tile == tile - TILE_XY(curw, 0)) { + // to the right + tile -= TILE_XY(curw, 0); + curw += w; + } else + return false; + } + // make sure the final size is not too big. + if (curw > 15 || curh > 15) return false; + + // now tile contains the new value for st->train_tile + // curw, curh contain the new value for width and height + fin[0] = tile; + fin[1] = curw; + fin[2] = curh; + return true; +} + +static byte FORCEINLINE *CreateSingle(byte *layout, int n) +{ + int i = n; + do *layout++ = 0; while (--i); + layout[((n-1) >> 1)-n] = 2; + return layout; +} + +static byte FORCEINLINE *CreateMulti(byte *layout, int n, byte b) +{ + int i = n; + do *layout++ = b; while (--i); + if (n > 4) { + layout[0-n] = 0; + layout[n-1-n] = 0; + } + return layout; +} + +// stolen from TTDPatch +static void GetStationLayout(byte *layout, int numtracks, int plat_len) +{ + if (plat_len == 1) { + CreateSingle(layout, numtracks); + } else { + if (numtracks & 1) + layout = CreateSingle(layout, plat_len); + numtracks>>=1; + + while (--numtracks >= 0) { + layout = CreateMulti(layout, plat_len, 4); + layout = CreateMulti(layout, plat_len, 6); + } + } +} + +/* build railroad station + * p1 & 1 - orientation + * (p1 >> 8) & 0xFF - numtracks + * (p1 >> 16) & 0xFF - platform length + * p2 - railtype + */ + +int32 CmdBuildRailroadStation(int x_org, int y_org, uint32 flags, uint32 p1, uint32 p2) +{ + /* unpack params */ + int w_org,h_org; + uint tile_org; + int32 cost, ret; + Station *st; + int est; + int plat_len, numtracks; + int direction; + uint finalvalues[3]; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile_org = TILE_FROM_XY(x_org,y_org); + + /* Does the authority allow this? */ + if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) + return CMD_ERROR; + + { + /* unpack parameters */ + direction = p1 & 1; + plat_len = (p1 >> 16) & 0xFF; + numtracks = (p1 >> 8) & 0xFF; + /* w = length, h = num_tracks */ + if (direction) { + h_org = plat_len; + w_org = numtracks; + } else { + w_org = plat_len; + h_org = numtracks; + } + } + + // these values are those that will be stored in train_tile and station_platforms + finalvalues[0] = tile_org; + finalvalues[1] = w_org; + finalvalues[2] = h_org; + + // Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) + est = -1; + if ((ret=CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << direction, _patches.nonuniform_stations ? &est : NULL)) == CMD_ERROR) return CMD_ERROR; + cost = ret + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len; + + // Make sure there are no similar stations around us. + st = GetStationAround(tile_org, w_org, h_org, est); + if (st == CHECK_STATIONS_ERR) return CMD_ERROR; + + // See if there is a deleted station close to us. + if (st == NULL) { + st = GetClosestStationFromTile(tile_org, 8, _current_player); + if (st != NULL && st->facilities) st = NULL; + } + + if (st != NULL) { + // Reuse an existing station. + if (st->owner != OWNER_NONE && st->owner != _current_player) + return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); + + if (st->train_tile != 0) { + // check if we want to expanding an already existing station? Only human players can do this. + if (_is_ai_player || !_patches.join_stations || !CanExpandRailroadStation(st, finalvalues, direction)) + return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD); + } + + if (!CheckStationSpreadOut(st, tile_org, w_org, h_org)) + return CMD_ERROR; + + } else { + // Create a new station + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = ClosestTownFromTile(tile_org, (uint)-1); + if (_current_player < MAX_PLAYERS && flags&DC_EXEC) + SETBIT(st->town->have_ratings, _current_player); + + if (!GenerateStationName(st, tile_org, 0)) + return CMD_ERROR; + + if (flags & DC_EXEC) + StationInitialize(st, tile_org); + } + + if (flags & DC_EXEC) { + int tile_delta; + byte *layout_ptr; + uint station_index = st->index; + + st->train_tile = finalvalues[0]; + if (!st->facilities) st->xy = finalvalues[0]; + st->facilities |= FACIL_TRAIN; + st->owner = _current_player; + + st->trainst_w = finalvalues[1]; + st->trainst_h = finalvalues[2]; + + tile_delta = direction ? TILE_XY(0,1) : TILE_XY(1,0); + + layout_ptr = alloca(numtracks * plat_len); + GetStationLayout(layout_ptr, numtracks, plat_len); + + do { + int tile = tile_org; + int w = plat_len; + do { + + ModifyTile(tile, + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP5 | MP_MAP3LO | MP_MAP3HI_CLEAR, + station_index, /* map2 parameter */ + p2, /* map3lo parameter */ + (*layout_ptr++) + direction /* map5 parameter */ + ); + + tile += tile_delta; + } while (--w); + tile_org += tile_delta ^ TILE_XY(1,1); + } while (--numtracks); + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + + return cost; +} + +static bool TileBelongsToRailStation(Station *st, uint tile) +{ + return IS_TILETYPE(tile, MP_STATION) && _map2[tile] == st->index && _map5[tile] < 8; +} + +static void MakeRailwayStationAreaSmaller(Station *st) +{ + uint w = st->trainst_w; + uint h = st->trainst_h; + uint tile = st->train_tile; + uint i; + +restart: + + // too small? + if (w != 0 && h != 0) { + // check the left side, x = constant, y changes + for(i=0; !TileBelongsToRailStation(st, tile + TILE_XY(0,i)) ;) + // the left side is unused? + if (++i==h) { tile += TILE_XY(1, 0); w--; goto restart; } + + // check the right side, x = constant, y changes + for(i=0; !TileBelongsToRailStation(st, tile + TILE_XY(w-1,i)) ;) + // the right side is unused? + if (++i==h) { w--; goto restart; } + + // check the upper side, y = constant, x changes + for(i=0; !TileBelongsToRailStation(st, tile + TILE_XY(i,0)) ;) + // the left side is unused? + if (++i==w) { tile += TILE_XY(0, 1); h--; goto restart; } + + // check the lower side, y = constant, x changes + for(i=0; !TileBelongsToRailStation(st, tile + TILE_XY(i,h-1)) ;) + // the left side is unused? + if (++i==w) { h--; goto restart; } + } else { + tile = 0; + } + + st->trainst_w = w; + st->trainst_h = h; + st->train_tile = tile; +} + +// remove a single tile from a railroad station +int32 CmdRemoveFromRailroadStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x, y); + Station *st; + + // make sure the specified tile belongs to the current player, and that it is a railroad station. + if (!IS_TILETYPE(tile, MP_STATION) || _map5[tile] >= 8 || !_patches.nonuniform_stations) return CMD_ERROR; + st = DEREF_STATION(_map2[tile]); + if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR; + + // if we reached here, it means we can actually delete it. do that. + if (flags & DC_EXEC) { + DoClearSquare(tile); + // now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges. + // we also need to adjust train_tile. + MakeRailwayStationAreaSmaller(st); + + // if we deleted the whole station, delete the train facility. + if (st->train_tile == 0) { + st->facilities &= ~FACIL_TRAIN; + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + } + return _price.remove_rail_station; +} + +// determine the number of platforms for the station +uint GetStationPlatforms(Station *st, uint tile) +{ + uint t; + int dir,delta; + int len; + assert(TileBelongsToRailStation(st, tile)); + + len = 0; + dir = _map5[tile]&1; + delta = dir ? TILE_XY(0,1) : TILE_XY(1,0); + + // find starting tile.. + t = tile; + do { t -= delta; len++; } while (TileBelongsToRailStation(st, t) && (_map5[t]&1) == dir); + + // find ending tile + t = tile; + do { t += delta; len++; }while (TileBelongsToRailStation(st, t) && (_map5[t]&1) == dir); + + return len - 1; +} + + +static int32 RemoveRailroadStation(Station *st, uint32 flags) +{ + uint tile; + int w,h; + int32 cost; + + /* Current player owns the station? */ + if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) + return CMD_ERROR; + + /* determine width and height of platforms */ + tile = st->train_tile; + w = st->trainst_w; + h = st->trainst_h; + + assert(w != 0 && h != 0); + + /* cost is area * constant */ + cost = w*h*_price.remove_rail_station; + + /* clear all areas of the station */ + do { + int w_bak = w; + do { + // for nonuniform stations, only remove tiles that are actually train station tiles + if (TileBelongsToRailStation(st, tile)) { + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + if (flags & DC_EXEC) + DoClearSquare(tile); + } + tile += TILE_XY(1, 0); + } while (--w); + w = w_bak; + tile = tile + TILE_XY(-w, 1); + } while (--h); + + if (flags & DC_EXEC) { + st->train_tile = 0; + st->facilities &= ~FACIL_TRAIN; + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return cost; +} + +int32 DoConvertStationRail(uint tile, uint totype, bool exec) +{ + Station *st; + + st = DEREF_STATION(_map2[tile]); + if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR; + + // tile is not a railroad station? + if (_map5[tile] >= 8) return CMD_ERROR; + + // tile is already of requested type? + if ( (uint)(_map3_lo[tile] & 0xF) == totype) return CMD_ERROR; + + if (exec) { + // change type. + _map3_lo[tile] = (_map3_lo[tile] & 0xF0) + totype; + MarkTileDirtyByTile(tile); + } + + return _price.build_rail >> 1; +} + +/* Build a bus station + * p1 - direction + * p2 - unused + */ + +int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + int32 cost; + Station *st; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) + return CMD_ERROR; + + if ((cost=CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL)) == CMD_ERROR) + return CMD_ERROR; + + st = GetStationAround(tile, 1, 1, -1); + if (st == CHECK_STATIONS_ERR) + return CMD_ERROR; + + /* Find a station close to us */ + if (st == NULL) { + st = GetClosestStationFromTile(tile, 8, _current_player); + if (st!=NULL && st->facilities) st = NULL; + } + + if (st != NULL) { + if (st->owner != OWNER_NONE && st->owner != _current_player) + return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); + + if (!CheckStationSpreadOut(st, tile, 1, 1)) + return CMD_ERROR; + + if (st->bus_tile != 0) + return_cmd_error(STR_3044_TOO_CLOSE_TO_ANOTHER_BUS); + } else { + Town *t; + + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = t = ClosestTownFromTile(tile, (uint)-1); + + if (_current_player < MAX_PLAYERS && flags&DC_EXEC) + SETBIT(t->have_ratings, _current_player); + + st->sign.width_1 = 0; + + if (!GenerateStationName(st, tile, 0)) + return CMD_ERROR; + + if (flags & DC_EXEC) + StationInitialize(st, tile); + } + + cost += _price.build_bus_station; + + if (flags & DC_EXEC) { + st->bus_tile = tile; + if (!st->facilities) st->xy = tile; + st->facilities |= FACIL_BUS_STOP; + st->bus_stop_status = 3; + st->owner = _current_player; + + ModifyTile(tile, + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP5 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, + st->index, /* map2 parameter */ + p1 + 0x47 /* map5 parameter */ + ); + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + return cost; +} + +// Remove a bus station +static int32 RemoveBusStation(Station *st, uint32 flags) +{ + uint tile; + + if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) + return CMD_ERROR; + + tile = st->bus_tile; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoClearSquare(tile); + + st->bus_tile = 0; + st->facilities &= ~FACIL_BUS_STOP; + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return _price.remove_bus_station; +} + + +/* Build a truck station + * p1 - direction + * p2 - unused + */ +int32 CmdBuildTruckStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + int32 cost = 0; + Station *st; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) + return CMD_ERROR; + + if ((cost=CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL)) == CMD_ERROR) + return CMD_ERROR; + + st = GetStationAround(tile, 1, 1, -1); + if (st == CHECK_STATIONS_ERR) + return CMD_ERROR; + + /* Find a station close to us */ + if (st == NULL) { + st = GetClosestStationFromTile(tile, 8, _current_player); + if (st!=NULL && st->facilities) st = NULL; + } + + if (st != NULL) { + if (st->owner != OWNER_NONE && st->owner != _current_player) + return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); + + if (!CheckStationSpreadOut(st, tile, 1, 1)) + return CMD_ERROR; + + if (st->lorry_tile != 0) + return_cmd_error(STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK); + } else { + Town *t; + + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = t = ClosestTownFromTile(tile, (uint)-1); + + if (_current_player < MAX_PLAYERS && flags&DC_EXEC) + SETBIT(t->have_ratings, _current_player); + + st->sign.width_1 = 0; + + if (!GenerateStationName(st, tile, 0)) + return CMD_ERROR; + + if (flags & DC_EXEC) + StationInitialize(st, tile); + } + + cost += _price.build_truck_station; + + if (flags & DC_EXEC) { + st->lorry_tile = tile; + if (!st->facilities) st->xy = tile; + st->facilities |= FACIL_TRUCK_STOP; + st->truck_stop_status = 3; + st->owner = _current_player; + + ModifyTile(tile, + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAP5, + st->index, /* map2 parameter */ + p1 + 0x43 /* map5 parameter */ + ); + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + return cost; +} + +// Remove a truck station +static int32 RemoveTruckStation(Station *st, uint32 flags) +{ + uint tile; + + if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) + return CMD_ERROR; + + tile = st->lorry_tile; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoClearSquare(tile); + + st->lorry_tile = 0; + st->facilities &= ~FACIL_TRUCK_STOP; + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return _price.remove_truck_station; +} + +// FIXME -- need to move to its corresponding Airport variable +// Country Airfield (small) +static const byte _airport_map5_tiles_country[] = { + 54, 53, 52, 65, + 58, 57, 56, 55, + 64, 63, 63, 62 +}; + +// City Airport (large) +static const byte _airport_map5_tiles_town[] = { + 31, 9, 33, 9, 9, 32, + 27, 36, 29, 34, 8, 10, + 30, 11, 35, 13, 20, 21, + 51, 12, 14, 17, 19, 28, + 38, 13, 15, 16, 18, 39, + 26, 22, 23, 24, 25, 26 +}; + +// Metropolitain Airport (large) - 2 runways +static const byte _airport_map5_tiles_metropolitan[] = { + 31, 9, 33, 9, 9, 32, + 27, 36, 29, 34, 8, 10, + 30, 11, 35, 13, 20, 21, + 102, 8, 8, 8, 8, 28, + 83, 84, 84, 84, 84, 83, + 26, 23, 23, 23, 23, 26 +}; + +// International Airport (large) - 2 runways +static const byte _airport_map5_tiles_international[] = { + 88, 89, 89, 89, 89, 89, 88, + 51, 8, 8, 8, 8, 8, 32, + 30, 8, 11, 27, 11, 8, 10, + 32, 8, 11, 27, 11, 8, 114, + 87, 8, 11, 85, 11, 8, 114, + 87, 8, 8, 8, 8, 8, 90, + 26, 23, 23, 23, 23, 23, 26 +}; + +// Heliport +static const byte _airport_map5_tiles_heliport[] = { + 66, +}; + +static const byte * const _airport_map5_tiles[] = { + _airport_map5_tiles_country, // Country Airfield (small) + _airport_map5_tiles_town, // City Airport (large) + _airport_map5_tiles_heliport, // Heliport + _airport_map5_tiles_metropolitan, // Metropolitain Airport (large) + _airport_map5_tiles_international, // International Airport (xlarge) +}; + +/* Place an Airport + * p1 - airport type + * p2 - unused + */ +int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile; + Town *t; + Station *st; + int32 cost; + int w,h; + bool airport_upgrade = true; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + + if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) + return CMD_ERROR; + + t = ClosestTownFromTile(tile, (uint)-1); + + /* Check if local auth refuses a new airport */ + { + uint num = 0; + FOR_ALL_STATIONS(st) { + if (st->xy != 0 && st->town == t && st->facilities&FACIL_AIRPORT && st->airport_type != AT_OILRIG) + num++; + } + if (num >= 2) { + SET_DPARAM16(0, t->index); + return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES); + } + } + + w = _airport_size_x[p1]; + h = _airport_size_y[p1]; + + cost = CheckFlatLandBelow(tile, w, h, flags, 0, NULL); + if (cost == CMD_ERROR) + return CMD_ERROR; + + st = GetStationAround(tile, w, h, -1); + if (st == CHECK_STATIONS_ERR) + return CMD_ERROR; + + /* Find a station close to us */ + if (st == NULL) { + st = GetClosestStationFromTile(tile, 8, _current_player); + if (st!=NULL && st->facilities) st = NULL; + } + + if (st != NULL) { + if (st->owner != OWNER_NONE && st->owner != _current_player) + return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); + + if (!CheckStationSpreadOut(st, tile, 1, 1)) + return CMD_ERROR; + + if (st->airport_tile != 0) + return_cmd_error(STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT); + } else { + Town *t; + + airport_upgrade = false; + + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = t = ClosestTownFromTile(tile, (uint)-1); + + if (_current_player < MAX_PLAYERS && flags&DC_EXEC) + SETBIT(t->have_ratings, _current_player); + + st->sign.width_1 = 0; + + // if airport type equals Heliport then generate + // type 5 name, which is heliport, otherwise airport names (1) + if (!GenerateStationName(st, tile, p1 == AT_HELIPORT ? 5 : 1)) + return CMD_ERROR; + + if (flags & DC_EXEC) + StationInitialize(st, tile); + } + + cost += _price.build_airport * w * h; + + if (flags & DC_EXEC) { + st->owner = _current_player; + if (_current_player == _local_player && p1 <= AT_INTERNATIONAL) { + _last_built_aircraft_depot_tile = tile + GetAirport(p1)->airport_depots[0]; + } + + st->airport_tile = tile; + if (!st->facilities) st->xy = tile; + st->facilities |= FACIL_AIRPORT; + st->airport_type = (byte)p1; + st->airport_flags = 0; + + /* if airport was demolished while planes were en-route to it, the positions can no longer + be the same (v->u.air.pos), since different airports have different indexes. So update + all planes en-route to this airport. Only update if + 1. airport is upgraded + 2. airport is added to existing station (unfortunately unavoideable) + */ + if (airport_upgrade) {UpdateAirplanesOnNewStation(st);} + + { + const byte *b = _airport_map5_tiles[p1]; +BEGIN_TILE_LOOP(tile_cur,w,h,tile) + ModifyTile(tile_cur, + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAP5, + st->index, *b++); +END_TILE_LOOP(tile_cur,w,h,tile) + } + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + + return cost; +} + +static int32 RemoveAirport(Station *st, uint32 flags) +{ + uint tile; + int w,h; + int32 cost; + + if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) + return CMD_ERROR; + + tile = st->airport_tile; + + w = _airport_size_x[st->airport_type]; + h = _airport_size_y[st->airport_type]; + + cost = w * h * _price.remove_airport; + + { +BEGIN_TILE_LOOP(tile_cur,w,h,tile) + if (!EnsureNoVehicle(tile_cur)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DeleteAnimatedTile(tile_cur); + DoClearSquare(tile_cur); + } +END_TILE_LOOP(tile_cur, w,h,tile) + } + + if (flags & DC_EXEC) { + if (st->airport_type <= AT_INTERNATIONAL) + DeleteWindowById(WC_VEHICLE_DEPOT, tile + GetAirport(st->airport_type)->airport_depots[0]); + st->airport_tile = 0; + st->facilities &= ~FACIL_AIRPORT; + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return cost; +} + +/* Build a buoy + * p1,p2 unused + */ + +int32 CmdBuildBuoy(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + Station *st; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + + if (ti.type != MP_WATER || ti.tileh != 0 || ti.map5 != 0 || ti.tile == 0) + return_cmd_error(STR_304B_SITE_UNSUITABLE); + + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = ClosestTownFromTile(ti.tile, (uint)-1); + st->sign.width_1 = 0; + + if (!GenerateStationName(st, ti.tile, 4)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + StationInitialize(st, ti.tile); + st->dock_tile = ti.tile; + st->facilities |= FACIL_DOCK; + st->had_vehicle_of_type |= HVOT_BUOY; + st->owner = OWNER_NONE; + + ModifyTile(ti.tile, + MP_SETTYPE(MP_STATION) | + MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAPOWNER | MP_MAP5, + st->index, /* map2 */ + OWNER_NONE, /* map_owner */ + 0x52 /* map5 */ + ); + + UpdateStationVirtCoordDirty(st); + + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + + return _price.build_dock; +} + +static int32 RemoveBuoy(Station *st, uint32 flags) +{ + uint tile; + + if (_current_player >= MAX_PLAYERS) { + /* XXX: strange stuff */ + return_cmd_error(INVALID_STRING_ID); + } + + tile = st->dock_tile; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + st->dock_tile = 0; + st->facilities &= ~FACIL_DOCK; + st->had_vehicle_of_type &= ~HVOT_BUOY; + + ModifyTile(tile, + MP_SETTYPE(MP_WATER) | + MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR, + OWNER_WATER, /* map_owner */ + 0 /* map5 */ + ); + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return _price.remove_truck_station; +} + +static const TileIndexDiff _dock_tileoffs_chkaround[4] = { + TILE_XY(-1,0), + 0,0, + TILE_XY(0,-1), +}; +static const byte _dock_w_chk[4] = { 2,1,2,1 }; +static const byte _dock_h_chk[4] = { 1,2,1,2 }; + +int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int direction; + int32 cost; + uint tile, tile_cur; + Station *st; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + FindLandscapeHeight(&ti, x, y); + + if ((direction=0,ti.tileh) != 3 && + (direction++,ti.tileh) != 9 && + (direction++,ti.tileh) != 12 && + (direction++,ti.tileh) != 6) + return_cmd_error(STR_304B_SITE_UNSUITABLE); + + if (!EnsureNoVehicle(ti.tile)) + return CMD_ERROR; + + cost = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (cost == CMD_ERROR) + return CMD_ERROR; + + tile_cur = (tile=ti.tile) + _tileoffs_by_dir[direction]; + + if (!EnsureNoVehicle(tile_cur)) + return CMD_ERROR; + + FindLandscapeHeightByTile(&ti, tile_cur); + if (ti.tileh != 0 || ti.type != MP_WATER) + return_cmd_error(STR_304B_SITE_UNSUITABLE); + + cost = DoCommandByTile(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (cost == CMD_ERROR) + return CMD_ERROR; + + tile_cur = tile_cur + _tileoffs_by_dir[direction]; + FindLandscapeHeightByTile(&ti, tile_cur); + if (ti.tileh != 0 || ti.type != MP_WATER) + return_cmd_error(STR_304B_SITE_UNSUITABLE); + + /* middle */ + st = GetStationAround(tile + _dock_tileoffs_chkaround[direction], + _dock_w_chk[direction], _dock_h_chk[direction], -1); + if (st == CHECK_STATIONS_ERR) + return CMD_ERROR; + + /* Find a station close to us */ + if (st == NULL) { + st = GetClosestStationFromTile(tile, 8, _current_player); + if (st!=NULL && st->facilities) st = NULL; + } + + if (st != NULL) { + if (st->owner != OWNER_NONE && st->owner != _current_player) + return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); + + if (!CheckStationSpreadOut(st, tile, 1, 1)) + return CMD_ERROR; + + if (st->dock_tile != 0) + return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK); + } else { + Town *t; + + st = AllocateStation(); + if (st == NULL) + return CMD_ERROR; + + st->town = t = ClosestTownFromTile(tile, (uint)-1); + + if (_current_player < MAX_PLAYERS && flags&DC_EXEC) + SETBIT(t->have_ratings, _current_player); + + st->sign.width_1 = 0; + + if (!GenerateStationName(st, tile, 3)) + return CMD_ERROR; + + if (flags & DC_EXEC) + StationInitialize(st, tile); + } + + if (flags & DC_EXEC) { + st->dock_tile = tile; + if (!st->facilities) st->xy = tile; + st->facilities |= FACIL_DOCK; + st->owner = _current_player; + + ModifyTile(tile, + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | + MP_MAP5, + st->index, + direction + 0x4C); + + ModifyTile(tile + _tileoffs_by_dir[direction], + MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT | + MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | + MP_MAP5, + st->index, + (direction&1) + 0x50); + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + InvalidateWindow(WC_STATION_LIST, st->owner); + } + return _price.build_dock; +} + +static int32 RemoveDock(Station *st, uint32 flags) +{ + uint tile1, tile2; + + if (!CheckOwnership(st->owner)) + return CMD_ERROR; + + tile1 = st->dock_tile; + tile2 = tile1 + _tileoffs_by_dir[_map5[tile1] - 0x4C]; + + if (!EnsureNoVehicle(tile1)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile2)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoClearSquare(tile1); + + // convert the water tile to water. + ModifyTile(tile2, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0); + + st->dock_tile = 0; + st->facilities &= ~FACIL_DOCK; + + UpdateStationVirtCoordDirty(st); + DeleteStationIfEmpty(st); + } + + return _price.remove_dock; +} + +#include "table/station_land.h" + + +typedef struct DrawTileSeqStruct { + int8 delta_x; + int8 delta_y; + int8 delta_z; + byte width,height; + byte unk; + SpriteID image; +} DrawTileSeqStruct; + + +static void DrawTile_Station(TileInfo *ti) +{ + uint32 image_or_modificator; + uint32 base_img, image; + const DrawTileSeqStruct *dtss; + const byte *t; + + // station_land array has been increased from 82 elements to 114 + // but this is something else. If AI builds station with 114 it looks all weird + base_img = (_map3_lo[ti->tile] & 0xF) * 82; + + { + uint owner = _map_owner[ti->tile]; + image_or_modificator = 0x315 << 16; /* NOTE: possible bug in ttd here? */ + if (owner < MAX_PLAYERS) + image_or_modificator = PLAYER_SPRITE_COLOR(owner); + } + + // don't show foundation for docks (docks are between 76 (0x4C) and 81 (0x51)) + if (ti->tileh != 0 && (ti->map5 < 0x4C || ti->map5 > 0x51)) + DrawFoundation(ti, ti->tileh); + + t = _station_display_datas[ti->map5]; + + image = *(uint32*)t; + t += sizeof(uint32); + if (image & 0x8000) + image |= image_or_modificator; + DrawGroundSprite(image + base_img); + + for(dtss = (DrawTileSeqStruct *)t; (byte)dtss->delta_x != 0x80; dtss++) { + if ((byte)dtss->delta_z != 0x80) { + image = dtss->image + base_img; + if (_display_opt & DO_TRANS_BUILDINGS) { + if (image&0x8000) image |= image_or_modificator; + } else { + image = (image & 0x3FFF) | 0x03224000; + } + + AddSortableSpriteToDraw(image, ti->x + dtss->delta_x, ti->y + dtss->delta_y, dtss->width, dtss->height, dtss->unk, ti->z + dtss->delta_z); + } else { + image = *(uint32*)&dtss->height + base_img; /* endian ok */ + + if (_display_opt & DO_TRANS_BUILDINGS) { + if (image&0x8000) image |= image_or_modificator; + } else { + image = (image & 0x3FFF) | 0x03224000; + } + AddChildSpriteScreen(image, dtss->delta_x, dtss->delta_y); + } + } +} + +void StationPickerDrawSprite(int x, int y, int railtype, int image) +{ + uint32 ormod, img; + const DrawTileSeqStruct *dtss; + const byte *t; + + /* baseimage */ + railtype *= TRACKTYPE_SPRITE_PITCH; + + ormod = PLAYER_SPRITE_COLOR(_local_player); + + t = _station_display_datas[image]; + + img = *(uint32*)t; + t += sizeof(uint32); + if (img & 0x8000) + img |= ormod; + DrawSprite(img, x, y); + + for(dtss = (DrawTileSeqStruct *)t; (byte)dtss->delta_x != 0x80; dtss++) { + Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); + DrawSprite((dtss->image | ormod) + railtype, x + pt.x, y + pt.y); + } +} + +static uint GetSlopeZ_Station(TileInfo *ti) +{ + uint z = ti->z; + if (ti->tileh != 0) + z += 8; + return z; +} + +static void GetAcceptedCargo_Station(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void GetTileDesc_Station(uint tile, TileDesc *td) +{ + byte m5; + StringID str; + + td->owner = _map_owner[tile]; + + m5 = _map5[tile]; + (str=STR_305E_RAILROAD_STATION, m5 < 8) || + (str=STR_305F_AIRCRAFT_HANGAR, m5==32 || m5==45) || // hangars + (str=STR_3060_AIRPORT, m5 < 0x43 || (m5 >= 83 && m5 <= 114)) || + (str=STR_3061_TRUCK_LOADING_AREA, m5 < 0x47) || + (str=STR_3062_BUS_STATION, m5 < 0x4B) || + (str=STR_4807_OIL_RIG, m5 == 0x4B) || + (str=STR_3063_SHIP_DOCK, m5 != 0x52) || + (str=STR_3069_BUOY, true); + td->str = str; +} + + +static const byte _tile_track_status_rail[8] = { 1,2,1,2,1,2,1,2 }; + +static uint32 GetTileTrackStatus_Station(uint tile, int mode) { + uint i = _map5[tile]; + uint j = 0; + + if (mode == 0) { + if (i < 8) + j = _tile_track_status_rail[i]; + } else if (mode == 2) { + // not needed + } else if (mode == 4) { + // buoy + if (i == 0x52) j = 0x3F; + } + + return j + (j << 8); +} + +static void TileLoop_Station(uint tile) +{ + //FIXME -- GetTileTrackStatus_Station -> animated stationtiles + // hardcoded.....not good + // 0x27 - large big airport (39) + // 0x66 - radar metropolitan airport (102) + // 0x5A - radar international airport (90) + // 0x3A - flag small airport (58) + if (_map5[tile] == 39 || _map5[tile] == 58 || _map5[tile] == 90 || _map5[tile] == 102) + AddAnimatedTile(tile); + + // treat a bouy tile as water. + else if (_map5[tile] == 0x52) + TileLoop_Water(tile); +} + + +static void AnimateTile_Station(uint tile) +{ + byte m5 = _map5[tile]; + //FIXME -- AnimateTile_Station -> not nice code, lots of things double + // again hardcoded...was a quick hack + + // turning radar / windsack on airport + if (m5 >= 39 && m5 <= 50) { // turning radar (39 - 50) + if (_tick_counter & 3) + return; + + if (++m5 == 50+1) + m5 = 39; + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); + //added - begin + } else if (m5 >= 90 && m5 <= 113) { // turning radar with ground under it (different fences) (90 - 101 | 102 - 113) + if (_tick_counter & 3) + return; + + m5++; + + if (m5 == 101+1) {m5 = 90;} // radar with fences in south + else if (m5 == 113+1) {m5 = 102;} // radar with fences in north + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); + //added - end + } else if (m5 >= 0x3A && m5 <= 0x3D) { // windsack (58 - 61) + if (_tick_counter & 1) + return; + + if (++m5 == 0x3D+1) + m5 = 0x3A; + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); + } +} + +static void ClickTile_Station(uint tile) +{ + // 0x20 - hangar large airport (32) + // 0x41 - hangar small airport (65) + if (_map5[tile] == 32 || _map5[tile] == 65) { + ShowAircraftDepotWindow(tile); + } else { + ShowStationViewWindow(_map2[tile]); + } +} + +static INLINE bool IsTrainStationTile(uint tile) { + return IS_TILETYPE(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0, 8); +} + +static const byte _enter_station_speedtable[12] = { + 215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0 +}; + +static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y) +{ + byte station_id; + byte dir; + uint16 spd; + + if (v->type == VEH_Train) { + if (IS_BYTE_INSIDE(_map5[tile], 0, 8) && v->subtype == 0 && + !IsTrainStationTile(tile + _tileoffs_by_dir[v->direction >> 1])) { + + station_id = _map2[tile]; + if ((!(v->next_order & OF_NON_STOP) && !_patches.new_nonstop) || + (((v->next_order & OT_MASK) == OT_GOTO_STATION && v->next_order_param == station_id))) { + + if (!(_patches.new_nonstop && (v->next_order & OF_NON_STOP)) && v->next_order != OT_LEAVESTATION && v->last_station_visited != station_id) { + x &= 0xF; + y &= 0xF; + + dir = v->direction & 6; + if (dir & 2) intswap(x,y); + if (y == 8) { + if (dir != 2 && dir != 4) { + x = (~x)&0xF; + } + if (x == 12) return 2 | (station_id << 8); /* enter station */ + if (x < 12) { + v->vehstatus |= VS_TRAIN_SLOWING; + spd = _enter_station_speedtable[x]; + if (spd < v->cur_speed) + v->cur_speed = spd; + } + } + } + } + } + } else if (v->type == VEH_Road) { + if (v->u.road.state < 16 && (v->u.road.state&4)==0 && v->u.road.frame==0) { + Station *st = DEREF_STATION(_map2[tile]); + byte m5 = _map5[tile]; + byte *b, bb,state; + + if (IS_BYTE_INSIDE(m5, 0x43, 0x4B)) { + b = (m5 >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status; + + bb = *b; + + /* bb bits 1..0 describe current the two parking spots. + 0 means occupied, 1 means free. */ + + // Station busy? + if (bb & 0x80 || (bb&3) == 0) + return 8; + + state = v->u.road.state + 32; + if (bb & 1) { + bb &= ~1; + } else { + bb &= ~2; + state += 2; + } + *b = bb; + v->u.road.state = state; + } + } + } + + return 0; +} + +static void DeleteStation(Station *st) +{ + int index; + st->xy = 0; + + DeleteName(st->string_id); + MarkStationDirty(st); + _station_sort_dirty = true; + + index = st->index; + DeleteWindowById(WC_STATION_VIEW, index); + DeleteCommandFromVehicleSchedule((index << 8) + OT_GOTO_STATION); + DeleteSubsidyWithStation(index); +} + +void DeleteAllPlayerStations() +{ + Station *st; + + FOR_ALL_STATIONS(st) { + if (st->xy && st->owner < MAX_PLAYERS) + DeleteStation(st); + } +} + +/* this function is called for one station each tick */ +static void StationHandleBigTick(Station *st) +{ + UpdateStationAcceptance(st, true); + + if (st->facilities == 0) { + if (++st->delete_ctr >= 8) + DeleteStation(st); + } +} + +static INLINE void byte_inc_sat(byte *p) { byte b = *p + 1; if (b != 0) *p = b; } + +static byte _rating_boost[3] = { 0, 31, 63}; + +static void UpdateStationRating(Station *st) +{ + GoodsEntry *ge; + int rating, index; + int waiting; + bool waiting_changed = false; + + byte_inc_sat(&st->time_since_load); + byte_inc_sat(&st->time_since_unload); + + ge = st->goods; + do { + if (ge->enroute_from != 0xFF) { + byte_inc_sat(&ge->enroute_time); + byte_inc_sat(&ge->days_since_pickup); + + rating = 0; + + { + int b = ge->last_speed; + if ((b-=85) >= 0) + rating += b >> 2; + } + + { + byte age = ge->last_age; + (age >= 3) || + (rating += 10, age >= 2) || + (rating += 10, age >= 1) || + (rating += 13, true); + } + + { + if (!IS_HUMAN_PLAYER(st->owner) && st->owner != OWNER_NONE) + rating += _rating_boost[_opt.diff.competitor_intelligence]; + } + + if (st->owner < 8 && HASBIT(st->town->statues, st->owner)) + rating += 26; + + { + byte days = ge->days_since_pickup; + if (st->last_vehicle != INVALID_VEHICLE && + (&_vehicles[st->last_vehicle])->type == VEH_Ship) + days >>= 2; + (days > 21) || + (rating += 25, days > 12) || + (rating += 25, days > 6) || + (rating += 45, days > 3) || + (rating += 35, true); + } + + { + waiting = ge->waiting_acceptance & 0xFFF; + (rating -= 90, waiting > 1500) || + (rating += 55, waiting > 1000) || + (rating += 35, waiting > 600) || + (rating += 10, waiting > 300) || + (rating += 20, waiting > 100) || + (rating += 10, true); + } + + { + int or = ge->rating; // old rating + + // only modify rating in steps of -2, -1, 0, 1 or 2 + ge->rating = rating = or + clamp(clamp(rating, 0, 255) - or, -2, 2); + + // if rating is <= 64 and more than 200 items waiting, remove some random amount of goods from the station + if (rating <= 64 && waiting >= 200) { + int dec = Random() & 0x1F; + if (waiting < 400) dec &= 7; + waiting -= dec + 1; + waiting_changed = true; + } + + // if rating is <= 127 and there are any items waiting, maybe remove some goods. + if (rating <= 127 && waiting != 0) { + uint32 r = Random(); + if ( (uint)rating <= (r & 0x7F) ) { + waiting = max(waiting - ((r >> 8)&3) - 1, 0); + waiting_changed = true; + } + } + + if (waiting_changed) + ge->waiting_acceptance = (ge->waiting_acceptance & ~0xFFF) + waiting; + } + } + } while (++ge != endof(st->goods)); + + index = st->index; + + if (waiting_changed) + InvalidateWindow(WC_STATION_VIEW, index); + else + InvalidateWindowWidget(WC_STATION_VIEW, index, 5); +} + +/* called for every station each tick */ +static void StationHandleSmallTick(Station *st) +{ + byte b; + + if (st->facilities == 0) + return; + + b = st->delete_ctr + 1; + if (b >= 185) b = 0; + st->delete_ctr = b; + + if (b == 0) + UpdateStationRating(st); +} + +void OnTick_Station() +{ + int i; + Station *st; + + if (_game_mode == GM_EDITOR) + return; + + i = _station_tick_ctr; + if (++_station_tick_ctr == lengthof(_stations)) + _station_tick_ctr = 0; + + st = DEREF_STATION(i); + if (st->xy != 0) + StationHandleBigTick(st); + + FOR_ALL_STATIONS(st) { + if (st->xy != 0) + StationHandleSmallTick(st); + } + +} + +void StationMonthlyLoop() +{ + Station *st; + + FOR_ALL_STATIONS(st) { + if (st->blocked_months != 0) + st->blocked_months--; + } + +} + + +void ModifyStationRatingAround(TileIndex tile, byte owner, int amount, uint radius) +{ + Station *st; + GoodsEntry *ge; + int i; + + FOR_ALL_STATIONS(st) { + if (st->xy != 0 && st->owner == owner && GetTileDist(tile, st->xy) <= radius) { + ge = st->goods; + for(i=0; i!=NUM_CARGO; i++,ge++) { + if (ge->enroute_from != 0xFF) { + ge->rating = clamp(ge->rating + amount, 0, 255); + } + } + } + } +} + +static void UpdateStationWaiting(Station *st, int type, uint amount) +{ + st->goods[type].waiting_acceptance = + (st->goods[type].waiting_acceptance & ~0xFFF) + + min(0xFFF, (st->goods[type].waiting_acceptance & 0xFFF) + amount); + + st->goods[type].enroute_time = 0; + st->goods[type].enroute_from = st->index; + InvalidateWindow(WC_STATION_VIEW, st->index); +} + +int32 CmdRenameStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str,old_str; + Station *st; + + str = AllocateName((byte*)_decode_parameters, 6); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + st = DEREF_STATION(p1); + old_str = st->string_id; + st->string_id = str; + UpdateStationVirtCoord(st); + DeleteName(old_str); + _station_sort_dirty = true; + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + + return 0; +} + + +uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount) +{ + Station *around_ptr[8]; + byte around[8], st_index; + int i; + Station *st; + uint moved; + uint best_rating, best_rating2; + Station *st1, *st2; + int t; + + memset(around, 0xff, sizeof(around)); + + w += 8; + h += 8; + + BEGIN_TILE_LOOP(cur_tile, w, h, tile - TILE_XY(4,4)) + cur_tile = TILE_MASK(cur_tile); + if (IS_TILETYPE(cur_tile, MP_STATION)) { + st_index = _map2[cur_tile]; + for(i=0; i!=8; i++) { + if (around[i] == 0xFF) { + st = DEREF_STATION(st_index); + if ((st->had_vehicle_of_type & HVOT_BUOY) == 0 && + st->blocked_months == 0 && + st->goods[type].rating != 0 && + (!_patches.selectgoods || st->goods[type].last_speed) && // if last_speed is 0, no vehicle has been there. + ((st->facilities & (byte)~FACIL_BUS_STOP)!=0 || type==CT_PASSENGERS) && + ((st->facilities & (byte)~FACIL_TRUCK_STOP)!=0 || type!=CT_PASSENGERS)) { + + around[i] = st_index; + around_ptr[i] = st; + } + break; + } else if (around[i] == st_index) + break; + } + } + END_TILE_LOOP(cur_tile, w, h, tile - TILE_XY(4,4)) + + /* no stations around at all? */ + if (around[0] == 0xFF) + return 0; + + if (around[1] == 0xFF) { + /* only one station around */ + moved = (amount * around_ptr[0]->goods[type].rating >> 8) + 1; + UpdateStationWaiting(around_ptr[0], type, moved); + return moved; + } + + /* several stations around, find the two with the highest rating */ + st2 = st1 = NULL; + best_rating = best_rating2 = 0; + for(i=0; i!=8 && around[i] != 0xFF; i++) { + if (around_ptr[i]->goods[type].rating >= best_rating) { + best_rating2 = best_rating; + st2 = st1; + + best_rating = around_ptr[i]->goods[type].rating; + st1 = around_ptr[i]; + } else if (around_ptr[i]->goods[type].rating >= best_rating2) { + best_rating2 = around_ptr[i]->goods[type].rating; + st2 = around_ptr[i]; + } + } + + assert(st1 != NULL); + assert(st2 != NULL); + assert(best_rating != 0 || best_rating2 != 0); + + /* the 2nd highest one gets a penalty */ + best_rating2 >>= 1; + + /* amount given to station 1 */ + t = (best_rating * (amount + 1)) / (best_rating + best_rating2); + + moved = 0; + if (t != 0) { + moved = (t * best_rating >> 8) + 1; + amount -= t; + UpdateStationWaiting(st1, type, moved); + } + + assert(amount >= 0); + + if (amount != 0) { + moved += (amount = (amount * best_rating2 >> 8) + 1); + UpdateStationWaiting(st2, type, amount); + } + + return moved; +} + +void BuildOilRig(uint tile) +{ + Station *st; + int j; + + FOR_ALL_STATIONS(st) { + if (st->xy == 0) { + st->town = ClosestTownFromTile(tile, (uint)-1); + st->sign.width_1 = 0; + if (!GenerateStationName(st, tile, 2)) + return; + + _map_type_and_height[tile] &= 0xF; + _map_type_and_height[tile] |= MP_STATION << 4; + _map5[tile] = 0x4B; + _map_owner[tile] = OWNER_NONE; + _map3_lo[tile] = 0; + _map3_hi[tile] = 0; + _map2[tile] = st->index; + + st->owner = 0x10; + st->airport_flags = 0; + st->airport_type = AT_OILRIG; + st->xy = tile; + st->bus_tile = 0; + st->lorry_tile = 0; + st->airport_tile = tile; + st->dock_tile = tile; + st->train_tile = 0; + st->had_vehicle_of_type = 0; + st->time_since_load = 255; + st->time_since_unload = 255; + st->delete_ctr = 0; + st->last_vehicle = INVALID_VEHICLE; + st->facilities = FACIL_AIRPORT | FACIL_DOCK; + for(j=0; j!=NUM_CARGO; j++) { + st->goods[j].waiting_acceptance = 0; + st->goods[j].days_since_pickup = 0; + st->goods[j].enroute_from = 0xFF; + st->goods[j].rating = 175; + st->goods[j].last_speed = 0; + st->goods[j].last_age = 255; + } + + UpdateStationVirtCoordDirty(st); + UpdateStationAcceptance(st, false); + return; + } + } +} + +void DeleteOilRig(uint tile) +{ + Station *st = DEREF_STATION(_map2[tile]); + + DoClearSquare(tile); + + st->dock_tile = 0; + st->airport_tile = 0; + st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK); + st->airport_flags = 0; + UpdateStationVirtCoordDirty(st); + DeleteStation(st); +} + +static void ChangeTileOwner_Station(uint tile, byte old_player, byte new_player) +{ + if (_map_owner[tile] != old_player) + return; + + if (new_player != 255) { + Station *st = DEREF_STATION(_map2[tile]); + _map_owner[tile] = new_player; + st->owner = new_player; + _station_sort_dirty = true; + } else { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } +} + +static int32 ClearTile_Station(uint tile, byte flags) { + byte m5 = _map5[tile]; + Station *st; + + if (flags & DC_AUTO) { + if (m5 < 8) return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD); + if (m5 < 0x43 || (m5 >= 83 && m5 <= 114)) return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST); + if (m5 < 0x47) return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION); + if (m5 < 0x4B) return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION); + if (m5 == 0x52) return_cmd_error(STR_306A_BUOY_IN_THE_WAY); + if (m5 != 0x4B && m5 < 0x53) return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST); + SET_DPARAM16(0, STR_4807_OIL_RIG); + return_cmd_error(STR_4800_IN_THE_WAY); + } + + st = DEREF_STATION(_map2[tile]); + + if (m5 < 8) + return RemoveRailroadStation(st, flags); + + // original airports < 67, new airports between 83 - 114 + if (m5 < 0x43 || ( m5 >= 83 && m5 <= 114) ) + return RemoveAirport(st, flags); + + if (m5 < 0x47) + return RemoveTruckStation(st, flags); + + if (m5 < 0x4B) + return RemoveBusStation(st, flags); + + if (m5 == 0x52) + return RemoveBuoy(st, flags); + + if (m5 != 0x4B && m5 < 0x53) + return RemoveDock(st, flags); + + return CMD_ERROR; + +} + +void InitializeStations() +{ + int i; + memset(_stations, 0, sizeof(_stations)); + for(i=0;i!=lengthof(_stations); i++) + _stations[i].index=i; + _station_tick_ctr = 0; + _station_sort_dirty = true; // set stations to be sorted on first load +} + + +const TileTypeProcs _tile_type_station_procs = { + DrawTile_Station, /* draw_tile_proc */ + GetSlopeZ_Station, /* get_slope_z_proc */ + ClearTile_Station, /* clear_tile_proc */ + GetAcceptedCargo_Station, /* get_accepted_cargo_proc */ + GetTileDesc_Station, /* get_tile_desc_proc */ + GetTileTrackStatus_Station, /* get_tile_track_status_proc */ + ClickTile_Station, /* click_tile_proc */ + AnimateTile_Station, /* animate_tile_proc */ + TileLoop_Station, /* tile_loop_clear */ + ChangeTileOwner_Station, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + VehicleEnter_Station, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; + + +static const byte _station_desc[] = { + SLE_VAR(Station,xy, SLE_UINT16), + SLE_VAR(Station,bus_tile, SLE_UINT16), + SLE_VAR(Station,lorry_tile, SLE_UINT16), + SLE_VAR(Station,train_tile, SLE_UINT16), + SLE_VAR(Station,airport_tile, SLE_UINT16), + SLE_VAR(Station,dock_tile, SLE_UINT16), + SLE_REF(Station,town, REF_TOWN), + SLE_VAR(Station,trainst_w, SLE_UINT8), + SLE_CONDVAR(Station,trainst_h, SLE_UINT8, 2, 255), + + // alpha_order was stored here in savegame format 0 - 3 + SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 1, 0, 3), + + SLE_VAR(Station,string_id, SLE_STRINGID), + SLE_VAR(Station,had_vehicle_of_type,SLE_UINT16), + + SLE_VAR(Station,time_since_load, SLE_UINT8), + SLE_VAR(Station,time_since_unload, SLE_UINT8), + SLE_VAR(Station,delete_ctr, SLE_UINT8), + SLE_VAR(Station,owner, SLE_UINT8), + SLE_VAR(Station,facilities, SLE_UINT8), + SLE_VAR(Station,airport_type, SLE_UINT8), + SLE_VAR(Station,truck_stop_status, SLE_UINT8), + SLE_VAR(Station,bus_stop_status, SLE_UINT8), + SLE_VAR(Station,blocked_months, SLE_UINT8), + + SLE_CONDVAR(Station,airport_flags, SLE_VAR_U32 | SLE_FILE_U16, 0, 2), + SLE_CONDVAR(Station,airport_flags, SLE_UINT32, 3, 255), + + SLE_VAR(Station,last_vehicle, SLE_UINT16), + + SLE_CONDVAR(Station,class_id, SLE_UINT8, 3, 255), + SLE_CONDVAR(Station,stat_id, SLE_UINT8, 3, 255), + SLE_CONDVAR(Station,build_date, SLE_UINT16, 3, 255), + + // reserve extra space in savegame here. (currently 32 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 32, 2, 255), + + SLE_END() +}; + +static const byte _goods_desc[] = { + SLE_VAR(GoodsEntry,waiting_acceptance,SLE_UINT16), + SLE_VAR(GoodsEntry,days_since_pickup, SLE_UINT8), + SLE_VAR(GoodsEntry,rating, SLE_UINT8), + SLE_VAR(GoodsEntry,enroute_from, SLE_UINT8), + SLE_VAR(GoodsEntry,enroute_time, SLE_UINT8), + SLE_VAR(GoodsEntry,last_speed, SLE_UINT8), + SLE_VAR(GoodsEntry,last_age, SLE_UINT8), + + SLE_END() +}; + + +static void SaveLoad_STNS(Station *st) +{ + int i; + SlObject(st, _station_desc); + for(i=0; i!=NUM_CARGO; i++) + SlObject(&st->goods[i], _goods_desc); +} + +static void Save_STNS() +{ + Station *st; + // Write the vehicles + FOR_ALL_STATIONS(st) { + if (st->xy != 0) { + SlSetArrayIndex(st->index); + SlAutolength((AutolengthProc*)SaveLoad_STNS, st); + } + } +} + +static void Load_STNS() +{ + int index; + while ((index = SlIterateArray()) != -1) { + Station *st = &_stations[index]; + SaveLoad_STNS(st); + + // this means it's an oldstyle savegame without support for nonuniform stations + if (st->train_tile && st->trainst_h == 0) { + int w = st->trainst_w >> 4; + int h = st->trainst_w & 0xF; + if (_map5[st->train_tile]&1) intswap(w,h); + st->trainst_w = w; + st->trainst_h = h; + } + } +} + +const ChunkHandler _station_chunk_handlers[] = { + { 'STNS', Save_STNS, Load_STNS, CH_ARRAY | CH_LAST}, +}; + diff --git a/station_gui.c b/station_gui.c new file mode 100644 --- /dev/null +++ b/station_gui.c @@ -0,0 +1,452 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "station.h" +#include "gfx.h" +#include "player.h" +#include "town.h" +#include "command.h" + +static void StationsWndShowStationRating(int x, int y, int type, uint acceptance, int rating) +{ + static const byte _rating_colors[NUM_CARGO] = {152,32,15,174,208,194,191,55,184,10,191,48}; + int color = _rating_colors[type]; + uint w; + + if (acceptance > 575) + acceptance = 575; + + acceptance = (acceptance + 7) >> 3; + + /* draw cargo */ + if ( (w=acceptance>>3) != 0) { + GfxFillRect(x, y, x+w-1, y+6, color); + x += w; + } + + if ( (w=acceptance&7) != 0) { + if (w==7) w--; + GfxFillRect(x, y+(w-1), x, y+6, color); + } + + x -= (acceptance>>3); + + DrawString(x+1, y, _cargoc.names_short[type], 0x10); + + /* draw green/red ratings bar */ + GfxFillRect(x+1, y+8, x+7, y+8, 0xB8); + + rating = (rating >> 5); + + if (rating != 0) { + GfxFillRect(x+1, y+8, x+rating, y+8, 0xD0); + } +} + +// used to get a sorted list of the stations +typedef struct StationSort { + uint16 index; + byte owner; +} StationSort; + +static StationSort _station_sort[lengthof(_stations)]; +static uint16 _num_station_sort[MAX_PLAYERS]; + +static char _bufcache[64]; +static uint16 _last_station_idx; + +static int CDECL StationSorterByName(const void *a, const void *b) +{ + char buf1[64]; + Station *st; + StationSort *cmp1, *cmp2; + cmp1 = (StationSort*)a; + cmp2 = (StationSort*)b; + + // sort stations by owner, and inside owner by name + if (cmp1->owner == cmp2->owner) { // if same owner, sort by name + st = DEREF_STATION(cmp1->index); + SET_DPARAM16(0, st->town->townnametype); + SET_DPARAM32(1, st->town->townnameparts); + GetString(buf1, st->string_id); + + if ( cmp2->index != _last_station_idx) { + _last_station_idx = cmp2->index; + st = DEREF_STATION(cmp2->index); + SET_DPARAM16(0, st->town->townnametype); + SET_DPARAM32(1, st->town->townnameparts); + GetString(_bufcache, st->string_id); + } + + return strcmp(buf1, _bufcache); // sort by name + } + return cmp1->owner - cmp2->owner; // sort by owner +} + +static void MakeSortedStationList(Window *w) +{ + Station *st; + uint16 n = 0; + uint16 *i; + // reset to 0 just to be sure + for (i = _num_station_sort; i != endof(_num_station_sort); i++) {*i = 0;} + + FOR_ALL_STATIONS(st) { + if(st->xy && st->owner != OWNER_NONE) { + _station_sort[n].index = st->index; + _station_sort[n++].owner = st->owner; + _num_station_sort[st->owner]++; // add number of stations of player + } + } + + // create cumulative station-ownage + // stations are stored as a cummulative index, eg 25, 41, 43. This means + // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 + for (i = &_num_station_sort[1]; i != endof(_num_station_sort); i++) {*i += *(i-1);} + + _last_station_idx = 255; // used for "cache" + qsort(_station_sort, n, sizeof(_station_sort[0]), StationSorterByName); + //#ifdef _DEBUG + // {printf("Resorting Stations list...\n");} + //#endif +} + +static void PlayerStationsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + byte i; + if (_station_sort_dirty) { + _station_sort_dirty = false; + MakeSortedStationList(w); + } + + // stations are stored as a cummulative index, eg 25, 41, 43. This means + // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 stations + i = (byte)(w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1];; + SetVScrollCount(w, _num_station_sort[w->window_number] - i); + + /* draw widgets, with player's name in the caption */ + { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, w->vscroll.count); + DrawWindowWidgets(w); + } + + { + byte p = 0; + Station *st; + int x,xb = 2; + int y = 16; // offset from top of widget + int j; + + if (w->vscroll.count == 0) { // player has no stations + DrawString(xb, y, STR_304A_NONE, 0); + return; + } + + i += w->vscroll.pos; // offset from sorted station list of current player + assert(i < _num_station_sort[w->window_number]); // at least one station must exist + + while (i < _num_station_sort[w->window_number]) { // do until max number of stations of owner + st = DEREF_STATION(_station_sort[i].index); + + SET_DPARAM16(0, st->index); + SET_DPARAM8(1, st->facilities); + x = DrawString(xb, y, STR_3049_0, 0) + 5; + + // show cargo waiting and station ratings + for(j=0; j!=NUM_CARGO; j++) { + int acc = (st->goods[j].waiting_acceptance & 0xFFF); + if (acc != 0) { + StationsWndShowStationRating(x, y, j, acc, st->goods[j].rating); + x += 10; + } + } + y += 10; + i++; // next station + if (++p == 12) { break;} // max number of stations in 1 window + } + } + } break; + case WE_CLICK: { + switch(e->click.widget) { + case 2: { + uint y = (e->click.pt.y - 15) / 10; + uint16 p; + + if (!IS_INT_INSIDE(y, 0, 12)) { return;} + + // get the p-th OUR station from globally sorted list + p = y + w->vscroll.pos; + p += (w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1]; // get offset of first station in list + if (p < _num_station_sort[w->window_number]) { + ScrollMainWindowToTile(DEREF_STATION(_station_sort[p].index)->xy); + } + } break; + } + } break; + + case WE_4: + WP(w,plstations_d).refresh_counter++; + if (WP(w,plstations_d).refresh_counter==5) { + WP(w,plstations_d).refresh_counter = 0; + SetWindowDirty(w); + } + break; + } +} + +static const Widget _player_stations_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 357, 0, 13, STR_3048_STATIONS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 346, 14, 137, 0x0, STR_3057_STATION_NAMES_CLICK_ON}, +{ WWT_SCROLLBAR, 14, 347, 357, 14, 137, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _player_stations_desc = { + -1, -1, 358, 138, + WC_STATION_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _player_stations_widgets, + PlayerStationsWndProc +}; + + +void ShowPlayerStations(int player) +{ + Window *w; + + w = AllocateWindowDescFront(&_player_stations_desc, player); + if (w) { + w->caption_color = (byte)w->window_number; + w->vscroll.cap = 12; + } +} + +static const Widget _station_view_expanded_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 248, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 237, 14, 65, 0x0, 0}, +{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_IMGBTN, 14, 0, 248, 66, 197, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 82, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, +{ WWT_PUSHTXTBTN, 14, 83, 165, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO}, +{ WWT_PUSHTXTBTN, 14, 166, 248, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_LAST}, +}; + +static const Widget _station_view_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 248, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 237, 14, 65, 0x0, 0}, +{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 14, 0, 248, 66, 97, 0x0, 0}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 82, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, +{ WWT_PUSHTXTBTN, 14, 83, 165, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS}, +{ WWT_PUSHTXTBTN, 14, 166, 248, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_LAST}, +}; + +static void DrawStationViewWindow(Window *w) +{ + Station *st; + int i; + int num; + int x,y; + int pos; + StringID str; + byte station_id; + byte *b; + + + station_id = (byte)w->window_number; + + st = DEREF_STATION(w->window_number); + + num = 1; + for(i=0; i!=NUM_CARGO; i++) { + if ((st->goods[i].waiting_acceptance & 0xFFF) != 0) { + num++; + if (st->goods[i].enroute_from != station_id) + num++; + } + } + SetVScrollCount(w, num); + + w->disabled_state = st->owner == _local_player ? 0 : (1 << 8); + SET_DPARAM16(0, st->index); + SET_DPARAM8(1, st->facilities); + DrawWindowWidgets(w); + + x = 2; + y = 15; + pos = w->vscroll.pos; + + if (--pos < 0) { + str = STR_00D0_NOTHING; + for(i=0; i!=NUM_CARGO; i++) + if (st->goods[i].waiting_acceptance & 0xFFF) + str = STR_EMPTY; + SET_DPARAM16(0, str); + DrawString(x, y, STR_0008_WAITING, 0); + y += 10; + } + + i = 0; + do { + uint waiting = (st->goods[i].waiting_acceptance & 0xFFF); + if (waiting == 0) + continue; + + num = (waiting + 5) / 10; + if (num != 0) { + int cur_x = x; + num = min(num, 23); + do { + DrawSprite(_cargoc.sprites[i], cur_x, y); + cur_x += 10; + } while (--num); + } + + if ( st->goods[i].enroute_from == station_id) { + if (--pos < 0) { + SET_DPARAM16(1, waiting); + SET_DPARAM16(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32)); + DrawStringRightAligned(x + 234, y, STR_0009, 0); + y += 10; + } + } else { + /* enroute */ + if (--pos < 0) { + SET_DPARAM16(1, waiting); + SET_DPARAM16(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32)); + DrawStringRightAligned(x + 234, y, STR_000A_EN_ROUTE_FROM, 0); + y += 10; + } + + if (pos > -5 && --pos < 0) { + SET_DPARAM16(0, st->goods[i].enroute_from); + DrawStringRightAligned(x + 234, y, STR_000B, 0); + y += 10; + } + } + } while (pos > -5 && ++i != 12); + + if (w->widget == _station_view_widgets) { + b = _userstring; + b[0] = 0x81; + b[1] = STR_000C_ACCEPTS; + b[2] = STR_000C_ACCEPTS >> 8; + b += 3; + + for(i=0; i!=NUM_CARGO; i++) { + if (st->goods[i].waiting_acceptance & 0x8000) { + b[0] = 0x81; + WRITE_LE_UINT16(b+1, _cargoc.names_s[i]); + WRITE_LE_UINT16(b+3, 0x202C); + b += 5; + } + } + + if (b == (byte*)&_userstring[3]) { + b[0] = 0x81; + b[1] = STR_00D0_NOTHING; + b[2] = STR_00D0_NOTHING >> 8; + b[3] = 0; + } else { + b[-2] = 0; + } + + DrawStringMultiLine(2, 67, STR_SPEC_USERSTRING, 245); + } else { + + DrawString(2, 67, STR_3034_LOCAL_RATING_OF_TRANSPORT, 0); + + y = 77; + for(i=0; i!=NUM_CARGO; i++) { + if (st->goods[i].enroute_from != 0xFF) { + SET_DPARAM16(0, _cargoc.names_s[i]); + SET_DPARAM8(2, st->goods[i].rating * 101 >> 8); + SET_DPARAM16(1, STR_3035_APPALLING + (st->goods[i].rating >> 5)); + DrawString(8, y, STR_303D, 0); + y += 10; + } + } + } +} + + +static void StationViewWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawStationViewWindow(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 6: + ScrollMainWindowToTile(DEREF_STATION(w->window_number)->xy); + break; + + case 7: + SetWindowDirty(w); + + /* toggle height/widget set */ + w->height ^= (210 ^ 110); + *(uint32*)&w->widget ^= (uint32)_station_view_expanded_widgets ^ (uint32)_station_view_widgets; + + SetWindowDirty(w); + break; + + case 8: { + Station *st = DEREF_STATION(w->window_number); + SET_DPARAM16(0, st->town->townnametype); + SET_DPARAM32(1, st->town->townnameparts); + ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number); + } break; + } + break; + + case WE_ON_EDIT_TEXT: { + Station *st; + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + + st = DEREF_STATION(w->window_number); + DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION)); + } break; + } +} + + +static const WindowDesc _station_view_desc = { + -1, -1, 249, 110, + WC_STATION_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _station_view_widgets, + StationViewWndProc +}; + +void ShowStationViewWindow(int station) +{ + Window *w; + byte color; + + w = AllocateWindowDescFront(&_station_view_desc, station); + if (w) { + color = DEREF_STATION(w->window_number)->owner; + if (color != 0x10) + w->caption_color = color; + w->vscroll.cap = 5; + } +} diff --git a/stdafx.h b/stdafx.h new file mode 100644 --- /dev/null +++ b/stdafx.h @@ -0,0 +1,184 @@ +#if !defined(_STDAFX_H) +#define _STDAFX_H + +#if defined(_MSC_VER) +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#pragma warning(disable: 4100) // parameter not used +#pragma warning(disable: 4244) // conversion +#pragma warning(disable: 4245) // conversion +#pragma warning(disable: 4201) // nameless union +#pragma warning(disable: 4514) // removed unref inline +#pragma warning(disable: 4127) // constant conditional expression +#pragma warning(disable: 4276) // MSVC BUG??? Complains about function body not declared when using function pointers +#pragma warning(disable: 4761) // warning C4761: integral size mismatch in argument; conversion supplied +#endif + +#include +#include +#include +#include + +#if defined(UNIX) +# include +#endif + +#ifdef __BEOS__ +#include +#endif + +#define BSWAP32(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | (((x) << 24) & 0xFF000000)) +#define BSWAP16(x) ((x) >> 8 | (x) << 8) + +// by default we use [] var arrays +#define VARARRAY_SIZE + + +// Stuff for GCC +#if defined(__GNUC__) +# define NORETURN +# define FORCEINLINE inline +# define INLINE inline +# define CDECL +//#include +//#include +# define __int64 long long +# define NOT_REACHED() +# define GCC_PACK __attribute__((packed)) + +# if (__GNUC__ == 2) +# undef VARARRAY_SIZE +# define VARARRAY_SIZE 0 +# endif +#endif + +// Stuff for MSVC +#if defined(_MSC_VER) +# include // alloca() +# define NORETURN __declspec(noreturn) +# define FORCEINLINE __forceinline +# define INLINE _inline +# define CDECL _cdecl +# define NOT_REACHED() _assume(0) +# define snprintf _snprintf +# undef TTD_ALIGNMENT_4 +# undef TTD_ALIGNMENT_2 +# define GCC_PACK +#endif + +#if defined(WIN32) +# define TTD_LITTLE_ENDIAN +#endif + +#if defined(i386) +# define TTD_LITTLE_ENDIAN +#endif + +#if defined(__MORPHOS__) +# define TTD_BIG_ENDIAN +#endif + +// Check endianness +#if !defined(TTD_LITTLE_ENDIAN) && !defined(TTD_BIG_ENDIAN) +# if defined(_BIG_ENDIAN) +# define TTD_BIG_ENDIAN +# elif defined(_LITTLE_ENDIAN) +# define TTD_LITTLE_ENDIAN +# else +# error No endianness defined, use either TTD_LITTLE_ENDIAN or TTD_BIG_ENDIAN +#endif +#endif + +#if defined(UNIX) +#define PATHSEP "/" +#else +#define PATHSEP "\\" +#endif + + +typedef unsigned char byte; +#ifndef __BEOS__ // already defined +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +#endif + +// This is already defined in unix +#if !defined(UNIX) && !defined(__CYGWIN__) + typedef unsigned int uint; +#endif + +#if defined(_MSC_VER) +#define memcpy_overlapping memcpy +#else +#define memcpy_overlapping memmove +#endif + +#ifndef __BEOS__ +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; +#ifndef __cplusplus +typedef unsigned char bool; +#endif +typedef signed __int64 int64; +typedef unsigned __int64 uint64; +#endif + +// Setup alignment and conversion macros +#if defined(TTD_BIG_ENDIAN) +# define TTD_ALIGNMENT_2 +# define TTD_ALIGNMENT_4 +static uint32 INLINE TO_LE32(uint32 x) { return BSWAP32(x); } +static uint16 INLINE TO_LE16(uint16 x) { return BSWAP16(x); } +# define TO_BE32(x) x +# define TO_BE16(x) x +#define TO_BE32X(x) x +#else +# define TO_LE32(x) x +# define TO_LE16(x) x +#define TO_BE32X(x) BSWAP32(x) +static uint32 FORCEINLINE TO_BE32(uint32 x) { return BSWAP32(x); } +static uint16 FORCEINLINE TO_BE16(uint16 x) { return BSWAP16(x); } +#endif + +#if !defined(GAME_DATA_DIR) +#define GAME_DATA_DIR "" +#endif + +#if !defined(PERSONAL_DIR) +#define PERSONAL_DIR "" +#endif + +#ifndef __cplusplus +#ifndef __BEOS__ +enum { + false = 0, + true = 1, +}; +#endif +#endif + +// Compile time assertions +#define assert_compile(expr) void __ct_assert__(int a[1 - 2 * !(expr)]); + +assert_compile(sizeof(uint32) == 4); +assert_compile(sizeof(uint16) == 2); +assert_compile(sizeof(uint8) == 1); + +#define lengthof(x) (sizeof(x)/sizeof(x[0])) +#define endof(x) (&x[lengthof(x)]) +#ifndef offsetof +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif + + +// take care of some name clashes on macos +#if defined(__APPLE__) +#define GetString OTTD_GetString +#define DrawString OTTD_DrawString +#define Random OTTD_Random +#endif + +#endif // !defined(_STDAFX_H) diff --git a/strgen/stdafx.c b/strgen/stdafx.c new file mode 100644 --- /dev/null +++ b/strgen/stdafx.c @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// strgen.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 diff --git a/strgen/stdafx.h b/strgen/stdafx.h new file mode 100644 --- /dev/null +++ b/strgen/stdafx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__532D0883_575C_4F5F_AE7E_10FB6FEC34F3__INCLUDED_) +#define AFX_STDAFX_H__532D0883_575C_4F5F_AE7E_10FB6FEC34F3__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__532D0883_575C_4F5F_AE7E_10FB6FEC34F3__INCLUDED_) diff --git a/strgen/strgen.c b/strgen/strgen.c new file mode 100644 --- /dev/null +++ b/strgen/strgen.c @@ -0,0 +1,784 @@ +#include "../stdafx.h" +#include +#include +#include +#include + +#if !defined(WIN32) || defined(__CYGWIN__) +#include +#endif + +#ifdef WITH_REV +extern char _openttd_revision[]; +#endif + +/* Compiles a list of strings into a compiled string list */ + +#define lengthof(x) (sizeof(x)/sizeof(x[0])) + +typedef void (*ParseCmdProc)(char *buf, int value); + +typedef struct { + uint32 ident; + uint32 version; // 32-bits of auto generated version info which is basically a hash of strings.h + char name[32]; // the international name of this language + char own_name[32]; // the localized name of this language + uint16 offsets[32]; // the offsets +} LanguagePackHeader; + +typedef struct CmdStruct { + const char *cmd; + ParseCmdProc proc; + long value; +} CmdStruct; + +typedef struct LineName { + struct LineName *hash_next; + int value; + char str[1]; +} LineName; + +int _cur_line; +bool _warnings; + +uint32 _hash; +char _lang_name[32], _lang_ownname[32]; + +#define HASH_SIZE 1023 +LineName *_hash_head[HASH_SIZE]; +unsigned int hash_str(const char *s) { + unsigned int hash = 0; + for(;*s;s++) + hash = ((hash << 3) | (hash >> 29)) ^ *s; + return hash % HASH_SIZE; +} +void hash_add(const char *s, int value) { + unsigned int len = strlen(s); + LineName *ln = (LineName*)malloc(sizeof(LineName) + len); + unsigned int hash = hash_str(s); + ln->hash_next = _hash_head[hash]; + _hash_head[hash] = ln; + ln->value = value; + ln->str[len] = 0; + memcpy(ln->str, s, len); +} + +int hash_find(const char *s) { + LineName *ln = _hash_head[hash_str(s)]; + while (ln != NULL) { + if (!strcmp(ln->str, s)) { + return ln->value; + } + ln = ln->hash_next; + } + return -1; +} + +void warning(const char *s, ...) { + char buf[1024]; + va_list va; + va_start(va, s); + vsprintf(buf, s, va); + va_end(va); + fprintf(stderr, "%d: ERROR: %s\n", _cur_line, buf); + _warnings = true; +} + +void NORETURN error(const char *s, ...) { + char buf[1024]; + va_list va; + va_start(va, s); + vsprintf(buf, s, va); + va_end(va); + fprintf(stderr, "%d: FATAL: %s\n", _cur_line, buf); + exit(1); +} + +void ttd_strlcpy(char *dst, const char *src, size_t len) +{ + assert(len > 0); + while (--len && *src) + *dst++=*src++; + *dst = 0; +} + + +// first byte tells if it's english.lng or a custom language file +// second part is the name of the string +// third part is the actual string contents +char *allstr[65536]; + +byte _put_buf[4096]; +int _put_pos; +int _next_string_id; + +void put_byte(byte c) { + if (_put_pos == lengthof(_put_buf)) + error("Put buffer too small"); + _put_buf[_put_pos++] = c; +} + +void emit_buf(int ent) { + char *s; + + if (ent < 0 || ent >= 0x10000) { + warning("Invalid string ID %d\n", ent); + return; + } + + if (allstr[ent] != 0) { + warning("Duplicate string ID %d\n", ent); + return; + } + + // Allocate the string, and put the uint16 before with the length. + s = (char*)malloc(sizeof(uint16) + _put_pos); + *((uint16*)s) = _put_pos; + memcpy(s + sizeof(uint16), _put_buf, _put_pos); + + allstr[ent] = s; + + _put_pos = 0; +} + +void EmitSingleByte(char *buf, int value) { + if (*buf != 0) + warning("Ignoring trailing letters in command"); + put_byte((byte)value); +} + +void EmitEscapedByte(char *buf, int value) { + if (*buf != 0) + warning("Ignoring trailing letters in command"); + put_byte((byte)0x85); + put_byte((byte)value); +} + + +void EmitStringInl(char *buf, int value) { + int id; + + if (*buf>='0' && *buf <= '9') { + id = strtol(buf, NULL, 0); + if (id < 0 || id>=0x10000) { + warning("Invalid inline num %s\n", buf); + return; + } + } else { + id = hash_find(buf); + if (id == -1) { + warning("Invalid inline string '%s'", buf); + return; + } + } + + put_byte(0x81); + put_byte((byte)(id & 0xFF)); + put_byte((byte)(id >> 8)); +} + +void EmitSetX(char *buf, int value) { + char *err; + int x = strtol(buf, &err, 0); + if (*err != 0) + error("SetX param invalid"); + put_byte(1); + put_byte((byte)x); +} + +void EmitSetXY(char *buf, int value) { + char *err; + int x = strtol(buf, &err, 0), y; + if (*err != 0) error("SetXY param invalid"); + y = strtol(err+1, &err, 0); + if (*err != 0) error("SetXY param invalid"); + + put_byte(0x1F); + put_byte((byte)x); + put_byte((byte)y); +} + +static const CmdStruct _cmd_structs[] = { + // Update position + {"SETX", EmitSetX, 1}, + {"SETXY", EmitSetXY, 2}, + + // Font size + {"TINYFONT", EmitSingleByte, 8}, + {"BIGFONT", EmitSingleByte, 9}, + + // New line + {"", EmitSingleByte, 10}, + + // Colors + {"BLUE", EmitSingleByte, 15}, + {"SILVER", EmitSingleByte, 16}, + {"GOLD", EmitSingleByte, 17}, + {"RED", EmitSingleByte, 18}, + {"PURPLE", EmitSingleByte, 19}, + {"LTBROWN", EmitSingleByte, 20}, + {"ORANGE", EmitSingleByte, 21}, + {"GREEN", EmitSingleByte, 22}, + {"YELLOW", EmitSingleByte, 23}, + {"DKGREEN", EmitSingleByte, 24}, + {"CREAM", EmitSingleByte, 25}, + {"BROWN", EmitSingleByte, 26}, + {"WHITE", EmitSingleByte, 27}, + {"LTBLUE", EmitSingleByte, 28}, + {"GRAY", EmitSingleByte, 29}, + {"DKBLUE", EmitSingleByte, 30}, + {"BLACK", EmitSingleByte, 31}, + + // 0x7B=123 is the LAST special character we may use. + + // Numbers + {"COMMA32", EmitSingleByte, 0x7B}, + {"COMMA16", EmitSingleByte, 0x7C}, + {"COMMA8", EmitSingleByte, 0x7D}, + {"NUMU16", EmitSingleByte, 0x7E}, + + {"CURRENCY", EmitSingleByte, 0x7F}, + + {"CURRCOMPACT", EmitEscapedByte, 0}, // compact currency + {"INT32", EmitEscapedByte, 1}, // compact currency + {"REV", EmitEscapedByte, 2}, // openttd revision string + {"SHORTCARGO", EmitEscapedByte, 3}, // short cargo description, only ### tons, or ### litres + + {"STRINL", EmitStringInl, 0x81}, + + {"DATE_LONG", EmitSingleByte, 0x82}, + {"DATE_SHORT", EmitSingleByte, 0x83}, + + {"VELOCITY", EmitSingleByte, 0x84}, + {"SKIP16", EmitSingleByte, 0x85}, + {"SKIP", EmitSingleByte, 0x86}, + {"VOLUME", EmitSingleByte, 0x87}, + + {"STRING", EmitSingleByte, 0x88}, + + {"CARGO", EmitSingleByte, 0x99}, + {"STATION", EmitSingleByte, 0x9A}, + {"TOWN", EmitSingleByte, 0x9B}, + {"CURRENCY64", EmitSingleByte, 0x9C}, + {"CHECKPOINT", EmitSingleByte, 0x9D}, // checkpoint name + // 0x9E=158 is the LAST special character we may use. + + {"UPARROW", EmitSingleByte, 0xA0}, + {"POUNDSIGN", EmitSingleByte, 0xA3}, + {"YENSIGN", EmitSingleByte, 0xA5}, + {"COPYRIGHT", EmitSingleByte, 0xA9}, + {"DOWNARROW", EmitSingleByte, 0xAA}, + {"CHECKMARK", EmitSingleByte, 0xAC}, + {"CROSS", EmitSingleByte, 0xAD}, + {"RIGHTARROW", EmitSingleByte, 0xAF}, + + {"SMALLUPARROW", EmitSingleByte, 0xBC}, + {"SMALLDOWNARROW", EmitSingleByte, 0xBD}, + {"THREE_FOURTH", EmitSingleByte, 0xBE}, +}; + +const CmdStruct *find_cmd(const char *s, int len) { + int i; + const CmdStruct *cs = _cmd_structs; + for(i=0; i!=lengthof(_cmd_structs); i++,cs++) { + if (!strncmp(cs->cmd, s, len) && cs->cmd[len] == 0) + return cs; + } + return NULL; +} + + +// returns 0 on EOL +// returns 1-255 on literal byte +// else returns command struct +const CmdStruct *parse_command_string(char **str, char *param, const char *errortext) +{ + char *s = *str, *start; + byte c = *s++; + const CmdStruct *cmd; + + if (c != '{') { + *str = s; + return (CmdStruct*) (int)c; + } + + // parse command name + start = s; + for(;;) { + c = *s++; + if (c == '}' || c == ' ') + break; + if (c == 0) { + if (errortext) warning("Missing } from command '%s' in '%s'", start, errortext); + return NULL; + } + } + + cmd = find_cmd(start, s - start - 1); + if (cmd == NULL) { + if (errortext) warning("Undefined command '%.*s' in '%s'", s - start - 1, start, errortext); + return NULL; + } + + if (c == ' ') { + // copy params + start = s; + for(;;) { + c = *s++; + if (c == '}') break; + if (c == 0) { + if (errortext) warning("Missing } from command '%s' in '%s'", start, errortext); + return NULL; + } + *param++ = c; + } + + } + *param = 0; + + *str = s; + + return cmd; +} + + +void handle_pragma(char *str) +{ + if (!memcmp(str, "id ", 3)) { + _next_string_id = strtoul(str + 3, NULL, 0); + } else if (!memcmp(str, "name ", 5)) { + ttd_strlcpy(_lang_name, str + 5, sizeof(_lang_name)); + } else if (!memcmp(str, "ownname ", 8)) { + ttd_strlcpy(_lang_ownname, str + 8, sizeof(_lang_ownname)); + } else { + error("unknown pragma '%s'", str); + } +} + +bool check_commands_match(char *a, char *b) +{ + const CmdStruct *ar, *br; + char param[100]; + + do { + // read until next command from a. + do { + ar = parse_command_string(&a, param, NULL); + } while (ar != NULL && (unsigned long)ar <= 255); + + // read until next command from b. + do { + br = parse_command_string(&b, param, NULL); + } while (br != NULL && (unsigned long)br <= 255); + + // make sure they are identical + if (ar != br) return false; + } while (ar); + + return true; +} + +void handle_string(char *str, bool master) { + char *s,*t,*r; + int ent; + + if (*str == '#') { + if (str[1] == '#' && str[2] != '#') + handle_pragma(str + 2); + return; + } + + // Ignore comments & blank lines + if (*str == ';' || *str == ' ' || *str == 0) + return; + + s = strchr(str, ':'); + if (s == NULL) { + warning("Line has no ':' delimiter"); + return; + } + + // Trim spaces + for(t=s;t > str && (t[-1]==' ' || t[-1]=='\t'); t--); + *t = 0; + + ent = hash_find(str); + + s++; // skip : + + // allocate string entry + r = malloc(strlen(str) + strlen(s) + 3); + *r = master; + strcpy(r + 1, str); + strcpy(r + 2 + strlen(str), s); + + if (master) { + if (ent != -1) { + warning("String name '%s' is used multiple times", str); + return; + } + + ent = _next_string_id++; + if (allstr[ent]) { + warning("String ID 0x%X for '%s' already in use by '%s'", ent, str, allstr[ent] + 1); + return; + } + allstr[ent] = r; + + // add to hash table + hash_add(str, ent); + } else { + if (ent == -1) { + warning("String name '%s' does not exist in master file", str); + _warnings = 0; // non-fatal + return; + } + + if (!allstr[ent][0]) { + warning("String name '%s' is used multiple times", str); + _warnings = 0; // non-fatal + return; + } + + // check that the commands match + if (!check_commands_match(s, allstr[ent] + 2 + strlen(allstr[ent] + 1))) { + fprintf(stderr, "Warning: String name '%s' does not match the layout of the master string\n", str); + _warnings = 0; // non-fatal + return; + } + + if (s[0] == ':' && s[1] == 0) { + allstr[ent][0] = 0; // use string from master file legitiately + free(r); + } else { + free(allstr[ent]); + allstr[ent] = r; + } + } +} + +uint32 my_hash_str(uint32 hash, const char *s) +{ + for(;*s;s++) { + hash = ((hash << 3) | (hash >> 29)) ^ *s; + if (hash & 1) hash = (hash>>1) ^ 0xDEADBEEF; else hash >>= 1; + } + return hash; + +} + +void parse_file(const char *file, bool english) { + char buf[2048]; + int i; + FILE *in; + + in = fopen(file, "r"); + if (in == NULL) { error("Cannot open file '%s'", file); } + + _cur_line = 1; + while (fgets(buf, sizeof(buf),in) != NULL) { + i = strlen(buf); + while (i>0 && (buf[i-1]=='\r' || buf[i-1]=='\n' || buf[i-1] == ' ')) i--; + buf[i] = 0; + + handle_string(buf, english); + _cur_line++; + } + + fclose(in); + + // make a hash of the file to get a unique "version number" + if (english) { + uint32 hash = 0; + char *s; + const CmdStruct *cs; + for(i = 0; i!=65536; i++) { + if ((s=allstr[i]) != NULL) { + hash ^= i * 0x717239; + if (hash & 1) hash = (hash>>1) ^ 0xDEADBEEF; else hash >>= 1; + hash = my_hash_str(hash, s + 1); + + s = s + 2 + strlen(s + 1); + while ((cs = parse_command_string(&s, buf, NULL)) != 0) { + if ( (uint)cs >= 256) { + hash ^= (cs - _cmd_structs) * 0x1234567; + if (hash & 1) hash = (hash>>1) ^ 0xF00BAA4; else hash >>= 1; + } + } + } + } + _hash = hash; + } +} + +int count_inuse(int grp) { + int i; + + for(i=0x800; --i >= 0;) { + if (allstr[(grp<<11)+i] != NULL) + break; + } + return i + 1; +} + +void check_all_used() { + int i; + LineName *ln; + int num_warn = 10; + + for (i=0; i!=HASH_SIZE; i++) { + for(ln = _hash_head[i]; ln!=NULL; ln = ln->hash_next) { + if (allstr[ln->value] == 0) { + if (++num_warn < 50) { + warning("String %s has no definition. Using NULL value", ln->str); + } + _put_pos = 0; + emit_buf(ln->value); + } + } + } +} + +void write_length(FILE *f, uint length) +{ + if (length < 0xC0) { + fputc(length, f); + } else if (length < 0x4000) { + fputc((length >> 8) | 0xC0, f); + fputc(length & 0xFF, f); + } else { + error("string too long"); + } +} + +void gen_output(FILE *f) { + uint16 in_use[32]; + uint16 in_use_file[32]; + int i,j; + int tot_str = 0; + + check_all_used(); + + for(i=0; i!=32; i++) { + int n = count_inuse(i); + in_use[i] = n; + in_use_file[i] = TO_LE16(n); + tot_str += n; + } + + fwrite(in_use_file, 32*sizeof(uint16), 1, f); + + for(i=0; i!=32; i++) { + for(j=0; j!=in_use[i]; j++) { + char *s = allstr[(i<<11)+j]; + if (s == NULL) error("Internal error, s==NULL"); + + write_length(f, *(uint16*)s); + fwrite(s + sizeof(uint16), *(uint16*)s , 1, f); + tot_str--; + } + } + + fputc(0, f); // write trailing nul character. + + if (tot_str != 0) { + error("Internal error, tot_str != 0"); + } +} + +bool compare_files(const char *n1, const char *n2) +{ + FILE *f1, *f2; + char b1[4096]; + char b2[4096]; + size_t l1, l2; + + f2 = fopen(n2, "rb"); + if (f2 == NULL) return false; + + f1 = fopen(n1, "rb"); + if (f1 == NULL) error("can't open %s", n1); + + do { + l1 = fread(b1, 1, sizeof(b1), f1); + l2 = fread(b2, 1, sizeof(b2), f2); + + if (l1 != l2 || memcmp(b1, b2, l1)) { + fclose(f2); + fclose(f1); + return false; + } + } while (l1); + + fclose(f2); + fclose(f1); + return true; +} + +void write_strings_h(const char *filename) +{ + FILE *out; + int i; + int next = -1; + int lastgrp; + + out = fopen("tmp.xxx", "w"); + if (out == NULL) { error("can't open tmp.xxx"); } + + fprintf(out, "enum {"); + + lastgrp = 0; + + for(i = 0; i!=65536; i++) { + if (allstr[i]) { + if (lastgrp != (i >> 11)) { + lastgrp = (i >> 11); + fprintf(out, "};\n\nenum {"); + } + + fprintf(out, next == i ? "%s,\n" : "\n%s = 0x%X,\n", allstr[i] + 1, i); + next = i + 1; + } + } + + fprintf(out, "};\n"); + + fprintf(out, + "\nenum {\n" + "\tLANGUAGE_PACK_IDENT = 'GNAL',\n" + "\tLANGUAGE_PACK_VERSION = 0x%X,\n" + "};\n", (unsigned int)_hash); + + + fclose(out); + + if (compare_files("tmp.xxx", filename)) { + // files are equal. tmp.xxx is not needed + unlink("tmp.xxx"); + } else { + // else rename tmp.xxx into filename +#if defined(WIN32) + unlink(filename); +#endif + if (rename("tmp.xxx", filename) == -1) error("rename() failed"); + } +} + +void write_langfile(const char *filename, int show_todo) +{ + FILE *f; + int in_use[32]; + LanguagePackHeader hdr; + int i,j; + const CmdStruct *cs; + char param[128]; + + f = fopen(filename, "wb"); + if (f == NULL) error("can't open %s", filename); + + memset(&hdr, 0, sizeof(hdr)); + for(i=0; i!=32; i++) { + int n = count_inuse(i); + in_use[i] = n; + hdr.offsets[i] = TO_LE16(n); + } + + + hdr.ident = TO_LE32('GNAL'); + hdr.version = TO_LE32(_hash); + strcpy(hdr.name, _lang_name); + strcpy(hdr.own_name, _lang_ownname); + + fwrite(&hdr, sizeof(hdr), 1, f); + + for(i=0; i!=32; i++) { + for(j=0; j!=in_use[i]; j++) { + char *s = allstr[(i<<11)+j], *str; + + if (s == NULL) { + write_length(f, 0); + } else { + // move to string + str = s + 2 + strlen(s + 1); + + if (show_todo && s[0]) { + if (show_todo == 2) { + fprintf(stderr, "Warning:%s: String '%s' is untranslated\n", filename, s + 1); + } else { + char *s = " "; + while(*s) put_byte(*s++); + } + } + + for(;;) { + cs = parse_command_string(&str, param, s[0] ? "english.lng" : filename); + if (cs == NULL) break; + if ( (unsigned long) cs <= 255) { + put_byte( (byte) (int)cs); + } else { + cs->proc(param, cs->value); + } + } + + write_length(f, _put_pos); + fwrite(_put_buf, 1, _put_pos, f); + _put_pos = 0; + } + } + } + + fputc(0, f); + + fclose(f); +} + +int main(int argc, char* argv[]) +{ + char *r; + char buf[256]; + int show_todo = 0; + + if (argc > 1 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) { +#ifdef WITH_REV + puts((char*)_openttd_revision); +#endif + return 0; + } + + if (argc > 1 && !strcmp(argv[1], "-t")) { + show_todo = 1; + argc--, argv++; + } + + if (argc > 1 && !strcmp(argv[1], "-w")) { + show_todo = 2; + argc--, argv++; + } + + + if (argc == 1) { + // parse master file + parse_file("lang/english.txt", true); + if (_warnings) return 1; + + // write english.lng and strings.h + + write_langfile("lang/english.lng", 0); + write_strings_h("table/strings.h"); + + } else if (argc == 2) { + parse_file("lang/english.txt", true); + parse_file(argv[1], false); + if (_warnings) return 1; + strcpy(buf, argv[1]); + r = strrchr(buf, '.'); + if (!r || strcmp(r, ".txt")) r = strchr(buf, 0); + strcpy(r, ".lng"); + write_langfile(buf, show_todo); + } else { + fprintf(stderr, "invalid arguments\n"); + } + + return 0; +} + diff --git a/strgen/strgen.dsp b/strgen/strgen.dsp new file mode 100644 --- /dev/null +++ b/strgen/strgen.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="strgen" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=strgen - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "strgen.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "strgen.mak" CFG="strgen - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "strgen - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "strgen - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "strgen - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x41d /d "_DEBUG" +# ADD RSC /l 0x41d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "strgen - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "strgen___Win32_Release" +# PROP BASE Intermediate_Dir "strgen___Win32_Release" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Zp4 /MD /W3 /GX /O1 /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# ADD BASE RSC /l 0x41d /d "_DEBUG" +# ADD RSC /l 0x41d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /debug + +!ENDIF + +# Begin Target + +# Name "strgen - Win32 Debug" +# Name "strgen - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\stdafx.c + +!IF "$(CFG)" == "strgen - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "strgen - Win32 Release" + +# SUBTRACT BASE CPP /YX /Yc /Yu +# ADD CPP /Gr /Zp4 /MD /GX- /O1 +# SUBTRACT CPP /Z /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\strgen.c + +!IF "$(CFG)" == "strgen - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "strgen - Win32 Release" + +# SUBTRACT BASE CPP /YX /Yc /Yu +# ADD CPP /Gr /Zp4 /MD /GX- /O1 +# SUBTRACT CPP /Z /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group +# End Target +# End Project diff --git a/strgen/strgen.dsw b/strgen/strgen.dsw new file mode 100644 --- /dev/null +++ b/strgen/strgen.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "strgen"=.\strgen.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/strgen/strgen.vcproj b/strgen/strgen.vcproj new file mode 100644 --- /dev/null +++ b/strgen/strgen.vcproj @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/strings.c b/strings.c new file mode 100644 --- /dev/null +++ b/strings.c @@ -0,0 +1,881 @@ +#include "stdafx.h" +#include "ttd.h" +#include "station.h" +#include "town.h" +#include "vehicle.h" + +#define USE_TABLE(x) { assert(index < lengthof(x)); str = x[index]; break; } + +static byte *StationGetSpecialString(byte *buff); +static byte *GetSpecialTownNameString(byte *buff, int ind); +static byte *GetSpecialPlayerNameString(byte *buff, int ind); + +static byte *DecodeString(byte *buff, const byte *str); + +static byte **_langpack_offs; +static byte *_langpack; +static uint _langtab_num[32]; // Offset into langpack offs +static uint _langtab_start[32]; // Offset into langpack offs + +#ifdef WITH_REV_HACK +#define WITH_REV +const char _openttd_revision[] = WITH_REV_HACK; +#endif + +#ifdef WITH_REV +extern const char _openttd_revision[]; +#endif + +typedef byte *PlayerNameGeneratorProc(byte *buffr); + +typedef struct { + uint32 ident; + uint32 version; // 32-bits of auto generated version info which is basically a hash of strings.h + char name[32]; // the international name of this language + char own_name[32]; // the localized name of this language + uint16 offsets[32]; // the offsets +} LanguagePackHeader; + +typedef struct { + uint16 rate; + char separator; + byte flags; + char pre[4]; + char post[4]; +} CurrencySpec; + +enum { + CF_TOEURO_2002 = 1, + CF_ISEURO = 2, +}; + +static const CurrencySpec _currency_specs[] = { + { 1, ',', 0, "\xA3", "" }, // british pounds + { 2, ',', 0, "$", "" }, // us dollars + { 10, '.', CF_TOEURO_2002, "FF ", "" }, // french francs + { 4, '.', CF_TOEURO_2002, "DM ", "" }, // deutsche mark + { 200, ',', 0, "\xA5", "" }, // yen + { 200, '.', CF_TOEURO_2002, "Pt", "" }, // spanish pesetas + { 376, ',', CF_TOEURO_2002, "", " Ft" }, + { 6, ' ', 0, "", " zl" }, + { 19, ',', CF_TOEURO_2002, "ATS ", "" }, + { 57, ',', CF_TOEURO_2002, "BEF ", "" }, + { 10, '.', 0, "", " kr" }, + { 8, ',', CF_TOEURO_2002, "FIM ", "" }, + { 480, ',', CF_TOEURO_2002, "GRD ", "" }, + { 2, ',', 0, "CHF ", "" }, + { 3, ',', CF_TOEURO_2002, "NLG ", "" }, + { 2730,',', CF_TOEURO_2002, "ITL ", "" }, + { 13, '.', 0, "", " kr" }, + { 5, ' ', 0, "", " rur" }, + { 50, ',', 0, "", " Kc" }, + { 130, '.', 0, "", " kr" }, + { 11, '.', 0, "", " kr" }, + { 2, ',', CF_ISEURO, "€", "" }, +}; + +const uint16 _currency_string_list[] = { + STR_CURR_POUNDS, + STR_CURR_DOLLARS, + STR_CURR_FF, + STR_CURR_DM, + STR_CURR_YEN, + STR_CURR_PT, + STR_CURR_FT, + STR_CURR_ZL, + STR_CURR_ATS, + STR_CURR_BEF, + STR_CURR_DKK, + STR_CURR_FIM, + STR_CURR_GRD, + STR_CURR_CHF, + STR_CURR_NLG, + STR_CURR_ITL, + STR_CURR_SEK, + STR_CURR_RUR, + STR_CURR_CZK, + STR_CURR_ISK, + STR_CURR_NOK, + STR_CURR_EUR, + INVALID_STRING_ID +}; + +static const uint16 _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = { + /* LT_NORMAL */ {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS, STR_TONS, STR_TONS, STR_TONS, STR_BAGS, STR_RES_OTHER}, + /* LT_HILLY */ {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS, STR_TONS, STR_RES_OTHER, STR_TONS, STR_BAGS, STR_TONS}, + /* LT_DESERT */ {STR_PASSENGERS, STR_LITERS, STR_BAGS, STR_LITERS, STR_TONS, STR_CRATES, STR_TONS, STR_TONS, STR_TONS, STR_LITERS, STR_BAGS, STR_TONS}, + /* LT_CANDY */ {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_NOTHING, STR_NOTHING, STR_TONS, STR_TONS, STR_LITERS, STR_TONS, STR_NOTHING, STR_LITERS, STR_NOTHING} +}; + +// get a mask of the allowed currencies depending on the year +uint GetMaskOfAllowedCurrencies() +{ + int i; + uint mask = 0; + for(i=0; i!=lengthof(_currency_specs); i++) { + byte flags = _currency_specs[i].flags; + if (_cur_year >= (2002-1920) && (flags & CF_TOEURO_2002)) continue; + if (_cur_year < (2000-1920) && (flags & CF_ISEURO)) continue; + mask |= (1 << i); + } + return mask; +} + +void CheckSwitchToEuro() +{ + if (_cur_year >= (2002-1920) && _currency_specs[_opt.currency].flags & CF_TOEURO_2002) { + _opt.currency = 21; // this is the index of euro above. + } +} + +static byte *str_cat(byte *dst, const byte *src) +{ + while ( (*dst++ = *src++) != 0) {} + return dst - 1; +} + +static byte *GetStringPtr(uint16 string) +{ + return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)]; +} + +byte *GetString(byte *buffr, uint16 string) +{ + uint index = string & 0x7FF; + uint tab = string >> 11; + + if (string == 0) error("!invalid string id 0 in GetString"); + + if ( tab == 4 && index >= 0xC0) + return GetSpecialTownNameString(buffr, index - 0xC0); + + if ( tab == 6 && index == 0xD1) + return StationGetSpecialString(buffr); + + if ( tab == 14 && index >= 0xE4) + return GetSpecialPlayerNameString(buffr, index - 0xE4); + + if ( tab == 15) + return GetName(index, buffr); + + // tab 31 is used for special or dynamic strings + if ( tab == 31) { + return DecodeString(buffr, index == (STR_SPEC_SCREENSHOT_NAME & 0x7FF) ? _screenshot_name : _userstring); + } + + if (index >= _langtab_num[tab]) + error("!String 0x%X is invalid. Probably because an old version of the .lng file.\n", string); + + return DecodeString(buffr, GetStringPtr(string)); +} + +void InjectDparam(int amount) +{ + memmove(_decode_parameters + amount, _decode_parameters, sizeof(_decode_parameters) - amount * sizeof(uint32)); +} + + +int32 GetParamInt32() +{ + int32 result = GET_DPARAM32(0); + memcpy_overlapping(&_decode_parameters[0], &_decode_parameters[1], sizeof(uint32) * (lengthof(_decode_parameters)-1)); + return result; +} + +int64 GetParamInt64() +{ + int64 result = GET_DPARAM32(0) + ((uint64)GET_DPARAM32(1) << 32); + memcpy_overlapping(&_decode_parameters[0], &_decode_parameters[2], sizeof(uint32) * (lengthof(_decode_parameters)-2)); + return result; +} + + +int GetParamInt16() +{ + int result = (int16)GET_DPARAM16(0); + memcpy_overlapping(&_decode_parameters[0], &_decode_parameters[1], sizeof(uint32) * (lengthof(_decode_parameters)-1)); + return result; +} + +int GetParamInt8() +{ + int result = (int8)GET_DPARAM8(0); + memcpy_overlapping(&_decode_parameters[0], &_decode_parameters[1], sizeof(uint32) * (lengthof(_decode_parameters)-1)); + return result; +} + +int GetParamUint16() +{ + int result = GET_DPARAM16(0); + memcpy_overlapping(&_decode_parameters[0], &_decode_parameters[1], sizeof(uint32) * (lengthof(_decode_parameters)-1)); + return result; +} + +static const uint32 _divisor_table[] = { + 1000000000, + 100000000, + 10000000, + 1000000, + + 100000, + 10000, + 1000, + 100, + 10, + 1 +}; + +static byte *FormatCommaNumber(byte *buff, int32 number) +{ + uint32 quot,divisor; + int i; + uint32 tot; + uint32 num; + + if (number < 0) { + *buff++ = '-'; + number = -number; + } + + num = number; + + tot = 0; + for(i=0; i!=10; i++) { + divisor = _divisor_table[i]; + quot = 0; + if (num >= divisor) { + quot = num / _divisor_table[i]; + num = num % _divisor_table[i]; + } + if (tot|=quot || i==9) { + *buff++ = (byte)('0' + quot); + if (i==0 || i==3 || i==6) *buff++ = ','; + } + } + + *buff = 0; + + return buff; +} + +static byte *FormatNoCommaNumber(byte *buff, int32 number) +{ + uint32 quot,divisor; + int i; + uint32 tot; + uint32 num; + + if (number < 0) { + *buff++ = '-'; + number = -number; + } + + num = number; + + tot = 0; + for(i=0; i!=10; i++) { + divisor = _divisor_table[i]; + quot = 0; + if (num >= divisor) { + quot = num / _divisor_table[i]; + num = num % _divisor_table[i]; + } + if (tot|=quot || i==9) { + *buff++ = (byte)('0' + quot); + } + } + + *buff = 0; + + return buff; +} + + +static byte *FormatYmdString(byte *buff, uint16 number) +{ + const byte *src; + YearMonthDay ymd; + + ConvertDayToYMD(&ymd, number); + + for(src = GetStringPtr(ymd.day+STR_01AC_1ST-1); (*buff++=*src++) != 0;) {} + + buff[-1] = ' '; + memcpy(buff, GetStringPtr(STR_0162_JAN + ymd.month), 4); + buff[3] = ' '; + + return FormatNoCommaNumber(buff+4, ymd.year + 1920); +} + +static byte *FormatMonthAndYear(byte *buff, uint16 number) +{ + const char *src; + YearMonthDay ymd; + + ConvertDayToYMD(&ymd, number); + + for(src = GetStringPtr(STR_MONTH_JAN + ymd.month); (*buff++=*src++) != 0;) {} + buff[-1] = ' '; + + return FormatNoCommaNumber(buff, ymd.year + 1920); +} + +static byte *FormatGenericCurrency(byte *buff, const CurrencySpec *spec, int64 number, bool compact) +{ + const char *s; + char c; + char buf[40], *p; + int j; + + // multiply by exchange rate + number *= spec->rate; + + // convert from negative + if (number < 0) { *buff++ = '-'; number = -number; } + + // add pre part + s = spec->pre; + while (s != spec->pre + lengthof(spec->pre) && (c=*s++)) *buff++ = c; + + // for huge numbers, compact the number into k or M + if (compact) { + compact = 0; + if (number >= 1000000000) { + number = (number + 500000) / 1000000; + compact = 'M'; + } else if (number >= 1000000) { + number = (number + 500) / 1000; + compact = 'k'; + } + } + + // convert to ascii number and add commas + p = buf; + j = 4; + do { + if (--j == 0) { *p++ = spec->separator; j = 3; } + *p++ = '0' + number % 10; + } while (number /= 10); + do *buff++ = *--p; while (p != buf); + + if (compact) *buff++ = compact; + + // add post part + s = spec->post; + while (s != spec->post + lengthof(spec->post) && (c=*s++)) *buff++ = c; + + return buff; +} + +static byte *DecodeString(byte *buff, const byte *str) +{ + byte b; + + while((b = *str++) != 0) { + switch(b) { + case 0x1: // {SETX} + *buff++ = b; + *buff++ = *str++; + break; + case 0x2: // {SETXY} + *buff++ = b; + *buff++ = *str++; + *buff++ = *str++; + break; + case 0x7B: // {COMMA32} + buff = FormatCommaNumber(buff, GetParamInt32()); + break; + case 0x7C: // {COMMA16} + buff = FormatCommaNumber(buff, GetParamInt16()); + break; + case 0x7D: // {COMMA8} + buff = FormatCommaNumber(buff, GetParamInt8()); + break; + case 0x7E: // {NUMU16} + buff = FormatNoCommaNumber(buff, GetParamInt16()); + break; + case 0x7F: // {CURRENCY} + buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt32(), false); + break; + // 0x80 is reserved for EURO + case 0x81: // {STRINL} + str += 2; + buff = GetString(buff, READ_LE_UINT16(str-2)); + break; + case 0x82: // {DATE_LONG} + buff = FormatYmdString(buff, GetParamUint16()); + break; + case 0x83: // {DATE_SHORT} + buff = FormatMonthAndYear(buff, GetParamUint16()); + break; + case 0x84: {// {VELOCITY} + int value = GetParamInt16(); + if (_opt.kilometers) value = value * 1648 >> 10; + buff = FormatCommaNumber(buff, value); + if (_opt.kilometers) { + memcpy(buff, " km/h", 5); + buff += 5; + } else { + memcpy(buff, " mph", 4); + buff += 4; + } + break; + } + + // 0x85 is used as escape character.. + case 0x85: + switch(*str++) { + case 0: + buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt32(), true); + break; + case 1: // {INT32} + buff = FormatNoCommaNumber(buff, GetParamInt32()); + break; + + case 2: // {REV} +#ifdef WITH_REV + buff = str_cat(buff, (const byte*)_openttd_revision); +#endif + break; + case 3: { // {SHORTCARGO} + // Layout: + // 8-bit = cargo type + // 16-bit = cargo count + char *s; + uint16 cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()]; + uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1; + // liquid type of cargo is multiplied by 100 to get correct amount + buff = FormatCommaNumber(buff, GetParamInt16() * multiplier ); + s = GetStringPtr(cargo_str); + + memcpy(buff++, " ", 1); + while (*s) *buff++ = *s++; + break; + } + + default: + error("!invalid escape sequence in string"); + } + break; + + case 0x86: // {SKIP} + GetParamInt16(); + //assert(0); + break; + case 0x87: { // {VOLUME} + char *s; + buff = FormatCommaNumber(buff, GetParamInt16() * 1000); + memcpy(buff++, " ", 1); + s = GetStringPtr(STR_LITERS); + while (*s) *buff++ = *s++; + break; + } + + case 0x88: // {STRING} + buff = GetString(buff, (uint16)GetParamUint16()); + break; + + case 0x99: { // {CARGO} + // Layout now is: + // 8bit - cargo type + // 16-bit - cargo count + int cargo_str = _cargoc.names_long_s[GetParamInt8()]; + // Now check if the cargo count is 1, if it is, increase string by 32. + if (GET_DPARAM16(0) != 1) cargo_str += 32; + buff = GetString(buff, cargo_str); + break; + } + + case 0x9A: { // {STATION} + Station *st; + InjectDparam(1); + st = DEREF_STATION(GET_DPARAM16(1)); + assert(st->xy); + SET_DPARAM16(0, st->town->townnametype); + SET_DPARAM32(1, st->town->townnameparts); + buff = GetString(buff, st->string_id); + break; + } + case 0x9B: { // {TOWN} + Town *t; + t = DEREF_TOWN(GET_DPARAM16(0)); + assert(t->xy); + SET_DPARAM32(0, t->townnameparts); + buff = GetString(buff, t->townnametype); + break; + } + + case 0x9C: { // {CURRENCY64} + buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt64(), false); + break; + } + + case 0x9D: { // {CHECKPOINT} + Checkpoint *cp = &_checkpoints[GET_DPARAM16(0)]; + StringID str; + int idx; + if (~cp->town_or_string & 0xC000) { + GetParamInt32(); // skip it + str = cp->town_or_string; + } else { + idx = (cp->town_or_string >> 8) & 0x3F; + if (idx == 0) { + str = STR_CHECKPOINTNAME_CITY; + } else { + InjectDparam(1); + SET_DPARAM16(1, idx + 1); + str = STR_CHECKPOINTNAME_CITY_SERIAL; + } + SET_DPARAM16(0, cp->town_or_string & 0xFF); + } + + buff = GetString(buff, str); + } break; + // case 0x88..0x98: // {COLORS} + // case 0xE: // {TINYFONT} + // case 0xF: // {BIGFONT} + // 0x9E is the highest number that is available. + default: + *buff++ = b; + } + } + buff[0] = 0; + return buff; +} + + +static byte *StationGetSpecialString(byte *buff) +{ + int x = GetParamInt8(); + if (x & 1) *buff++ = 0xB4; + if (x & 2) *buff++ = 0xB5; + if (x & 4) *buff++ = 0xB6; + if (x & 8) *buff++ = 0xB7; + if (x & 16) *buff++ = 0xB8; + *buff = 0; + return buff; +} + +static byte *GetSpecialTownNameString(byte *buff, int ind) { + uint32 x = GetParamInt32(); + + _town_name_generators[ind](buff, x); + + while (*buff != 0) buff++; + return buff; +} + +static const char * const _silly_company_names[] = { + "Bloggs Brothers", + "Tiny Transport Ltd.", + "Express Travel", + "Comfy-Coach & Co.", + "Crush & Bump Ltd.", + "Broken & Late Ltd.", + "Sam Speedy & Son", + "Supersonic Travel", + "Mike's Motors", + "Lightning International", + "Pannik & Loozit Ltd.", + "Inter-City Transport", + "Getout & Pushit Ltd.", +}; + +static const char * const _surname_list[] = { + "Adams", + "Allan", + "Baker", + "Bigwig", + "Black", + "Bloggs", + "Brown", + "Campbell", + "Gordon", + "Hamilton", + "Hawthorn", + "Higgins", + "Green", + "Gribble", + "Jones", + "McAlpine", + "MacDonald", + "McIntosh", + "Muir", + "Murphy", + "Nelson", + "O'Donnell", + "Parker", + "Phillips", + "Pilkington", + "Quigley", + "Sharkey", + "Thomson", + "Watkins", + "Grumpy", + "Dozy", + "Speedy", + "Nosey", + "Dribble", + "Mushroom", + "Cabbage", + "Sniffle", + "Fishy", + "Swindle", + "Sneaky", + "Nutkins", +}; + +static const byte _initial_name_letters[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', +}; + +static byte *GenAndCoName(byte *buff) +{ + uint32 x = GetParamInt32(); + uint base,num; + + base = 0; + num = 29; + if (_opt.landscape == LT_CANDY) { + base = num; + num = 12; + } + + buff = str_cat(buff, _surname_list[base + ((num * (byte)(x >> 16)) >> 8)]); + buff = str_cat(buff, " & Co."); + + return buff; +} + +static byte *GenPlayerName_4(byte *buff) +{ + uint32 x = GetParamInt32(); + uint i, base, num; + + buff[0] = _initial_name_letters[ (sizeof(_initial_name_letters) * (byte)x) >> 8]; + buff[1] = '.'; + buff += 2; + + i = ((sizeof(_initial_name_letters) + 35) * (byte)(x >> 8)) >> 8; + if (i < sizeof(_initial_name_letters)) { + buff[0] = _initial_name_letters[i]; + buff[1] = '.'; + buff += 2; + } + + base = 0; + num = 29; + if (_opt.landscape == LT_CANDY) { + base = num; + num = 12; + } + + buff = str_cat(buff, _surname_list[base + ((num * (byte)(x >> 16)) >> 8)]); + + return buff; +} + +static const char * const _song_names[] = { + "Tycoon DELUXE Theme", + "Easy Driver", + "Little Red Diesel", + "Cruise Control", + "Don't Walk!", + "Fell Apart On Me", + "City Groove", + "Funk Central", + "Stoke It", + "Road Hog", + "Aliens Ate My Railway", + "Snarl Up", + "Stroll On", + "Can't Get There From Here", + "Sawyer's Tune", + "Hold That Train!", + "Movin' On", + "Goss Groove", + "Small Town", + "Broomer's Oil Rag", + "Jammit", + "Hard Drivin'" +}; + +static byte *GetSpecialPlayerNameString(byte *buff, int ind) +{ + switch(ind) { + + // not used + case 1: { + int i = GetParamInt32() & 0xFFFF; + return str_cat(buff, _silly_company_names[i]); + } + + case 2: // used for Foobar & Co company names + return GenAndCoName(buff); + + case 3: // President name + return GenPlayerName_4(buff); + + // song names + case 4: { + const char *song = _song_names[GetParamUint16() - 1]; + return str_cat(buff, song); + } + } + + // town name? + if (IS_INT_INSIDE(ind-6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START+1)) { + buff = GetSpecialTownNameString(buff, ind - 6); + return str_cat(buff, " Transport"); + } + + // language name? + if (IS_INT_INSIDE(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) { + int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4); + return str_cat(buff, i == _dynlang.curr ? ((LanguagePackHeader*)_langpack)->own_name : _dynlang.ent[i].name); + } + + // resolution size? + if (IS_INT_INSIDE(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) { + int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4); + return buff + sprintf(buff, "%dx%d", _resolutions[i][0], _resolutions[i][1]); + } + + // screenshot format name? + if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) { + int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4); + return str_cat(buff, GetScreenshotFormatDesc(i)); + } + + + assert(0); + return NULL; +} + +// remap a string ID from the old format to the new format +StringID RemapOldStringID(StringID s) +{ + if (s == 0x7000) s = STR_SV_UNNAMED; + else if (s == 0x0006) s = STR_SV_EMPTY; + else if (s == 0x8864) s = STR_SV_TRAIN_NAME; + else if (s == 0x902B) s = STR_SV_ROADVEH_NAME; + else if (s == 0x9830) s = STR_SV_SHIP_NAME; + else if (s == 0xA02F) s = STR_SV_AIRCRAFT_NAME; + else if (IS_INT_INSIDE(s, 0x300F, 0x3030)) s = s - 0x300F + STR_SV_STNAME; + else if (s == 0x70E4 || s == 0x70E9) s = SPECSTR_PLAYERNAME_ENGLISH; + return s; +} + +bool ReadLanguagePack(int lang_index) { + int tot_count, i; + byte *lang_pack; + size_t len; + byte **langpack_offs; + byte *s; + +#define HDR ((LanguagePackHeader*)lang_pack) + { + char *lang = str_fmt("%s%s", _path.lang_dir, _dynlang.ent[lang_index].file); + lang_pack = ReadFileToMem(lang, &len, 100000); + free(lang); + } + if (lang_pack == NULL) return false; + if (len < sizeof(LanguagePackHeader) || + HDR->ident != TO_LE32(LANGUAGE_PACK_IDENT) || + HDR->version != TO_LE32(LANGUAGE_PACK_VERSION)) { + free(lang_pack); + return false; + } +#undef HDR + +#if defined(TTD_BIG_ENDIAN) + for(i=0; i!=32; i++) { + ((LanguagePackHeader*)lang_pack)->offsets[i] = READ_LE_UINT16(&((LanguagePackHeader*)lang_pack)->offsets[i]); + } +#endif + + tot_count = 0; + for(i=0; i!=32; i++) { + uint num = ((LanguagePackHeader*)lang_pack)->offsets[i]; + _langtab_start[i] = tot_count; + _langtab_num[i] = num; + tot_count += num; + } + + // Allocate offsets + langpack_offs = (byte**)malloc(tot_count * sizeof(byte*)); + + // Fill offsets + s = lang_pack + sizeof(LanguagePackHeader); + for(i=0; i!=tot_count; i++) { + len = *s; + *s++ = 0; // zero terminate the string before. + if (len >= 0xC0) { len = ((len & 0x3F) << 8) + *s++; } + langpack_offs[i] = s; + s += len; + } + + if (_langpack) free(_langpack); + _langpack = lang_pack; + + if (_langpack_offs) free(_langpack_offs); + _langpack_offs = langpack_offs; + + ttd_strlcpy(_dynlang.curr_file, _dynlang.ent[lang_index].file, sizeof(_dynlang.curr_file)); + + + _dynlang.curr = lang_index; + return true; +} + +// make a list of the available language packs. put the data in _dynlang struct. +void InitializeLanguagePacks() +{ + DynamicLanguages *dl = &_dynlang; + int i, j, n, m,def; + LanguagePackHeader hdr; + FILE *in; + char *files[32]; + + n = GetLanguageList(files, lengthof(files)); + + def = 0; // default language file + + // go through the language files and make sure that they are valid. + for(i=m=0; i!=n; i++) { + char *s = str_fmt("%s%s", _path.lang_dir, files[i]); + in = fopen(s, "rb"); + free(s); + if (!in || + (j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 || + hdr.ident != TO_LE32(LANGUAGE_PACK_IDENT) || + hdr.version != TO_LE32(LANGUAGE_PACK_VERSION)) { + free(files[i]); + continue; + } + + dl->ent[m].file = files[i]; + dl->ent[m].name = strdup(hdr.name); + + if (!strcmp(hdr.name, "English")) def = m; + + m++; + } + + if (m == 0) + error(n == 0 ? "No available language packs" : "Invalid version of language packs"); + + dl->num = m; + for(i=0; i!=dl->num; i++) + dl->dropdown[i] = SPECSTR_LANGUAGE_START + i; + dl->dropdown[i] = INVALID_STRING_ID; + + for(i=0; i!=dl->num; i++) + if (!strcmp(dl->ent[i].file, dl->curr_file)) { + def = i; + break; + } + + if (!ReadLanguagePack(def)) + error("can't read language pack '%s'", dl->ent[def].file); +} diff --git a/subsidy_gui.c b/subsidy_gui.c new file mode 100644 --- /dev/null +++ b/subsidy_gui.c @@ -0,0 +1,164 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gui.h" +#include "station.h" +#include "industry.h" +#include "town.h" +#include "player.h" +#include "gfx.h" +#include "economy.h" + +static void HandleSubsidyClick(int y) +{ + Subsidy *s; + int num,offs; + TileIndex xy; + + if (y < 0) + return; + + num = 0; + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age < 12) { + y -= 10; + if (y < 0) goto handle_click; + num++; + } + } + + if (num == 0) { + y -= 10; + if (y < 0) return; + } + + y -= 11; + if (y < 0) return; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age >= 12) { + y -= 10; + if (y < 0) goto handle_click; + } + } + return; + +handle_click: + + /* determine from coordinate for subsidy and try to scroll to it */ + offs = s->from; + if (s->age >= 12) { + xy = DEREF_STATION(offs)->xy; + } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL) { + xy = DEREF_TOWN(offs)->xy; + } else { + xy = _industries[offs].xy; + + } + if (!ScrollMainWindowToTile(xy)) { + /* otherwise determine to coordinate for subsidy and scroll to it */ + offs = s->to; + if (s->age >= 12) { + xy = DEREF_STATION(offs)->xy; + } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL || s->cargo_type == CT_GOODS || s->cargo_type == CT_FOOD) { + xy = DEREF_TOWN(offs)->xy; + } else { + xy = _industries[offs].xy; + } + ScrollMainWindowToTile(xy); + } +} + +static void DrawSubsidiesWindow(Window *w) +{ + YearMonthDay ymd; + Subsidy *s; + int x,xt,y,num,x2; + Player *p; + + DrawWindowWidgets(w); + + ConvertDayToYMD(&ymd, _date); + + y = 15; + x = 1; + DrawString(x, y, STR_2026_SUBSIDIES_ON_OFFER_FOR, 0); + y += 10; + num = 0; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age < 12) { + SetupSubsidyDecodeParam(s, 1); + x2 = DrawString(x+2, y, STR_2027_FROM_TO, 0); + + SET_DPARAM16(0, _date - ymd.day + 384 - s->age * 32); + DrawString(x2, y, STR_2028_BY, 0); + y += 10; + num++; + } + } + + if (num == 0) { + DrawString(x+2, y, STR_202A_NONE, 0); + y += 10; + } + + DrawString(x, y+1, STR_202B_SERVICES_ALREADY_SUBSIDISED, 0); + y += 10; + num = 0; + + for(s=_subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != 0xFF && s->age >= 12) { + SetupSubsidyDecodeParam(s, 1); + + p = DEREF_PLAYER(DEREF_STATION(s->to)->owner); + SET_DPARAM16(3, p->name_1); + SET_DPARAM32(4, p->name_2); + + xt = DrawString(x+2, y, STR_202C_FROM_TO, 0); + + SET_DPARAM16(0, _date - ymd.day + 768 - s->age * 32); + DrawString(xt, y, STR_202D_UNTIL, 0); + y += 10; + num++; + } + } + + if (num == 0) { + DrawString(x+2, y, STR_202A_NONE, 0); + } +} + +static void SubsidiesListWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: DrawSubsidiesWindow(w); break; + case WE_CLICK: { + switch(e->click.widget) { + case 2: HandleSubsidyClick(e->click.pt.y - 25); break; + } + } + break; + } +} + +static const Widget _subsidies_list_widgets[] = { +{ WWT_CLOSEBOX, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 629, 0, 13, STR_2025_SUBSIDIES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 13, 0, 629, 14, 126, 0x0, STR_01FD_CLICK_ON_SERVICE_TO_CENTER}, +{ WWT_LAST}, +}; + +static const WindowDesc _subsidies_list_desc = { + -1, -1, 630, 127, + WC_SUBSIDIES_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _subsidies_list_widgets, + SubsidiesListWndProc +}; + + +void ShowSubsidiesList() +{ + AllocateWindowDescFront(&_subsidies_list_desc, 0); +} diff --git a/svnup.sh b/svnup.sh new file mode 100644 --- /dev/null +++ b/svnup.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# This script updates the svn source and displays log changes +# This is only useful for users of CLI based SVN clients +# Written by Bjarni + + +# reads what version you have now +Base=`svn info | grep "Revision" | xargs -n 1 | tail -n 1` + +# updates the source +svn update + +# if the revision number changed +if [ "$Base" -ne "`svn info | grep "Revision" | xargs -n 1 | tail -n 1`" ]; then +# displays the log changes +svn log -r HEAD:$(($Base + 1)) +fi diff --git a/table/ai_rail.h b/table/ai_rail.h new file mode 100644 --- /dev/null +++ b/table/ai_rail.h @@ -0,0 +1,480 @@ +typedef struct { + byte mode; + byte attr; + TileIndexDiff tileoffs; +} AiDefaultBlockData; + +typedef struct { + byte p0; + byte p1; + byte p2; + byte p3; + byte dir; + AiDefaultBlockData data[VARARRAY_SIZE]; +} AiDefaultRailBlock; + +typedef struct { + byte dir; + AiDefaultBlockData data[VARARRAY_SIZE]; +} AiDefaultRoadBlock; + + +#define MKHDR(a,b,c,d,e) a,b,c,d,e,{ +#define MKDEPOT(a,b) {0,a,b} +#define MKSTATION(a,b) {1,a,b} +#define MKRAIL(a,b) {2,a,b} +#define MKCLRRAIL(a,b) {3,a,b} +#define MKEND {4}} + +static const AiDefaultRailBlock _raildata_ai_0 = { + MKHDR(1,2,1,0,1) + MKDEPOT(2,TILE_XY(-1,1)), + MKSTATION(0x15,TILE_XY(0,-1)), + MKRAIL(0x26,TILE_XY(0,1)), + MKCLRRAIL(1,TILE_XY(0,2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_1 = { + MKHDR(1,2,1,0,3) + MKDEPOT(2,TILE_XY(-1,-1)), + MKRAIL(0x26,TILE_XY(0,-1)), + MKSTATION(0x15,TILE_XY(0,0)), + MKCLRRAIL(3,TILE_XY(0,-2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_2 = { + MKHDR(1,2,1,0,0) + MKDEPOT(1,TILE_XY(-1,-1)), + MKRAIL(0x15,TILE_XY(-1,0)), + MKSTATION(0x14,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(-2,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_3 = { + MKHDR(1,2,1,0,2) + MKDEPOT(1,TILE_XY(1,-1)), + MKRAIL(0x15,TILE_XY(1,0)), + MKSTATION(0x14,TILE_XY(-1,0)), + MKCLRRAIL(2,TILE_XY(2,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_4 = { + MKHDR(1,2,2,0,255) + MKSTATION(0x15,TILE_XY(0,0)), + MKCLRRAIL(3,TILE_XY(0,-1)), + MKCLRRAIL(1,TILE_XY(0,2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_5 = { + MKHDR(1,2,2,0,255) + MKSTATION(0x14,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(2,TILE_XY(2,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_6 = { + MKHDR(2,3,1,0,1) + MKSTATION(0x27,TILE_XY(0,-2)), + MKRAIL(0xC2,TILE_XY(0,1)), + MKRAIL(0xC2,TILE_XY(1,1)), + MKRAIL(0x1A,TILE_XY(0,2)), + MKRAIL(0x26,TILE_XY(1,2)), + MKDEPOT(3,TILE_XY(1,3)), + MKCLRRAIL(1,TILE_XY(0,3)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_7 = { + MKHDR(2,3,1,0,3) + MKDEPOT(1,TILE_XY(0,-3)), + MKRAIL(0x1A,TILE_XY(0,-2)), + MKRAIL(0x26,TILE_XY(1,-2)), + MKRAIL(0xC2,TILE_XY(0,-1)), + MKRAIL(0xC2,TILE_XY(1,-1)), + MKSTATION(0x27,TILE_XY(0,0)), + MKCLRRAIL(3,TILE_XY(1,-3)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_8 = { + MKHDR(2,3,1,0,2) + MKSTATION(0x26,TILE_XY(-2,0)), + MKRAIL(0xC1,TILE_XY(1,0)), + MKRAIL(0xC1,TILE_XY(1,1)), + MKRAIL(0x29,TILE_XY(2,0)), + MKRAIL(0x15,TILE_XY(2,1)), + MKDEPOT(0,TILE_XY(3,0)), + MKCLRRAIL(2,TILE_XY(3,1)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_9 = { + MKHDR(2,3,1,0,0) + MKDEPOT(2,TILE_XY(-3,-1)), + MKRAIL(0x29,TILE_XY(-2,-1)), + MKRAIL(0x15,TILE_XY(-2,0)), + MKRAIL(0xC1,TILE_XY(-1,-1)), + MKRAIL(0xC1,TILE_XY(-1,0)), + MKSTATION(0x26,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(-3,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_10 = { + MKHDR(2,3,2,0,255) + MKRAIL(0x1A,TILE_XY(0,-3)), + MKRAIL(0x20,TILE_XY(1,-3)), + MKRAIL(0xC2,TILE_XY(0,-2)), + MKRAIL(0xC2,TILE_XY(1,-2)), + MKSTATION(0x27,TILE_XY(0,-1)), + MKRAIL(0xC2,TILE_XY(0,2)), + MKRAIL(0xC2,TILE_XY(1,2)), + MKRAIL(0x1A,TILE_XY(0,3)), + MKRAIL(0x4,TILE_XY(1,3)), + MKCLRRAIL(3,TILE_XY(0,-4)), + MKCLRRAIL(1,TILE_XY(0,4)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_11 = { + MKHDR(2,3,2,0,255) + MKRAIL(0x29,TILE_XY(-3,0)), + MKRAIL(0x10,TILE_XY(-3,1)), + MKRAIL(0xC1,TILE_XY(-2,0)), + MKRAIL(0xC1,TILE_XY(-2,1)), + MKSTATION(0x26,TILE_XY(-1,0)), + MKRAIL(0xC1,TILE_XY(2,0)), + MKRAIL(0xC1,TILE_XY(2,1)), + MKRAIL(0x29,TILE_XY(3,0)), + MKRAIL(0x4,TILE_XY(3,1)), + MKCLRRAIL(0,TILE_XY(-4,0)), + MKCLRRAIL(2,TILE_XY(4,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_12 = { + MKHDR(2,3,2,1,3) + MKRAIL(0x88,TILE_XY(-1,-3)), + MKRAIL(0x6,TILE_XY(0,-3)), + MKRAIL(0x2,TILE_XY(-1,-2)), + MKRAIL(0x42,TILE_XY(0,-2)), + MKRAIL(0x2,TILE_XY(-1,-1)), + MKRAIL(0x2,TILE_XY(0,-1)), + MKRAIL(0x2,TILE_XY(-1,0)), + MKRAIL(0x2,TILE_XY(0,0)), + MKRAIL(0x82,TILE_XY(-1,1)), + MKRAIL(0x2,TILE_XY(0,1)), + MKRAIL(0xA,TILE_XY(-1,2)), + MKRAIL(0x44,TILE_XY(0,2)), + MKCLRRAIL(3,TILE_XY(0,-4)), + MKCLRRAIL(1,TILE_XY(-1,3)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_13 = { + MKHDR(2,3,2,1,0) + MKRAIL(0x21,TILE_XY(-3,0)), + MKRAIL(0x90,TILE_XY(-3,1)), + MKRAIL(0x81,TILE_XY(-2,0)), + MKRAIL(0x1,TILE_XY(-2,1)), + MKRAIL(0x1,TILE_XY(-1,0)), + MKRAIL(0x1,TILE_XY(-1,1)), + MKRAIL(0x1,TILE_XY(0,0)), + MKRAIL(0x1,TILE_XY(0,1)), + MKRAIL(0x1,TILE_XY(1,0)), + MKRAIL(0x41,TILE_XY(1,1)), + MKRAIL(0x60,TILE_XY(2,0)), + MKRAIL(0x11,TILE_XY(2,1)), + MKCLRRAIL(0,TILE_XY(-4,0)), + MKCLRRAIL(2,TILE_XY(3,1)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_14 = { + MKHDR(2,3,2,1,1) + MKRAIL(0x88,TILE_XY(-1,-3)), + MKRAIL(0x6,TILE_XY(0,-3)), + MKRAIL(0x2,TILE_XY(-1,-2)), + MKRAIL(0x42,TILE_XY(0,-2)), + MKRAIL(0x2,TILE_XY(-1,-1)), + MKRAIL(0x2,TILE_XY(0,-1)), + MKRAIL(0x2,TILE_XY(-1,0)), + MKRAIL(0x2,TILE_XY(0,0)), + MKRAIL(0x82,TILE_XY(-1,1)), + MKRAIL(0x2,TILE_XY(0,1)), + MKRAIL(0xA,TILE_XY(-1,2)), + MKRAIL(0x44,TILE_XY(0,2)), + MKCLRRAIL(1,TILE_XY(-1,3)), + MKCLRRAIL(3,TILE_XY(0,-4)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_15 = { + MKHDR(2,3,2,1,2) + MKRAIL(0x21,TILE_XY(-3,0)), + MKRAIL(0x90,TILE_XY(-3,1)), + MKRAIL(0x81,TILE_XY(-2,0)), + MKRAIL(0x1,TILE_XY(-2,1)), + MKRAIL(0x1,TILE_XY(-1,0)), + MKRAIL(0x1,TILE_XY(-1,1)), + MKRAIL(0x1,TILE_XY(0,0)), + MKRAIL(0x1,TILE_XY(0,1)), + MKRAIL(0x1,TILE_XY(1,0)), + MKRAIL(0x41,TILE_XY(1,1)), + MKRAIL(0x60,TILE_XY(2,0)), + MKRAIL(0x11,TILE_XY(2,1)), + MKCLRRAIL(2,TILE_XY(3,1)), + MKCLRRAIL(0,TILE_XY(-4,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_16 = { + MKHDR(1,3,1,0,1) + MKSTATION(0x17,TILE_XY(0,-2)), + MKRAIL(0x1A,TILE_XY(0,1)), + MKCLRRAIL(1,TILE_XY(0,2)), + MKDEPOT(0,TILE_XY(1,1)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_17 = { + MKHDR(1,3,1,0,3) + MKCLRRAIL(3,TILE_XY(0,-2)), + MKRAIL(0x26,TILE_XY(0,-1)), + MKDEPOT(2,TILE_XY(-1,-1)), + MKSTATION(0x17,TILE_XY(0,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_18 = { + MKHDR(1,3,1,0,0) + MKCLRRAIL(0,TILE_XY(-2,0)), + MKRAIL(0x29,TILE_XY(-1,0)), + MKDEPOT(3,TILE_XY(-1,1)), + MKSTATION(0x16,TILE_XY(0,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_19 = { + MKHDR(1,3,1,0,2) + MKSTATION(0x16,TILE_XY(-2,0)), + MKDEPOT(2,TILE_XY(0,-1)), + MKRAIL(0x20,TILE_XY(1,-1)), + MKRAIL(0x15,TILE_XY(1,0)), + MKCLRRAIL(2,TILE_XY(2,0)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_20 = { + MKHDR(2,3,1,0,1) + MKSTATION(0x26,TILE_XY(-2,0)), + MKRAIL(0xC1,TILE_XY(1,0)), + MKRAIL(0xC1,TILE_XY(1,1)), + MKRAIL(0x26,TILE_XY(2,0)), + MKRAIL(0x26,TILE_XY(2,1)), + MKDEPOT(1,TILE_XY(2,-1)), + MKCLRRAIL(1,TILE_XY(2,2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_21 = { + MKHDR(2,3,1,0,3) + MKDEPOT(2,TILE_XY(-3,-1)), + MKRAIL(0x3F,TILE_XY(-2,-1)), + MKRAIL(0x10,TILE_XY(-2,0)), + MKRAIL(0xC1,TILE_XY(-1,-1)), + MKRAIL(0xC1,TILE_XY(-1,0)), + MKSTATION(0x26,TILE_XY(0,-1)), + MKCLRRAIL(3,TILE_XY(-2,-2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_22 = { + MKHDR(2,3,1,0,0) + MKSTATION(0x27,TILE_XY(0,-2)), + MKRAIL(0xC2,TILE_XY(0,1)), + MKRAIL(0xC2,TILE_XY(1,1)), + MKRAIL(0x15,TILE_XY(0,2)), + MKRAIL(0x4,TILE_XY(1,2)), + MKRAIL(0x15,TILE_XY(-1,2)), + MKDEPOT(1,TILE_XY(-1,1)), + MKCLRRAIL(0,TILE_XY(-2,2)), + MKEND +}; + +static const AiDefaultRailBlock _raildata_ai_23 = { + MKHDR(2,3,1,0,2) + MKDEPOT(1,TILE_XY(0,-3)), + MKRAIL(0x1A,TILE_XY(0,-2)), + MKRAIL(0x29,TILE_XY(1,-2)), + MKRAIL(0xC2,TILE_XY(0,-1)), + MKRAIL(0xC2,TILE_XY(1,-1)), + MKSTATION(0x27,TILE_XY(0,0)), + MKCLRRAIL(2,TILE_XY(2,-2)), + MKEND +}; + + + +static const AiDefaultRailBlock * const _default_rail_track_data[] = { + &_raildata_ai_0, + &_raildata_ai_1, + &_raildata_ai_2, + &_raildata_ai_3, + &_raildata_ai_4, + &_raildata_ai_5, + &_raildata_ai_6, + &_raildata_ai_7, + &_raildata_ai_8, + &_raildata_ai_9, + &_raildata_ai_10, + &_raildata_ai_11, + &_raildata_ai_12, + &_raildata_ai_13, + &_raildata_ai_14, + &_raildata_ai_15, + &_raildata_ai_16, + &_raildata_ai_17, + &_raildata_ai_18, + &_raildata_ai_19, + &_raildata_ai_20, + &_raildata_ai_21, + &_raildata_ai_22, + &_raildata_ai_23, + NULL +}; + +#undef MKHDR + +#define MKHDR(a) a,{ + +static const AiDefaultRoadBlock _roaddata_ai_0 = { + MKHDR(0) + MKDEPOT(2,TILE_XY(-1,1)), + MKSTATION(0x2,TILE_XY(-1,0)), + MKRAIL(0xC,TILE_XY(0,0)), + MKRAIL(0x9,TILE_XY(0,1)), + MKCLRRAIL(0,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(1,0)), + MKCLRRAIL(0,TILE_XY(1,1)), + MKCLRRAIL(0,TILE_XY(0,2)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_1 = { + MKHDR(0) + MKDEPOT(1,TILE_XY(0,-1)), + MKSTATION(0x1,TILE_XY(1,-1)), + MKRAIL(0x3,TILE_XY(0,0)), + MKRAIL(0x9,TILE_XY(1,0)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(0,TILE_XY(0,1)), + MKCLRRAIL(0,TILE_XY(1,1)), + MKCLRRAIL(0,TILE_XY(2,0)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_2 = { + MKHDR(0) + MKDEPOT(3,TILE_XY(1,1)), + MKSTATION(0x3,TILE_XY(0,1)), + MKRAIL(0x6,TILE_XY(0,0)), + MKRAIL(0xC,TILE_XY(1,0)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(0,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(1,-1)), + MKCLRRAIL(0,TILE_XY(2,0)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_3 = { + MKHDR(0) + MKDEPOT(0,TILE_XY(1,0)), + MKSTATION(0x0,TILE_XY(1,1)), + MKRAIL(0x6,TILE_XY(0,0)), + MKRAIL(0x3,TILE_XY(0,1)), + MKCLRRAIL(0,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(0,TILE_XY(-1,1)), + MKCLRRAIL(0,TILE_XY(0,2)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_4 = { + MKHDR(1) + MKSTATION(0x2,TILE_XY(-1,0)), + MKRAIL(0x8,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(1,0)), + MKCLRRAIL(0,TILE_XY(0,1)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_5 = { + MKHDR(1) + MKSTATION(0x3,TILE_XY(0,1)), + MKRAIL(0x4,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(0,TILE_XY(0,-1)), + MKCLRRAIL(0,TILE_XY(1,0)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_6 = { + MKHDR(1) + MKSTATION(0x0,TILE_XY(1,1)), + MKRAIL(0x2,TILE_XY(0,1)), + MKCLRRAIL(0,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(-1,0)), + MKCLRRAIL(0,TILE_XY(0,2)), + MKEND +}; + +static const AiDefaultRoadBlock _roaddata_ai_7 = { + MKHDR(1) + MKSTATION(0x1,TILE_XY(1,-1)), + MKRAIL(0x1,TILE_XY(1,0)), + MKCLRRAIL(0,TILE_XY(0,0)), + MKCLRRAIL(0,TILE_XY(1,1)), + MKCLRRAIL(0,TILE_XY(2,0)), + MKEND +}; + + +static const AiDefaultRoadBlock * const _road_default_block_data[] = { + &_roaddata_ai_0, + &_roaddata_ai_1, + &_roaddata_ai_2, + &_roaddata_ai_3, + &_roaddata_ai_4, + &_roaddata_ai_5, + &_roaddata_ai_6, + &_roaddata_ai_7, + NULL +}; + +#define MKAIR(a,b) {0,a,b} + +static const AiDefaultBlockData _airportdata_ai_0[] = { + MKAIR(1, 0), + {1}, +}; + +static const AiDefaultBlockData _airportdata_ai_1[] = { + MKAIR(0, 0), + {1} +}; + +static const AiDefaultBlockData * const _airport_default_block_data[] = { + _airportdata_ai_0, // city airport + _airportdata_ai_1, // country airport + NULL +}; + + diff --git a/table/animcursors.h b/table/animcursors.h new file mode 100644 --- /dev/null +++ b/table/animcursors.h @@ -0,0 +1,45 @@ +#define ANIM_CURSOR_LINE(a,b) a,b, +#define ANIM_CURSOR_END() 0xFFFF + +static const uint16 _demolish_animcursor[] = { + ANIM_CURSOR_LINE(0x2C0, 29) + ANIM_CURSOR_LINE(0x2C1, 29) + ANIM_CURSOR_LINE(0x2C2, 29) + ANIM_CURSOR_LINE(0x2C3, 29) + ANIM_CURSOR_END() +}; + +static const uint16 _lower_land_animcursor[] = { + ANIM_CURSOR_LINE(0x2BB, 29) + ANIM_CURSOR_LINE(0x2BC, 29) + ANIM_CURSOR_LINE(0x2BD, 98) + ANIM_CURSOR_END() +}; + +static const uint16 _raise_land_animcursor[] = { + ANIM_CURSOR_LINE(0x2B8, 29) + ANIM_CURSOR_LINE(0x2B9, 29) + ANIM_CURSOR_LINE(0x2BA, 98) + ANIM_CURSOR_END() +}; + +static const uint16 _pick_station_animcursor[] = { + ANIM_CURSOR_LINE(0x2CC, 29) + ANIM_CURSOR_LINE(0x2CD, 29) + ANIM_CURSOR_LINE(0x2CE, 98) + ANIM_CURSOR_END() +}; + +static const uint16 _build_signals_animcursor[] = { + ANIM_CURSOR_LINE(0x50C, 148) + ANIM_CURSOR_LINE(0x50D, 148) + ANIM_CURSOR_END() +}; + +static const uint16 * const _animcursors[] = { + _demolish_animcursor, + _lower_land_animcursor, + _raise_land_animcursor, + _pick_station_animcursor, + _build_signals_animcursor +}; diff --git a/table/build_industry.h b/table/build_industry.h new file mode 100644 --- /dev/null +++ b/table/build_industry.h @@ -0,0 +1,1258 @@ +#define MK(x,y, m) {TILE_XY(x,y), m} + +#define MKEND {-0x8000, 0} + +static const IndustryTileTable _tile_table_coal_mine_0[] = { + MK(1,1, 0), + MK(1,2, 2), + MK(0,0, 5), + MK(1,0, 6), + MK(2,0, 3), + MK(2,2, 3), + MKEND +}; + +static const IndustryTileTable _tile_table_coal_mine_1[] = { + MK(1,1, 0), + MK(1,2, 2), + MK(2,0, 0), + MK(2,1, 2), + MK(1,0, 3), + MK(0,0, 3), + MK(0,1, 4), + MK(0,2, 4), + MK(2,2, 4), + MKEND +}; + +static const IndustryTileTable _tile_table_coal_mine_2[] = { + MK(0,0, 0), + MK(0,1, 2), + MK(0,2, 5), + MK(1,0, 3), + MK(1,1, 3), + MK(1,2, 6), + MKEND +}; + +static const IndustryTileTable _tile_table_coal_mine_3[] = { + MK(0,1, 0), + MK(0,2, 2), + MK(0,3, 4), + MK(1,0, 5), + MK(1,1, 0), + MK(1,2, 2), + MK(1,3, 3), + MK(2,0, 6), + MK(2,1, 4), + MK(2,2, 3), + MKEND +}; + +static const IndustryTileTable * const _tile_table_coal_mine[] = { + _tile_table_coal_mine_0, + _tile_table_coal_mine_1, + _tile_table_coal_mine_2, + _tile_table_coal_mine_3, +}; + +static const IndustryTileTable _tile_table_power_station_0[] = { + MK(0,0, 7), + MK(0,1, 9), + MK(1,0, 7), + MK(1,1, 8), + MK(2,0, 7), + MK(2,1, 8), + MK(3,0, 10), + MK(3,1, 10), + MKEND +}; + +static const IndustryTileTable _tile_table_power_station_1[] = { + MK(0,1, 7), + MK(0,2, 7), + MK(1,0, 8), + MK(1,1, 8), + MK(1,2, 7), + MK(2,0, 9), + MK(2,1, 10), + MK(2,2, 9), + MKEND +}; + +static const IndustryTileTable _tile_table_power_station_2[] = { + MK(0,0, 7), + MK(0,1, 7), + MK(1,0, 9), + MK(1,1, 8), + MK(2,0, 10), + MK(2,1, 9), + MKEND +}; + +static const IndustryTileTable * const _tile_table_power_station[] = { + _tile_table_power_station_0, + _tile_table_power_station_1, + _tile_table_power_station_2, +}; + +static const IndustryTileTable _tile_table_sawmill_0[] = { + MK(1,0, 14), + MK(1,1, 12), + MK(1,2, 11), + MK(2,0, 14), + MK(2,1, 13), + MK(0,0, 15), + MK(0,1, 15), + MK(0,2, 12), + MKEND +}; + +static const IndustryTileTable _tile_table_sawmill_1[] = { + MK(0,0, 15), + MK(0,1, 11), + MK(0,2, 14), + MK(1,0, 15), + MK(1,1, 13), + MK(1,2, 12), + MK(2,0, 11), + MK(2,1, 13), + MKEND +}; + +static const IndustryTileTable * const _tile_table_sawmill[] = { + _tile_table_sawmill_0, + _tile_table_sawmill_1, +}; + +static const IndustryTileTable _tile_table_forest_0[] = { + MK(0,0, 16), + MK(0,1, 16), + MK(0,2, 16), + MK(0,3, 16), + MK(1,0, 16), + MK(1,1, 16), + MK(1,2, 16), + MK(1,3, 16), + MK(2,0, 16), + MK(2,1, 16), + MK(2,2, 16), + MK(2,3, 16), + MK(3,0, 16), + MK(3,1, 16), + MK(3,2, 16), + MK(3,3, 16), + MK(1,4, 16), + MK(2,4, 16), + MKEND +}; + +static const IndustryTileTable _tile_table_forest_1[] = { + MK(0,0, 16), + MK(1,0, 16), + MK(2,0, 16), + MK(3,0, 16), + MK(4,0, 16), + MK(0,1, 16), + MK(1,1, 16), + MK(2,1, 16), + MK(3,1, 16), + MK(4,1, 16), + MK(0,2, 16), + MK(1,2, 16), + MK(2,2, 16), + MK(3,2, 16), + MK(4,2, 16), + MK(0,3, 16), + MK(1,3, 16), + MK(2,3, 16), + MK(3,3, 16), + MK(4,3, 16), + MK(1,4, 16), + MK(2,4, 16), + MK(3,4, 16), + MKEND +}; + +static const IndustryTileTable * const _tile_table_forest[] = { + _tile_table_forest_0, + _tile_table_forest_1, +}; + +static const IndustryTileTable _tile_table_oil_refinery_0[] = { + MK(0,0, 20), + MK(0,1, 21), + MK(0,2, 22), + MK(0,3, 21), + MK(1,0, 20), + MK(1,1, 19), + MK(1,2, 22), + MK(1,3, 20), + MK(2,1, 18), + MK(2,2, 18), + MK(2,3, 18), + MK(3,2, 18), + MK(3,3, 18), + MK(2,0, 23), + MK(3,1, 23), + MKEND +}; + +static const IndustryTileTable _tile_table_oil_refinery_1[] = { + MK(0,0, 18), + MK(0,1, 18), + MK(0,2, 21), + MK(0,3, 22), + MK(0,4, 20), + MK(1,0, 18), + MK(1,1, 18), + MK(1,2, 19), + MK(1,3, 20), + MK(2,0, 18), + MK(2,1, 18), + MK(2,2, 19), + MK(2,3, 22), + MK(1,4, 23), + MK(2,4, 23), + MKEND +}; + +static const IndustryTileTable * const _tile_table_oil_refinery[] = { + _tile_table_oil_refinery_0, + _tile_table_oil_refinery_1, +}; + +static const IndustryTileTable _tile_table_oil_rig_0[] = { + MK(0,0, 24), + MK(0,1, 24), + MK(0,2, 25), + MK(1,0, 26), + MK(1,1, 27), + MK(1,2, 28), + MK(-4,-5, 255), + MK(-4,-4, 255), + MK(-4,-3, 255), + MK(-4,-2, 255), + MK(-4,-1, 255), + MK(-4,0, 255), + MK(-4,1, 255), + MK(-4,2, 255), + MK(-4,3, 255), + MK(-4,4, 255), + MK(-4,5, 255), + MK(-3,5, 255), + MK(-2,5, 255), + MK(-1,5, 255), + MK(0,6, 255), + MK(1,6, 255), + MK(2,6, 255), + MK(3,6, 255), + MK(4,6, 255), + MK(5,6, 255), + MK(5,5, 255), + MK(5,4, 255), + MK(5,3, 255), + MK(5,2, 255), + MK(5,1, 255), + MK(5,0, 255), + MK(5,-1, 255), + MK(5,-2, 255), + MK(5,-3, 255), + MK(5,-4, 255), + MK(4,-4, 255), + MK(3,-4, 255), + MK(2,-4, 255), + MK(1,-4, 255), + MK(0,-4, 255), + MK(-1,-5, 255), + MK(-2,-5, 255), + MK(-3,-5, 255), + MK(2,0, 255), + MKEND +}; + +static const IndustryTileTable * const _tile_table_oil_rig[] = { + _tile_table_oil_rig_0, +}; + +static const IndustryTileTable _tile_table_factory_0[] = { + MK(0,0, 39), + MK(0,1, 40), + MK(1,0, 41), + MK(1,1, 42), + MK(0,2, 39), + MK(0,3, 40), + MK(1,2, 41), + MK(1,3, 42), + MK(2,1, 39), + MK(2,2, 40), + MK(3,1, 41), + MK(3,2, 42), + MKEND +}; + +static const IndustryTileTable _tile_table_factory_1[] = { + MK(0,0, 39), + MK(0,1, 40), + MK(1,0, 41), + MK(1,1, 42), + MK(2,0, 39), + MK(2,1, 40), + MK(3,0, 41), + MK(3,1, 42), + MK(1,2, 39), + MK(1,3, 40), + MK(2,2, 41), + MK(2,3, 42), + MKEND +}; + +static const IndustryTileTable * const _tile_table_factory[] = { + _tile_table_factory_0, + _tile_table_factory_1, +}; + +static const IndustryTileTable _tile_table_printing_works_0[] = { + MK(0,0, 43), + MK(0,1, 44), + MK(1,0, 45), + MK(1,1, 46), + MK(0,2, 43), + MK(0,3, 44), + MK(1,2, 45), + MK(1,3, 46), + MK(2,1, 43), + MK(2,2, 44), + MK(3,1, 45), + MK(3,2, 46), + MKEND +}; + +static const IndustryTileTable _tile_table_printing_works_1[] = { + MK(0,0, 43), + MK(0,1, 44), + MK(1,0, 45), + MK(1,1, 46), + MK(2,0, 43), + MK(2,1, 44), + MK(3,0, 45), + MK(3,1, 46), + MK(1,2, 43), + MK(1,3, 44), + MK(2,2, 45), + MK(2,3, 46), + MKEND +}; + +static const IndustryTileTable * const _tile_table_printing_works[] = { + _tile_table_printing_works_0, + _tile_table_printing_works_1, +}; + +static const IndustryTileTable _tile_table_steel_mill_0[] = { + MK(2,1, 52), + MK(2,2, 53), + MK(3,1, 54), + MK(3,2, 55), + MK(0,0, 56), + MK(1,0, 57), + MK(0,1, 56), + MK(1,1, 57), + MK(0,2, 56), + MK(1,2, 57), + MK(2,0, 56), + MK(3,0, 57), + MKEND +}; + +static const IndustryTileTable _tile_table_steel_mill_1[] = { + MK(0,0, 52), + MK(0,1, 53), + MK(1,0, 54), + MK(1,1, 55), + MK(2,0, 52), + MK(2,1, 53), + MK(3,0, 54), + MK(3,1, 55), + MK(0,2, 56), + MK(1,2, 57), + MK(2,2, 56), + MK(3,2, 57), + MK(1,3, 56), + MK(2,3, 57), + MKEND +}; + +static const IndustryTileTable * const _tile_table_steel_mill[] = { + _tile_table_steel_mill_0, + _tile_table_steel_mill_1, +}; + +static const IndustryTileTable _tile_table_farm_0[] = { + MK(1,0, 33), + MK(1,1, 34), + MK(1,2, 36), + MK(0,0, 37), + MK(0,1, 37), + MK(0,2, 36), + MK(2,0, 35), + MK(2,1, 38), + MK(2,2, 38), + MKEND +}; + +static const IndustryTileTable _tile_table_farm_1[] = { + MK(1,1, 33), + MK(1,2, 34), + MK(0,0, 35), + MK(0,1, 36), + MK(0,2, 36), + MK(0,3, 35), + MK(1,0, 37), + MK(1,3, 38), + MK(2,0, 37), + MK(2,1, 37), + MK(2,2, 38), + MK(2,3, 38), + MKEND +}; + +static const IndustryTileTable _tile_table_farm_2[] = { + MK(2,0, 33), + MK(2,1, 34), + MK(0,0, 36), + MK(0,1, 36), + MK(0,2, 37), + MK(0,3, 37), + MK(1,0, 35), + MK(1,1, 38), + MK(1,2, 38), + MK(1,3, 37), + MK(2,2, 37), + MK(2,3, 35), + MKEND +}; + +static const IndustryTileTable * const _tile_table_farm[] = { + _tile_table_farm_0, + _tile_table_farm_1, + _tile_table_farm_2, +}; + +static const IndustryTileTable _tile_table_copper_mine_0[] = { + MK(0,0, 47), + MK(0,1, 49), + MK(0,2, 51), + MK(1,0, 47), + MK(1,1, 49), + MK(1,2, 50), + MK(2,0, 51), + MK(2,1, 51), + MKEND +}; + +static const IndustryTileTable _tile_table_copper_mine_1[] = { + MK(0,0, 50), + MK(0,1, 47), + MK(0,2, 49), + MK(1,0, 47), + MK(1,1, 49), + MK(1,2, 51), + MK(2,0, 51), + MK(2,1, 47), + MK(2,2, 49), + MKEND +}; + +static const IndustryTileTable * const _tile_table_copper_mine[] = { + _tile_table_copper_mine_0, + _tile_table_copper_mine_1, +}; + +static const IndustryTileTable _tile_table_oil_well_0[] = { + MK(0,0, 29), + MK(1,0, 29), + MK(2,0, 29), + MK(0,1, 29), + MK(0,2, 29), + MKEND +}; + +static const IndustryTileTable _tile_table_oil_well_1[] = { + MK(0,0, 29), + MK(1,0, 29), + MK(1,1, 29), + MK(2,2, 29), + MK(2,3, 29), + MKEND +}; + +static const IndustryTileTable * const _tile_table_oil_well[] = { + _tile_table_oil_well_0, + _tile_table_oil_well_1, +}; + +static const IndustryTileTable _tile_table_bank_0[] = { + MK(0,0, 58), + MK(1,0, 59), + MKEND +}; + +static const IndustryTileTable * const _tile_table_bank[] = { + _tile_table_bank_0, +}; + +static const IndustryTileTable _tile_table_food_process_0[] = { + MK(0,0, 60), + MK(1,0, 60), + MK(2,0, 60), + MK(0,1, 60), + MK(1,1, 60), + MK(2,1, 60), + MK(0,2, 61), + MK(1,2, 61), + MK(2,2, 63), + MK(0,3, 62), + MK(1,3, 62), + MK(2,3, 63), + MKEND +}; + +static const IndustryTileTable _tile_table_food_process_1[] = { + MK(0,0, 61), + MK(1,0, 60), + MK(2,0, 61), + MK(3,0, 61), + MK(0,1, 62), + MK(1,1, 63), + MK(2,1, 63), + MK(3,1, 63), + MK(0,2, 60), + MK(1,2, 60), + MK(2,2, 60), + MK(3,2, 60), + MK(0,3, 62), + MK(1,3, 62), + MKEND +}; + +static const IndustryTileTable * const _tile_table_food_process[] = { + _tile_table_food_process_0, + _tile_table_food_process_1, +}; + +static const IndustryTileTable _tile_table_paper_mill_0[] = { + MK(0,0, 64), + MK(1,0, 65), + MK(2,0, 66), + MK(3,0, 67), + MK(0,1, 68), + MK(1,1, 69), + MK(2,1, 67), + MK(3,1, 67), + MK(0,2, 66), + MK(1,2, 71), + MK(2,2, 71), + MK(3,2, 70), + MKEND +}; + +static const IndustryTileTable * const _tile_table_paper_mill[] = { + _tile_table_paper_mill_0, +}; + +static const IndustryTileTable _tile_table_gold_mine_0[] = { + MK(0,0, 72), + MK(0,1, 73), + MK(0,2, 74), + MK(0,3, 75), + MK(1,0, 76), + MK(1,1, 77), + MK(1,2, 78), + MK(1,3, 79), + MK(2,0, 80), + MK(2,1, 81), + MK(2,2, 82), + MK(2,3, 83), + MK(3,0, 84), + MK(3,1, 85), + MK(3,2, 86), + MK(3,3, 87), + MKEND +}; + +static const IndustryTileTable * const _tile_table_gold_mine[] = { + _tile_table_gold_mine_0, +}; + +static const IndustryTileTable _tile_table_bank2_0[] = { + MK(0,0, 89), + MK(1,0, 90), + MKEND +}; + +static const IndustryTileTable * const _tile_table_bank2[] = { + _tile_table_bank2_0, +}; + +static const IndustryTileTable _tile_table_diamond_mine_0[] = { + MK(0,0, 91), + MK(0,1, 92), + MK(0,2, 93), + MK(1,0, 94), + MK(1,1, 95), + MK(1,2, 96), + MK(2,0, 97), + MK(2,1, 98), + MK(2,2, 99), + MKEND +}; + +static const IndustryTileTable * const _tile_table_diamond_mine[] = { + _tile_table_diamond_mine_0, +}; + +static const IndustryTileTable _tile_table_iron_mine_0[] = { + MK(0,0, 100), + MK(0,1, 101), + MK(0,2, 102), + MK(0,3, 103), + MK(1,0, 104), + MK(1,1, 105), + MK(1,2, 106), + MK(1,3, 107), + MK(2,0, 108), + MK(2,1, 109), + MK(2,2, 110), + MK(2,3, 111), + MK(3,0, 112), + MK(3,1, 113), + MK(3,2, 114), + MK(3,3, 115), + MKEND +}; + +static const IndustryTileTable * const _tile_table_iron_mine[] = { + _tile_table_iron_mine_0, +}; + +static const IndustryTileTable _tile_table_fruit_plantation_0[] = { + MK(0,0, 116), + MK(0,1, 116), + MK(0,2, 116), + MK(0,3, 116), + MK(1,0, 116), + MK(1,1, 116), + MK(1,2, 116), + MK(1,3, 116), + MK(2,0, 116), + MK(2,1, 116), + MK(2,2, 116), + MK(2,3, 116), + MK(3,0, 116), + MK(3,1, 116), + MK(3,2, 116), + MK(3,3, 116), + MK(4,0, 116), + MK(4,1, 116), + MK(4,2, 116), + MK(4,3, 116), + MKEND +}; + +static const IndustryTileTable * const _tile_table_fruit_plantation[] = { + _tile_table_fruit_plantation_0, +}; + +static const IndustryTileTable _tile_table_rubber_plantation_0[] = { + MK(0,0, 117), + MK(0,1, 117), + MK(0,2, 117), + MK(0,3, 117), + MK(1,0, 117), + MK(1,1, 117), + MK(1,2, 117), + MK(1,3, 117), + MK(2,0, 117), + MK(2,1, 117), + MK(2,2, 117), + MK(2,3, 117), + MK(3,0, 117), + MK(3,1, 117), + MK(3,2, 117), + MK(3,3, 117), + MK(4,0, 117), + MK(4,1, 117), + MK(4,2, 117), + MK(4,3, 117), + MKEND +}; + +static const IndustryTileTable * const _tile_table_rubber_plantation[] = { + _tile_table_rubber_plantation_0, +}; + +static const IndustryTileTable _tile_table_water_supply_0[] = { + MK(0,0, 118), + MK(0,1, 119), + MK(1,0, 118), + MK(1,1, 119), + MKEND +}; + +static const IndustryTileTable * const _tile_table_water_supply[] = { + _tile_table_water_supply_0, +}; + +static const IndustryTileTable _tile_table_water_tower_0[] = { + MK(0,0, 120), + MKEND +}; + +static const IndustryTileTable * const _tile_table_water_tower[] = { + _tile_table_water_tower_0, +}; + +static const IndustryTileTable _tile_table_factory2_0[] = { + MK(0,0, 121), + MK(0,1, 122), + MK(1,0, 123), + MK(1,1, 124), + MK(0,2, 121), + MK(0,3, 122), + MK(1,2, 123), + MK(1,3, 124), + MKEND +}; + +static const IndustryTileTable _tile_table_factory2_1[] = { + MK(0,0, 121), + MK(0,1, 122), + MK(1,0, 123), + MK(1,1, 124), + MK(2,0, 121), + MK(2,1, 122), + MK(3,0, 123), + MK(3,1, 124), + MKEND +}; + +static const IndustryTileTable * const _tile_table_factory2[] = { + _tile_table_factory2_0, + _tile_table_factory2_1, +}; + +static const IndustryTileTable _tile_table_farm2_0[] = { + MK(1,0, 33), + MK(1,1, 34), + MK(1,2, 36), + MK(0,0, 37), + MK(0,1, 37), + MK(0,2, 36), + MK(2,0, 35), + MK(2,1, 38), + MK(2,2, 38), + MKEND +}; + +static const IndustryTileTable _tile_table_farm2_1[] = { + MK(1,1, 33), + MK(1,2, 34), + MK(0,0, 35), + MK(0,1, 36), + MK(0,2, 36), + MK(0,3, 35), + MK(1,0, 37), + MK(1,3, 38), + MK(2,0, 37), + MK(2,1, 37), + MK(2,2, 38), + MK(2,3, 38), + MKEND +}; + +static const IndustryTileTable _tile_table_farm2_2[] = { + MK(2,0, 33), + MK(2,1, 34), + MK(0,0, 36), + MK(0,1, 36), + MK(0,2, 37), + MK(0,3, 37), + MK(1,0, 35), + MK(1,1, 38), + MK(1,2, 38), + MK(1,3, 37), + MK(2,2, 37), + MK(2,3, 35), + MKEND +}; + +static const IndustryTileTable * const _tile_table_farm2[] = { + _tile_table_farm2_0, + _tile_table_farm2_1, + _tile_table_farm2_2, +}; + +static const IndustryTileTable _tile_table_lumber_mill_0[] = { + MK(0,0, 125), + MK(0,1, 126), + MK(1,0, 127), + MK(1,1, 128), + MKEND +}; + +static const IndustryTileTable * const _tile_table_lumber_mill[] = { + _tile_table_lumber_mill_0, +}; + +static const IndustryTileTable _tile_table_cotton_candy_0[] = { + MK(0,0, 129), + MK(0,1, 129), + MK(0,2, 129), + MK(0,3, 129), + MK(1,0, 129), + MK(1,1, 129), + MK(1,2, 129), + MK(1,3, 129), + MK(2,0, 129), + MK(2,1, 129), + MK(2,2, 129), + MK(2,3, 129), + MK(3,0, 129), + MK(3,1, 129), + MK(3,2, 129), + MK(3,3, 129), + MK(1,4, 129), + MK(2,4, 129), + MKEND +}; + +static const IndustryTileTable _tile_table_cotton_candy_1[] = { + MK(0,0, 129), + MK(1,0, 129), + MK(2,0, 129), + MK(3,0, 129), + MK(4,0, 129), + MK(0,1, 129), + MK(1,1, 129), + MK(2,1, 129), + MK(3,1, 129), + MK(4,1, 129), + MK(0,2, 129), + MK(1,2, 129), + MK(2,2, 129), + MK(3,2, 129), + MK(4,2, 129), + MK(0,3, 129), + MK(1,3, 129), + MK(2,3, 129), + MK(3,3, 129), + MK(4,3, 129), + MK(1,4, 129), + MK(2,4, 129), + MK(3,4, 129), + MKEND +}; + +static const IndustryTileTable * const _tile_table_cotton_candy[] = { + _tile_table_cotton_candy_0, + _tile_table_cotton_candy_1, +}; + +static const IndustryTileTable _tile_table_candy_factory_0[] = { + MK(0,0, 131), + MK(0,1, 132), + MK(1,0, 133), + MK(1,1, 134), + MK(0,2, 131), + MK(0,3, 132), + MK(1,2, 133), + MK(1,3, 134), + MK(2,1, 131), + MK(2,2, 132), + MK(3,1, 133), + MK(3,2, 134), + MKEND +}; + +static const IndustryTileTable _tile_table_candy_factory_1[] = { + MK(0,0, 131), + MK(0,1, 132), + MK(1,0, 133), + MK(1,1, 134), + MK(2,0, 131), + MK(2,1, 132), + MK(3,0, 133), + MK(3,1, 134), + MK(1,2, 131), + MK(1,3, 132), + MK(2,2, 133), + MK(2,3, 134), + MKEND +}; + +static const IndustryTileTable * const _tile_table_candy_factory[] = { + _tile_table_candy_factory_0, + _tile_table_candy_factory_1, +}; + +static const IndustryTileTable _tile_table_battery_farm_0[] = { + MK(0,0, 135), + MK(0,1, 135), + MK(0,2, 135), + MK(0,3, 135), + MK(1,0, 135), + MK(1,1, 135), + MK(1,2, 135), + MK(1,3, 135), + MK(2,0, 135), + MK(2,1, 135), + MK(2,2, 135), + MK(2,3, 135), + MK(3,0, 135), + MK(3,1, 135), + MK(3,2, 135), + MK(3,3, 135), + MK(4,0, 135), + MK(4,1, 135), + MK(4,2, 135), + MK(4,3, 135), + MKEND +}; + +static const IndustryTileTable * const _tile_table_battery_farm[] = { + _tile_table_battery_farm_0, +}; + +static const IndustryTileTable _tile_table_cola_wells_0[] = { + MK(0,0, 137), + MK(0,1, 137), + MK(0,2, 137), + MK(1,0, 137), + MK(1,1, 137), + MK(1,2, 137), + MK(2,1, 137), + MK(2,2, 137), + MKEND +}; + +static const IndustryTileTable _tile_table_cola_wells_1[] = { + MK(0,1, 137), + MK(0,2, 137), + MK(0,3, 137), + MK(1,0, 137), + MK(1,1, 137), + MK(1,2, 137), + MK(2,1, 137), + MKEND +}; + +static const IndustryTileTable * const _tile_table_cola_wells[] = { + _tile_table_cola_wells_0, + _tile_table_cola_wells_1, +}; + +static const IndustryTileTable _tile_table_toy_shop_0[] = { + MK(0,0, 138), + MK(0,1, 139), + MK(1,0, 140), + MK(1,1, 141), + MKEND +}; + +static const IndustryTileTable * const _tile_table_toy_shop[] = { + _tile_table_toy_shop_0, +}; + +static const IndustryTileTable _tile_table_toy_factory_0[] = { + MK(0,0, 147), + MK(0,1, 142), + MK(1,0, 147), + MK(1,1, 143), + MK(2,0, 147), + MK(2,1, 144), + MK(3,0, 146), + MK(3,1, 145), + MKEND +}; + +static const IndustryTileTable * const _tile_table_toy_factory[] = { + _tile_table_toy_factory_0, +}; + +static const IndustryTileTable _tile_table_plastic_fountain_0[] = { + MK(0,0, 148), + MK(0,1, 151), + MK(0,2, 154), + MKEND +}; + +static const IndustryTileTable _tile_table_plastic_fountain_1[] = { + MK(0,0, 148), + MK(1,0, 151), + MK(2,0, 154), + MKEND +}; + +static const IndustryTileTable * const _tile_table_plastic_fountain[] = { + _tile_table_plastic_fountain_0, + _tile_table_plastic_fountain_1, +}; + +static const IndustryTileTable _tile_table_fizzy_drink_0[] = { + MK(0,0, 156), + MK(0,1, 157), + MK(1,0, 158), + MK(1,1, 159), + MKEND +}; + +static const IndustryTileTable * const _tile_table_fizzy_drink[] = { + _tile_table_fizzy_drink_0, +}; + +static const IndustryTileTable _tile_table_bubble_generator_0[] = { + MK(0,0, 163), + MK(0,1, 160), + MK(1,0, 163), + MK(1,1, 161), + MK(2,0, 163), + MK(2,1, 162), + MK(0,2, 163), + MK(0,3, 160), + MK(1,2, 163), + MK(1,3, 161), + MK(2,2, 163), + MK(2,3, 162), + MKEND +}; + +static const IndustryTileTable * const _tile_table_bubble_generator[] = { + _tile_table_bubble_generator_0, +}; + +static const IndustryTileTable _tile_table_toffee_quarry_0[] = { + MK(0,0, 164), + MK(1,0, 165), + MK(2,0, 166), + MKEND +}; + +static const IndustryTileTable * const _tile_table_toffee_quarry[] = { + _tile_table_toffee_quarry_0, +}; + +static const IndustryTileTable _tile_table_sugar_mine_0[] = { + MK(0,0, 167), + MK(0,1, 168), + MK(1,0, 169), + MK(1,1, 170), + MK(2,0, 171), + MK(2,1, 172), + MK(3,0, 173), + MK(3,1, 174), + MKEND +}; + +static const IndustryTileTable * const _tile_table_sugar_mine[] = { + _tile_table_sugar_mine_0, +}; + +#undef MK +#undef MKEND + +#define MK(tbl, a,b,c, p1,p2, r1,r2, a1,a2,a3, proc) {tbl,lengthof(tbl),a,b,c,{p1,p2},{r1,r2},{a1,a2,a3},proc} + +static const IndustrySpec _industry_spec[37] = { +/* name not close to produce prodrate accepts checkproc */ + MK(_tile_table_coal_mine, 1,255,255, 1,255, 15, 0, 255,255,255, 0), + MK(_tile_table_power_station, 0,255,255, 255,255, 0, 0, 1,255,255, 0), + MK(_tile_table_sawmill, 3,255,255, 5,255, 0, 0, 7,255,255, 0), + MK(_tile_table_forest, 2, 14,255, 7,255, 13, 0, 255,255,255, 1), + MK(_tile_table_oil_refinery, 5,255,255, 5,255, 0, 0, 3,255,255, 2), + MK(_tile_table_oil_rig, 4,255,255, 3, 0, 15, 2, 255,255,255, 2), + MK(_tile_table_factory, 9, 8,255, 5,255, 0, 0, 4, 6, 9, 0), + MK(_tile_table_printing_works, 14,255,255, 5,255, 0, 0, 9,255,255, 0), + MK(_tile_table_steel_mill, 18, 6,255, 9,255, 0, 0, 8,255,255, 0), + MK(_tile_table_farm, 6, 13,255, 6, 4, 10,10, 255,255,255, 3), + MK(_tile_table_copper_mine, 23,255,255, 8,255, 10, 0, 255,255,255, 0), + MK(_tile_table_oil_well, 4,255,255, 3,255, 12, 0, 255,255,255, 0), + MK(_tile_table_bank, 12,255,255, 10,255, 6, 0, 10,255,255, 0), + MK(_tile_table_food_process, 9, 19, 24, 11,255, 0, 0, 4, 6,255, 0), + MK(_tile_table_paper_mill, 3, 7,255, 9,255, 0, 0, 7,255,255, 0), + MK(_tile_table_gold_mine, 16,255,255, 10,255, 7, 0, 255,255,255, 0), + MK(_tile_table_bank2, 15, 17,255, 255,255, 0, 0, 10,255,255, 0), + MK(_tile_table_diamond_mine, 16,255,255, 10,255, 7, 0, 255,255,255, 0), + MK(_tile_table_iron_mine, 8,255,255, 8,255, 10, 0, 255,255,255, 0), + MK(_tile_table_fruit_plantation, 13,255,255, 4,255, 10, 0, 255,255,255, 4), + MK(_tile_table_rubber_plantation,23,255,255, 1,255, 10, 0, 255,255,255, 4), + MK(_tile_table_water_supply, 22,255,255, 9,255, 12, 0, 255,255,255, 5), + MK(_tile_table_water_tower, 21,255,255, 255,255, 0, 0, 9,255,255, 5), + MK(_tile_table_factory2, 10, 20, 25, 5,255, 0, 0, 1, 8, 7, 4), + MK(_tile_table_farm2, 13,255,255, 6,255, 11, 0, 255,255,255, 4), + MK(_tile_table_lumber_mill, 23,255,255, 7,255, 0, 0, 255,255,255, 6), + MK(_tile_table_cotton_candy, 27,255,255, 8,255, 13, 0, 255,255,255, 0), + MK(_tile_table_candy_factory, 26, 35, 36, 5,255, 0, 0, 1, 6, 8, 0), + MK(_tile_table_battery_farm, 31,255,255, 4,255, 11, 0, 255,255,255, 0), + MK(_tile_table_cola_wells, 33,255,255, 7,255, 12, 0, 255,255,255, 0), + MK(_tile_table_toy_shop, 31,255,255, 255,255, 0, 0, 3,255,255, 0), + MK(_tile_table_toy_factory, 30, 28, 32, 3,255, 0, 0, 10, 4,255, 0), + MK(_tile_table_plastic_fountain, 31,255,255, 10,255, 14, 0, 255,255,255, 0), + MK(_tile_table_fizzy_drink, 29, 34,255, 11,255, 0, 0, 7, 9,255, 0), + MK(_tile_table_bubble_generator, 33,255,255, 9,255, 13, 0, 255,255,255, 7), + MK(_tile_table_toffee_quarry, 27,255,255, 6,255, 10, 0, 255,255,255, 0), + MK(_tile_table_sugar_mine, 27,255,255, 1,255, 11, 0, 255,255,255, 0), +}; +#undef MK + +const byte _industry_type_costs[37] = { + 210, 30, 28, 200, 31, 240, 26, 26, 27, 250, 205, 220, 193, 26, + 28, 208, 19, 213, 220, 225, 218, 199, 14, 26, 250, 17, 195, 26, + 187, 193, 17, 20, 192, 22, 203, 213, 210 +}; + + +static const byte _industry_create_table_0[] = { + 4, 4, + 5, 3, + 5, 2, + 8, 0, + 5, 1, + 4, 11, + 5, 18, + 9, 9, + 5, 8, + 5, 6, + 0 +}; + +static const byte _industry_create_table_1[] = { + 4, 4, + 5, 3, + 5, 14, + 8, 0, + 5, 1, + 5, 11, + 5, 13, + 9, 9, + 4, 15, + 5, 7, + 6, 16, + 0 +}; + +static const byte _industry_create_table_2[] = { + 4, 4, + 5, 11, + 5, 16, + 4, 13, + 4, 17, + 4, 10, + 4, 19, + 4, 20, + 4, 21, + 8, 22, + 4, 13, + 4, 23, + 2, 24, + 0 +}; + +static const byte _industry_create_table_3[] = { + 5, 26, + 5, 27, + 4, 28, + 5, 29, + 4, 30, + 5, 31, + 5, 32, + 4, 33, + 5, 34, + 5, 35, + 4, 36, + 0 +}; + +static const byte * const _industry_create_table[4] = { + _industry_create_table_0, + _industry_create_table_1, + _industry_create_table_2, + _industry_create_table_3, +}; + + +static const int8 _industry_map5_accepts_1[] = { + -1, -1, -1, 0, -1, -1, -1, -1, + 0, -1, -1, 0, 0, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, 0, -1, -1, -1, -1, 6, + 6, 6, 6, -1, -1, -1, -1, -1, + -1, -1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8, 8, 8, 8, -1, -1, -1, + -1, -1, -1, 8, 8, 8, 8, -1, + -1, -1, -1, -1, -1, -1, 4, 4, + 4, 4, 4, 4, -1, -1, -1, -1, + -1, -1, -1, -1, 9, 9, 9, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, +}; + + +static const int8 _industry_map5_accepts_2[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 9, + 9, 9, 9, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 7, 7, 7, 7, -1, -1, -1, + -1, -1, -1, 6, 6, 6, 6, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, +}; + +static const int8 _industry_map5_accepts_3[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + 1, -1, -1, -1, -1, 7, -1, -1, + -1, -1, -1, -1, 3, -1, -1, -1, + 0, 2, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 4, + 4, 4, 4, 9, 9, 9, 9, -1, + -1, -1, -1, -1, 8, 8, 8, 8, + 8, 8, 10, 10, 4, 4, 4, 4, + 7, 7, 7, 7, 7, 7, 7, 7, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 9, 1, 1, 1, 1, -1, -1, -1, + -1, -1, -1, 1, 1, 1, 1, -1, + -1, -1, 3, 3, 3, 3, 10, 10, + 10, 10, 10, 10, -1, -1, -1, -1, + -1, -1, -1, -1, 7, 7, 7, 7, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, +}; diff --git a/table/clear_land.h b/table/clear_land.h new file mode 100644 --- /dev/null +++ b/table/clear_land.h @@ -0,0 +1,61 @@ +static const SpriteID _landscape_clear_sprites[8] = { + 0xFA0, + 0xFB3, + 0xFB4, + 0xFB5, + 0xFB6, + 0xFA0, + 0xFB3, + 0xFB4, +}; + +static const byte _fence_mod_by_tileh[32] = { + 0,2,4,0,0,2,4,0, + 0,2,4,0,0,2,4,0, + 0,2,4,0,0,2,4,4, + 0,2,4,2,0,2,4,0, +}; + +static const byte _fence_mod_by_tileh_2[32] = { + 1,1,5,5,3,3,1,1, + 1,1,5,5,3,3,1,1, + 1,1,5,5,3,3,1,5, + 1,1,5,5,3,3,3,1, +}; + + +static const SpriteID _clear_land_fence_sprites_1[7] = { + 0xFFA, + 0x1000, + 0x1006, + 0x100C, + 0x1012, + 0x1018, +}; + +static const SpriteID _clear_land_sprites_1[16] = { + 0x101E, + 0x1031, + 0x1044, + 0x1057, + 0x106A, + 0x107D, + 0x1090, + 0x10A3, + 0x10B6, +}; + +static const SpriteID _clear_land_sprites_2[8] = { + 0x118D, + 0x11A0, + 0x11B3, + 0x11C6, +}; + +static const SpriteID _clear_land_sprites_3[8] = { + 0x118D, + 0x11A0, + 0x11B3, + 0x11C6, +}; + diff --git a/table/engines.h b/table/engines.h new file mode 100644 --- /dev/null +++ b/table/engines.h @@ -0,0 +1,404 @@ +#define MK(a,b,c,d,e,f) {a,b,c,d,((e)<<4)|(f)} +#define MW(a,b,c,d,e,f) {a,b|0x80,c,d,((e)<<4)|(f)} + +EngineInfo _engine_info[TOTAL_NUM_ENGINES] = { + MK( 4809, 20, 15, 30, 0, 1), /* 0 */ + MK( 12784, 20, 22, 30, 0, 6), /* 1 */ + MK( 9497, 20, 20, 50, 0, 8), /* 2 */ + MK( 11688, 20, 20, 30, 0, 8), /* 3 */ + MK( 16802, 20, 20, 30, 0, 8), /* 4 */ + MK( 18993, 20, 20, 30, 0, 8), /* 5 */ + MK( 20820, 20, 20, 30, 0, 8), /* 6 */ + MK( 8766, 20, 20, 30, 0, 6), /* 7 */ + MK( 5114, 20, 21, 30, 0, 1), /* 8 */ + MK( 5479, 20, 20, 30, 0, 1), /* 9 */ + MK( 12419, 20, 23, 25, 0, 1), /* 10 */ + MK( 13149, 20, 12, 30, 0, 1), /* 11 */ + MK( 23376, 20, 15, 35, 0, 1), /* 12 */ + MK( 14976, 20, 18, 28, 0, 1), /* 13 */ + MK( 14245, 20, 20, 30, 0, 1), /* 14 */ + MK( 15341, 20, 22, 33, 0, 1), /* 15 */ + MK( 14976, 20, 20, 25, 0, 6), /* 16 */ + MK( 16437, 20, 20, 30, 0, 6), /* 17 */ + MK( 18993, 20, 22, 30, 0, 6), /* 18 */ + MK( 13880, 20, 22, 30, 0, 6), /* 19 */ + MK( 20454, 20, 22, 30, 0, 6), /* 20 */ + MK( 16071, 20, 22, 30, 0, 6), /* 21 */ + MK( 20820, 20, 20, 25, 0, 1), /* 22 */ + MK( 16437, 20, 23, 30, 0, 1), /* 23 */ + MK( 19359, 20, 23, 80, 0, 1), /* 24 */ + MK( 23376, 20, 25, 30, 0, 1), /* 25 */ + MK( 26298, 20, 25, 50, 0, 1), /* 26 */ + MW( 1827, 20, 20, 50, 0, 15), /* 27 */ + MW( 1827, 20, 20, 50, 0, 15), /* 28 */ + MW( 1827, 20, 20, 50, 0, 3), /* 29 */ + MW( 1827, 20, 20, 50, 0, 7), /* 30 */ + MW( 1827, 20, 20, 50, 0, 3), /* 31 */ + MW( 1827, 20, 20, 50, 0, 7), /* 32 */ + MW( 1827, 20, 20, 50, 0, 7), /* 33 */ + MW( 1827, 20, 20, 50, 0, 7), /* 34 */ + MW( 1827, 20, 20, 50, 0, 1), /* 35 */ + MW( 1827, 20, 20, 50, 0, 1), /* 36 */ + MW( 1827, 20, 20, 50, 0, 7), /* 37 */ + MW( 1827, 20, 20, 50, 0, 6), /* 38 */ + MW( 1827, 20, 20, 50, 0, 2), /* 39 */ + MW( 1827, 20, 20, 50, 0, 4), /* 40 */ + MW( 1827, 20, 20, 50, 0, 4), /* 41 */ + MW( 1827, 20, 20, 50, 0, 4), /* 42 */ + MW( 1827, 20, 20, 50, 0, 4), /* 43 */ + MW( 1827, 20, 20, 50, 0, 8), /* 44 */ + MW( 1827, 20, 20, 50, 0, 8), /* 45 */ + MW( 1827, 20, 20, 50, 0, 8), /* 46 */ + MW( 1827, 20, 20, 50, 0, 8), /* 47 */ + MW( 1827, 20, 20, 50, 0, 8), /* 48 */ + MW( 1827, 20, 20, 50, 0, 8), /* 49 */ + MW( 1827, 20, 20, 50, 0, 8), /* 50 */ + MW( 1827, 20, 20, 50, 0, 8), /* 51 */ + MW( 1827, 20, 20, 50, 0, 8), /* 52 */ + MW( 1827, 20, 20, 50, 0, 8), /* 53 */ + MK( 28490, 20, 20, 50, 1, 7), /* 54 */ + MK( 31047, 20, 20, 50, 1, 7), /* 55 */ + MK( 28855, 20, 20, 50, 1, 8), /* 56 */ + MW( 1827, 20, 20, 50, 1, 15), /* 57 */ + MW( 1827, 20, 20, 50, 1, 15), /* 58 */ + MW( 1827, 20, 20, 50, 1, 3), /* 59 */ + MW( 1827, 20, 20, 50, 1, 7), /* 60 */ + MW( 1827, 20, 20, 50, 1, 3), /* 61 */ + MW( 1827, 20, 20, 50, 1, 7), /* 62 */ + MW( 1827, 20, 20, 50, 1, 7), /* 63 */ + MW( 1827, 20, 20, 50, 1, 7), /* 64 */ + MW( 1827, 20, 20, 50, 1, 1), /* 65 */ + MW( 1827, 20, 20, 50, 1, 1), /* 66 */ + MW( 1827, 20, 20, 50, 1, 7), /* 67 */ + MW( 1827, 20, 20, 50, 1, 6), /* 68 */ + MW( 1827, 20, 20, 50, 1, 2), /* 69 */ + MW( 1827, 20, 20, 50, 1, 4), /* 70 */ + MW( 1827, 20, 20, 50, 1, 4), /* 71 */ + MW( 1827, 20, 20, 50, 1, 4), /* 72 */ + MW( 1827, 20, 20, 50, 1, 4), /* 73 */ + MW( 1827, 20, 20, 50, 1, 8), /* 74 */ + MW( 1827, 20, 20, 50, 1, 8), /* 75 */ + MW( 1827, 20, 20, 50, 1, 8), /* 76 */ + MW( 1827, 20, 20, 50, 1, 8), /* 77 */ + MW( 1827, 20, 20, 50, 1, 8), /* 78 */ + MW( 1827, 20, 20, 50, 1, 8), /* 79 */ + MW( 1827, 20, 20, 50, 1, 8), /* 80 */ + MW( 1827, 20, 20, 50, 1, 8), /* 81 */ + MW( 1827, 20, 20, 50, 1, 8), /* 82 */ + MW( 1827, 20, 20, 50, 1, 8), /* 83 */ + MK( 36525, 20, 20, 50, 2, 7), /* 84 */ + MK( 39447, 20, 20, 50, 2, 7), /* 85 */ + MK( 42004, 20, 20, 50, 2, 7), /* 86 */ + MK( 42735, 20, 20, 50, 2, 7), /* 87 */ + MK( 36891, 20, 20, 60, 2, 8), /* 88 */ + MW( 1827, 20, 20, 50, 2, 15), /* 89 */ + MW( 1827, 20, 20, 50, 2, 15), /* 90 */ + MW( 1827, 20, 20, 50, 2, 3), /* 91 */ + MW( 1827, 20, 20, 50, 2, 7), /* 92 */ + MW( 1827, 20, 20, 50, 2, 3), /* 93 */ + MW( 1827, 20, 20, 50, 2, 7), /* 94 */ + MW( 1827, 20, 20, 50, 2, 7), /* 95 */ + MW( 1827, 20, 20, 50, 2, 7), /* 96 */ + MW( 1827, 20, 20, 50, 2, 1), /* 97 */ + MW( 1827, 20, 20, 50, 2, 1), /* 98 */ + MW( 1827, 20, 20, 50, 2, 7), /* 99 */ + MW( 1827, 20, 20, 50, 2, 6), /* 100 */ + MW( 1827, 20, 20, 50, 2, 2), /* 101 */ + MW( 1827, 20, 20, 50, 2, 4), /* 102 */ + MW( 1827, 20, 20, 50, 2, 4), /* 103 */ + MW( 1827, 20, 20, 50, 2, 4), /* 104 */ + MW( 1827, 20, 20, 50, 2, 4), /* 105 */ + MW( 1827, 20, 20, 50, 2, 8), /* 106 */ + MW( 1827, 20, 20, 50, 2, 8), /* 107 */ + MW( 1827, 20, 20, 50, 2, 8), /* 108 */ + MW( 1827, 20, 20, 50, 2, 8), /* 109 */ + MW( 1827, 20, 20, 50, 2, 8), /* 110 */ + MW( 1827, 20, 20, 50, 2, 8), /* 111 */ + MW( 1827, 20, 20, 50, 2, 8), /* 112 */ + MW( 1827, 20, 20, 50, 2, 8), /* 113 */ + MW( 1827, 20, 20, 50, 2, 8), /* 114 */ + MW( 1827, 20, 20, 50, 2, 8), /* 115 */ + MK( 3378, 20, 12, 40, 0, 7), /* 116 */ + MK( 16071, 20, 15, 30, 0, 7), /* 117 */ + MK( 24107, 20, 15, 40, 0, 7), /* 118 */ + MK( 32142, 20, 15, 80, 0, 7), /* 119 */ + MK( 9132, 20, 15, 40, 0, 8), /* 120 */ + MK( 18993, 20, 15, 40, 0, 8), /* 121 */ + MK( 32873, 20, 15, 80, 0, 8), /* 122 */ + MK( 5479, 20, 15, 55, 0, 3), /* 123 */ + MK( 20089, 20, 15, 55, 0, 3), /* 124 */ + MK( 33969, 20, 15, 85, 0, 3), /* 125 */ + MK( 5479, 20, 15, 55, 0, 7), /* 126 */ + MK( 21550, 20, 15, 55, 0, 7), /* 127 */ + MK( 35795, 20, 15, 85, 0, 7), /* 128 */ + MK( 5479, 20, 15, 55, 0, 8), /* 129 */ + MK( 21550, 20, 15, 55, 0, 8), /* 130 */ + MK( 35795, 20, 15, 85, 0, 8), /* 131 */ + MK( 5479, 20, 15, 55, 0, 7), /* 132 */ + MK( 19359, 20, 15, 55, 0, 7), /* 133 */ + MK( 31047, 20, 15, 85, 0, 7), /* 134 */ + MK( 5479, 20, 15, 55, 0, 3), /* 135 */ + MK( 21915, 20, 15, 55, 0, 3), /* 136 */ + MK( 37256, 20, 15, 85, 0, 3), /* 137 */ + MK( 5479, 20, 15, 55, 0, 7), /* 138 */ + MK( 19724, 20, 15, 55, 0, 7), /* 139 */ + MK( 31047, 20, 15, 85, 0, 7), /* 140 */ + MK( 5479, 20, 15, 55, 0, 7), /* 141 */ + MK( 21185, 20, 15, 55, 0, 7), /* 142 */ + MK( 32873, 20, 15, 85, 0, 7), /* 143 */ + MK( 5479, 20, 15, 55, 0, 7), /* 144 */ + MK( 19724, 20, 15, 55, 0, 7), /* 145 */ + MK( 35430, 20, 15, 85, 0, 7), /* 146 */ + MK( 5479, 20, 15, 55, 0, 1), /* 147 */ + MK( 20820, 20, 15, 55, 0, 1), /* 148 */ + MK( 33238, 20, 15, 85, 0, 1), /* 149 */ + MK( 5479, 20, 15, 55, 0, 1), /* 150 */ + MK( 21185, 20, 15, 55, 0, 1), /* 151 */ + MK( 31777, 20, 15, 85, 0, 1), /* 152 */ + MK( 5479, 20, 15, 55, 0, 7), /* 153 */ + MK( 22281, 20, 15, 55, 0, 7), /* 154 */ + MK( 33603, 20, 15, 85, 0, 7), /* 155 */ + MK( 5479, 20, 15, 55, 0, 6), /* 156 */ + MK( 18628, 20, 15, 55, 0, 6), /* 157 */ + MK( 30681, 20, 15, 85, 0, 6), /* 158 */ + MK( 5479, 20, 15, 55, 0, 2), /* 159 */ + MK( 21185, 20, 15, 55, 0, 2), /* 160 */ + MK( 31777, 20, 15, 85, 0, 2), /* 161 */ + MK( 5479, 20, 15, 55, 0, 4), /* 162 */ + MK( 20820, 20, 15, 55, 0, 4), /* 163 */ + MK( 33238, 20, 15, 85, 0, 4), /* 164 */ + MK( 5479, 20, 15, 55, 0, 4), /* 165 */ + MK( 20970, 20, 15, 55, 0, 4), /* 166 */ + MK( 33388, 20, 15, 85, 0, 4), /* 167 */ + MK( 5479, 20, 15, 55, 0, 4), /* 168 */ + MK( 21335, 20, 15, 55, 0, 4), /* 169 */ + MK( 33753, 20, 15, 85, 0, 4), /* 170 */ + MK( 5479, 20, 15, 55, 0, 4), /* 171 */ + MK( 20604, 20, 15, 55, 0, 4), /* 172 */ + MK( 33023, 20, 15, 85, 0, 4), /* 173 */ + MK( 5479, 20, 15, 55, 0, 8), /* 174 */ + MK( 19724, 20, 15, 55, 0, 8), /* 175 */ + MK( 33238, 20, 15, 85, 0, 8), /* 176 */ + MK( 5479, 20, 15, 55, 0, 8), /* 177 */ + MK( 20089, 20, 15, 55, 0, 8), /* 178 */ + MK( 33603, 20, 15, 85, 0, 8), /* 179 */ + MK( 5479, 20, 15, 55, 0, 8), /* 180 */ + MK( 20454, 20, 15, 55, 0, 8), /* 181 */ + MK( 33969, 20, 15, 85, 0, 8), /* 182 */ + MK( 5479, 20, 15, 55, 0, 8), /* 183 */ + MK( 20820, 20, 15, 55, 0, 8), /* 184 */ + MK( 34334, 20, 15, 85, 0, 8), /* 185 */ + MK( 5479, 20, 15, 55, 0, 8), /* 186 */ + MK( 21185, 20, 15, 55, 0, 8), /* 187 */ + MK( 34699, 20, 15, 85, 0, 8), /* 188 */ + MK( 5479, 20, 15, 55, 0, 8), /* 189 */ + MK( 21550, 20, 15, 55, 0, 8), /* 190 */ + MK( 35064, 20, 15, 85, 0, 8), /* 191 */ + MK( 5479, 20, 15, 55, 0, 8), /* 192 */ + MK( 19874, 20, 15, 55, 0, 8), /* 193 */ + MK( 35430, 20, 15, 85, 0, 8), /* 194 */ + MK( 5479, 20, 15, 55, 0, 8), /* 195 */ + MK( 20239, 20, 15, 55, 0, 8), /* 196 */ + MK( 35795, 20, 15, 85, 0, 8), /* 197 */ + MK( 5479, 20, 15, 55, 0, 8), /* 198 */ + MK( 20604, 20, 15, 55, 0, 8), /* 199 */ + MK( 32873, 20, 15, 85, 0, 8), /* 200 */ + MK( 5479, 20, 15, 55, 0, 8), /* 201 */ + MK( 20970, 20, 15, 55, 0, 8), /* 202 */ + MK( 33023, 20, 15, 85, 0, 8), /* 203 */ + MK( 2922, 5, 30, 50, 0, 7), /* 204 */ + MK( 17167, 5, 30, 90, 0, 7), /* 205 */ + MK( 2192, 5, 30, 55, 0, 7), /* 206 */ + MK( 18628, 5, 30, 90, 0, 7), /* 207 */ + MK( 17257, 10, 25, 90, 0, 7), /* 208 */ + MK( 9587, 5, 30, 40, 0, 8), /* 209 */ + MK( 20544, 5, 30, 90, 0, 8), /* 210 */ + MK( 2557, 5, 30, 55, 0, 7), /* 211 */ + MK( 19724, 5, 30, 98, 0, 7), /* 212 */ + MK( 9587, 5, 30, 45, 0, 8), /* 213 */ + MK( 22371, 5, 30, 90, 0, 8), /* 214 */ + MK( 2922, 20, 20, 20, 0, 7), /* 215 */ + MK( 9922, 20, 24, 20, 0, 7), /* 216 */ + MK( 12659, 20, 18, 20, 0, 7), /* 217 */ + MK( 17652, 20, 25, 35, 0, 7), /* 218 */ + MK( 4929, 20, 30, 30, 0, 7), /* 219 */ + MK( 13695, 20, 23, 25, 0, 7), /* 220 */ + MK( 16341, 20, 26, 30, 0, 7), /* 221 */ + MK( 21395, 20, 25, 30, 0, 7), /* 222 */ + MK( 18263, 20, 20, 30, 0, 7), /* 223 */ + MK( 25233, 20, 25, 30, 0, 7), /* 224 */ + MK( 15371, 20, 22, 25, 0, 7), /* 225 */ + MK( 15461, 20, 25, 25, 0, 7), /* 226 */ + MK( 16952, 20, 22, 25, 0, 7), /* 227 */ + MK( 17227, 20, 25, 30, 0, 7), /* 228 */ + MK( 22371, 20, 25, 35, 0, 7), /* 229 */ + MK( 22341, 20, 25, 30, 0, 7), /* 230 */ + MK( 27209, 20, 25, 30, 0, 7), /* 231 */ + MK( 17988, 20, 20, 30, 0, 7), /* 232 */ + MK( 18993, 20, 24, 35, 0, 7), /* 233 */ + MK( 22401, 20, 24, 30, 0, 7), /* 234 */ + MK( 24472, 20, 24, 30, 0, 7), /* 235 */ + MK( 26724, 20, 24, 30, 0, 7), /* 236 */ + MK( 22005, 20, 25, 30, 0, 7), /* 237 */ + MK( 24107, 20, 20, 35, 0, 7), /* 238 */ + MK( 29310, 20, 25, 60, 0, 7), /* 239 */ + MK( 35520, 20, 22, 30, 0, 7), /* 240 */ + MK( 36981, 20, 22, 30, 0, 7), /* 241 */ + MK( 38807, 20, 22, 50, 0, 7), /* 242 */ + MK( 42094, 20, 25, 30, 0, 7), /* 243 */ + MK( 44651, 20, 23, 30, 0, 7), /* 244 */ + MK( 40268, 20, 25, 30, 0, 7), /* 245 */ + MK( 33693, 20, 25, 50, 0, 7), /* 246 */ + MK( 32963, 20, 20, 60, 0, 7), /* 247 */ + MK( 9222, 20, 20, 35, 0, 8), /* 248 */ + MK( 12874, 20, 20, 35, 0, 8), /* 249 */ + MK( 16892, 20, 20, 35, 0, 8), /* 250 */ + MK( 21275, 20, 20, 99, 0, 8), /* 251 */ + MK( 23832, 20, 20, 99, 0, 8), /* 252 */ + MK( 13575, 20, 20, 40, 0, 7), /* 253 */ + MK( 28215, 20, 20, 30, 0, 7), /* 254 */ + MK( 13575, 20, 20, 99, 0, 8), /* 255 */ +}; + +RailVehicleInfo _rail_vehicle_info[] = { + // image_index max_speed (kph) running_cost_base + // | flags | power (hp)| running_cost_class + // | | base_cost | weight | capacity + // | | | | | | | | | cargo_type + // | | | | | | | | | | + { 2, 0, 7, 64, 300, 47, 50, 0, 0, 0}, /* 0 */ + { 19, 0, 8, 80, 600, 65, 65, 1, 0, 0}, /* 1 */ + { 2, 0, 10, 72, 400, 85, 90, 0, 0, 0}, /* 2 */ + { 0, 0, 15, 96, 900, 130, 130, 0, 0, 0}, /* 3 */ + { 1, 0, 19, 112, 1000, 140, 145, 0, 0, 0}, /* 4 */ + { 12, 0, 16, 120, 1400, 95, 125, 1, 0, 0}, /* 5 */ + { 14, 0, 20, 152, 2000, 120, 135, 1, 0, 0}, /* 6 */ + { 3, 0, 14, 88, 1100, 145, 130, 0, 0, 0}, /* 7 */ + { 0, 0, 13, 112, 1000, 131, 120, 0, 0, 0}, /* 8 */ + { 1, 0, 19, 128, 1200, 162, 140, 0, 0, 0}, /* 9 */ + { 0, 0, 22, 144, 1600, 170, 130, 0, 0, 0}, /* 10 */ + { 8, 1, 11, 112, 600/2, 32,85/2, 1, 38, CT_PASSENGERS}, /* 11 */ + { 10, 1, 14, 120, 700/2, 38,70/2, 1, 40, CT_PASSENGERS}, /* 12 */ + { 4, 0, 15, 128, 1250, 72, 95, 1, 0, 0}, /* 13 */ + { 5, 0, 17, 144, 1750, 101, 120, 1, 0, 0}, /* 14 */ + { 4, 0, 18, 160, 2580, 112, 140, 1, 0, 0}, /* 15 */ + { 14, 0, 23, 96, 4000, 150, 135, 1, 0, 0}, /* 16 */ + { 12, 0, 16, 112, 2400, 120, 105, 1, 0, 0}, /* 17 */ + { 13, 0, 30, 112, 6600, 207, 155, 1, 0, 0}, /* 18 */ + { 15, 0, 18, 104, 1500, 110, 105, 1, 0, 0}, /* 19 */ + { 16, 1, 35, 160,3500/2, 95, 205/2, 1, 0, 0}, /* 20 */ + { 18, 0, 21, 104, 2200, 120, 145, 1, 0, 0}, /* 21 */ + { 6, 1, 20, 200,4500/2, 70, 190/2, 1, 4, CT_MAIL}, /* 22 */ + { 20, 0, 26, 160, 3600, 84, 180, 2, 0, 0}, /* 23 */ + { 20, 0, 30, 176, 5000, 82, 205, 2, 0, 0}, /* 24 */ + { 21, 1, 40, 240,7000/2, 90, 240/2, 2, 0, 0}, /* 25 */ + { 23, 1, 43, 264,8000/2, 95, 250/2, 2, 0, 0}, /* 26 */ + { 33, 2, 247, 0, 0, 25, 0, 0, 40, CT_PASSENGERS}, /* 27 */ + { 35, 2, 228, 0, 0, 21, 0, 0, 30, CT_MAIL}, /* 28 */ + { 34, 2, 176, 0, 0, 18, 0, 0, 30, CT_COAL}, /* 29 */ + { 36, 2, 200, 0, 0, 24, 0, 0, 30, CT_OIL}, /* 30 */ + { 37, 2, 192, 0, 0, 20, 0, 0, 25, CT_LIVESTOCK}, /* 31 */ + { 38, 2, 190, 0, 0, 21, 0, 0, 25, CT_GOODS}, /* 32 */ + { 39, 2, 182, 0, 0, 19, 0, 0, 30, CT_GRAIN}, /* 33 */ + { 40, 2, 181, 0, 0, 16, 0, 0, 30, CT_WOOD}, /* 34 */ + { 41, 2, 179, 0, 0, 19, 0, 0, 30, CT_IRON_ORE}, /* 35 */ + { 42, 2, 196, 0, 0, 18, 0, 0, 20, CT_STEEL}, /* 36 */ + { 43, 2, 255, 0, 0, 30, 0, 0, 20, CT_VALUABLES}, /* 37 */ + { 44, 2, 191, 0, 0, 22, 0, 0, 25, CT_FOOD}, /* 38 */ + { 45, 2, 196, 0, 0, 18, 0, 0, 20, CT_PAPER}, /* 39 */ + { 46, 2, 179, 0, 0, 19, 0, 0, 30, CT_COPPER_ORE}, /* 40 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 25, CT_WATER}, /* 41 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 25, CT_FRUIT}, /* 42 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 21, CT_RUBBER}, /* 43 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 30, CT_SUGAR}, /* 44 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 30, CT_COTTON_CANDY}, /* 45 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 30, CT_TOFFEE}, /* 46 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 20, CT_BUBBLES}, /* 47 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 25, CT_COLA}, /* 48 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 25, CT_CANDY}, /* 49 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 20, CT_TOYS}, /* 50 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 22, CT_BATTERIES}, /* 51 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 25, CT_FIZZY_DRINKS}, /* 52 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 30, CT_PLASTIC}, /* 53 */ + { 25, 0, 52, 304, 9000, 95, 230, 2, 0, 0}, /* 54 */ + { 26, 1, 60, 336,10000/2, 85, 240/2, 2, 25, CT_PASSENGERS}, /* 55 */ + { 26, 0, 53, 320, 5000, 95, 230, 2, 0, 0}, /* 56 */ + { 60, 2, 247, 0, 0, 25, 0, 0, 45, CT_PASSENGERS}, /* 57 */ + { 62, 2, 228, 0, 0, 21, 0, 0, 35, CT_MAIL}, /* 58 */ + { 61, 2, 176, 0, 0, 18, 0, 0, 35, CT_COAL}, /* 59 */ + { 63, 2, 200, 0, 0, 24, 0, 0, 35, CT_OIL}, /* 60 */ + { 64, 2, 192, 0, 0, 20, 0, 0, 30, CT_LIVESTOCK}, /* 61 */ + { 65, 2, 190, 0, 0, 21, 0, 0, 30, CT_GOODS}, /* 62 */ + { 66, 2, 182, 0, 0, 19, 0, 0, 35, CT_GRAIN}, /* 63 */ + { 67, 2, 181, 0, 0, 16, 0, 0, 35, CT_WOOD}, /* 64 */ + { 68, 2, 179, 0, 0, 19, 0, 0, 35, CT_IRON_ORE}, /* 65 */ + { 69, 2, 196, 0, 0, 18, 0, 0, 25, CT_STEEL}, /* 66 */ + { 70, 2, 255, 0, 0, 30, 0, 0, 25, CT_VALUABLES}, /* 67 */ + { 71, 2, 191, 0, 0, 22, 0, 0, 30, CT_FOOD}, /* 68 */ + { 72, 2, 196, 0, 0, 18, 0, 0, 25, CT_PAPER}, /* 69 */ + { 73, 2, 179, 0, 0, 19, 0, 0, 35, CT_COPPER_ORE}, /* 70 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 30, CT_WATER}, /* 71 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 30, CT_FRUIT}, /* 72 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 26, CT_RUBBER}, /* 73 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 35, CT_SUGAR}, /* 74 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 35, CT_COTTON_CANDY}, /* 75 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 35, CT_TOFFEE}, /* 76 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 25, CT_BUBBLES}, /* 77 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 30, CT_COLA}, /* 78 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 30, CT_CANDY}, /* 79 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 25, CT_TOYS}, /* 80 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 27, CT_BATTERIES}, /* 81 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 30, CT_FIZZY_DRINKS}, /* 82 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 35, CT_PLASTIC}, /* 83 */ + { 28, 0, 70, 400, 10000, 105, 250, 2, 0, 0}, /* 84 */ + { 29, 0, 74, 448, 12000, 120, 253, 2, 0, 0}, /* 85 */ + { 30, 0, 82, 480, 15000, 130, 254, 2, 0, 0}, /* 86 */ + { 31, 1, 95, 640,20000/2,150, 255/2, 2, 0, 0}, /* 87 */ + { 28, 0, 70, 480, 10000, 120, 250, 2, 0, 0}, /* 88 */ + { 60, 2, 247, 0, 0, 25, 0, 0, 47, CT_PASSENGERS}, /* 89 */ + { 62, 2, 228, 0, 0, 21, 0, 0, 37, CT_MAIL}, /* 90 */ + { 61, 2, 176, 0, 0, 18, 0, 0, 37, CT_COAL}, /* 91 */ + { 63, 2, 200, 0, 0, 24, 0, 0, 37, CT_OIL}, /* 92 */ + { 64, 2, 192, 0, 0, 20, 0, 0, 32, CT_LIVESTOCK}, /* 93 */ + { 65, 2, 190, 0, 0, 21, 0, 0, 32, CT_GOODS}, /* 94 */ + { 66, 2, 182, 0, 0, 19, 0, 0, 37, CT_GRAIN}, /* 95 */ + { 67, 2, 181, 0, 0, 16, 0, 0, 37, CT_WOOD}, /* 96 */ + { 68, 2, 179, 0, 0, 19, 0, 0, 37, CT_IRON_ORE}, /* 97 */ + { 69, 2, 196, 0, 0, 18, 0, 0, 27, CT_STEEL}, /* 98 */ + { 70, 2, 255, 0, 0, 30, 0, 0, 27, CT_VALUABLES}, /* 99 */ + { 71, 2, 191, 0, 0, 22, 0, 0, 32, CT_FOOD}, /* 100 */ + { 72, 2, 196, 0, 0, 18, 0, 0, 27, CT_PAPER}, /* 101 */ + { 73, 2, 179, 0, 0, 19, 0, 0, 37, CT_COPPER_ORE}, /* 102 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 32, CT_WATER}, /* 103 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 32, CT_FRUIT}, /* 104 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 28, CT_RUBBER}, /* 105 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 37, CT_SUGAR}, /* 106 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 37, CT_COTTON_CANDY}, /* 107 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 37, CT_TOFFEE}, /* 108 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 27, CT_BUBBLES}, /* 109 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 32, CT_COLA}, /* 110 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 32, CT_CANDY}, /* 111 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 27, CT_TOYS}, /* 112 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 29, CT_BATTERIES}, /* 113 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 32, CT_FIZZY_DRINKS}, /* 114 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 37, CT_PLASTIC}, /* 115 */ +}; + + +ShipVehicleInfo _ship_vehicle_info[] = { + // image_index cargo_type cargo_amount refittable + // | base_cost | | running_cost + // | | max_speed | | sfx | + // | | | | | | | | + { 1, 160, 48, CT_OIL, 220, 140, 4, 0 }, /* 0 */ + { 1, 176, 80, CT_OIL, 350, 125, 4, 0 }, /* 1 */ + { 2, 96, 64, CT_PASSENGERS, 100, 90, 5, 0 }, /* 2 */ + { 2, 112, 128, CT_PASSENGERS, 130, 80, 5, 0 }, /* 3 */ + { 3, 148, 224, CT_PASSENGERS, 100, 190, 5, 0 }, /* 4 */ + { 2, 96, 64, CT_PASSENGERS, 100, 90, 5, 0 }, /* 5 */ + { 2, 112, 128, CT_PASSENGERS, 130, 80, 5, 0 }, /* 6 */ + { 0, 128, 48, CT_GOODS, 160, 150, 4, 1 }, /* 7 */ + { 0, 144, 80, CT_GOODS, 190, 113, 4, 1 }, /* 8 */ + { 0, 128, 48, CT_GOODS, 160, 150, 4, 1 }, /* 9 */ + { 0, 144, 80, CT_GOODS, 190, 113, 4, 1 }, /* 10 */ +}; diff --git a/table/genland.h b/table/genland.h new file mode 100644 --- /dev/null +++ b/table/genland.h @@ -0,0 +1,159 @@ +#define M(x,y) TILE_XY(x,y) + +#define MDORD_LAST 99 +static const TileIndexDiff _make_desert_or_rainforest_data[150] = { + M(-5,-6), + M(-4,-6), + M(-3,-6), + M(-2,-6), + M(-1,-6), + M(0,-5), + M(1,-5), + M(2,-5), + M(3,-5), + M(4,-5), + M(5,-5), + M(-5,-5), + M(-4,-5), + M(-3,-5), + M(-2,-5), + M(-1,-5), + M(0,-4), + M(1,-4), + M(2,-4), + M(3,-4), + M(4,-4), + M(5,-4), + M(-5,-4), + M(-4,-4), + M(-3,-4), + M(-2,-4), + M(-1,-4), + M(0,-3), + M(1,-3), + M(2,-3), + M(3,-3), + M(4,-3), + M(5,-3), + M(-5,-3), + M(-4,-3), + M(-3,-3), + M(-2,-3), + M(-1,-3), + M(0,-2), + M(1,-2), + M(2,-2), + M(3,-2), + M(4,-2), + M(5,-2), + M(-5,-2), + M(-4,-2), + M(-3,-2), + M(-2,-2), + M(-1,-2), + M(0,-1), + M(1,-1), + M(2,-1), + M(3,-1), + M(4,-1), + M(5,-1), + M(-5,-1), + M(-4,-1), + M(-3,-1), + M(-2,-1), + M(-1,-1), + M(0,0), + M(1,0), + M(2,0), + M(3,0), + M(4,0), + M(5,0), + M(-5,0), + M(-4,0), + M(-3,0), + M(-2,0), + M(-1,0), + M(0,1), + M(1,1), + M(2,1), + M(3,1), + M(4,1), + M(5,1), + M(-5,1), + M(-4,1), + M(-3,1), + M(-2,1), + M(-1,1), + M(0,2), + M(1,2), + M(2,2), + M(3,2), + M(4,2), + M(5,2), + M(-5,2), + M(-4,2), + M(-3,2), + M(-2,2), + M(-1,2), + M(0,3), + M(1,3), + M(2,3), + M(3,3), + M(4,3), + M(5,3), + M(-5,3), + M(-4,3), + M(-3,3), + M(-2,3), + M(-1,3), + M(0,4), + M(1,4), + M(2,4), + M(3,4), + M(4,4), + M(5,4), + M(-5,4), + M(-4,4), + M(-3,4), + M(-2,4), + M(-1,4), + M(0,5), + M(1,5), + M(2,5), + M(3,5), + M(4,5), + M(5,5), + M(6,-3), + M(-6,-4), + M(-3,5), + M(-3,-7), + M(6,-2), + M(-6,-3), + M(-2,5), + M(-2,-7), + M(6,-1), + M(-6,-2), + M(-1,5), + M(-1,-7), + M(6,0), + M(-6,-1), + M(0,6), + M(0,-6), + M(6,1), + M(-6,0), + M(1,6), + M(1,-6), + M(6,2), + M(-6,1), + M(2,6), + M(2,-6), + M(6,3), + M(-6,2), + M(3,6), + M(3,-6), + MDORD_LAST, +}; + + + +#undef M diff --git a/table/industry_land.h b/table/industry_land.h new file mode 100644 --- /dev/null +++ b/table/industry_land.h @@ -0,0 +1,939 @@ +#define M(s1,s2,sx,sy,w,h,dz,p) {s1,s2,(sx<<4)|sy,((w-1)<<4)|(h-1),dz,p} + +static const DrawIndustryTileStruct _industry_draw_tile_data[700] = { + M( 0xf54, 0x7db, 7, 0, 9, 9, 10, 0), + M( 0xf54, 0x7dc, 7, 0, 9, 9, 30, 0), + M( 0xf54, 0x7dd, 7, 0, 9, 9, 30, 0), + M( 0x7e6, 0x7dd, 7, 0, 9, 9, 30, 0), + M( 0x7e6, 0x7dd, 7, 0, 9, 9, 30, 0), + M( 0x7e6, 0x7de, 7, 0, 9, 9, 30, 0), + M( 0x7e6, 0x7df, 7, 0, 9, 9, 30, 0), + M( 0x7e6, 0x7df, 7, 0, 9, 9, 30, 0), + M( 0xf54, 0x7e0, 1, 2, 15, 9, 30, 0), + M( 0xf54, 0x7e1, 1, 2, 15, 9, 30, 0), + M( 0xf54, 0x7e2, 1, 2, 15, 9, 30, 0), + M( 0x7e6, 0x7e2, 1, 2, 15, 9, 30, 0), + M( 0xf54, 0x7e3, 4, 4, 9, 9, 30, 0), + M( 0xf54, 0x7e4, 4, 4, 9, 9, 30, 0), + M( 0xf54, 0x7e5, 4, 4, 9, 9, 30, 0), + M( 0x7e6, 0x7e5, 4, 4, 9, 9, 30, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e9, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e7, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e8, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x7fd, 1, 1, 14, 14, 5, 0), + M( 0xf54, 0x7fe, 1, 1, 14, 14, 44, 0), + M( 0xf54, 0x7ff, 1, 1, 14, 14, 44, 0), + M( 0xf54, 0x7ff, 1, 1, 14, 14, 44, 0), + M( 0xf54, 0x800, 0, 2, 16, 12, 6, 0), + M( 0xf54, 0x801, 0, 2, 16, 12, 47, 0), + M( 0xf54, 0x802, 0, 2, 16, 12, 50, 0), + M( 0xf54, 0x802, 0, 2, 16, 12, 50, 0), + M( 0xf54, 0x803, 1, 0, 14, 15, 5, 0), + M( 0xf54, 0x804, 1, 0, 14, 15, 19, 0), + M( 0xf54, 0x805, 1, 0, 14, 15, 21, 0), + M( 0xf54, 0x805, 1, 0, 14, 15, 21, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x806, 1, 2, 14, 11, 32, 5), + M( 0xf54, 0x80d, 1, 0, 13, 16, 8, 0), + M( 0xf54, 0x80e, 1, 0, 13, 16, 20, 0), + M( 0xf54, 0x80f, 1, 0, 13, 16, 20, 0), + M( 0xf54, 0x80f, 1, 0, 13, 16, 20, 0), + M( 0xf54, 0x810, 0, 1, 16, 14, 8, 0), + M( 0xf54, 0x811, 0, 1, 16, 14, 21, 0), + M( 0xf54, 0x812, 0, 1, 16, 14, 21, 0), + M( 0xf54, 0x812, 0, 1, 16, 14, 21, 0), + M( 0xf54, 0x813, 1, 1, 14, 14, 12, 0), + M( 0xf54, 0x814, 1, 1, 14, 14, 15, 0), + M( 0xf54, 0x815, 1, 1, 14, 14, 22, 0), + M( 0xf54, 0x815, 1, 1, 14, 14, 22, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x816, 0, 0, 16, 15, 20, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x817, 0, 1, 16, 13, 19, 0), + M( 0x81d, 0x818, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x819, 0, 0, 16, 16, 15, 0), + M( 0x81d, 0x81a, 0, 0, 16, 16, 31, 0), + M( 0x81d, 0x81b, 0, 0, 16, 16, 39, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0xf54, 0x881e, 1, 1, 14, 14, 4, 0), + M( 0xf54, 0x881f, 1, 1, 14, 14, 24, 0), + M( 0xf54, 0x8820, 1, 1, 14, 14, 27, 0), + M( 0x58c, 0x8820, 1, 1, 14, 14, 27, 0), + M( 0xf54, 0x8821, 3, 3, 10, 9, 3, 0), + M( 0xf54, 0x8822, 3, 3, 10, 9, 63, 0), + M( 0xf54, 0x8823, 3, 3, 10, 9, 62, 0), + M( 0x58c, 0x8823, 3, 3, 10, 9, 62, 0), + M( 0xf54, 0x8824, 4, 4, 7, 7, 3, 0), + M( 0xf54, 0x8825, 4, 4, 7, 7, 72, 0), + M( 0xf54, 0x8825, 4, 4, 7, 7, 72, 0), + M( 0x58c, 0x8826, 4, 4, 7, 7, 80, 0), + M( 0xf54, 0x8827, 2, 0, 12, 16, 51, 0), + M( 0xf54, 0x8828, 2, 0, 12, 16, 51, 0), + M( 0xf54, 0x8829, 2, 0, 12, 16, 51, 0), + M( 0x58c, 0x8829, 2, 0, 12, 16, 51, 0), + M( 0xf54, 0x882a, 0, 0, 16, 16, 26, 0), + M( 0xf54, 0x882b, 0, 0, 16, 16, 44, 0), + M( 0xf54, 0x882c, 0, 0, 16, 16, 46, 0), + M( 0x58c, 0x882c, 0, 0, 16, 16, 46, 0), + M( 0xf54, 0x82d, 3, 1, 10, 13, 2, 0), + M( 0xf54, 0x82e, 3, 1, 10, 13, 11, 0), + M( 0xf54, 0x82f, 3, 1, 10, 13, 11, 0), + M( 0x58c, 0x82f, 3, 1, 10, 13, 11, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xfdd, 0x833, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x837, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x834, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x834, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x830, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x838, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x835, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x835, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x831, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x839, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x836, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x836, 0, 0, 16, 16, 20, 0), + M( 0xfdd, 0x832, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x87d, 0x87e, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87e, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87e, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87e, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87f, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x880, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x881, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x882, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x883, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x883, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x882, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x881, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x880, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87f, 0, 0, 16, 16, 20, 0), + M( 0x87d, 0x87e, 0, 0, 16, 16, 20, 0), + M( 0x83a, 0x883c, 0, 0, 16, 16, 18, 0), + M( 0x83a, 0x883c, 0, 0, 16, 16, 18, 0), + M( 0x83a, 0x883c, 0, 0, 16, 16, 18, 0), + M( 0x83a, 0x883c, 0, 0, 16, 16, 18, 0), + M( 0x83b, 0x883d, 0, 0, 16, 16, 18, 0), + M( 0x83b, 0x883d, 0, 0, 16, 16, 18, 0), + M( 0x83b, 0x883d, 0, 0, 16, 16, 18, 0), + M( 0x83b, 0x883d, 0, 0, 16, 16, 18, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x83e, 0x883f, 0, 0, 16, 16, 18, 0), + M( 0x83e, 0x883f, 0, 0, 16, 16, 18, 0), + M( 0x83e, 0x883f, 0, 0, 16, 16, 18, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x840, 0x841, 0, 0, 16, 16, 18, 0), + M( 0x840, 0x841, 0, 0, 16, 16, 18, 0), + M( 0x840, 0x841, 0, 0, 16, 16, 18, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x842, 0x843, 0, 0, 16, 16, 30, 0), + M( 0x842, 0x843, 0, 0, 16, 16, 30, 0), + M( 0x842, 0x843, 0, 0, 16, 16, 30, 0), + M( 0x7e6, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x844, 0x845, 0, 0, 16, 16, 16, 0), + M( 0x844, 0x845, 0, 0, 16, 16, 16, 0), + M( 0x844, 0x845, 0, 0, 16, 16, 16, 0), + M( 0x7e6, 0x869, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86d, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86d, 0, 0, 16, 16, 50, 0), + M( 0x8862, 0x8866, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86a, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86e, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86e, 0, 0, 16, 16, 50, 0), + M( 0x8863, 0x8867, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86b, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86f, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86f, 0, 0, 16, 16, 50, 0), + M( 0x8864, 0x8868, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86c, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x870, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x870, 0, 0, 16, 16, 50, 0), + M( 0x8865, 0x0, 0, 0, 1, 1, 0, 0), + M( 0xf54, 0x8871, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8875, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8875, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8879, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8872, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8876, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8876, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x887a, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8873, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8877, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8877, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x887b, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8874, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8878, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x8878, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x887c, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x7ea, 3, 2, 8, 8, 18, 0), + M( 0xf54, 0x7eb, 3, 2, 8, 8, 37, 0), + M( 0xf54, 0x7ec, 3, 2, 8, 8, 49, 0), + M( 0x7e6, 0x7ec, 3, 2, 8, 8, 49, 0), + M( 0x7e6, 0x7ec, 3, 2, 8, 8, 49, 0), + M( 0x7e6, 0x7ed, 3, 2, 8, 8, 49, 0), + M( 0x7e6, 0x7ee, 3, 2, 8, 8, 49, 0), + M( 0x7e6, 0x7ee, 3, 2, 8, 8, 49, 0), + M( 0xf54, 0x7ef, 3, 2, 10, 7, 20, 0), + M( 0xf54, 0x7f0, 3, 2, 10, 7, 40, 0), + M( 0xf54, 0x7f1, 3, 2, 10, 7, 40, 0), + M( 0x7e6, 0x7f1, 3, 2, 10, 7, 40, 0), + M( 0xf54, 0x7f2, 4, 4, 7, 8, 22, 0), + M( 0xf54, 0x7f3, 4, 4, 7, 8, 22, 0), + M( 0xf54, 0x7f4, 4, 4, 7, 8, 22, 0), + M( 0x7e6, 0x7f4, 4, 4, 7, 8, 22, 0), + M( 0xf54, 0x7f5, 2, 1, 11, 13, 12, 0), + M( 0xf54, 0x7f6, 2, 1, 11, 13, 12, 0), + M( 0xf54, 0x7f7, 2, 1, 11, 13, 12, 0), + M( 0x7e6, 0x7f7, 2, 1, 11, 13, 12, 0), + M( 0x7e6, 0x85c, 0, 0, 1, 1, 1, 0), + M( 0x851, 0x852, 0, 0, 16, 16, 20, 0), + M( 0x851, 0x852, 0, 0, 16, 16, 20, 0), + M( 0x8846, 0x8847, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x85d, 0, 0, 1, 1, 1, 0), + M( 0x853, 0x854, 0, 0, 16, 16, 20, 0), + M( 0x853, 0x854, 0, 0, 16, 16, 20, 0), + M( 0x8848, 0x8849, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x85e, 0, 0, 1, 1, 1, 0), + M( 0x855, 0x856, 0, 0, 16, 16, 20, 0), + M( 0x855, 0x856, 0, 0, 16, 16, 20, 0), + M( 0x884a, 0x884b, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x85f, 0, 0, 1, 1, 1, 0), + M( 0x857, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x857, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x884c, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e6, 0x860, 0, 0, 1, 1, 1, 0), + M( 0x858, 0x859, 0, 0, 16, 16, 20, 0), + M( 0x858, 0x859, 0, 0, 16, 16, 20, 0), + M( 0x884d, 0x884e, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x861, 0, 0, 1, 1, 1, 0), + M( 0x85a, 0x85b, 0, 0, 16, 16, 20, 0), + M( 0x85a, 0x85b, 0, 0, 16, 16, 20, 0), + M( 0x884f, 0x8850, 0, 0, 16, 16, 20, 0), + M( 0x7e6, 0x884, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x884, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x884, 0, 0, 16, 16, 25, 0), + M( 0x886, 0x884, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x885, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x885, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x885, 0, 0, 16, 16, 25, 0), + M( 0x887, 0x885, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x888c, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x888d, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x888d, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x888e, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x888f, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8890, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8890, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8891, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8892, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8893, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8893, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8894, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8895, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8896, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8896, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8897, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x898, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x899, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x899, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89a, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a6, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89b, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89c, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89c, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89d, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89e, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89f, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x89f, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a1, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a2, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a3, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a4, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a2, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a3, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8a5, 0, 0, 16, 16, 25, 0), + M( 0x8a7, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8b7, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8b7, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8c7, 0, 0, 16, 16, 25, 0), + M( 0x8a8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8a9, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8b9, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8b9, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8c9, 0, 0, 16, 16, 25, 0), + M( 0x8aa, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ba, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ba, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ca, 0, 0, 16, 16, 25, 0), + M( 0x8ab, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8cb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ac, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bc, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bc, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8cc, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ad, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bd, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bd, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8cd, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ae, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8be, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8be, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ce, 0x8d7, 0, 0, 16, 16, 35, 0), + M( 0x8af, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bf, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8bf, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8cf, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b2, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c2, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c2, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d2, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b3, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c3, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c3, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d3, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b4, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c4, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c4, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d4, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b5, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c5, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c5, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d5, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8b6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8c6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8d6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ce, 0x8d7, 0, 0, 16, 16, 35, 0), + M( 0x8ce, 0x8d8, 0, 0, 16, 16, 35, 0), + M( 0x8ce, 0x8d9, 0, 0, 16, 16, 35, 0), + M( 0x8ce, 0x8d9, 0, 0, 16, 16, 35, 0), + M( 0x7e6, 0x88a, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x88a, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x88a, 0, 0, 16, 16, 25, 0), + M( 0x888, 0x88a, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x88b, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x88b, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x88b, 0, 0, 16, 16, 25, 0), + M( 0x889, 0x88b, 0, 0, 16, 16, 25, 0), + M( 0x8da, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e3, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e3, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ec, 0, 0, 16, 16, 25, 0), + M( 0x8db, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e4, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e4, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ed, 0, 0, 16, 16, 25, 0), + M( 0x8dc, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e5, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e5, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ee, 0, 0, 16, 16, 25, 0), + M( 0x8dd, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e6, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e6, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8ef, 0, 0, 16, 16, 25, 0), + M( 0x8de, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e7, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e7, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8df, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e0, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e9, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8e9, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x8f2, 0, 0, 16, 16, 25, 0), + M( 0x8e1, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ea, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ea, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f3, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8e2, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8eb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8eb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f4, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f5, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x905, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x905, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x915, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f6, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x906, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x906, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x916, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f7, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x907, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x907, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x917, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f8, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x908, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x908, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x918, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8f9, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x909, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x909, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x919, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8fa, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90a, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90a, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91a, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8fb, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90b, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90b, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91b, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8fc, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90c, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90c, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91c, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8fd, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90d, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90d, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91d, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8fe, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90e, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90e, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91e, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x8ff, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90f, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x90f, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x91f, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x900, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x910, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x910, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x920, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x901, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x911, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x911, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x921, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x902, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x912, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x912, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x922, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x903, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x913, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x913, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x923, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x904, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x914, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x914, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x924, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x925, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x925, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x925, 0x926, 0, 0, 16, 16, 30, 0), + M( 0x925, 0x926, 0, 0, 16, 16, 30, 0), + M( 0x925, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x925, 0x0, 0, 0, 16, 16, 25, 0), + M( 0x925, 0x927, 0, 0, 16, 16, 30, 0), + M( 0x925, 0x927, 0, 0, 16, 16, 30, 0), + M( 0x11c6, 0x892b, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892c, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892c, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892d, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892e, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892f, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892f, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x8930, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x8928, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x8929, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x8929, 0, 0, 16, 16, 25, 0), + M( 0x11c6, 0x892a, 0, 0, 16, 16, 25, 0), + M( 0x7e6, 0x869, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86d, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86d, 0, 0, 16, 16, 50, 0), + M( 0x8862, 0x8866, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86a, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86e, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86e, 0, 0, 16, 16, 50, 0), + M( 0x8863, 0x8867, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86b, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86f, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86f, 0, 0, 16, 16, 50, 0), + M( 0x8864, 0x8868, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x86c, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x870, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x870, 0, 0, 16, 16, 50, 0), + M( 0x8865, 0x0, 0, 0, 1, 1, 0, 0), + M( 0x7e6, 0x931, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x935, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x935, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x939, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x932, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x936, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x936, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x93a, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x933, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x937, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x937, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x93b, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x934, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x938, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x938, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x93c, 0, 0, 16, 16, 50, 0), + M( 0x81d, 0x818, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x819, 0, 0, 16, 16, 15, 0), + M( 0x81d, 0x81a, 0, 0, 16, 16, 31, 0), + M( 0x81d, 0x81b, 0, 0, 16, 16, 39, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x81d, 0x81c, 0, 0, 16, 16, 7, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9245, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9248, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9248, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x924b, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9247, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x924a, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x924a, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x924d, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9246, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9249, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x9249, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x924c, 0, 0, 16, 16, 50, 0), + M( 0x81d, 0x124e, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x124f, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1250, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1251, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1252, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1252, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1252, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1252, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1253, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1254, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1254, 0, 0, 16, 16, 10, 0), + M( 0x81d, 0x1255, 0, 0, 16, 16, 10, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125b, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125e, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125e, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x1261, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125c, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125f, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125f, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x1262, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x125d, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x1260, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x1260, 0, 0, 16, 16, 50, 0), + M( 0x7e6, 0x1263, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1264, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1264, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1268, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1265, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1265, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1269, 0, 0, 16, 16, 50, 4), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1266, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1266, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x126a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1267, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1267, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x126b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x126c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1271, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1271, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1271, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1271, 0x1279, 0, 0, 16, 16, 50, 0), + M( 0x1272, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1272, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1272, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1272, 0x127a, 0, 0, 16, 16, 50, 0), + M( 0x1273, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1273, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1273, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1273, 0x127b, 0, 0, 16, 16, 50, 0), + M( 0x1274, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1274, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1274, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1274, 0x127c, 0, 0, 16, 16, 50, 0), + M( 0x1275, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1275, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1275, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1275, 0x127d, 0, 0, 16, 16, 50, 0), + M( 0x1276, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1276, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1276, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1276, 0x127e, 0, 0, 16, 16, 50, 0), + M( 0x1277, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1277, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1277, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1277, 0x127f, 0, 0, 16, 16, 50, 0), + M( 0x1278, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1278, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1278, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1278, 0x1280, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9284, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9283, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9283, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9286, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9281, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9282, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9282, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x9285, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9287, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9287, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9287, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9288, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9288, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9288, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9289, 0, 0, 16, 16, 50, 3), + M( 0x1243, 0x30b9289, 0, 0, 16, 16, 50, 3), + M( 0x1243, 0x30b9289, 0, 0, 16, 16, 50, 3), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129b, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129b, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129b, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129b, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129c, 0, 0, 16, 16, 50, 2), + M( 0xf8d, 0x129c, 0, 0, 16, 16, 50, 2), + M( 0xf8d, 0x129c, 0, 0, 16, 16, 50, 2), + M( 0xf8d, 0x129c, 0, 0, 16, 16, 50, 2), + M( 0xf8d, 0x129d, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129d, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129d, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x129d, 0, 0, 16, 16, 50, 0), + M( 0x92a0, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a0, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a0, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a0, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a1, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a1, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a1, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a1, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a2, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a2, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a2, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a2, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a3, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a3, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a3, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x92a3, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x0, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a4, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a4, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a4, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a4, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a6, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a6, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a6, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a6, 0, 0, 16, 16, 50, 0), + M( 0xf8d, 0x92a5, 0, 0, 16, 16, 50, 1), + M( 0xf8d, 0x92a5, 0, 0, 16, 16, 50, 1), + M( 0xf8d, 0x92a5, 0, 0, 16, 16, 50, 1), + M( 0xf8d, 0x92a5, 0, 0, 16, 16, 50, 1), +}; + +static const DrawIndustrySpec1Struct _draw_industry_spec1[96] = { + { 8, 4, 0, 0}, + { 6, 0, 1, 0}, + { 4, 0, 2, 0}, + { 6, 0, 3, 0}, + { 8, 0, 4, 0}, + { 10, 0, 5, 0}, + { 12, 0, 6, 0}, + { 10, 0, 1, 0}, + { 8, 0, 2, 0}, + { 6, 0, 3, 0}, + { 4, 0, 4, 0}, + { 6, 0, 5, 1}, + { 8, 0, 6, 1}, + { 10, 0, 1, 1}, + { 12, 0, 2, 1}, + { 10, 0, 3, 1}, + { 8, 1, 4, 1}, + { 6, 1, 5, 1}, + { 4, 1, 6, 1}, + { 6, 1, 1, 1}, + { 8, 1, 2, 1}, + { 10, 1, 3, 1}, + { 12, 1, 4, 1}, + { 10, 1, 5, 2}, + { 8, 1, 6, 2}, + { 6, 1, 1, 2}, + { 4, 1, 2, 2}, + { 6, 1, 3, 2}, + { 8, 1, 4, 2}, + { 10, 1, 5, 2}, + { 12, 1, 6, 2}, + { 10, 1, 1, 2}, + { 8, 2, 2, 2}, + { 6, 2, 3, 2}, + { 4, 2, 4, 3}, + { 6, 2, 5, 3}, + { 8, 2, 6, 3}, + { 10, 2, 1, 3}, + { 12, 2, 2, 3}, + { 10, 2, 3, 3}, + { 8, 2, 4, 3}, + { 6, 2, 5, 3}, + { 4, 2, 6, 3}, + { 6, 2, 1, 3}, + { 8, 2, 2, 3}, + { 10, 2, 3, 4}, + { 12, 2, 4, 4}, + { 10, 2, 5, 4}, + { 8, 3, 6, 4}, + { 6, 3, 1, 4}, + { 4, 3, 2, 4}, + { 6, 3, 3, 4}, + { 8, 3, 4, 4}, + { 10, 3, 5, 4}, + { 12, 3, 6, 4}, + { 10, 3, 1, 4}, + { 8, 3, 2, 4}, + { 6, 3, 3, 4}, + { 4, 3, 4, 4}, + { 6, 3, 5, 4}, + { 8, 3, 6, 4}, + { 10, 3, 1, 4}, + { 12, 3, 2, 4}, + { 10, 3, 3, 4}, + { 8, 4, 4, 4}, + { 6, 4, 5, 4}, + { 4, 4, 6, 4}, + { 6, 4, 0, 4}, + { 8, 4, 0, 4}, + { 10, 4, 0, 4}, + { 12, 4, 0, 4}, + { 10, 4, 0, 4}, + { 8, 4, 0, 4}, + { 6, 4, 0, 4}, + { 4, 4, 0, 4}, + { 6, 4, 0, 4}, + { 8, 4, 0, 4}, + { 10, 4, 0, 4}, + { 12, 4, 0, 4}, + { 10, 4, 0, 4}, + { 8, 4, 0, 4}, + { 6, 4, 0, 4}, + { 4, 4, 0, 4}, + { 6, 4, 0, 4}, + { 8, 4, 0, 4}, + { 10, 4, 0, 4}, + { 12, 4, 0, 4}, + { 10, 4, 0, 4}, + { 8, 4, 0, 4}, + { 6, 4, 0, 4}, + { 4, 4, 0, 4}, + { 6, 4, 0, 4}, + { 8, 4, 0, 4}, + { 10, 4, 0, 4}, + { 12, 4, 0, 4}, + { 10, 4, 0, 4}, +}; + +static const byte _drawtile_proc1_x[5] = { + 22, 17, 14, 10, 8 +}; + +static const byte _drawtile_proc1_y[5] = { + 73, 70, 69, 66, 41 +}; + +static const DrawIndustrySpec4Struct _industry_anim_offs_3[] = { + {255, 255, 0}, + { 0, 255, 0}, + { 1, 255, 0}, + { 2, 255, 0}, + { 3, 255, 0}, + { 4, 255, 0}, + { 5, 255, 0}, + { 6, 255, 0}, + { 7, 255, 0}, + { 8, 255, 0}, + { 9, 255, 0}, + { 10, 255, 0}, + { 11, 255, 0}, + { 12, 255, 0}, + { 13, 255, 0}, + { 14, 255, 0}, + { 15, 255, 0}, + { 16, 255, 0}, + { 17, 255, 0}, + { 18, 255, 0}, + { 18, 255, 1}, + { 18, 255, 2}, + { 18, 255, 4}, + { 18, 255, 6}, + { 18, 255, 8}, + { 18, 255, 11}, + { 18, 255, 14}, + { 18, 255, 17}, + { 18, 255, 20}, + { 18, 255, 24}, + {255, 0, 29}, + {255, 0, 24}, + {255, 0, 20}, + {255, 0, 17}, + {255, 0, 14}, + {255, 0, 11}, + {255, 0, 8}, + {255, 0, 6}, + {255, 0, 4}, + {255, 0, 2}, + {255, 0, 1}, + {255, 1, 0}, + {255, 2, 0}, + {255, 3, 0}, + {255, 4, 0}, + {255, 5, 0}, + {255, 6, 0}, + {255, 7, 0}, + {255, 8, 0}, + {255, 255, 0}, +}; + +static const byte _industry_anim_offs[] = { + 255, 0, 0, 0, 2, 4, 6, 8, 10, 9, + 7, 5, 3, 1, 255, 0, 0, 0, 2, 4, + 6, 8, 10, 9, 7, 5, 3, 1, 255, 0, + 0, 0, 2, 4, 6, 8, 10, 9, 7, 5, + 3, 1, 255, 0, 0, 0, 2, 4, 6, 8, + 10, 9, 7, 5, 3, 1, 255, 0, 0, 0, + 2, 4, 6, 8, 10, 9, 7, 5, 3, 1 +}; + +static const byte _industry_anim_offs_2[] = { + 68, 69, 71, 74, 77, 80, 83, 85, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 85, 84, 83, 82, 81, 80, 79, 78, + 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, +}; + +static const byte _coal_plant_sparkles_x[] = {11, 11, 14, 13, 18, 15}; +static const byte _coal_plant_sparkles_y[] = {23, 11, 6, 3, 1, 0}; + +/* next frame in an animation */ +#define N 255 +static const byte _industry_map5_animation_next[] = { +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, 16, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, 129, N, N, N, N, N, +135, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, +}; + +/* animation to start when goods is produced */ +static const byte _industry_produce_map5[] = { +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +17, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, 130, N, N, N, N, N, 136, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, N, +N, N, N, N, N, N, N, +}; + +#undef N diff --git a/table/landscape_const.h b/table/landscape_const.h new file mode 100644 --- /dev/null +++ b/table/landscape_const.h @@ -0,0 +1,215 @@ +static const LandscapePredefVar _landscape_predef_var[4] = { + { + /* normal names */ + { + STR_000F_PASSENGERS, + STR_0010_COAL, + STR_0011_MAIL, + STR_0012_OIL, + STR_0013_LIVESTOCK, + STR_0014_GOODS, + STR_0015_GRAIN, + STR_0016_WOOD, + STR_0017_IRON_ORE, + STR_0018_STEEL, + STR_0019_VALUABLES, + STR_000E, + }, + /* normal weights */ + { + 1, 16, 4, 16, 3, 8, 16, 16, 16, 16, 2, 0, + }, + + /* normal sprites */ + { + 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, 0x10D0, 0x10D1, 0x10D2, 0x10D3, + }, + + /* normal initial cargo payment */ + { + 3185, 5916, 4550, 4437, 4322, 6144, 4778, 5005, 5120, 5688, 7509, 5688 + }, + + /* normal transit days table 1 */ + { + 0, 7, 20, 25, 4, 5, 4, 15, 9, 7, 1, 0, + }, + + /* normal transit days table 2 */ + { + 24, 255, 90, 255, 18, 28, 40, 255, 255, 255, 32, 30, + }, + + /* normal railveh by cargo */ + { + {27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38}, + {57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68}, + {89, 91, 90, 92, 93, 94, 95, 96, 97, 98, 99, 100} + }, + + /* normal road veh by cargo start & count */ + {116, 123, 126, 132, 135, 138, 141, 144, 147, 150, 153, 156}, + {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} + }, + + { + /* hilly names */ + { + STR_000F_PASSENGERS, + STR_0010_COAL, + STR_0011_MAIL, + STR_0012_OIL, + STR_0013_LIVESTOCK, + STR_0014_GOODS, + STR_0022_WHEAT, + STR_0016_WOOD, + STR_000E, + STR_001F_PAPER, + STR_0020_GOLD, + STR_001E_FOOD, + }, + /* hilly weights */ + { + 1, 16, 4, 16, 3, 8, 16, 16, 0, 16, 8, 16 + }, + + /* hilly sprites */ + { + 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, 0x10D0, 0x2, 0x10D9, 0x10D3, 0x10D8 + }, + + /* hilly initial cargo payment */ + { + 3185, 5916, 4550, 4437, 4322, 6144, 4778, 5005, 5120, 5461, 5802, 5688 + }, + + /* hilly transit days table 1 */ + { + 0, 7, 20, 25, 4, 5, 4, 15, 9, 7, 10, 0, + }, + + /* hilly transit days table 2 */ + { + 24, 255, 90, 255, 18, 28, 40, 255, 255, 60, 40, 30 + }, + + /* hilly railveh by cargo */ + { + {27, 29, 28, 30, 31, 32, 33, 34, 35, 39, 37, 38}, + {57, 59, 58, 60, 61, 62, 63, 64, 65, 69, 67, 68}, + {89, 91, 90, 92, 93, 94, 95, 96, 97, 101, 99, 100} + }, + + + /* hilly road veh by cargo start & count */ + {116, 123, 126, 132, 135, 138, 141, 144, 147, 159, 153, 156}, + {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + }, + + + { + /* desert names */ + { + STR_000F_PASSENGERS, + STR_0023_RUBBER, + STR_0011_MAIL, + STR_0012_OIL, + STR_001C_FRUIT, + STR_0014_GOODS, + STR_001B_MAIZE, + STR_0016_WOOD, + STR_001A_COPPER_ORE, + STR_0021_WATER, + STR_001D_DIAMONDS, + STR_001E_FOOD + }, + /* desert weights */ + { + 1, 16, 4, 16, 16, 8, 16, 16, 16, 16, 2, 16, + }, + + /* desert sprites */ + { + 0x10C9, 0x10DA, 0x10CB, 0x10CC, 0x10D4, 0x10CE, 0x10CF, 0x10D0, 0x10D5, 0x10D6, 0x10D7, 0x10D8 + }, + + /* desert initial cargo payment */ + { + 3185, 4437, 4550, 4892, 4209, 6144, 4322, 7964, 4892, 4664, 5802, 5688 + }, + + /* desert transit days table 1 */ + { + 0, 2, 20, 25, 0, 5, 4, 15, 12, 20, 10, 0 + }, + + /* desert transit days table 2 */ + { + 24, 20, 90, 255, 15, 28, 40, 255, 255, 80, 255, 30 + }, + + /* desert railveh by cargo */ + { + {27, 43, 28, 30, 42, 32, 33, 34, 40, 41, 37, 38}, + {57, 73, 58, 60, 72, 62, 63, 64, 70, 71, 67, 68}, + {89, 105, 90, 92, 104, 94, 95, 96, 102, 103, 99, 100} + }, + + /* desert road veh by cargo start & count */ + {116, 171, 126, 132, 168, 138, 141, 144, 162, 165, 153, 156}, + {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} + }, + + { + /* candy names */ + { + STR_000F_PASSENGERS, + STR_0024_SUGAR, + STR_0011_MAIL, + STR_0025_TOYS, + STR_002B_BATTERIES, + STR_0026_CANDY, + STR_002A_TOFFEE, + STR_0027_COLA, + STR_0028_COTTON_CANDY, + STR_0029_BUBBLES, + STR_002C_PLASTIC, + STR_002D_FIZZY_DRINKS, + }, + /* candy weights */ + { + 1, 16, 4, 2, 4, 5, 16, 16, 16, 1, 16, 2 + }, + + /* candy sprites */ + { + 0x10C9, 0x10DC, 0x10CB, 0x10DD, 0x10E3, 0x10DB, 0x10E0, 0x10D6, 0x10DE, 0x10E1, 0x10E2, 0x10DF + }, + + /* candy initial cargo payment */ + { + 3185, 4437, 4550, 5574, 4322, 6144, 4778, 4892, 5005, 5077, 4664, 6250 + }, + + /* candy transit days table 1 */ + { + 0, 20, 20, 25, 2, 8, 14, 5, 10, 20, 30, 30, + }, + + /* candy transit days table 2 */ + { + 24, 255, 90, 255, 30, 40, 60, 75, 25, 80, 255, 50 + }, + + /* candy railveh by cargo */ + { + {27, 44, 28, 50, 51, 49, 46, 48, 45, 47, 53, 52}, + {57, 74, 58, 80, 81, 79, 76, 78, 75, 77, 83, 82}, + {89, 106, 90, 112, 113, 111, 108, 110, 107, 109, 115, 114} + }, + + /* candy road veh by cargo start & count */ + {116, 174, 126, 186, 192, 189, 183, 177, 180, 201, 198, 195}, + {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} + } +}; diff --git a/table/landscape_sprite.h b/table/landscape_sprite.h new file mode 100644 --- /dev/null +++ b/table/landscape_sprite.h @@ -0,0 +1,134 @@ +static const SpriteID _landscape_spriteindexes_1[] = { + 0xF67, 0xF9F, + 0xAAD, 0xAB0, + 0x83A, 0x845, + 0xFA0, 0xFC9, + 0x43F, 0x45E, + 0x566, 0x56D, + 0x945, 0x94C, + 0x3ED, 0x40C, + 0x515, 0x51C, + 0x55A, 0x561, + 0x534, 0x546, + 0x93D, 0x944, + 0x955, 0x95C, + 0xFDD, 0xFEC, + 0x87D, 0x883, + 0xA2B, 0xA39, + 0x497, 0x4B0, + 0x572, 0x575, + 0x94D, 0x954, + 0x818, 0x81D, + 0x3DE, 0x3EB, +0x1212, 0x1212, +0xffff, +}; + +static const SpriteID _landscape_spriteindexes_2[] = { + 0xF67, 0xF9F, + 0xAAD, 0xAB0, + 0xFA0, 0xFC9, + 0x43F, 0x45E, + 0x566, 0x56D, + 0x945, 0x94C, + 0x3ED, 0x40C, + 0x515, 0x51C, + 0x55A, 0x561, + 0x547, 0x559, + 0x93D, 0x944, + 0x955, 0x95C, + 0xFDD, 0xFEC, + 0x87D, 0x883, + 0xA2B, 0xA39, + 0x497, 0x4B0, + 0x572, 0x575, + 0x94D, 0x954, + 0x5AE, 0x5AF, +0x118D, 0x11D8, + 0x534, 0x546, + 0x40D, 0x426, + 0x45F, 0x478, + 0x4B1, 0x4CA, + 0x95D, 0x97C, + 0x3DE, 0x3EB, + 0x562, 0x565, + 0x56E, 0x571, + 0x57A, 0x57D, + 0x83A, 0x845, + 0xFF5, 0xFF5, + 0xFF8, 0xFF8, +0x1212, 0x1212, +0xffff, +}; + +static const SpriteID _landscape_spriteindexes_3[] = { + 0xF54, 0xF9F, + 0xFDD, 0xFE5, + 0xFEC, 0xFEC, + 0xFA0, 0xFC9, + 0x818, 0x81D, + 0x521, 0x546, + 0x57E, 0x57F, + 0x3ED, 0x40C, + 0x43F, 0x45E, + 0x491, 0x4B0, + 0xA48, 0xA48, + 0x4FB, 0x50A, + 0x55A, 0x561, + 0x566, 0x56D, + 0x572, 0x579, + 0x427, 0x42C, + 0x479, 0x47E, + 0x4CB, 0x4D0, + 0x4EF, 0x4FA, + 0xE9D, 0xECC, + 0xF3D, 0xF40, + 0xB59, 0xB60, + 0xE5D, 0xE6C, + 0xA49, 0xA59, + 0xA63, 0xA68, + 0xA5A, 0xA62, + 0xA78, 0xA83, + 0xA69, 0xA77, + 0xA84, 0xAA3, + 0xAA7, 0xAAC, + 0xA2B, 0xA47, + 0x3DE, 0x3EB, + 0x47F, 0x488, + 0x4D1, 0x4DA, + 0x42D, 0x436, + 0x515, 0x51C, + 0x580, 0x585, + 0xC14, 0xCB3, + 0xAAD, 0xAB0, + 0xAB5, 0xB00, + 0xB69, 0xB70, + 0xB61, 0xB68, + 0xBC9, 0xBD0, + 0xBD9, 0xBE0, + 0xBA9, 0xBB0, + 0xBC1, 0xBC4, + 0x2D0, 0x2D0, + 0xAA5, 0xAA6, + 0x50F, 0x50F, + 0x2EA, 0x2EA, + 0x2ED, 0x2EE, + 0x512, 0x513, + 0x4EB, 0x4EE, + 0x4E7, 0x4EA, + 0x985, 0xA28, +0x10E4, 0x1133, + 0x93D, 0x95C, + 0x97D, 0x984, + 0x7DA, 0x7DA, + 0x2E6, 0x2E6, + 0x1, 0x1, + 0xE54, 0xE54, + 0x51F, 0x520, + 0x514, 0x514, + 0x511, 0x511, + 0x322, 0x322, + 0xffff, +}; + + diff --git a/table/palettes.h b/table/palettes.h new file mode 100644 --- /dev/null +++ b/table/palettes.h @@ -0,0 +1,96 @@ +byte _palettes[4][256 * 3] = { +/* palette 1 */ +{ +0, 0, 0, 212, 0, 212, 212, 0, 212, 212, 0, 212, +212, 0, 212, 212, 0, 212, 212, 0, 212, 212, 0, 212, +212, 0, 212, 212, 0, 212, 168, 168, 168, 184, 184, 184, +200, 200, 200, 216, 216, 216, 232, 232, 232, 252, 252, 252, + 52, 60, 72, 68, 76, 92, 88, 96, 112, 108, 116, 132, +132, 140, 152, 156, 160, 172, 176, 184, 196, 204, 208, 220, + 48, 44, 4, 64, 60, 12, 80, 76, 20, 96, 92, 28, +120, 120, 64, 148, 148, 100, 176, 176, 132, 204, 204, 168, +100, 100, 100, 116, 116, 116, 104, 80, 44, 124, 104, 72, +152, 132, 92, 184, 160, 120, 212, 188, 148, 244, 220, 176, +132, 132, 132, 88, 4, 16, 112, 16, 32, 136, 32, 52, +160, 56, 76, 188, 84, 108, 204, 104, 124, 220, 132, 144, +236, 156, 164, 252, 188, 192, 252, 212, 0, 252, 232, 60, +252, 248, 128, 76, 40, 0, 96, 60, 8, 116, 88, 28, +136, 116, 56, 156, 136, 80, 176, 156, 108, 196, 180, 136, + 68, 24, 0, 96, 44, 4, 128, 68, 8, 156, 96, 16, +184, 120, 24, 212, 156, 32, 232, 184, 16, 252, 212, 0, +252, 248, 128, 252, 252, 192, 32, 4, 0, 64, 20, 8, + 84, 28, 16, 108, 44, 28, 128, 56, 40, 148, 72, 56, +168, 92, 76, 184, 108, 88, 196, 128, 108, 212, 148, 128, + 8, 52, 0, 16, 64, 0, 32, 80, 4, 48, 96, 4, + 64, 112, 12, 84, 132, 20, 104, 148, 28, 128, 168, 44, + 64, 64, 64, 44, 68, 32, 60, 88, 48, 80, 104, 60, +104, 124, 76, 128, 148, 92, 152, 176, 108, 180, 204, 124, + 16, 52, 24, 32, 72, 44, 56, 96, 72, 76, 116, 88, + 96, 136, 108, 120, 164, 136, 152, 192, 168, 184, 220, 200, + 32, 24, 0, 56, 28, 0, 80, 80, 80, 88, 52, 12, +104, 64, 24, 124, 84, 44, 140, 108, 64, 160, 128, 88, + 76, 40, 16, 96, 52, 24, 116, 68, 40, 136, 84, 56, +164, 96, 64, 184, 112, 80, 204, 128, 96, 212, 148, 112, +224, 168, 128, 236, 188, 148, 80, 28, 4, 100, 40, 20, +120, 56, 40, 140, 76, 64, 160, 100, 96, 184, 136, 136, + 36, 40, 68, 48, 52, 84, 64, 64, 100, 80, 80, 116, +100, 100, 136, 132, 132, 164, 172, 172, 192, 212, 212, 224, + 48, 48, 48, 64, 44, 144, 88, 64, 172, 104, 76, 196, +120, 88, 224, 140, 104, 252, 160, 136, 252, 188, 168, 252, + 0, 24, 108, 0, 36, 132, 0, 52, 160, 0, 72, 184, + 0, 96, 212, 24, 120, 220, 56, 144, 232, 88, 168, 240, +128, 196, 252, 188, 224, 252, 16, 64, 96, 24, 80, 108, + 40, 96, 120, 52, 112, 132, 80, 140, 160, 116, 172, 192, +156, 204, 220, 204, 240, 252, 172, 52, 52, 212, 52, 52, +252, 52, 52, 252, 100, 88, 252, 144, 124, 252, 184, 160, +252, 216, 200, 252, 244, 236, 72, 20, 112, 92, 44, 140, +112, 68, 168, 140, 100, 196, 168, 136, 224, 204, 180, 252, +204, 180, 252, 232, 208, 252, 60, 0, 0, 92, 0, 0, +128, 0, 0, 160, 0, 0, 196, 0, 0, 224, 0, 0, +252, 0, 0, 252, 80, 0, 252, 108, 0, 252, 136, 0, +252, 164, 0, 252, 192, 0, 252, 220, 0, 252, 252, 0, +204, 136, 8, 228, 144, 4, 252, 156, 0, 252, 176, 48, +252, 196, 100, 252, 216, 152, 8, 24, 88, 12, 36, 104, + 20, 52, 124, 28, 68, 140, 40, 92, 164, 56, 120, 188, + 72, 152, 216, 100, 172, 224, 92, 156, 52, 108, 176, 64, +124, 200, 76, 144, 224, 92, 224, 244, 252, 204, 240, 252, +180, 220, 236, 132, 188, 216, 88, 152, 172, 16, 16, 16, + 32, 32, 32, 8, 92, 104, 16, 100, 112, 24, 108, 120, + 32, 116, 128, 44, 124, 140, 92, 164, 184, 116, 180, 196, +148, 200, 216, 180, 220, 232, 216, 244, 252, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +252, 60, 0, 252, 80, 0, 252, 104, 0, 252, 128, 0, +252, 148, 0, 252, 172, 0, 252, 196, 0, 252, 0, 0, +252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +252, 228, 0, 148, 148, 148, 212, 0, 212, 212, 0, 212, +212, 0, 212, 212, 0, 212, 212, 0, 212, 212, 0, 212, +212, 0, 212, 212, 0, 212, 212, 0, 212, 252, 252, 252, +}}; + +#define GET_PALETTE(x) _palettes[x] + +typedef struct { + byte a[15]; + byte ac[15]; + byte lighthouse[12]; + byte oil_ref[21]; + byte e[15]; + byte b[45]; + byte bc[45]; +} ExtraPaletteValues; + +static const ExtraPaletteValues _extra_palette_values = { + {32, 68,112, 36, 72,116, 40, 76,120, 44, 80,124, 48, 84,128}, + {28,108,124, 32,112,128, 36,116,132, 40,120,136, 44,124,140}, + {240,208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {252, 60, 0,252, 84, 0,252,108, 0,252,124, 0,252,148, 0, + 252,172, 0,252,196, 0}, + { 76, 24, 8,108, 44, 24,144, 72, 52,176,108, 84,212,148,128}, + {216,244,252,172,208,224,132,172,196,100,132,168, 72,100,144, + 72,100,144, 72,100,144, 72,100,144, 72,100,144, 72,100,144, + 72,100,144, 72,100,144,100,132,168,132,172,196,172,208,224}, + {216,244,252,180,220,232,148,200,216,116,180,196, 92,164,184, + 92,164,184, 92,164,184, 92,164,184, 92,164,184, 92,164,184, + 92,164,184, 92,164,184,116,180,196,148,200,216,180,220,232}, +}; + diff --git a/table/road_land.h b/table/road_land.h new file mode 100644 --- /dev/null +++ b/table/road_land.h @@ -0,0 +1,278 @@ +#define TILE_SEQ_BEGIN(x) ADD_DWORD(x), +#define TILE_SEQ_LINE(a,b,c,d,e) ADD_DWORD(a), b,c,d,e, +#define TILE_SEQ_END() 0,0,0,0 + +static const byte _road_display_datas_0[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE(0x8584, 0, 15, 16, 1) + TILE_SEQ_END() +}; + +static const byte _road_display_datas_1[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE(0x580, 0, 0, 1, 16) + TILE_SEQ_LINE(0x8581, 15, 0, 1, 16) + TILE_SEQ_END() +}; + +static const byte _road_display_datas_2[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE(0x582, 0, 0, 16, 1) + TILE_SEQ_LINE(0x8583, 0, 15, 16, 1) + TILE_SEQ_END() +}; + +static const byte _road_display_datas_3[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE(0x8585, 15, 0, 1, 16) + TILE_SEQ_END() +}; + +static const byte * const _road_display_datas[4] = { + _road_display_datas_0, + _road_display_datas_1, + _road_display_datas_2, + _road_display_datas_3, +}; + + +static const SpriteID _road_tile_sprites_1[16] = { + 0, 0x546, 0x545, 0x53B, 0x544, 0x534, 0x53E, 0x539, + 0x543, 0x53C, 0x535, 0x538, 0x53D, 0x537, 0x53A, 0x536 +}; + + + +#define MAKELINE(a,b,c) ADD_WORD(a), b, c, +static const byte _road_display_datas2_0[] = { + 0,0 +}; + +static const byte _road_display_datas2_1[] = { + 0,0 +}; + +static const byte _road_display_datas2_2[] = { + 0,0 +}; + +static const byte _road_display_datas2_3[] = { + MAKELINE(0x57f,1,8) + 0,0 +}; + +static const byte _road_display_datas2_4[] = { + 0,0 +}; + +static const byte _road_display_datas2_5[] = { + MAKELINE(0x57f,1,8) + MAKELINE(0x57e,14,8) + 0,0 +}; + +static const byte _road_display_datas2_6[] = { + MAKELINE(0x57e,8,1) + 0,0 +}; + +static const byte _road_display_datas2_7[] = { + MAKELINE(0x57f,1,8) + 0,0 +}; + +static const byte _road_display_datas2_8[] = { + 0,0 +}; + +static const byte _road_display_datas2_9[] = { + MAKELINE(0x57f,8,14) + 0,0 +}; + +static const byte _road_display_datas2_10[] = { + MAKELINE(0x57f,8,14) + MAKELINE(0x57e,8,1) + 0,0 +}; + +static const byte _road_display_datas2_11[] = { + MAKELINE(0x57f,8,14) + 0,0 +}; + +static const byte _road_display_datas2_12[] = { + MAKELINE(0x57e,8,1) + 0,0 +}; + +static const byte _road_display_datas2_13[] = { + MAKELINE(0x57e,14,8) + 0,0 +}; + +static const byte _road_display_datas2_14[] = { + MAKELINE(0x57e,8,1) + 0,0 +}; + +static const byte _road_display_datas2_15[] = { + 0,0 +}; + +static const byte _road_display_datas2_16[] = { + 0,0 +}; + +static const byte _road_display_datas2_17[] = { + 0,0 +}; + +static const byte _road_display_datas2_18[] = { + 0,0 +}; + +static const byte _road_display_datas2_19[] = { + MAKELINE(0x1212,0,2) + MAKELINE(0x1212,3,9) + MAKELINE(0x1212,10,12) + 0,0 +}; + +static const byte _road_display_datas2_20[] = { + 0,0 +}; + +static const byte _road_display_datas2_21[] = { + MAKELINE(0x1212,0,2) + MAKELINE(0x1212,0,10) + MAKELINE(0x1212,12,2) + MAKELINE(0x1212,12,10) + 0,0 +}; + +static const byte _road_display_datas2_22[] = { + MAKELINE(0x1212,10,0) + MAKELINE(0x1212,3,3) + MAKELINE(0x1212,0,10) + 0,0 +}; + +static const byte _road_display_datas2_23[] = { + MAKELINE(0x1212,0,2) + MAKELINE(0x1212,0,10) + 0,0 +}; + +static const byte _road_display_datas2_24[] = { + 0,0 +}; + +static const byte _road_display_datas2_25[] = { + MAKELINE(0x1212,12,2) + MAKELINE(0x1212,9,9) + MAKELINE(0x1212,2,12) + 0,0 +}; + +static const byte _road_display_datas2_26[] = { + MAKELINE(0x1212,2,0) + MAKELINE(0x1212,10,0) + MAKELINE(0x1212,2,12) + MAKELINE(0x1212,10,12) + 0,0 +}; + +static const byte _road_display_datas2_27[] = { + MAKELINE(0x1212,2,12) + MAKELINE(0x1212,10,12) + 0,0 +}; + +static const byte _road_display_datas2_28[] = { + MAKELINE(0x1212,2,0) + MAKELINE(0x1212,9,3) + MAKELINE(0x1212,12,10) + 0,0 +}; + +static const byte _road_display_datas2_29[] = { + MAKELINE(0x1212,12,2) + MAKELINE(0x1212,12,10) + 0,0 +}; + +static const byte _road_display_datas2_30[] = { + MAKELINE(0x1212,2,0) + MAKELINE(0x1212,10,0) + 0,0 +}; + +static const byte _road_display_datas2_31[] = { + 0,0 +}; + +static const byte _road_display_datas2_32[] = { + 0,0 +}; + +#undef MAKELINE + +static const byte * const _road_display_table_1[16] = { + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, + _road_display_datas2_32,_road_display_datas2_32, +}; + +static const byte * const _road_display_table_2[16] = { + _road_display_datas2_0, + _road_display_datas2_1, + _road_display_datas2_2, + _road_display_datas2_3, + _road_display_datas2_4, + _road_display_datas2_5, + _road_display_datas2_6, + _road_display_datas2_7, + _road_display_datas2_8, + _road_display_datas2_9, + _road_display_datas2_10, + _road_display_datas2_11, + _road_display_datas2_12, + _road_display_datas2_13, + _road_display_datas2_14, + _road_display_datas2_15, +}; + +static const byte * const _road_display_table_3[16] = { + _road_display_datas2_16, + _road_display_datas2_17, + _road_display_datas2_18, + _road_display_datas2_19, + _road_display_datas2_20, + _road_display_datas2_21, + _road_display_datas2_22, + _road_display_datas2_23, + + _road_display_datas2_24, + _road_display_datas2_25, + _road_display_datas2_26, + _road_display_datas2_27, + _road_display_datas2_28, + _road_display_datas2_29, + _road_display_datas2_30, + _road_display_datas2_31, +}; + +static const byte* const * const _road_display_table[6] = { + _road_display_table_1, + _road_display_table_1, + _road_display_table_1, + _road_display_table_2, + _road_display_table_1, + _road_display_table_3, +}; diff --git a/table/roadveh.h b/table/roadveh.h new file mode 100644 --- /dev/null +++ b/table/roadveh.h @@ -0,0 +1,1075 @@ +static const RoadDriveEntry _roadveh_drive_data_0[] = { + {15,5}, + {14,5}, + {13,5}, + {12,5}, + {11,5}, + {10,5}, + {9,5}, + {8,5}, + {7,5}, + {6,5}, + {5,5}, + {4,5}, + {3,5}, + {2,5}, + {1,5}, + {0,5}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_1[] = { + {5,0}, + {5,1}, + {5,2}, + {5,3}, + {5,4}, + {5,5}, + {5,6}, + {5,7}, + {5,8}, + {5,9}, + {5,10}, + {5,11}, + {5,12}, + {5,13}, + {5,14}, + {5,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_2[] = { + {5,0}, + {5,1}, + {5,2}, + {4,3}, + {3,4}, + {2,5}, + {1,5}, + {0,5}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_3[] = { + {15,5}, + {14,5}, + {13,5}, + {12,5}, + {11,5}, + {10,5}, + {9,6}, + {8,7}, + {7,8}, + {6,9}, + {5,10}, + {5,11}, + {5,12}, + {5,13}, + {5,14}, + {5,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_4[] = { + {5,0}, + {5,1}, + {5,2}, + {5,3}, + {5,4}, + {5,5}, + {6,6}, + {7,7}, + {8,8}, + {9,9}, + {10,9}, + {11,9}, + {12,9}, + {13,9}, + {14,9}, + {15,9}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_5[] = { + {0,9}, + {1,9}, + {2,9}, + {3,10}, + {4,11}, + {5,12}, + {5,13}, + {5,14}, + {5,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_6[] = { + {0,6}, + {0,7}, + {0,8}, + {0,9}, + {0x42,0} +}; +static const RoadDriveEntry _roadveh_drive_data_7[] = { + {6,15}, + {7,15}, + {8,15}, + {9,15}, + {0x43,0} +}; +static const RoadDriveEntry _roadveh_drive_data_8[] = { + {0,9}, + {1,9}, + {2,9}, + {3,9}, + {4,9}, + {5,9}, + {6,9}, + {7,9}, + {8,9}, + {9,9}, + {10,9}, + {11,9}, + {12,9}, + {13,9}, + {14,9}, + {15,9}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_9[] = { + {9,15}, + {9,14}, + {9,13}, + {9,12}, + {9,11}, + {9,10}, + {9,9}, + {9,8}, + {9,7}, + {9,6}, + {9,5}, + {9,4}, + {9,3}, + {9,2}, + {9,1}, + {9,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_10[] = { + {0,9}, + {1,9}, + {2,9}, + {3,9}, + {4,9}, + {5,9}, + {6,8}, + {7,7}, + {8,6}, + {9,5}, + {9,4}, + {9,3}, + {9,2}, + {9,1}, + {9,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_11[] = { + {9,15}, + {9,14}, + {9,13}, + {10,12}, + {11,11}, + {12,10}, + {13,9}, + {14,9}, + {15,9}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_12[] = { + {15,5}, + {14,5}, + {13,5}, + {12,4}, + {11,3}, + {10,2}, + {9,1}, + {9,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_13[] = { + {9,15}, + {9,14}, + {9,13}, + {9,12}, + {9,11}, + {9,10}, + {8,9}, + {7,8}, + {6,7}, + {5,6}, + {4,5}, + {3,5}, + {2,5}, + {1,5}, + {0,5}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_14[] = { + {15,8}, + {15,7}, + {15,6}, + {15,5}, + {0x40,0} +}; +static const RoadDriveEntry _roadveh_drive_data_15[] = { + {8,0}, + {7,0}, + {6,0}, + {5,0}, + {0x41,0} +}; +static const RoadDriveEntry _roadveh_drive_data_16[] = { + {15,9}, + {14,9}, + {13,9}, + {12,9}, + {11,9}, + {10,9}, + {9,9}, + {8,9}, + {7,9}, + {6,9}, + {5,9}, + {4,9}, + {3,9}, + {2,9}, + {1,9}, + {0,9}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_17[] = { + {9,0}, + {9,1}, + {9,2}, + {9,3}, + {9,4}, + {9,5}, + {9,6}, + {9,7}, + {9,8}, + {9,9}, + {9,10}, + {9,11}, + {9,12}, + {9,13}, + {9,14}, + {9,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_18[] = { + {9,0}, + {9,1}, + {9,2}, + {9,3}, + {9,4}, + {9,5}, + {8,6}, + {7,7}, + {6,8}, + {5,9}, + {4,9}, + {3,9}, + {2,9}, + {1,9}, + {0,9}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_19[] = { + {15,9}, + {14,9}, + {13,9}, + {12,10}, + {11,11}, + {10,12}, + {9,13}, + {9,14}, + {9,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_20[] = { + {9,0}, + {9,1}, + {10,2}, + {11,3}, + {12,4}, + {13,5}, + {14,5}, + {15,5}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_21[] = { + {0,5}, + {1,5}, + {2,5}, + {3,5}, + {4,5}, + {5,6}, + {6,7}, + {7,8}, + {8,9}, + {9,10}, + {9,11}, + {9,12}, + {9,13}, + {9,14}, + {9,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_22[] = { + {0,8}, + {0,7}, + {0,6}, + {0,5}, + {0x42,0} +}; +static const RoadDriveEntry _roadveh_drive_data_23[] = { + {8,15}, + {7,15}, + {6,15}, + {5,15}, + {0x43,0} +}; +static const RoadDriveEntry _roadveh_drive_data_24[] = { + {0,5}, + {1,5}, + {2,5}, + {3,5}, + {4,5}, + {5,5}, + {6,5}, + {7,5}, + {8,5}, + {9,5}, + {10,5}, + {11,5}, + {12,5}, + {13,5}, + {14,5}, + {15,5}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_25[] = { + {5,15}, + {5,14}, + {5,13}, + {5,12}, + {5,11}, + {5,10}, + {5,9}, + {5,8}, + {5,7}, + {5,6}, + {5,5}, + {5,4}, + {5,3}, + {5,2}, + {5,1}, + {5,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_26[] = { + {0,5}, + {1,5}, + {2,5}, + {3,4}, + {4,3}, + {5,2}, + {5,1}, + {5,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_27[] = { + {5,15}, + {5,14}, + {5,13}, + {5,12}, + {5,11}, + {5,10}, + {6,9}, + {7,8}, + {8,7}, + {9,6}, + {10,5}, + {11,5}, + {12,5}, + {13,5}, + {14,5}, + {15,5}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_28[] = { + {15,9}, + {14,9}, + {13,9}, + {12,9}, + {11,9}, + {10,9}, + {9,9}, + {8,8}, + {7,7}, + {6,6}, + {5,5}, + {5,4}, + {5,3}, + {5,2}, + {5,1}, + {5,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_29[] = { + {5,15}, + {5,14}, + {5,13}, + {5,12}, + {4,11}, + {3,10}, + {2,9}, + {1,9}, + {0,9}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_30[] = { + {15,6}, + {15,7}, + {15,8}, + {15,9}, + {0x40,0} +}; +static const RoadDriveEntry _roadveh_drive_data_31[] = { + {6,0}, + {7,0}, + {8,0}, + {9,0}, + {0x41,0} +}; +static const RoadDriveEntry _roadveh_drive_data_32[] = { + {15,5}, + {14,5}, + {13,6}, + {13,7}, + {13,8}, + {13,9}, + {13,10}, + {13,11}, + {12,12}, + {11,12}, + {10,12}, + {9,12}, + {8,12}, + {7,12}, + {6,12}, + {5,11}, + {5,10}, + {5,9}, + {5,8}, + {5,7}, + {5,6}, + {5,7}, + {5,8}, + {5,9}, + {5,10}, + {5,11}, + {6,12}, + {7,12}, + {8,12}, + {9,12}, + {10,12}, + {11,12}, + {12,12}, + {13,11}, + {13,10}, + {14,9}, + {15,9}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_33[] = { + {5,0}, + {5,1}, + {6,2}, + {7,2}, + {8,2}, + {9,2}, + {10,2}, + {11,2}, + {12,3}, + {12,4}, + {12,5}, + {12,6}, + {12,7}, + {12,8}, + {12,9}, + {11,10}, + {10,10}, + {9,10}, + {8,10}, + {7,10}, + {6,10}, + {7,10}, + {8,10}, + {9,10}, + {10,10}, + {11,10}, + {12,9}, + {12,8}, + {12,7}, + {12,6}, + {12,5}, + {12,4}, + {12,3}, + {11,2}, + {10,2}, + {9,1}, + {9,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_34[] = { + {15,5}, + {14,5}, + {13,6}, + {13,7}, + {13,8}, + {13,9}, + {13,10}, + {13,11}, + {12,12}, + {11,12}, + {10,12}, + {9,11}, + {9,10}, + {9,9}, + {9,8}, + {9,7}, + {9,6}, + {9,7}, + {9,8}, + {9,9}, + {9,10}, + {9,11}, + {10,12}, + {11,12}, + {12,12}, + {13,11}, + {13,10}, + {14,9}, + {15,9}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_35[] = { + {5,0}, + {5,1}, + {6,2}, + {7,2}, + {8,2}, + {9,2}, + {10,2}, + {11,2}, + {12,3}, + {12,4}, + {12,5}, + {11,6}, + {10,6}, + {9,6}, + {8,6}, + {7,6}, + {6,6}, + {7,6}, + {8,6}, + {9,6}, + {10,6}, + {11,6}, + {12,5}, + {12,4}, + {12,3}, + {11,2}, + {10,2}, + {9,1}, + {9,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_40[] = { + {0,9}, + {1,9}, + {2,8}, + {2,7}, + {2,6}, + {2,5}, + {2,4}, + {3,3}, + {4,3}, + {5,3}, + {6,3}, + {7,3}, + {8,3}, + {9,3}, + {10,4}, + {10,5}, + {10,6}, + {10,7}, + {10,8}, + {10,9}, + {10,8}, + {10,7}, + {10,6}, + {10,5}, + {10,4}, + {9,3}, + {8,3}, + {7,3}, + {6,3}, + {5,3}, + {4,3}, + {3,3}, + {2,4}, + {1,5}, + {0,5}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_41[] = { + {9,15}, + {9,14}, + {8,13}, + {7,13}, + {6,13}, + {5,13}, + {4,13}, + {3,12}, + {3,11}, + {3,10}, + {3,9}, + {3,8}, + {3,7}, + {3,6}, + {4,5}, + {5,5}, + {6,5}, + {7,5}, + {8,5}, + {9,5}, + {8,5}, + {7,5}, + {6,5}, + {5,5}, + {4,5}, + {3,6}, + {3,7}, + {3,8}, + {3,9}, + {3,10}, + {3,11}, + {3,12}, + {4,13}, + {5,14}, + {5,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_42[] = { + {0,9}, + {1,9}, + {2,8}, + {2,7}, + {2,6}, + {2,5}, + {2,4}, + {3,3}, + {4,3}, + {5,3}, + {6,4}, + {6,5}, + {6,6}, + {6,7}, + {6,8}, + {6,9}, + {6,8}, + {6,7}, + {6,6}, + {6,5}, + {6,4}, + {5,3}, + {4,3}, + {3,3}, + {2,4}, + {1,5}, + {0,5}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_43[] = { + {9,15}, + {9,14}, + {8,13}, + {7,13}, + {6,13}, + {5,13}, + {4,13}, + {3,12}, + {3,11}, + {3,10}, + {4,9}, + {5,9}, + {6,9}, + {7,9}, + {8,9}, + {9,9}, + {8,9}, + {7,9}, + {6,9}, + {5,9}, + {4,9}, + {3,10}, + {3,11}, + {3,12}, + {4,13}, + {5,14}, + {5,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_48[] = { + {15,9}, + {14,9}, + {13,10}, + {13,11}, + {12,12}, + {11,12}, + {10,12}, + {9,12}, + {8,12}, + {7,12}, + {6,12}, + {5,11}, + {5,10}, + {5,9}, + {5,8}, + {5,7}, + {5,6}, + {5,7}, + {5,8}, + {5,9}, + {5,10}, + {5,11}, + {6,12}, + {7,12}, + {8,12}, + {9,12}, + {10,12}, + {11,12}, + {12,12}, + {13,11}, + {13,10}, + {13,9}, + {13,8}, + {13,7}, + {13,6}, + {14,5}, + {15,5}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_49[] = { + {9,0}, + {9,1}, + {10,2}, + {11,2}, + {12,3}, + {12,4}, + {12,5}, + {12,6}, + {12,7}, + {12,8}, + {12,9}, + {11,10}, + {10,10}, + {9,10}, + {8,10}, + {7,10}, + {6,10}, + {7,10}, + {8,10}, + {9,10}, + {10,10}, + {11,10}, + {12,9}, + {12,8}, + {12,7}, + {12,6}, + {12,5}, + {12,4}, + {12,3}, + {11,2}, + {10,2}, + {9,2}, + {8,2}, + {7,2}, + {6,2}, + {5,1}, + {5,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_50[] = { + {15,9}, + {14,9}, + {13,10}, + {13,11}, + {12,12}, + {11,12}, + {10,12}, + {9,11}, + {9,10}, + {9,9}, + {9,8}, + {9,7}, + {9,6}, + {9,7}, + {9,8}, + {9,9}, + {9,10}, + {9,11}, + {10,12}, + {11,12}, + {12,12}, + {13,11}, + {13,10}, + {13,9}, + {13,8}, + {13,7}, + {13,6}, + {14,5}, + {15,5}, + {0x82,0} +}; +static const RoadDriveEntry _roadveh_drive_data_51[] = { + {9,0}, + {9,1}, + {10,2}, + {11,2}, + {12,3}, + {12,4}, + {12,5}, + {11,6}, + {10,6}, + {9,6}, + {8,6}, + {7,6}, + {6,6}, + {7,6}, + {8,6}, + {9,6}, + {10,6}, + {11,6}, + {12,5}, + {12,4}, + {12,3}, + {11,2}, + {10,2}, + {9,2}, + {8,2}, + {7,2}, + {6,2}, + {5,1}, + {5,0}, + {0x83,0} +}; +static const RoadDriveEntry _roadveh_drive_data_56[] = { + {0,5}, + {1,5}, + {2,4}, + {3,3}, + {4,3}, + {5,3}, + {6,3}, + {7,3}, + {8,3}, + {9,3}, + {10,4}, + {10,5}, + {10,6}, + {10,7}, + {10,8}, + {10,9}, + {10,8}, + {10,7}, + {10,6}, + {10,5}, + {10,4}, + {9,3}, + {8,3}, + {7,3}, + {6,3}, + {5,3}, + {4,3}, + {3,3}, + {2,4}, + {2,5}, + {2,6}, + {2,7}, + {2,8}, + {1,9}, + {0,9}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_57[] = { + {5,15}, + {5,14}, + {4,13}, + {3,12}, + {3,11}, + {3,10}, + {3,9}, + {3,8}, + {3,7}, + {3,6}, + {4,5}, + {5,5}, + {6,5}, + {7,5}, + {8,5}, + {9,5}, + {8,5}, + {7,5}, + {6,5}, + {5,5}, + {4,5}, + {3,6}, + {3,7}, + {3,8}, + {3,9}, + {3,10}, + {3,11}, + {3,12}, + {4,13}, + {5,13}, + {6,13}, + {7,13}, + {8,13}, + {9,14}, + {9,15}, + {0x81,0} +}; +static const RoadDriveEntry _roadveh_drive_data_58[] = { + {0,5}, + {1,5}, + {2,4}, + {3,3}, + {4,3}, + {5,3}, + {6,4}, + {6,5}, + {6,6}, + {6,7}, + {6,8}, + {6,9}, + {6,8}, + {6,7}, + {6,6}, + {6,5}, + {6,4}, + {5,3}, + {4,3}, + {3,3}, + {2,4}, + {2,5}, + {2,6}, + {2,7}, + {2,8}, + {1,9}, + {0,9}, + {0x80,0} +}; +static const RoadDriveEntry _roadveh_drive_data_59[] = { + {5,15}, + {5,14}, + {4,13}, + {3,12}, + {3,11}, + {3,10}, + {4,9}, + {5,9}, + {6,9}, + {7,9}, + {8,9}, + {9,9}, + {8,9}, + {7,9}, + {6,9}, + {5,9}, + {4,9}, + {3,10}, + {3,11}, + {3,12}, + {4,13}, + {5,13}, + {6,13}, + {7,13}, + {8,13}, + {9,14}, + {9,15}, + {0x81,0} +}; + +static const RoadDriveEntry * const _road_drive_data[] = { + _roadveh_drive_data_0, + _roadveh_drive_data_1, + _roadveh_drive_data_2, + _roadveh_drive_data_3, + _roadveh_drive_data_4, + _roadveh_drive_data_5, + _roadveh_drive_data_6, + _roadveh_drive_data_7, + _roadveh_drive_data_8, + _roadveh_drive_data_9, + _roadveh_drive_data_10, + _roadveh_drive_data_11, + _roadveh_drive_data_12, + _roadveh_drive_data_13, + _roadveh_drive_data_14, + _roadveh_drive_data_15, + _roadveh_drive_data_16, + _roadveh_drive_data_17, + _roadveh_drive_data_18, + _roadveh_drive_data_19, + _roadveh_drive_data_20, + _roadveh_drive_data_21, + _roadveh_drive_data_22, + _roadveh_drive_data_23, + _roadveh_drive_data_24, + _roadveh_drive_data_25, + _roadveh_drive_data_26, + _roadveh_drive_data_27, + _roadveh_drive_data_28, + _roadveh_drive_data_29, + _roadveh_drive_data_30, + _roadveh_drive_data_31, + _roadveh_drive_data_32, + _roadveh_drive_data_33, + _roadveh_drive_data_34, + _roadveh_drive_data_35, + NULL, + NULL, + NULL, + NULL, + _roadveh_drive_data_40, + _roadveh_drive_data_41, + _roadveh_drive_data_42, + _roadveh_drive_data_43, + NULL, + NULL, + NULL, + NULL, + _roadveh_drive_data_48, + _roadveh_drive_data_49, + _roadveh_drive_data_50, + _roadveh_drive_data_51, + NULL, + NULL, + NULL, + NULL, + _roadveh_drive_data_56, + _roadveh_drive_data_57, + _roadveh_drive_data_58, + _roadveh_drive_data_59, + NULL, + NULL, + NULL, + NULL, +}; diff --git a/table/station_land.h b/table/station_land.h new file mode 100644 --- /dev/null +++ b/table/station_land.h @@ -0,0 +1,885 @@ +#define TILE_SEQ_BEGIN(x) ADD_DWORD(x), +#define TILE_SEQ_LINE(a,b,c,d,e,f,g) a,b,c,d,e,f,ADD_WORD(g), +#define TILE_SEQ_SPEC(a,b,g) a,b,0x80,0,ADD_DWORD(g), +#define TILE_SEQ_END() 0x80 + +static const byte _station_display_datas_0[] = { + TILE_SEQ_BEGIN(0x3F4) + TILE_SEQ_LINE( 0, 0, 0, 16, 5, 2, 0x842E) + TILE_SEQ_LINE( 0, 11, 0, 16, 5, 2, 0x8430) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_1[] = { + TILE_SEQ_BEGIN(0x3F3) + TILE_SEQ_LINE( 0, 0, 0, 5, 16, 2, 0x842F) + TILE_SEQ_LINE( 11, 0, 0, 5, 16, 2, 0x842D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_2[] = { + TILE_SEQ_BEGIN(0x3F4) + TILE_SEQ_LINE( 0, 0, 0, 16, 5, 2, 0x8431) + TILE_SEQ_LINE( 0, 11, 0, 16, 5, 2, 0x8430) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_3[] = { + TILE_SEQ_BEGIN(0x3F3) + TILE_SEQ_LINE( 0, 0, 0, 5, 16, 2, 0x8432) + TILE_SEQ_LINE( 11, 0, 0, 5, 16, 2, 0x842D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_4[] = { + TILE_SEQ_BEGIN(0x3F4) + TILE_SEQ_LINE( 0, 0, 0, 16, 5, 7, 0x8434) + TILE_SEQ_LINE( 0, 11, 0, 16, 5, 2, 0x8430) + TILE_SEQ_LINE( 0, 0, 16, 16, 16, 10, 0x8437) + TILE_SEQ_SPEC( 0, 0, 0x322443B) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_5[] = { + TILE_SEQ_BEGIN(0x3F3) + TILE_SEQ_LINE( 0, 0, 0, 5, 16, 2, 0x8435) + TILE_SEQ_LINE( 11, 0, 0, 5, 16, 2, 0x842D) + TILE_SEQ_LINE( 0, 0, 16, 16, 16, 10, 0x8438) + TILE_SEQ_SPEC( 0, 0, 0x322443C) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_6[] = { + TILE_SEQ_BEGIN(0x3F4) + TILE_SEQ_LINE( 0, 0, 0, 16, 5, 2, 0x842E) + TILE_SEQ_LINE( 0, 11, 0, 16, 5, 2, 0x8436) + TILE_SEQ_LINE( 0, 0, 16, 16, 16, 10, 0x8439) + TILE_SEQ_SPEC( 0, 0, 0x322443D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_7[] = { + TILE_SEQ_BEGIN(0x3F3) + TILE_SEQ_LINE( 0, 0, 0, 5, 16, 2, 0x842F) + TILE_SEQ_LINE( 11, 0, 0, 5, 16, 2, 0x8433) + TILE_SEQ_LINE( 0, 0, 16, 16, 16, 10, 0x843A) + TILE_SEQ_SPEC( 0, 0, 0x322443E) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_8[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_9[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 0, 0, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_10[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_11[] = { + TILE_SEQ_BEGIN(0xA4B) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_12[] = { + TILE_SEQ_BEGIN(0xA4C) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_13[] = { + TILE_SEQ_BEGIN(0xA4D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_14[] = { + TILE_SEQ_BEGIN(0xA4E) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_15[] = { + TILE_SEQ_BEGIN(0xA4F) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_16[] = { + TILE_SEQ_BEGIN(0xA50) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_17[] = { + TILE_SEQ_BEGIN(0xA51) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_18[] = { + TILE_SEQ_BEGIN(0xA52) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_19[] = { + TILE_SEQ_BEGIN(0xA53) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_20[] = { + TILE_SEQ_BEGIN(0xA54) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_21[] = { + TILE_SEQ_BEGIN(0xA53) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_22[] = { + TILE_SEQ_BEGIN(0xA55) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_23[] = { + TILE_SEQ_BEGIN(0xA56) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_24[] = { + TILE_SEQ_BEGIN(0xA57) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_25[] = { + TILE_SEQ_BEGIN(0xA58) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_26[] = { + TILE_SEQ_BEGIN(0xA59) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_27[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 2, 0, 0, 11, 16, 40, 0x8A5A) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_28[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 3, 3, 0, 10, 10, 60, 0x8A5B) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_29[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 0, 1, 0, 14, 14, 30, 0x8A5C) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_30[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 3, 3, 0, 10, 11, 35, 0x8A5D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_31[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 0, 3, 0, 16, 11, 40, 0x8A5E) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_32[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 14, 0, 0, 2, 16, 28, 0x8A5F) + TILE_SEQ_LINE( 0, 0, 0, 2, 16, 28, 0xA60) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_33[] = { + TILE_SEQ_BEGIN(0xA4B) + TILE_SEQ_LINE( 7, 11, 0, 3, 3, 14, 0xA63) + TILE_SEQ_LINE( 0, 0, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_34[] = { + TILE_SEQ_BEGIN(0xA4B) + TILE_SEQ_LINE( 2, 7, 0, 3, 3, 14, 0xA64) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_35[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 3, 2, 0, 3, 3, 14, 0xA65) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_36[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 0, 8, 0, 14, 3, 14, 0xA66) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_37[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_38[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_39[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA78) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_40[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA79) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_41[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7A) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_42[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7B) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_43[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7C) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_44[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7D) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_45[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7E) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_46[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7F) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_47[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA80) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_48[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA81) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_49[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA82) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_50[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA83) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_51[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 70, 0xA29) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_52[] = { + TILE_SEQ_BEGIN(0xA69) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_53[] = { + TILE_SEQ_BEGIN(0xA6A) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_54[] = { + TILE_SEQ_BEGIN(0x8A6B) + TILE_SEQ_LINE( 0, 0, 0, 15, 15, 30, 0x8A6C) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_55[] = { + TILE_SEQ_BEGIN(0xA6D) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_56[] = { + TILE_SEQ_BEGIN(0xA6E) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_57[] = { + TILE_SEQ_BEGIN(0xA6F) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_58[] = { + TILE_SEQ_BEGIN(0xA70) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_LINE( 4, 11, 0, 1, 1, 20, 0x8A74) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_59[] = { + TILE_SEQ_BEGIN(0xA70) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_LINE( 4, 11, 0, 1, 1, 20, 0x8A75) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_60[] = { + TILE_SEQ_BEGIN(0xA70) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_LINE( 4, 11, 0, 1, 1, 20, 0x8A76) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_61[] = { + TILE_SEQ_BEGIN(0xA70) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_LINE( 4, 11, 0, 1, 1, 20, 0x8A77) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_62[] = { + TILE_SEQ_BEGIN(0xA71) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_63[] = { + TILE_SEQ_BEGIN(0xA72) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_64[] = { + TILE_SEQ_BEGIN(0xA73) + TILE_SEQ_LINE( 0, 15, 0, 16, 1, 6, 0x8A68) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_65[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 14, 0, 0, 2, 16, 28, 0x8A61) + TILE_SEQ_LINE( 0, 0, 0, 2, 16, 28, 0xA62) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_66[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 60, 0x8A49) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_67[] = { + TILE_SEQ_BEGIN(0x8A94) + TILE_SEQ_LINE( 0, 15, 0, 13, 1, 10, 0x8A98) + TILE_SEQ_LINE( 13, 0, 0, 3, 16, 10, 0x8A9C) + TILE_SEQ_LINE( 2, 0, 0, 11, 1, 10, 0x8AA0) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_68[] = { + TILE_SEQ_BEGIN(0x8A95) + TILE_SEQ_LINE( 15, 3, 0, 1, 13, 10, 0x8A99) + TILE_SEQ_LINE( 0, 0, 0, 16, 3, 10, 0x8A9D) + TILE_SEQ_LINE( 0, 3, 0, 1, 11, 10, 0x8AA1) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_69[] = { + TILE_SEQ_BEGIN(0x8A96) + TILE_SEQ_LINE( 3, 0, 0, 13, 1, 10, 0x8A9A) + TILE_SEQ_LINE( 0, 0, 0, 3, 16, 10, 0x8A9E) + TILE_SEQ_LINE( 3, 15, 0, 11, 1, 10, 0x8AA2) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_70[] = { + TILE_SEQ_BEGIN(0x8A97) + TILE_SEQ_LINE( 0, 0, 0, 1, 13, 10, 0x8A9B) + TILE_SEQ_LINE( 0, 13, 0, 16, 3, 10, 0x8A9F) + TILE_SEQ_LINE( 15, 2, 0, 1, 11, 10, 0x8AA3) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_71[] = { + TILE_SEQ_BEGIN(0x8A84) + TILE_SEQ_LINE( 2, 0, 0, 11, 1, 10, 0x8A88) + TILE_SEQ_LINE( 13, 0, 0, 3, 16, 10, 0x8A8C) + TILE_SEQ_LINE( 0, 13, 0, 13, 3, 10, 0x8A90) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_72[] = { + TILE_SEQ_BEGIN(0x8A85) + TILE_SEQ_LINE( 0, 3, 0, 1, 11, 10, 0x8A89) + TILE_SEQ_LINE( 0, 0, 0, 16, 3, 10, 0x8A8D) + TILE_SEQ_LINE( 13, 3, 0, 3, 13, 10, 0x8A91) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_73[] = { + TILE_SEQ_BEGIN(0x8A86) + TILE_SEQ_LINE( 3, 15, 0, 11, 1, 10, 0x8A8A) + TILE_SEQ_LINE( 0, 0, 0, 3, 16, 10, 0x8A8E) + TILE_SEQ_LINE( 3, 0, 0, 13, 3, 10, 0x8A92) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_74[] = { + TILE_SEQ_BEGIN(0x8A87) + TILE_SEQ_LINE( 15, 2, 0, 1, 11, 10, 0x8A8B) + TILE_SEQ_LINE( 0, 13, 0, 16, 3, 10, 0x8A8F) + TILE_SEQ_LINE( 0, 0, 0, 3, 13, 10, 0x8A93) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_75[] = { + TILE_SEQ_BEGIN(0xFDD) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_76[] = { + TILE_SEQ_BEGIN(0xFE4) + TILE_SEQ_LINE( 0, 4, 0, 16, 8, 8, 0xAA7) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_77[] = { + TILE_SEQ_BEGIN(0xFE5) + TILE_SEQ_LINE( 4, 0, 0, 8, 16, 8, 0xAA8) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_78[] = { + TILE_SEQ_BEGIN(0xFE3) + TILE_SEQ_LINE( 0, 4, 0, 16, 8, 8, 0xAA9) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_79[] = { + TILE_SEQ_BEGIN(0xFE2) + TILE_SEQ_LINE( 4, 0, 0, 8, 16, 8, 0xAAA) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_80[] = { + TILE_SEQ_BEGIN(0xFDD) + TILE_SEQ_LINE( 0, 4, 0, 16, 8, 8, 0xAAB) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_81[] = { + TILE_SEQ_BEGIN(0xFDD) + TILE_SEQ_LINE( 4, 0, 0, 8, 16, 8, 0xAAC) + TILE_SEQ_END() +}; + +static const byte _station_display_datas_82[] = { + TILE_SEQ_BEGIN(0xFEC) + TILE_SEQ_END() +}; + +// end of runway +const byte _station_display_datas_083[] = { + TILE_SEQ_BEGIN(0xA59) + TILE_SEQ_END() +}; + +// runway tiles +const byte _station_display_datas_084[] = { + TILE_SEQ_BEGIN(0xA56) + TILE_SEQ_END() +}; + +// control tower with concrete underground and no fence +const byte _station_display_datas_085[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 3, 3, 0, 10, 10, 60, 0x8A5B) // control tower + TILE_SEQ_END() +}; + +// new airportdepot, facing west +const byte _station_display_datas_086[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 14, 0, 0, 2, 16, 28, 0x8A61) + TILE_SEQ_LINE( 0, 0, 0, 2, 16, 28, 0xA62) + TILE_SEQ_END() +}; + +// asphalt tile with fences in north +const byte _station_display_datas_087[] = { + TILE_SEQ_BEGIN(0xA4A) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +// end of runway +const byte _station_display_datas_088[] = { + TILE_SEQ_BEGIN(0xA59) + TILE_SEQ_LINE( 0, 0, 0, 16, 1, 6, 0x8A68) // fences + TILE_SEQ_END() +}; + +// runway tiles +const byte _station_display_datas_089[] = { + TILE_SEQ_BEGIN(0xA56) + TILE_SEQ_LINE( 0, 0, 0, 16, 1, 6, 0x8A68) // fences + TILE_SEQ_END() +}; + +// turning radar with concrete underground fences on south -- needs 12 tiles +//BEGIN +const byte _station_display_datas_090[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA78) // turning radar + TILE_SEQ_LINE(15, 0, 0, 1, 16, 6, 0x8A67) //fences + TILE_SEQ_END() +}; + +const byte _station_display_datas_091[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA79) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_092[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7A) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_093[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7B) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_094[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7C) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_095[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7D) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_096[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7E) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_097[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7F) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_098[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA80) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_099[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA81) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0100[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA82) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0101[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA83) + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; +//END + +// turning radar with concrete underground fences on north -- needs 12 tiles +//BEGIN +const byte _station_display_datas_0102[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA78) // turning radar + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0103[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA79) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0104[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7A) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0105[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7B) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0106[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7C) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0107[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7D) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0108[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7E) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0109[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA7F) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0110[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA80) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0111[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA81) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0112[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA82) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; + +const byte _station_display_datas_0113[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE( 7, 7, 0, 2, 2, 8, 0xA83) + TILE_SEQ_LINE( 0, 0, 0, 1, 16, 6, 0x8A67) + TILE_SEQ_END() +}; +//END + +// helipad for international airport +const byte _station_display_datas_0114[] = { + TILE_SEQ_BEGIN(0xA4A) // concrete underground + TILE_SEQ_LINE(10, 6, 0, 0, 0, 0, SPR_OPENTTD_BASE + 31) // helipad + TILE_SEQ_LINE( 15, 0, 0, 1, 16, 6, 0x8A67) // fences bottom + TILE_SEQ_END() +}; + +static const byte * const _station_display_datas[] = { + _station_display_datas_0, + _station_display_datas_1, + _station_display_datas_2, + _station_display_datas_3, + _station_display_datas_4, + _station_display_datas_5, + _station_display_datas_6, + _station_display_datas_7, + _station_display_datas_8, + _station_display_datas_9, + _station_display_datas_10, + _station_display_datas_11, + _station_display_datas_12, + _station_display_datas_13, + _station_display_datas_14, + _station_display_datas_15, + _station_display_datas_16, + _station_display_datas_17, + _station_display_datas_18, + _station_display_datas_19, + _station_display_datas_20, + _station_display_datas_21, + _station_display_datas_22, + _station_display_datas_23, + _station_display_datas_24, + _station_display_datas_25, + _station_display_datas_26, + _station_display_datas_27, + _station_display_datas_28, + _station_display_datas_29, + _station_display_datas_30, + _station_display_datas_31, + _station_display_datas_32, + _station_display_datas_33, + _station_display_datas_34, + _station_display_datas_35, + _station_display_datas_36, + _station_display_datas_37, + _station_display_datas_38, + _station_display_datas_39, + _station_display_datas_40, + _station_display_datas_41, + _station_display_datas_42, + _station_display_datas_43, + _station_display_datas_44, + _station_display_datas_45, + _station_display_datas_46, + _station_display_datas_47, + _station_display_datas_48, + _station_display_datas_49, + _station_display_datas_50, + _station_display_datas_51, + _station_display_datas_52, + _station_display_datas_53, + _station_display_datas_54, + _station_display_datas_55, + _station_display_datas_56, + _station_display_datas_57, + _station_display_datas_58, + _station_display_datas_59, + _station_display_datas_60, + _station_display_datas_61, + _station_display_datas_62, + _station_display_datas_63, + _station_display_datas_64, + _station_display_datas_65, + _station_display_datas_66, + _station_display_datas_67, + _station_display_datas_68, + _station_display_datas_69, + _station_display_datas_70, + _station_display_datas_71, + _station_display_datas_72, + _station_display_datas_73, + _station_display_datas_74, + _station_display_datas_75, + _station_display_datas_76, + _station_display_datas_77, + _station_display_datas_78, + _station_display_datas_79, + _station_display_datas_80, + _station_display_datas_81, + _station_display_datas_82, + _station_display_datas_083, + _station_display_datas_084, + _station_display_datas_085, + _station_display_datas_086, + _station_display_datas_087, + _station_display_datas_088, + _station_display_datas_089, + _station_display_datas_090, + _station_display_datas_091, + _station_display_datas_092, + _station_display_datas_093, + _station_display_datas_094, + _station_display_datas_095, + _station_display_datas_096, + _station_display_datas_097, + _station_display_datas_098, + _station_display_datas_099, + _station_display_datas_0100, + _station_display_datas_0101, + _station_display_datas_0102, + _station_display_datas_0103, + _station_display_datas_0104, + _station_display_datas_0105, + _station_display_datas_0106, + _station_display_datas_0107, + _station_display_datas_0108, + _station_display_datas_0109, + _station_display_datas_0110, + _station_display_datas_0111, + _station_display_datas_0112, + _station_display_datas_0113, + _station_display_datas_0114, +}; diff --git a/table/town_land.h b/table/town_land.h new file mode 100644 --- /dev/null +++ b/table/town_land.h @@ -0,0 +1,2169 @@ +#define M(s1,s2,sx,sy,w,h,dz,p) {s1,s2,(sx<<4)|sy,((w-1)<<4)|(h-1),dz,p} + +static const DrawTownTileStruct _town_draw_tile_data[] = { + M( 0xf54, 0x58d, 0, 0, 14, 14, 8, 0), + M( 0xf54, 0x58e, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x58f, 0, 0, 14, 14, 60, 0), + M( 0x590, 0x58f, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x58d, 0, 0, 14, 14, 8, 0), + M( 0xf54, 0x58e, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x591, 0, 0, 14, 14, 60, 0), + M( 0x590, 0x591, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x31d858d, 0, 0, 14, 14, 8, 0), + M( 0xf54, 0x31d858e, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x31d8591, 0, 0, 14, 14, 60, 0), + M( 0x590, 0x31d8591, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x320858d, 0, 0, 14, 14, 8, 0), + M( 0xf54, 0x320858e, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x3208591, 0, 0, 14, 14, 60, 0), + M( 0x590, 0x3208591, 0, 0, 14, 14, 60, 0), + M( 0xf54, 0x592, 0, 0, 14, 16, 11, 0), + M( 0xf54, 0x593, 0, 0, 14, 16, 33, 0), + M( 0xf54, 0x594, 0, 0, 14, 16, 33, 0), + M( 0x595, 0x594, 0, 0, 14, 16, 33, 0), + M( 0xf54, 0x31d8592, 0, 0, 16, 16, 11, 0), + M( 0xf54, 0x31d8593, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x31d8594, 0, 0, 16, 16, 33, 0), + M( 0x595, 0x31d8594, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x3208592, 0, 0, 16, 16, 11, 0), + M( 0xf54, 0x3208593, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x3208594, 0, 0, 16, 16, 33, 0), + M( 0x595, 0x3208594, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x31c8592, 0, 0, 16, 16, 11, 0), + M( 0xf54, 0x31c8593, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x31c8594, 0, 0, 16, 16, 33, 0), + M( 0x595, 0x31c8594, 0, 0, 16, 16, 33, 0), + M( 0xf54, 0x596, 0, 0, 12, 12, 6, 0), + M( 0xf54, 0x597, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x598, 0, 0, 12, 12, 17, 0), + M( 0x599, 0x598, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x596, 0, 0, 12, 12, 6, 0), + M( 0xf54, 0x597, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x598, 0, 0, 12, 12, 17, 0), + M( 0x599, 0x598, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x596, 0, 0, 12, 12, 6, 0), + M( 0xf54, 0x597, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x598, 0, 0, 12, 12, 17, 0), + M( 0x599, 0x598, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x596, 0, 0, 12, 12, 6, 0), + M( 0xf54, 0x597, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x598, 0, 0, 12, 12, 17, 0), + M( 0x599, 0x598, 0, 0, 12, 12, 17, 0), + M( 0xf54, 0x59a, 0, 0, 14, 16, 16, 0), + M( 0xf54, 0x59b, 0, 0, 14, 16, 22, 0), + M( 0xf54, 0x59c, 0, 0, 14, 16, 35, 0), + M( 0x59d, 0x59c, 0, 0, 14, 16, 35, 0), + M( 0xf54, 0x59e859a, 0, 0, 14, 16, 16, 0), + M( 0xf54, 0x59e859b, 0, 0, 14, 16, 22, 0), + M( 0xf54, 0x59e859c, 0, 0, 14, 16, 35, 0), + M( 0x59d, 0x59e859c, 0, 0, 14, 16, 35, 0), + M( 0xf54, 0x59f859a, 0, 0, 14, 16, 16, 0), + M( 0xf54, 0x59f859b, 0, 0, 14, 16, 22, 0), + M( 0xf54, 0x59f859c, 0, 0, 14, 16, 35, 0), + M( 0x59d, 0x59f859c, 0, 0, 14, 16, 35, 0), + M( 0xf54, 0x59f859a, 0, 0, 14, 16, 16, 0), + M( 0xf54, 0x59f859b, 0, 0, 14, 16, 22, 0), + M( 0xf54, 0x59f859c, 0, 0, 14, 16, 35, 0), + M( 0x59d, 0x59f859c, 0, 0, 14, 16, 35, 0), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x5a2, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x5a2, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x5a2, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x5a2, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x5a2, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x5a2, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x5a2, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x5a2, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x11d9, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x11d9, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x11d9, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x11d9, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x11d9, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x11d9, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a0, 0, 0, 15, 15, 5, 0), + M( 0xf54, 0x5a1, 0, 0, 15, 15, 53, 0), + M( 0xf54, 0x11d9, 0, 0, 15, 15, 53, 0), + M( 0x58c, 0x11d9, 0, 0, 15, 15, 53, 1), + M( 0xf54, 0x5a4, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a5, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a6, 0, 0, 16, 16, 16, 0), + M( 0x5a7, 0x5a6, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a4, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a5, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a6, 0, 0, 16, 16, 16, 0), + M( 0x5a7, 0x5a6, 0, 0, 16, 16, 16, 0), + M( 0x5dd, 0x5de, 0, 0, 16, 16, 16, 0), + M( 0x5df, 0x5e0, 0, 0, 16, 16, 16, 0), + M( 0x5e1, 0x5e2, 0, 0, 16, 16, 16, 0), + M( 0x5e1, 0x5e2, 0, 0, 16, 16, 16, 0), + M( 0x5dd, 0x5de, 0, 0, 16, 16, 16, 0), + M( 0x5df, 0x5e0, 0, 0, 16, 16, 16, 0), + M( 0x5e1, 0x5e2, 0, 0, 16, 16, 16, 0), + M( 0x5e1, 0x5e2, 0, 0, 16, 16, 16, 0), + M( 0xf54, 0x5a8, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5a9, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5a8, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5a9, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5a8, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5a9, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5a8, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5a9, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5aa, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5ab, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5ac, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5ab, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5ac, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5ab, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5ac, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x5ab, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5ac, 0, 0, 16, 16, 38, 0), + M( 0xf54, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0x58c, 0x5ad, 0, 0, 16, 16, 45, 0), + M( 0xf54, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0xf54, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0xf54, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0xf54, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x0, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0x58c, 0x5ae, 6, 5, 3, 6, 8, 0), + M( 0xf54, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0xf54, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0xf54, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0xf54, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x0, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0x58c, 0x5af, 3, 3, 9, 9, 8, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b0, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf8d, 0x5b1, 0, 0, 16, 16, 15, 0), + M( 0xf54, 0x5b2, 0, 0, 16, 16, 8, 0), + M( 0xf54, 0x5b3, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x5b4, 0, 0, 16, 16, 42, 0), + M( 0x58c, 0x5b4, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31d85b2, 0, 0, 16, 16, 8, 0), + M( 0xf54, 0x31d85b3, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31d85b4, 0, 0, 16, 16, 42, 0), + M( 0x58c, 0x31d85b4, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31e85b2, 0, 0, 16, 16, 8, 0), + M( 0xf54, 0x31e85b3, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31e85b4, 0, 0, 16, 16, 42, 0), + M( 0x58c, 0x31e85b4, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31c85b2, 0, 0, 16, 16, 8, 0), + M( 0xf54, 0x31c85b3, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x31c85b4, 0, 0, 16, 16, 42, 0), + M( 0x58c, 0x31c85b4, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x5b5, 1, 3, 14, 11, 7, 0), + M( 0xf54, 0x5b6, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0x58c, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b5, 1, 3, 14, 11, 7, 0), + M( 0xf54, 0x5b6, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0x58c, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b5, 1, 3, 14, 11, 7, 0), + M( 0xf54, 0x5b6, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0x58c, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b5, 1, 3, 14, 11, 7, 0), + M( 0xf54, 0x5b6, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0x58c, 0x5b7, 1, 3, 14, 11, 53, 0), + M( 0xf54, 0x5b8, 3, 1, 11, 14, 6, 0), + M( 0xf54, 0x5b9, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0x58c, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5b8, 3, 1, 11, 14, 6, 0), + M( 0xf54, 0x5b9, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0x58c, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5b8, 3, 1, 11, 14, 6, 0), + M( 0xf54, 0x5b9, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0x58c, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5b8, 3, 1, 11, 14, 6, 0), + M( 0xf54, 0x5b9, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0x58c, 0x5ba, 3, 1, 11, 14, 28, 0), + M( 0xf54, 0x5bb, 2, 0, 13, 16, 6, 0), + M( 0xf54, 0x5bc, 2, 0, 13, 16, 45, 0), + M( 0xf54, 0x5bd, 2, 0, 13, 16, 46, 0), + M( 0x58c, 0x5bd, 2, 0, 13, 16, 46, 0), + M( 0xf54, 0x5bb, 2, 0, 13, 16, 6, 0), + M( 0xf54, 0x5bc, 2, 0, 13, 16, 45, 0), + M( 0xf54, 0x5bd, 2, 0, 13, 16, 46, 0), + M( 0x58c, 0x5bd, 2, 0, 13, 16, 46, 0), + M( 0xf54, 0x31b85bb, 2, 0, 13, 16, 6, 0), + M( 0xf54, 0x31b85bc, 2, 0, 13, 16, 45, 0), + M( 0xf54, 0x31b85bd, 2, 0, 13, 16, 46, 0), + M( 0x58c, 0x31b85bd, 2, 0, 13, 16, 46, 0), + M( 0xf54, 0x31d85bb, 2, 0, 13, 16, 6, 0), + M( 0xf54, 0x31d85bc, 2, 0, 13, 16, 45, 0), + M( 0xf54, 0x31d85bd, 2, 0, 13, 16, 46, 0), + M( 0x58c, 0x31d85bd, 2, 0, 13, 16, 46, 0), + M( 0xf54, 0x30b85be, 2, 0, 13, 16, 13, 0), + M( 0xf54, 0x30b85bf, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x30b85c0, 2, 0, 13, 16, 110, 0), + M( 0x58c, 0x30b85c0, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x30f85be, 2, 0, 13, 16, 13, 0), + M( 0xf54, 0x30f85bf, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x30f85c0, 2, 0, 13, 16, 110, 0), + M( 0x58c, 0x30f85c0, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x31385be, 2, 0, 13, 16, 13, 0), + M( 0xf54, 0x31385bf, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x31385c0, 2, 0, 13, 16, 110, 0), + M( 0x58c, 0x31385c0, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x30d85be, 2, 0, 13, 16, 13, 0), + M( 0xf54, 0x30d85bf, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x30d85c0, 2, 0, 13, 16, 110, 0), + M( 0x58c, 0x30d85c0, 2, 0, 13, 16, 110, 0), + M( 0xf54, 0x5c1, 1, 2, 15, 12, 4, 0), + M( 0xf54, 0x5c2, 1, 2, 15, 12, 24, 0), + M( 0xf54, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0x58c, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0xf54, 0x5c1, 1, 2, 15, 12, 4, 0), + M( 0xf54, 0x5c2, 1, 2, 15, 12, 24, 0), + M( 0xf54, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0x58c, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0xf54, 0x5c1, 1, 2, 15, 12, 4, 0), + M( 0xf54, 0x5c2, 1, 2, 15, 12, 24, 0), + M( 0xf54, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0x58c, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0xf54, 0x5c1, 1, 2, 15, 12, 4, 0), + M( 0xf54, 0x5c2, 1, 2, 15, 12, 24, 0), + M( 0xf54, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0x58c, 0x5c3, 1, 2, 15, 12, 31, 0), + M( 0xf54, 0x5c4, 1, 0, 14, 15, 20, 0), + M( 0xf54, 0x5c5, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0x58c, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c4, 1, 0, 14, 15, 20, 0), + M( 0xf54, 0x5c5, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0x58c, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c4, 1, 0, 14, 15, 20, 0), + M( 0xf54, 0x5c5, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0x58c, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c4, 1, 0, 14, 15, 20, 0), + M( 0xf54, 0x5c5, 1, 0, 14, 15, 42, 0), + M( 0xf54, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0x58c, 0x5c6, 1, 0, 14, 15, 42, 0), + M( 0x5c7, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c7, 0x5cb, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c8, 0x5cc, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5c9, 0x5cd, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0x5ca, 0x5ce, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x5d4, 0, 0, 16, 16, 22, 0), + M( 0x5d3, 0x5d4, 0, 0, 16, 16, 22, 0), + M( 0x5d3, 0x5d4, 0, 0, 16, 16, 22, 0), + M( 0x5d3, 0x5d4, 0, 0, 16, 16, 22, 0), + M( 0xf54, 0x5d6, 0, 0, 16, 16, 22, 0), + M( 0x5d5, 0x5d6, 0, 0, 16, 16, 22, 0), + M( 0x5d5, 0x5d6, 0, 0, 16, 16, 22, 0), + M( 0x5d5, 0x5d6, 0, 0, 16, 16, 22, 0), + M( 0xf54, 0x5d0, 0, 0, 16, 16, 21, 0), + M( 0x5cf, 0x5d0, 0, 0, 16, 16, 21, 0), + M( 0x5cf, 0x5d0, 0, 0, 16, 16, 21, 0), + M( 0x5cf, 0x5d0, 0, 0, 16, 16, 21, 0), + M( 0xf54, 0x5d2, 0, 0, 16, 16, 11, 0), + M( 0x5d1, 0x5d2, 0, 0, 16, 16, 11, 0), + M( 0x5d1, 0x5d2, 0, 0, 16, 16, 11, 0), + M( 0x5d1, 0x5d2, 0, 0, 16, 16, 11, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d7, 0x5d8, 0, 0, 16, 16, 22, 0), + M( 0x5d9, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5da, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5db, 0x5dc, 0, 0, 16, 16, 22, 0), + M( 0x5db, 0x5dc, 0, 0, 16, 16, 22, 0), + M( 0x622, 0x623, 0, 0, 16, 16, 22, 0), + M( 0x624, 0x625, 0, 0, 16, 16, 22, 0), + M( 0x626, 0x627, 0, 0, 16, 16, 22, 0), + M( 0x626, 0x627, 0, 0, 16, 16, 22, 0), + M( 0x5e3, 0x5e4, 0, 0, 16, 16, 22, 0), + M( 0x5e5, 0x5e6, 0, 0, 16, 16, 22, 0), + M( 0x5e7, 0x5e8, 0, 0, 16, 16, 22, 0), + M( 0x5e7, 0x5e8, 0, 0, 16, 16, 22, 0), + M( 0x5e9, 0x5ea, 0, 0, 16, 16, 22, 0), + M( 0x5eb, 0x5ec, 0, 0, 16, 16, 22, 0), + M( 0x5ed, 0x5ee, 0, 0, 16, 16, 22, 0), + M( 0x5ed, 0x5ee, 0, 0, 16, 16, 22, 0), + M( 0x5ef, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5f0, 0x5f1, 0, 0, 16, 16, 22, 0), + M( 0x5f2, 0x5f3, 0, 0, 16, 16, 22, 0), + M( 0x5f2, 0x5f3, 0, 0, 16, 16, 22, 0), + M( 0x5ef, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x5f0, 0x5f1, 0, 0, 16, 16, 22, 0), + M( 0x5f2, 0x5f3, 0, 0, 16, 16, 22, 0), + M( 0x5f2, 0x5f3, 0, 0, 16, 16, 22, 0), + M( 0x5f4, 0x5f5, 0, 0, 16, 16, 22, 0), + M( 0x5f6, 0x5f7, 0, 0, 16, 16, 22, 0), + M( 0x5f8, 0x5f9, 0, 0, 16, 16, 22, 0), + M( 0x5f8, 0x5f9, 0, 0, 16, 16, 22, 0), + M( 0x5f4, 0x5f5, 0, 0, 16, 16, 22, 0), + M( 0x5f6, 0x5f7, 0, 0, 16, 16, 22, 0), + M( 0x5f8, 0x5f9, 0, 0, 16, 16, 22, 0), + M( 0x5f8, 0x5f9, 0, 0, 16, 16, 22, 0), + M( 0x5fa, 0x5fb, 0, 0, 16, 16, 85, 0), + M( 0x5fc, 0x5fd, 0, 0, 16, 16, 85, 0), + M( 0x5fe, 0x5ff, 0, 0, 16, 16, 85, 0), + M( 0x5fe, 0x5ff, 0, 0, 16, 16, 85, 0), + M( 0x5fa, 0x5fb, 0, 0, 16, 16, 85, 0), + M( 0x5fc, 0x5fd, 0, 0, 16, 16, 85, 0), + M( 0x5fe, 0x5ff, 0, 0, 16, 16, 85, 0), + M( 0x5fe, 0x5ff, 0, 0, 16, 16, 85, 0), + M( 0x60a, 0x60b, 0, 0, 16, 16, 95, 0), + M( 0x60c, 0x60d, 0, 0, 16, 16, 95, 0), + M( 0x60e, 0x60f, 0, 0, 16, 16, 95, 0), + M( 0x60e, 0x60f, 0, 0, 16, 16, 95, 0), + M( 0x60a, 0x60b, 0, 0, 16, 16, 95, 0), + M( 0x60c, 0x60d, 0, 0, 16, 16, 95, 0), + M( 0x60e, 0x60f, 0, 0, 16, 16, 95, 0), + M( 0x60e, 0x60f, 0, 0, 16, 16, 95, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x600, 0x601, 0, 0, 16, 16, 55, 0), + M( 0x600, 0x601, 0, 0, 16, 16, 55, 0), + M( 0x600, 0x601, 0, 0, 16, 16, 55, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x31d8600, 0x31d8601, 0, 0, 16, 16, 55, 0), + M( 0x31d8600, 0x31d8601, 0, 0, 16, 16, 55, 0), + M( 0x31d8600, 0x31d8601, 0, 0, 16, 16, 55, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x602, 0x603, 0, 0, 16, 16, 42, 0), + M( 0x602, 0x603, 0, 0, 16, 16, 42, 0), + M( 0x602, 0x603, 0, 0, 16, 16, 42, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x3208602, 0x3208603, 0, 0, 16, 16, 42, 0), + M( 0x3208602, 0x3208603, 0, 0, 16, 16, 42, 0), + M( 0x3208602, 0x3208603, 0, 0, 16, 16, 42, 0), + M( 0x604, 0x605, 0, 0, 16, 16, 88, 0), + M( 0x606, 0x607, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x604, 0x605, 0, 0, 16, 16, 88, 0), + M( 0x606, 0x607, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x604, 0x605, 0, 0, 16, 16, 88, 0), + M( 0x606, 0x607, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x604, 0x605, 0, 0, 16, 16, 88, 0), + M( 0x606, 0x607, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0x608, 0x609, 0, 0, 16, 16, 88, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x610, 0x611, 0, 0, 16, 16, 40, 0), + M( 0x612, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x612, 0x616, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x613, 0x617, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x614, 0x618, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0x615, 0x619, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61c, 0x61d, 0, 0, 16, 16, 100, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61c, 0x61d, 0, 0, 16, 16, 100, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61c, 0x61d, 0, 0, 16, 16, 100, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61a, 0x61b, 0, 0, 16, 16, 100, 0), + M( 0x61c, 0x61d, 0, 0, 16, 16, 100, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x61e, 0x61f, 0, 0, 16, 16, 25, 0), + M( 0x61e, 0x61f, 0, 0, 16, 16, 25, 0), + M( 0x61e, 0x61f, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x31d861e, 0x31d861f, 0, 0, 16, 16, 25, 0), + M( 0x31d861e, 0x31d861f, 0, 0, 16, 16, 25, 0), + M( 0x31d861e, 0x31d861f, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x620, 0x621, 0, 0, 16, 16, 25, 0), + M( 0x620, 0x621, 0, 0, 16, 16, 25, 0), + M( 0x620, 0x621, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x3108620, 0x3108621, 0, 0, 16, 16, 25, 0), + M( 0x3108620, 0x3108621, 0, 0, 16, 16, 25, 0), + M( 0x3108620, 0x3108621, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x11da, 0x11db, 0, 0, 16, 16, 25, 0), + M( 0x11da, 0x11db, 0, 0, 16, 16, 25, 0), + M( 0x11da, 0x11db, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x31d91da, 0x31d91db, 0, 0, 16, 16, 25, 0), + M( 0x31d91da, 0x31d91db, 0, 0, 16, 16, 25, 0), + M( 0x31d91da, 0x31d91db, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x11dc, 0x11dd, 0, 0, 16, 16, 25, 0), + M( 0x11dc, 0x11dd, 0, 0, 16, 16, 25, 0), + M( 0x11dc, 0x11dd, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x31091dc, 0x31091dd, 0, 0, 16, 16, 25, 0), + M( 0x31091dc, 0x31091dd, 0, 0, 16, 16, 25, 0), + M( 0x31091dc, 0x31091dd, 0, 0, 16, 16, 25, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 22, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1134, 0x1135, 0, 0, 16, 16, 40, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x1136, 0x1137, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x113b, 0x113c, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1138, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x113d, 0x113e, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1139, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x113f, 0x1140, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x113a, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0x1141, 0x0, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x1147, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x1147, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x1147, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1144, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1145, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1146, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x1147, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1142, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x114b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x114b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x114b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1148, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1149, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114a, 0, 0, 16, 16, 40, 0), + M( 0x1143, 0x114b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1150, 0, 0, 16, 16, 40, 0), + M( 0x114c, 0x1150, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x309914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x309914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3099150, 0, 0, 16, 16, 40, 0), + M( 0x114c, 0x3099150, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x310914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x310914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109150, 0, 0, 16, 16, 40, 0), + M( 0x114c, 0x3109150, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e9150, 0, 0, 16, 16, 40, 0), + M( 0x114c, 0x30e9150, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x114f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1150, 0, 0, 16, 16, 40, 0), + M( 0x114d, 0x1151, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x309914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x309914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3099150, 0, 0, 16, 16, 40, 0), + M( 0x114d, 0x3099151, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x310914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x310914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109150, 0, 0, 16, 16, 40, 0), + M( 0x114d, 0x3109151, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e914e, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e914f, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x30e9150, 0, 0, 16, 16, 40, 0), + M( 0x114d, 0x30e9151, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1155, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x1155, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9155, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x30b9155, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9155, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x30e9155, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3159153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3159154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3159155, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x3159155, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11de, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x11de, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b91de, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x30b91de, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e91de, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x30e91de, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3159153, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3159154, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31591de, 0, 0, 16, 16, 60, 0), + M( 0x1152, 0x31591de, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1159, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x1159, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9159, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x30e9159, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3109157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3109158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3109159, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x3109159, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9159, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x30a9159, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11df, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x11df, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e9158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30e91df, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x30e91df, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3109157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3109158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31091df, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x31091df, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9157, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9158, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a91df, 0, 0, 16, 16, 60, 0), + M( 0x1156, 0x30a91df, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x115b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x115c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x115d, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x115d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b915d, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x30b915d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x313915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x313915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x313915d, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x313915d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x314915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x314915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x314915d, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x314915d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x115b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x115c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11e0, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x11e0, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b91e0, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x30b91e0, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x313915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x313915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31391e0, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x31391e0, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x314915b, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x314915c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31491e0, 0, 0, 16, 16, 60, 0), + M( 0x115a, 0x31491e0, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1160, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1161, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0x115e, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1160, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1161, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0x115e, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1166, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1167, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0x1164, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1166, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1167, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0x1164, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1160, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1161, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0x115f, 0x1163, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1160, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1161, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1162, 0, 0, 16, 16, 20, 0), + M( 0x115f, 0x1163, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1166, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1167, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0x1165, 0x1169, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1166, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1167, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x1168, 0, 0, 16, 16, 20, 0), + M( 0x1165, 0x1169, 0, 0, 16, 16, 20, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x116d, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116b, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x116c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116a, 0x11e2, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x1171, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116f, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1170, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0x116e, 0x11e3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1175, 0, 0, 16, 16, 40, 0), + M( 0x1172, 0x1175, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149175, 0, 0, 16, 16, 40, 0), + M( 0x1172, 0x3149175, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109175, 0, 0, 16, 16, 40, 0), + M( 0x1172, 0x3109175, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159175, 0, 0, 16, 16, 40, 0), + M( 0x1172, 0x3159175, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1175, 0, 0, 16, 16, 40, 0), + M( 0x11e4, 0x11e5, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3149175, 0, 0, 16, 16, 40, 0), + M( 0x11e4, 0x31491e5, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3109175, 0, 0, 16, 16, 40, 0), + M( 0x11e4, 0x31091e5, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159173, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159174, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x3159175, 0, 0, 16, 16, 40, 0), + M( 0x11e4, 0x31591e5, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c9176, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x31c91e6, 0, 0, 16, 16, 60, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117b, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117c, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0x1177, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1179, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e7, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0x1178, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117a, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11e8, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x117d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117f, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x117f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117f, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x117f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c917d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c917e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c917f, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x31c917f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d917d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d917e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d917f, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x31d917f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x11e1, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x11e1, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x117e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x11e1, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x11e1, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c917d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c917e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31c91e1, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x31c91e3, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d917d, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d917e, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x31d91e1, 0, 0, 16, 16, 50, 0), + M( 0x58c, 0x31d91e1, 0, 0, 16, 16, 50, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x30e9182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x30e9182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x30e9184, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3139182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3139182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3139184, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3149182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3149182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3149184, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3159182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3159182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3159184, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x30e9182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x30e9182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x30e91e9, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3139182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3139182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x31391e9, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3149182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3149182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x31491e9, 0, 0, 16, 16, 60, 0), + M( 0x1180, 0x1181, 0, 0, 16, 16, 10, 0), + M( 0x1183, 0x3159182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x3159182, 0, 0, 16, 16, 60, 0), + M( 0x1183, 0x31591e9, 0, 0, 16, 16, 60, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x118b, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x118b, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x118b, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x118b, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118c, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118c, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118c, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118c, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x11ea, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x11ea, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x11ea, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1187, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x1189, 0, 0, 16, 16, 10, 0), + M( 0x1185, 0x11ea, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x11eb, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x11eb, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x11eb, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x1188, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x118a, 0, 0, 16, 16, 10, 0), + M( 0x1186, 0x11eb, 0, 0, 16, 16, 10, 0), + M( 0xf54, 0x11ec, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ee, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ec, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ee, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ec, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ee, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ec, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ed, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ee, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ef, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f1, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ef, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f1, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ef, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f1, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ef, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f1, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f2, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f4, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f2, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f4, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f2, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f4, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f2, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f3, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11f4, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f5, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f5, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f5, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f6, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f6, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f6, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f7, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f7, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f7, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f8, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f8, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f8, 0, 0, 16, 16, 20, 0), + M( 0xf54, 0x11f9, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fb, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11f9, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fb, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11f9, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fb, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11f9, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fa, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x11fb, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x0, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fc, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fd, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ff, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fd, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ff, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fd, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ff, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fd, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11fe, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x11ff, 0, 0, 16, 16, 40, 0), + M( 0xf54, 0x1200, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1202, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099200, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099202, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9200, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9202, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9200, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9201, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9202, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1203, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1205, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099203, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x3099205, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9203, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30a9205, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9203, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9204, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x30b9205, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x1206, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120a, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1206, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120a, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1206, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120a, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1206, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1208, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120a, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1207, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120b, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1207, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120b, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1207, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120b, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1207, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x1209, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120b, 0, 0, 16, 16, 80, 0), + M( 0xf54, 0x120c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120e, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120e, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120e, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120c, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120d, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120e, 0, 0, 16, 16, 60, 0), + M( 0xf54, 0x120f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1211, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x120f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1211, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x120f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1211, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x120f, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1210, 0, 0, 16, 16, 50, 0), + M( 0xf54, 0x1211, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1213, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1214, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1214, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1215, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9213, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9214, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9214, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9215, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099213, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099214, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099214, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099215, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089213, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089214, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089214, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089215, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1216, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1218, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1216, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1218, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1216, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1218, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1216, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1217, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1218, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1219, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1219, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1219, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1219, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121d, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x121e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x121f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1220, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1220, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1221, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x309921f, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099220, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099220, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099221, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x311921f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3119220, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3119220, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3119221, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x310921f, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3109220, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3109220, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3109221, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1222, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1223, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1223, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1224, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099222, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099223, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099223, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3099224, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109222, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109223, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109223, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109224, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089222, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089223, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089223, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089224, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1225, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1226, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1226, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1227, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3099225, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3099226, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3099226, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3099227, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9225, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9226, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9226, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x30b9227, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089225, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089226, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089226, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x3089227, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1228, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1228, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1228, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1228, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1229, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122b, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x122f, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1230, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1230, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1230, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x122e, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1230, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1231, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1233, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1231, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1233, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1231, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1233, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1231, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1232, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1233, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1234, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1236, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1234, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1236, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1234, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1236, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1234, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1235, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1236, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1237, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1239, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1237, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1239, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1237, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1239, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1237, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1238, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x1239, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123c, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123a, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123b, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x123c, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123f, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123d, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123e, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x123f, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1240, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1242, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1240, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1242, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1240, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1242, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1240, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1241, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1242, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3089256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x30b9256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109256, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x3109256, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1257, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1259, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1257, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1259, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1257, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1259, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1257, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1258, 0, 0, 16, 16, 50, 0), + M( 0x1243, 0x1259, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x0, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), + M( 0x1244, 0x125a, 0, 0, 16, 16, 50, 0), +}; +#undef M + + +static const StringID _town_tile_names[] = { + STR_200F_TALL_OFFICE_BLOCK, + STR_2010_OFFICE_BLOCK, + STR_2011_SMALL_BLOCK_OF_FLATS, + STR_2012_CHURCH, + STR_2013_LARGE_OFFICE_BLOCK, + STR_2013_LARGE_OFFICE_BLOCK, + STR_2014_TOWN_HOUSES, + STR_2015_HOTEL, + STR_2015_HOTEL, + STR_2016_STATUE, + STR_2017_FOUNTAIN, + STR_2018_PARK, + STR_2018_PARK, + STR_2019_OFFICE_BLOCK, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_201B_MODERN_OFFICE_BUILDING, + STR_201C_WAREHOUSE, + STR_201D_OFFICE_BLOCK, + STR_201E_STADIUM, + STR_201E_STADIUM, + STR_201E_STADIUM, + STR_201E_STADIUM, + STR_201F_OLD_HOUSES, + STR_2036_COTTAGES, + STR_2037_HOUSES, + STR_2038_FLATS, + STR_2039_TALL_OFFICE_BLOCK, + STR_203A_SHOPS_AND_OFFICES, + STR_203B_SHOPS_AND_OFFICES, + STR_203C_THEATER, + STR_203D_STADIUM, + STR_203D_STADIUM, + STR_203D_STADIUM, + STR_203D_STADIUM, + STR_203E_OFFICES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_2040_CINEMA, + STR_2041_SHOPPING_MALL, + STR_2041_SHOPPING_MALL, + STR_2041_SHOPPING_MALL, + STR_2041_SHOPPING_MALL, + STR_2038_FLATS, + STR_2038_FLATS, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_2012_CHURCH, + STR_2012_CHURCH, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_2015_HOTEL, + STR_2015_HOTEL, + STR_2015_HOTEL, + STR_2015_HOTEL, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_2038_FLATS, + STR_2012_CHURCH, + STR_203F_HOUSES, + STR_2038_FLATS, + STR_2038_FLATS, + STR_200F_TALL_OFFICE_BLOCK, + STR_200F_TALL_OFFICE_BLOCK, + STR_2038_FLATS, + STR_200F_TALL_OFFICE_BLOCK, + STR_2012_CHURCH, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_200F_TALL_OFFICE_BLOCK, + STR_203F_HOUSES, + STR_203F_HOUSES, + STR_200F_TALL_OFFICE_BLOCK, + STR_2059_IGLOO, + STR_205A_TEPEES, + STR_201A_SHOPS_AND_OFFICES, + STR_201A_SHOPS_AND_OFFICES, + STR_200F_TALL_OFFICE_BLOCK, + STR_2016_STATUE, + STR_205B_TEAPOT_HOUSE, + STR_205C_PIGGY_BANK, +}; + +static const uint16 _housetype_flags[110] = { + 0x1010, 0x1018, 0x100E, 0x100F, 0x7010, 0x0810, 0x100F, 0x1014, + 0x0000, 0x7018, 0x7010, 0x1004, 0x1008, 0x1018, 0x101C, 0x101C, + 0x101C, 0x7010, 0x1010, 0x1010, 0x100F, 0x0000, 0x0000, 0x0000, + 0x1003, 0x1001, 0x100F, 0x101C, 0x101C, 0x101C, 0x5014, 0x1018, + 0x700F, 0x0000, 0x0000, 0x0000, 0x7018, 0x2003, 0x0803, 0x101C, + 0x101E, 0x0000, 0x0000, 0x0000, 0x201C, 0x081C, 0x200F, 0x080F, + 0x2007, 0x0807, 0x6018, 0x0818, 0x2018, 0x0818, 0x6018, 0x0818, + 0x2001, 0x0801, 0x201E, 0x081E, 0x200F, 0x080F, 0x2007, 0x0807, + 0x201C, 0x081C, 0x201C, 0x0000, 0x081C, 0x0000, 0x601C, 0x081C, + 0x2018, 0x0818, 0x201C, 0x0000, 0x081C, 0x0000, 0x401E, 0x401E, + 0x401E, 0x4001, 0x401C, 0x400E, 0x401E, 0x401C, 0x401C, 0x4018, + 0x4000, 0x401C, 0x4018, 0x801F, 0x801F, 0x8003, 0x800F, 0x800F, + 0x800F, 0x800F, 0x801C, 0x801F, 0x0000, 0x801C, 0x8001, 0x8001, + 0x801C, 0x801C, 0x801C, 0x801C, 0x801F, 0x801F, +}; + +static const byte _housetype_extra_flags[110] = { + 0, 0, 0, 0,32,32, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 8, 0, 0, 0, + 0, 0, 4, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const byte _housetype_population[110] = { + 187, 85, 40, 5, 220, 220, 30, 140, + 0, 0, 0, 0, 0, 150, 95, 95, + 95, 130, 6, 110, 65, 0, 0, 0, + 15, 12, 13, 100, 170, 100, 180, 35, + 65, 0, 0, 0, 140, 15, 15, 35, + 180, 0, 0, 0, 80, 80, 16, 16, + 14, 14, 135, 135, 170, 170, 210, 210, + 10, 10, 25, 25, 6, 6, 17, 17, + 90, 90, 140, 0, 140, 0, 105, 105, + 190, 190, 250, 0, 250, 0, 16, 16, + 16, 7, 45, 8, 18, 90, 120, 250, + 0, 80, 180, 8, 18, 7, 15, 17, + 19, 21, 75, 35, 0, 85, 11, 10, + 67, 86, 95, 30, 25, 18, +}; + +static const byte _housetype_mailamount[110] = { + 70, 55, 20, 2, 85, 85, 12, 22, + 22, 0, 0, 0, 0, 65, 48, 48, + 48, 50, 10, 55, 5, 5, 5, 5, + 6, 7, 8, 35, 50, 40, 64, 23, + 5, 5, 5, 5, 65, 6, 6, 23, + 5, 5, 5, 5, 20, 20, 6, 6, + 6, 6, 60, 60, 70, 70, 80, 80, + 5, 5, 20, 20, 2, 2, 7, 7, + 45, 45, 25, 25, 25, 25, 50, 50, + 75, 75, 60, 60, 60, 60, 6, 6, + 5, 4, 15, 3, 7, 24, 25, 80, + 80, 23, 90, 3, 5, 3, 6, 6, + 6, 6, 20, 9, 0, 18, 3, 3, + 22, 23, 28, 10, 8, 7, +}; + + +static const byte _housetype_remove_cost[110] = { + 150, 140, 100, 90, 160, 160, 80, 180, + 180, 65, 65, 60, 60, 130, 110, 105, + 107, 200, 145, 155, 250, 250, 250, 250, + 70, 75, 71, 135, 145, 132, 155, 220, + 250, 250, 250, 250, 170, 70, 70, 210, + 250, 250, 250, 250, 100, 100, 70, 70, + 80, 80, 150, 150, 170, 170, 200, 200, + 60, 60, 100, 100, 85, 85, 80, 80, + 140, 140, 160, 160, 160, 160, 130, 130, + 190, 190, 140, 140, 140, 140, 80, 80, + 80, 30, 130, 90, 80, 110, 120, 190, + 190, 110, 180, 90, 90, 70, 80, 80, + 80, 80, 160, 90, 90, 150, 60, 60, + 140, 145, 165, 90, 75, 85, +}; + +static const uint16 _housetype_remove_ratingmod[110] = { + 140, 130, 90, 230, 160, 160, 80, 150, + 150, 40, 40, 75, 75, 110, 100, 100, + 100, 150, 110, 110, 300, 300, 300, 300, + 75, 75, 75, 100, 170, 135, 180, 230, + 300, 300, 300, 300, 250, 75, 75, 230, + 300, 300, 300, 300, 90, 90, 70, 70, + 70, 70, 120, 120, 130, 130, 140, 140, + 60, 60, 80, 80, 230, 230, 80, 80, + 110, 110, 160, 160, 160, 160, 105, 105, + 135, 135, 200, 200, 200, 200, 80, 80, + 80, 30, 95, 200, 80, 95, 95, 140, + 140, 95, 150, 200, 90, 50, 75, 75, + 75, 75, 130, 80, 80, 130, 45, 45, + 130, 130, 130, 70, 65, 95, +}; + + +typedef struct { + byte min,max; +} HousetypeYear; + +static const HousetypeYear _housetype_years[110] = { + {43, 255}, + {37, 255}, + {48, 255}, + {0, 255}, + {55, 255}, + {55, 255}, + {0, 255}, + {39, 255}, + {39, 255}, + {25, 255}, + {25, 255}, + {0, 255}, + {15, 255}, + {31, 255}, + {10, 40}, + {10, 40}, + {10, 40}, + {57, 255}, + {63, 255}, + {65, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 31}, + {0, 32}, + {11, 255}, + {15, 255}, + {43, 255}, + {0, 35}, + {53, 255}, + {0, 255}, + {38, 255}, + {38, 255}, + {38, 255}, + {38, 255}, + {80, 255}, + {0, 40}, + {0, 40}, + {25, 255}, + {63, 255}, + {63, 255}, + {63, 255}, + {63, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 43}, + {0, 43}, + {46, 255}, + {46, 255}, + {50, 255}, + {50, 255}, + {54, 255}, + {54, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 40}, + {0, 40}, + {52, 255}, + {52, 255}, + {52, 255}, + {52, 255}, + {43, 255}, + {43, 255}, + {58, 255}, + {58, 255}, + {47, 255}, + {47, 255}, + {47, 255}, + {47, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {53, 255}, + {42, 255}, + {64, 255}, + {64, 255}, + {0, 255}, + {73, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, + {0, 255}, +}; + +static const byte _housetype_cargo_passengers[110] = { + 8, 8, 8, 2, 10,10,4, 6, + 6, 2, 2, 2, 2, 8, 6, 6, + 6, 10,6, 6, 4, 4, 4, 4, + 3, 3, 3, 7, 8, 6, 8, 8, + 4, 4, 4, 4, 8, 3, 3, 8, + 8, 8, 8, 8, 5, 5, 3, 3, + 3, 3, 8, 8, 9, 9,10, 10, + 2, 2, 3, 3, 2, 2, 3, 3, + 6, 6, 6, 6, 6, 6, 7, 7, + 9, 9, 7, 7, 7, 7, 3, 3, + 3, 3, 6, 2, 3, 6, 6, 8, + 8, 6, 8, 2, 6, 3, 3, 3, + 3, 3, 8, 4, 4, 8, 3, 3, + 8, 8, 8, 4, 3, 3, +}; + +static const byte _housetype_cargo_mail[110] = { + 3, 3, 3, 0, 4, 4, 1, 1, + 1, 0, 0, 0, 0, 2, 2, 2, + 2, 3, 3, 2, 0, 0, 0, 0, + 1, 1, 1, 2, 3, 2, 3, 2, + 0, 0, 0, 0, 3, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 0, 0, 1, 1, + 2, 2, 1, 1, 1, 1, 2, 2, + 3, 3, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 0, 1, 2, 2, 3, + 3, 2, 3, 0, 2, 1, 1, 1, + 1, 1, 4, 1, 1, 4, 1, 1, + 4, 4, 4, 1, 1, 2, +}; + +static const int8 _housetype_cargo_goods[110] = { + 4, 4, 1, 0, 6, 6, 0, 2, + 2, 0, 0, 0, 0, 4, 3, 3, + 3, 6, 8, 6, 0, 0, 0, 0, + 0, 0, 0, 2, 3, 3, 3, 2, + 0, 0, 0, 0, 2,-1,-1, 2, + 3, 3, 3, 3,-2,-2,-2,-2, + -2,-2, 4, 4, 4, 4, 5, 5, + -1,-1,-1,-1, 0, 0,-1,-1, + 3, 3,-3, 2,-3, 2, 3, 3, + 4, 4, 2, 2, 2, 2,-2,-2, + -2,-1, 1, 0,-2, 1, 1, 4, + 4, 1, 4, 0, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, + -4,-4, 2, 2, 2,-4, +}; + +static const byte _house_more_flags[110] = { + 8, 8, 8, 8, 8, 8, 8, 12, + 0, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 15, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, + 15, 0, 0, 0, 8, 8, 8, 8, + 15, 0, 0, 0, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 12, 0, 12, 0, 8, 8, + 8, 8, 10, 0, 10, 0, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 10, + 0, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 12, 0, 8, 8, 8, + 8, 8, 8, 8, 8, 8, +}; + diff --git a/table/track_land.h b/table/track_land.h new file mode 100644 --- /dev/null +++ b/table/track_land.h @@ -0,0 +1,61 @@ +#define TILE_SEQ_BEGIN(x) ADD_WORD(x), +#define TILE_SEQ_LINE(a,b,c,d,e) ADD_WORD(a), b,c,d,e, +#define TILE_SEQ_END() 0,0,0,0 + +static const byte _track_depot_layout_table_0[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE(0x842B, 2, 13, 13, 1) + TILE_SEQ_END() +}; + +static const byte _track_depot_layout_table_1[] = { + TILE_SEQ_BEGIN(0x83F3) + TILE_SEQ_LINE(0x8427, 2, 2, 1, 13) + TILE_SEQ_LINE(0x8428, 13, 2, 1, 13) + TILE_SEQ_END() +}; + +static const byte _track_depot_layout_table_2[] = { + TILE_SEQ_BEGIN(0x83F4) + TILE_SEQ_LINE(0x8429, 2, 2, 13, 1) + TILE_SEQ_LINE(0x842A, 2, 13, 13, 1) + TILE_SEQ_END() +}; + +static const byte _track_depot_layout_table_3[] = { + TILE_SEQ_BEGIN(0xF8D) + TILE_SEQ_LINE(0x842C, 13, 2, 1, 13) + TILE_SEQ_END() +}; + +static const byte _track_checkpoint_table_0[] = { + TILE_SEQ_BEGIN(0x83F4) + TILE_SEQ_LINE(0x8431, 0, 0, 16, 5) + TILE_SEQ_LINE(0x8430, 0, 11, 16, 5) + TILE_SEQ_END() +}; + +static const byte _track_checkpoint_table_1[] = { + TILE_SEQ_BEGIN(0x83F3) + TILE_SEQ_LINE(0x8432, 0, 0, 5, 16) + TILE_SEQ_LINE(0x842D, 11, 0, 5, 16) + TILE_SEQ_END() +}; + + +static const byte * const _track_depot_layout_table[6] = { + _track_depot_layout_table_0, + _track_depot_layout_table_1, + _track_depot_layout_table_2, + _track_depot_layout_table_3, + + _track_checkpoint_table_0, + _track_checkpoint_table_1, +}; + +const byte _track_sloped_sprites[14] = { + 14, 15, 22, 13, + 0, 21, 17, 12, + 23, 0, 18, 20, + 19, 16 +}; diff --git a/table/train_cmd.h b/table/train_cmd.h new file mode 100644 --- /dev/null +++ b/table/train_cmd.h @@ -0,0 +1,55 @@ +static const SpriteID _engine_sprite_base[] = { +0x0B59, 0x0B61, 0x0B69, 0x0BE1, 0x0B71, 0x0B75, 0x0B7D, 0x0B7D, +0x0B85, 0x0B85, 0x0B8D, 0x0B8D, 0x0BC9, 0x0BD1, 0x0BD9, 0x0BE9, +0x0BED, 0x0BED, 0x0BF5, 0x0BF9, 0x0B79, 0x0B9D, 0x0B9D, 0x0B95, +0x0B95, 0x0BA5, 0x0BA9, 0x0BA9, 0x0BC1, 0x0BC5, 0x0BB1, 0x0BB9, +0x0BB9, 0x0AAD, 0x0AB1, 0x0AB5, 0x0AB9, 0x0ABD, 0x0AC1, 0x0AC9, +0x0ACD, 0x0AD5, 0x0AD1, 0x0AD9, 0x0AC5, 0x0AD1, 0x0AD5, 0x0AF9, +0x0AFD, 0x0B05, 0x0AB9, 0x0AC1, 0x0AC9, 0x0AD1, 0x0AD9, 0x0AE1, +0x0AE5, 0x0AE9, 0x0AF1, 0x0AF9, 0x0B0D, 0x0B11, 0x0B15, 0x0B19, +0x0B1D, 0x0B21, 0x0B29, 0x0B2D, 0x0B35, 0x0B31, 0x0B39, 0x0B25, +0x0B31, 0x0B35, +}; + +/* For how many directions do we have sprites? (8 or 4; if 4, the other 4 + * directions are symmetric. */ +static const byte _engine_sprite_and[] = { +7, 7, 7, 7, 3, 3, 7, 7, +7, 7, 7, 7, 7, 7, 7, 3, +7, 7, 3, 7, 3, 7, 7, 7, +7, 3, 7, 7, 3, 3, 7, 7, +7, 3, 3, 3, 3, 3, 3, 3, +3, 3, 3, 3, 3, 3, 3, 3, +3, 3, 3, 3, 3, 3, 3, 3, +3, 3, 3, 3, 3, 3, 3, 3, +3, 3, 3, 3, 3, 3, 3, 3, +3, 3, +}; + +/* Non-zero for multihead trains. */ +static const byte _engine_sprite_add[] = { +0, 0, 0, 0, 0, 0, 0, 4, +0, 4, 0, 4, 0, 0, 0, 0, +0, 4, 0, 0, 0, 0, 4, 0, +4, 0, 0, 4, 0, 0, 0, 0, +4, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, +0, 0, +}; + + +static const byte _wagon_full_adder[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 44, 0, 0, 0, 0, 24, + 24, 24, 24, 0, 0, 32, 32, 0, + 4, 4, 4, 4, 4, 4, 4, 0, + 0, 4, 4, 4, 0, 44, 0, 0, + 0, 0, 24, 24, 24, 24, 0, 0, + 32, 32 +}; diff --git a/table/tree_land.h b/table/tree_land.h new file mode 100644 --- /dev/null +++ b/table/tree_land.h @@ -0,0 +1,213 @@ +static const SpriteID _tree_sprites_1[4] = { + 0x118D, + 0x11A0, + 0x11B3, + 0x11C6, +}; + +static const byte _tree_layout_xy[4][8] = { +{9, 3, 1, 8, 0, 0, 8, 9}, +{4, 4, 9, 1, 6, 9, 0, 9}, +{9, 1, 0, 9, 6, 6, 3, 0}, +{3, 9, 8, 2, 9, 9, 1, 5}, +}; + +static const PalSpriteID _tree_layout_sprite[164+(79-48+1)][4] = { + { 0x652, 0x659, 0x660, 0x667}, /* 0 */ + { 0x652, 0x667, 0x66e, 0x675}, /* 1 */ + { 0x652, 0x66e, 0x659, 0x675}, /* 2 */ + { 0x652, 0x652, 0x660, 0x66e}, /* 3 */ + { 0x660, 0x667, 0x659, 0x652}, /* 4 */ + { 0x660, 0x675, 0x660, 0x660}, /* 5 */ + { 0x660, 0x652, 0x652, 0x66e}, /* 6 */ + { 0x660, 0x675, 0x667, 0x659}, /* 7 */ + { 0x675, 0x660, 0x675, 0x675}, /* 8 */ + { 0x675, 0x659, 0x652, 0x652}, /* 9 */ + { 0x675, 0x66e, 0x652, 0x652}, /* 10 */ + { 0x675, 0x667, 0x659, 0x667}, /* 11 */ + { 0x628, 0x652, 0x660, 0x62f}, /* 12 */ + { 0x628, 0x636, 0x675, 0x644}, /* 13 */ + { 0x628, 0x652, 0x63d, 0x66e}, /* 14 */ + { 0x628, 0x667, 0x644, 0x652}, /* 15 */ + { 0x644, 0x659, 0x660, 0x628}, /* 16 */ + { 0x644, 0x64b, 0x659, 0x636}, /* 17 */ + { 0x644, 0x675, 0x652, 0x63d}, /* 18 */ + { 0x644, 0x63d, 0x66e, 0x652}, /* 19 */ + { 0x636, 0x636, 0x628, 0x636}, /* 20 */ + { 0x636, 0x63d, 0x636, 0x636}, /* 21 */ + { 0x636, 0x64b, 0x636, 0x636}, /* 22 */ + { 0x636, 0x636, 0x636, 0x636}, /* 23 */ + { 0x64b, 0x628, 0x62f, 0x636}, /* 24 */ + { 0x64b, 0x63d, 0x644, 0x636}, /* 25 */ + { 0x64b, 0x636, 0x63d, 0x628}, /* 26 */ + { 0x64b, 0x64b, 0x636, 0x63d}, /* 27 */ + { 0x62f, 0x644, 0x644, 0x636}, /* 28 */ + { 0x62f, 0x62f, 0x636, 0x628}, /* 29 */ + { 0x62f, 0x64b, 0x636, 0x636}, /* 30 */ + { 0x62f, 0x636, 0x62f, 0x636}, /* 31 */ + { 0x67c, 0x675, 0x683, 0x67c}, /* 32 */ + { 0x67c, 0x69f, 0x67c, 0x659}, /* 33 */ + { 0x67c, 0x67c, 0x67c, 0x6a6}, /* 34 */ + { 0x67c, 0x691, 0x66e, 0x68a}, /* 35 */ + { 0x68a, 0x68a, 0x698, 0x68a}, /* 36 */ + { 0x68a, 0x698, 0x683, 0x68a}, /* 37 */ + { 0x68a, 0x67c, 0x691, 0x68a}, /* 38 */ + { 0x68a, 0x683, 0x6a6, 0x69f}, /* 39 */ + { 0x698, 0x68a, 0x698, 0x652}, /* 40 */ + { 0x698, 0x698, 0x660, 0x667}, /* 41 */ + { 0x698, 0x67c, 0x6a6, 0x698}, /* 42 */ + { 0x698, 0x698, 0x698, 0x691}, /* 43 */ + { 0x6a6, 0x6a6, 0x67c, 0x660}, /* 44 */ + { 0x6a6, 0x69f, 0x6a6, 0x652}, /* 45 */ + { 0x6a6, 0x67c, 0x6a6, 0x691}, /* 46 */ + { 0x6a6, 0x691, 0x69f, 0x6a6}, /* 47 */ + { 0x6ad, 0x6ad, 0x6ad, 0x6ad}, /* 48 */ + { 0x6ad, 0x6ad, 0x6c2, 0x6d0}, /* 49 */ + { 0x6ad, 0x6d7, 0x6ad, 0x6ad}, /* 50 */ + { 0x6ad, 0x6d0, 0x6c9, 0x6ad}, /* 51 */ + { 0x6d0, 0x6d0, 0x6d0, 0x6ad}, /* 52 */ + { 0x6d0, 0x6ad, 0x6d7, 0x6c9}, /* 53 */ + { 0x6d0, 0x6d7, 0x6d0, 0x6c2}, /* 54 */ + { 0x6d0, 0x6d0, 0x6d0, 0x6ad}, /* 55 */ + { 0x6d7, 0x6d7, 0x6d7, 0x6d7}, /* 56 */ + { 0x6d7, 0x6d7, 0x6ad, 0x6ad}, /* 57 */ + { 0x6d7, 0x6d0, 0x6d7, 0x6ad}, /* 58 */ + { 0x6d7, 0x6d7, 0x6d0, 0x6ad}, /* 59 */ + { 0x6c2, 0x6d0, 0x6c9, 0x6c2}, /* 60 */ + { 0x6c2, 0x6c9, 0x6c2, 0x6ad}, /* 61 */ + { 0x6c2, 0x6c2, 0x6c2, 0x6ad}, /* 62 */ + { 0x6c2, 0x6c2, 0x6c2, 0x6c9}, /* 63 */ + { 0x6c9, 0x6d0, 0x6b4, 0x6c2}, /* 64 */ + { 0x6c9, 0x6bb, 0x6de, 0x6d7}, /* 65 */ + { 0x6c9, 0x6c2, 0x6bb, 0x6b4}, /* 66 */ + { 0x6c9, 0x6bb, 0x6c2, 0x6de}, /* 67 */ + { 0x6b4, 0x6b4, 0x6de, 0x6c9}, /* 68 */ + { 0x6b4, 0x6bb, 0x6bb, 0x6ad}, /* 69 */ + { 0x6b4, 0x6de, 0x6bb, 0x6b4}, /* 70 */ + { 0x6b4, 0x6ad, 0x6c2, 0x6de}, /* 71 */ + { 0x6bb, 0x6d0, 0x6de, 0x6c2}, /* 72 */ + { 0x6bb, 0x6b4, 0x6bb, 0x6d7}, /* 73 */ + { 0x6bb, 0x6de, 0x6bb, 0x6b4}, /* 74 */ + { 0x6bb, 0x6c9, 0x6c2, 0x6de}, /* 75 */ + { 0x6de, 0x6d7, 0x6de, 0x6c2}, /* 76 */ + { 0x6de, 0x6bb, 0x6de, 0x6d0}, /* 77 */ + { 0x6de, 0x6de, 0x6bb, 0x6b4}, /* 78 */ + { 0x6de, 0x6c9, 0x6c2, 0x6de}, /* 79 */ + { 0x72b, 0x732, 0x72b, 0x739}, /* 80 */ + { 0x72b, 0x747, 0x755, 0x72b}, /* 81 */ + { 0x72b, 0x72b, 0x76a, 0x786}, /* 82 */ + { 0x72b, 0x74e, 0x72b, 0x72b}, /* 83 */ + { 0x732, 0x732, 0x72b, 0x739}, /* 84 */ + { 0x732, 0x747, 0x732, 0x732}, /* 85 */ + { 0x732, 0x732, 0x755, 0x794}, /* 86 */ + { 0x732, 0x74e, 0x732, 0x78d}, /* 87 */ + { 0x747, 0x732, 0x747, 0x740}, /* 88 */ + { 0x747, 0x747, 0x732, 0x76a}, /* 89 */ + { 0x747, 0x72b, 0x755, 0x747}, /* 90 */ + { 0x747, 0x786, 0x732, 0x747}, /* 91 */ + { 0x74e, 0x74e, 0x72b, 0x794}, /* 92 */ + { 0x74e, 0x755, 0x732, 0x74e}, /* 93 */ + { 0x74e, 0x72b, 0x786, 0x747}, /* 94 */ + { 0x74e, 0x74e, 0x732, 0x794}, /* 95 */ + { 0x76a, 0x76a, 0x74e, 0x74e}, /* 96 */ + { 0x76a, 0x794, 0x732, 0x76a}, /* 97 */ + { 0x76a, 0x732, 0x786, 0x76a}, /* 98 */ + { 0x76a, 0x786, 0x732, 0x78d}, /* 99 */ + { 0x78d, 0x78d, 0x74e, 0x794}, /* 100 */ + { 0x78d, 0x732, 0x739, 0x747}, /* 101 */ + { 0x78d, 0x732, 0x786, 0x76a}, /* 102 */ + { 0x78d, 0x786, 0x78d, 0x794}, /* 103 */ + { 0x786, 0x786, 0x740, 0x732}, /* 104 */ + { 0x786, 0x786, 0x72b, 0x732}, /* 105 */ + { 0x786, 0x732, 0x786, 0x786}, /* 106 */ + { 0x786, 0x786, 0x78d, 0x794}, /* 107 */ + { 0x778, 0x778, 0x77f, 0x778}, /* 108 */ + { 0x778, 0x77f, 0x778, 0x77f}, /* 109 */ + { 0x778, 0x77f, 0x77f, 0x778}, /* 110 */ + { 0x778, 0x778, 0x778, 0x77f}, /* 111 */ + { 0x75c, 0x71d, 0x75c, 0x724}, /* 112 */ + { 0x75c, 0x72b, 0x75c, 0x763}, /* 113 */ + { 0x75c, 0x75c, 0x771, 0x71d}, /* 114 */ + { 0x75c, 0x771, 0x75c, 0x75c}, /* 115 */ + { 0x771, 0x771, 0x75c, 0x71d}, /* 116 */ + { 0x771, 0x747, 0x75c, 0x771}, /* 117 */ + { 0x771, 0x75c, 0x771, 0x724}, /* 118 */ + { 0x771, 0x771, 0x75c, 0x763}, /* 119 */ + { 0x71d, 0x71d, 0x771, 0x724}, /* 120 */ + { 0x71d, 0x74e, 0x763, 0x71d}, /* 121 */ + { 0x71d, 0x724, 0x794, 0x71d}, /* 122 */ + { 0x71d, 0x71d, 0x75c, 0x78d}, /* 123 */ + { 0x794, 0x724, 0x75c, 0x794}, /* 124 */ + { 0x794, 0x794, 0x75c, 0x71d}, /* 125 */ + { 0x794, 0x724, 0x794, 0x71d}, /* 126 */ + { 0x794, 0x794, 0x771, 0x78d}, /* 127 */ + { 0x30b879b, 0x308879b, 0x311879b, 0x312879b}, /* 128 */ + { 0x79b, 0x315879b, 0x30d879b, 0x316879b}, /* 129 */ + { 0x30d879b, 0x313879b, 0x309879b, 0x79b}, /* 130 */ + { 0x30a879b, 0x30b879b, 0x310879b, 0x30b879b}, /* 131 */ + { 0x7a2, 0x30b87a2, 0x30987a2, 0x31287a2}, /* 132 */ + { 0x31187a2, 0x30d87a2, 0x30987a2, 0x31587a2}, /* 133 */ + { 0x30b87a2, 0x30887a2, 0x30a87a2, 0x31687a2}, /* 134 */ + { 0x31387a2, 0x31187a2, 0x31087a2, 0x31487a2}, /* 135 */ + { 0x30b87a9, 0x7a9, 0x31387a9, 0x31587a9}, /* 136 */ + { 0x31387a9, 0x30d87a9, 0x30887a9, 0x31187a9}, /* 137 */ + { 0x30987a9, 0x30b87a9, 0x30d87a9, 0x31487a9}, /* 138 */ + { 0x30d87a9, 0x7a9, 0x30b87a9, 0x31087a9}, /* 139 */ + { 0x7b0, 0x7b0, 0x7b0, 0x7b0}, /* 140 */ + { 0x7b0, 0x7b0, 0x7b0, 0x7b0}, /* 141 */ + { 0x7b0, 0x7b0, 0x7b0, 0x7b0}, /* 142 */ + { 0x7b0, 0x7b0, 0x7b0, 0x7b0}, /* 143 */ + { 0x30987b7, 0x30b87b7, 0x31387b7, 0x31187b7}, /* 144 */ + { 0x30b87b7, 0x7b7, 0x31587b7, 0x31087b7}, /* 145 */ + { 0x30d87b7, 0x31487b7, 0x30987b7, 0x30b87b7}, /* 146 */ + { 0x7b7, 0x30887b7, 0x31387b7, 0x30b87b7}, /* 147 */ + { 0x30b87be, 0x30987be, 0x30d87be, 0x7be}, /* 148 */ + { 0x30d87be, 0x31487be, 0x31287be, 0x31587be}, /* 149 */ + { 0x31187be, 0x31087be, 0x31387be, 0x30b87be}, /* 150 */ + { 0x7be, 0x30b87be, 0x30887be, 0x30987be}, /* 151 */ + { 0x30a87c5, 0x30b87c5, 0x31687c5, 0x31087c5}, /* 152 */ + { 0x30b87c5, 0x30887c5, 0x31487c5, 0x30a87c5}, /* 153 */ + { 0x7c5, 0x31287c5, 0x30d87c5, 0x30a87c5}, /* 154 */ + { 0x30987c5, 0x31087c5, 0x7c5, 0x31587c5}, /* 155 */ + { 0x30a87cc, 0x31587cc, 0x31287cc, 0x31487cc}, /* 156 */ + { 0x30d87cc, 0x7cc, 0x31087cc, 0x31687cc}, /* 157 */ + { 0x30b87cc, 0x30887cc, 0x31187cc, 0x30b87cc}, /* 158 */ + { 0x30987cc, 0x31387cc, 0x30d87cc, 0x30a87cc}, /* 159 */ + { 0x30b87d3, 0x30987d3, 0x31487d3, 0x31687d3}, /* 160 */ + { 0x30d87d3, 0x31387d3, 0x31587d3, 0x31187d3}, /* 161 */ + { 0x30a87d3, 0x30887d3, 0x7d3, 0x31087d3}, /* 162 */ + { 0x31587d3, 0x30b87d3, 0x31687d3, 0x7d3}, /* 163 */ + /* the extra things follow */ + { 0x6e5, 0x6e5, 0x6e5, 0x6e5}, /* 0 */ + { 0x6e5, 0x6e5, 0x6fa, 0x708}, /* 1 */ + { 0x6e5, 0x70f, 0x6e5, 0x6e5}, /* 2 */ + { 0x6e5, 0x708, 0x701, 0x6e5}, /* 3 */ + { 0x708, 0x708, 0x708, 0x6e5}, /* 4 */ + { 0x708, 0x6e5, 0x70f, 0x701}, /* 5 */ + { 0x708, 0x70f, 0x708, 0x6fa}, /* 6 */ + { 0x708, 0x708, 0x708, 0x6e5}, /* 7 */ + { 0x70f, 0x70f, 0x70f, 0x70f}, /* 8 */ + { 0x70f, 0x70f, 0x6e5, 0x6e5}, /* 9 */ + { 0x70f, 0x708, 0x70f, 0x6e5}, /* 10 */ + { 0x70f, 0x70f, 0x708, 0x6e5}, /* 11 */ + { 0x6fa, 0x708, 0x701, 0x6fa}, /* 12 */ + { 0x6fa, 0x701, 0x6fa, 0x6e5}, /* 13 */ + { 0x6fa, 0x6fa, 0x6fa, 0x6e5}, /* 14 */ + { 0x6fa, 0x6fa, 0x6fa, 0x701}, /* 15 */ + { 0x701, 0x708, 0x6ec, 0x6fa}, /* 16 */ + { 0x701, 0x6f3, 0x716, 0x70f}, /* 17 */ + { 0x701, 0x6fa, 0x6f3, 0x6ec}, /* 18 */ + { 0x701, 0x6f3, 0x6fa, 0x716}, /* 19 */ + { 0x6ec, 0x6ec, 0x716, 0x701}, /* 20 */ + { 0x6ec, 0x6f3, 0x6f3, 0x6e5}, /* 21 */ + { 0x6ec, 0x716, 0x6f3, 0x6ec}, /* 22 */ + { 0x6ec, 0x6e5, 0x6fa, 0x716}, /* 23 */ + { 0x6f3, 0x708, 0x716, 0x6fa}, /* 24 */ + { 0x6f3, 0x6ec, 0x6f3, 0x70f}, /* 25 */ + { 0x6f3, 0x716, 0x6f3, 0x6ec}, /* 26 */ + { 0x6f3, 0x701, 0x6fa, 0x716}, /* 27 */ + { 0x716, 0x70f, 0x716, 0x6fa}, /* 28 */ + { 0x716, 0x6f3, 0x716, 0x708}, /* 29 */ + { 0x716, 0x716, 0x6f3, 0x6ec}, /* 30 */ + { 0x716, 0x701, 0x6fa, 0x716}, /* 31 */ +}; diff --git a/table/tunnel_land.h b/table/tunnel_land.h new file mode 100644 --- /dev/null +++ b/table/tunnel_land.h @@ -0,0 +1,755 @@ +static const SpriteID _draw_tunnel_table_1[] = { + 0x93D, 0x955, +}; + +static const SpriteID _bridge_land_below[] = { + 0xF8D, 0xFDD,0x11C6, 0xFDD, +}; + +static const SpriteID _bridge_transp_below[] = { + 0x3F3, 0x3F4, 0xF8D, 0xF8D, // without ice + 0x40D, 0x40E, 0x11C6, 0x11C6, // with ice +}; + +static const SpriteID _bridge_transp_overlay[] = { + 0, 0, 0x534, 0x535, // without ice + 0, 0, 0x547, 0x548, // with ice +}; + +static const PalSpriteID _bridge_sprite_table_2_0[] = { + 0x9C3, 0x9C7, 0x9C9, 0x0, 0x9C4, 0x9C8, 0x9CA, 0x0, + 0x9C5, 0x9C7, 0x9C9, 0x0, 0x9C6, 0x9C8, 0x9CA, 0x0, + 0x10E4, 0x9C7, 0x9C9, 0x0, 0x10E5, 0x9C8, 0x9CA, 0x0, + 0x110C, 0x9C7, 0x9C9, 0x0, 0x110D, 0x9C8, 0x9CA, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_2_1[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x31D898E, 0x31D8990, 0x31D898D, 0x31D898F, 0x31D8992, 0x31D8994, 0x31D8991, 0x31D8993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_2_poles[] = { + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 38 + 6*3, + 0x0, + + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 35 + 6*3, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_0[] = { + 0x9A9, 0x99F, 0x9B1, 0x0, 0x9A5, 0x997, 0x9AD, 0x0, + 0x99D, 0x99F, 0x9B1, 0x0, 0x995, 0x997, 0x9AD, 0x0, + 0x10F2, 0x99F, 0x9B1, 0x0, 0x10EE, 0x997, 0x9AD, 0x0, + 0x111A, 0x99F, 0x9B1, 0x0, 0x1116, 0x997, 0x9AD, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_1[] = { + 0x9AA, 0x9A0, 0x9B2, 0x0, 0x9A6, 0x998, 0x9AE, 0x0, + 0x99E, 0x9A0, 0x9B2, 0x0, 0x996, 0x998, 0x9AE, 0x0, + 0x10F3, 0x9A0, 0x9B2, 0x0, 0x10EF, 0x998, 0x9AE, 0x0, + 0x111B, 0x9A0, 0x9B2, 0x0, 0x1117, 0x998, 0x9AE, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_2[] = { + 0x9AC, 0x9A4, 0x9B4, 0x0, 0x9A8, 0x99C, 0x9B0, 0x0, + 0x9A2, 0x9A4, 0x9B4, 0x0, 0x99A, 0x99C, 0x9B0, 0x0, + 0x10F5, 0x9A4, 0x9B4, 0x0, 0x10F1, 0x99C, 0x9B0, 0x0, + 0x111D, 0x9A4, 0x9B4, 0x0, 0x1119, 0x99C, 0x9B0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_3[] = { + 0x9AB, 0x9A3, 0x9B3, 0x0, 0x9A7, 0x99B, 0x9AF, 0x0, + 0x9A1, 0x9A3, 0x9B3, 0x0, 0x999, 0x99B, 0x9AF, 0x0, + 0x10F4, 0x9A3, 0x9B3, 0x0, 0x10F0, 0x99B, 0x9AF, 0x0, + 0x111C, 0x9A3, 0x9B3, 0x0, 0x1118, 0x99B, 0x9AF, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_4[] = { + 0x9B6, 0x9BA, 0x9BC, 0x0, 0x9B5, 0x9B9, 0x9BB, 0x0, + 0x9B8, 0x9BA, 0x9BC, 0x0, 0x9B7, 0x9B9, 0x9BB, 0x0, + 0x10F7, 0x9BA, 0x9BC, 0x0, 0x10F6, 0x9B9, 0x9BB, 0x0, + 0x111F, 0x9BA, 0x9BC, 0x0, 0x111E, 0x9B9, 0x9BB, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_5[] = { + 0x9BD, 0x9C1, 0x0, 0x0, 0x9BE, 0x9C2, 0x0, 0x0, + 0x9BF, 0x9C1, 0x0, 0x0, 0x9C0, 0x9C2, 0x0, 0x0, + 0x10F8, 0x9C1, 0x0, 0x0, 0x10F9, 0x9C2, 0x0, 0x0, + 0x1120, 0x9C1, 0x0, 0x0, 0x1121, 0x9C2, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_4_6[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x98E, 0x990, 0x98D, 0x98F, 0x992, 0x994, 0x991, 0x993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_4_poles[] = { + SPR_OPENTTD_BASE + 36, + SPR_OPENTTD_BASE + 37, + SPR_OPENTTD_BASE + 37, + SPR_OPENTTD_BASE + 36, + SPR_OPENTTD_BASE + 38, + 0x0, + + SPR_OPENTTD_BASE + 33, + SPR_OPENTTD_BASE + 34, + SPR_OPENTTD_BASE + 34, + SPR_OPENTTD_BASE + 33, + SPR_OPENTTD_BASE + 35, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_5_0[] = { + 0x32189A9, 0x321899F, 0x32189B1, 0x0, 0x32189A5, 0x3218997, 0x32189AD, 0x0, + 0x321899D, 0x321899F, 0x32189B1, 0x0, 0x3218995, 0x3218997, 0x32189AD, 0x0, + 0x32190F2, 0x321899F, 0x32189B1, 0x0, 0x32190EE, 0x3218997, 0x32189AD, 0x0, + 0x321911A, 0x321899F, 0x32189B1, 0x0, 0x3219116, 0x3218997, 0x32189AD, 0x0, + SPR_OPENTTD_BASE + 35, +}; + +static const PalSpriteID _bridge_sprite_table_5_1[] = { + 0x32189AA, 0x32189A0, 0x32189B2, 0x0, 0x32189A6, 0x3218998, 0x32189AE, 0x0, + 0x321899E, 0x32189A0, 0x32189B2, 0x0, 0x3218996, 0x3218998, 0x32189AE, 0x0, + 0x32190F3, 0x32189A0, 0x32189B2, 0x0, 0x32190EF, 0x3218998, 0x32189AE, 0x0, + 0x321911B, 0x32189A0, 0x32189B2, 0x0, 0x3219117, 0x3218998, 0x32189AE, 0x0, + SPR_OPENTTD_BASE + 36, +}; + +static const PalSpriteID _bridge_sprite_table_5_2[] = { + 0x32189AC, 0x32189A4, 0x32189B4, 0x0, 0x32189A8, 0x321899C, 0x32189B0, 0x0, + 0x32189A2, 0x32189A4, 0x32189B4, 0x0, 0x321899A, 0x321899C, 0x32189B0, 0x0, + 0x32190F5, 0x32189A4, 0x32189B4, 0x0, 0x32190F1, 0x321899C, 0x32189B0, 0x0, + 0x321911D, 0x32189A4, 0x32189B4, 0x0, 0x3219119, 0x321899C, 0x32189B0, 0x0, + SPR_OPENTTD_BASE + 36, +}; + +static const PalSpriteID _bridge_sprite_table_5_3[] = { + 0x32189AB, 0x32189A3, 0x32189B3, 0x0, 0x32189A7, 0x321899B, 0x32189AF, 0x0, + 0x32189A1, 0x32189A3, 0x32189B3, 0x0, 0x3218999, 0x321899B, 0x32189AF, 0x0, + 0x32190F4, 0x32189A3, 0x32189B3, 0x0, 0x32190F0, 0x321899B, 0x32189AF, 0x0, + 0x321911C, 0x32189A3, 0x32189B3, 0x0, 0x3219118, 0x321899B, 0x32189AF, 0x0, + SPR_OPENTTD_BASE + 35, +}; + +static const PalSpriteID _bridge_sprite_table_5_4[] = { + 0x32189B6, 0x32189BA, 0x32189BC, 0x0, 0x32189B5, 0x32189B9, 0x32189BB, 0x0, + 0x32189B8, 0x32189BA, 0x32189BC, 0x0, 0x32189B7, 0x32189B9, 0x32189BB, 0x0, + 0x32190F7, 0x32189BA, 0x32189BC, 0x0, 0x32190F6, 0x32189B9, 0x32189BB, 0x0, + 0x321911F, 0x32189BA, 0x32189BC, 0x0, 0x321911E, 0x32189B9, 0x32189BB, 0x0, + SPR_OPENTTD_BASE+38, 0x0, 0x0, 0x0, SPR_OPENTTD_BASE + 37, +}; + +static const PalSpriteID _bridge_sprite_table_5_5[] = { + 0x32189BD, 0x32189C1, 0x0, 0x0, 0x32189BE, 0x32189C2, 0x0, 0x0, + 0x32189BF, 0x32189C1, 0x0, 0x0, 0x32189C0, 0x32189C2, 0x0, 0x0, + 0x32190F8, 0x32189C1, 0x0, 0x0, 0x32190F9, 0x32189C2, 0x0, 0x0, + 0x3219120, 0x32189C1, 0x0, 0x0, 0x3219121, 0x32189C2, 0x0, 0x0, + 0x0, SPR_OPENTTD_BASE + 35, +}; + +static const PalSpriteID _bridge_sprite_table_5_6[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x321898E, 0x3218990, 0x321898D, 0x321898F, 0x3218992, 0x3218994, 0x3218991, 0x3218993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, + 0x0, SPR_OPENTTD_BASE + 35, +}; + +static const PalSpriteID _bridge_sprite_table_5_poles[] = { + SPR_OPENTTD_BASE + 36 + 0x3218000, + SPR_OPENTTD_BASE + 37 + 0x3218000, + SPR_OPENTTD_BASE + 37 + 0x3218000, + SPR_OPENTTD_BASE + 36 + 0x3218000, + SPR_OPENTTD_BASE + 38 + 0x3218000, + 0x0, + + SPR_OPENTTD_BASE + 33 + 0x3218000, + SPR_OPENTTD_BASE + 34 + 0x3218000, + SPR_OPENTTD_BASE + 34 + 0x3218000, + SPR_OPENTTD_BASE + 33 + 0x3218000, + SPR_OPENTTD_BASE + 35 + 0x3218000, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_0[] = { + 0x32089A9, 0x320899F, 0x32089B1, 0x0, 0x32089A5, 0x3208997, 0x32089AD, 0x0, + 0x320899D, 0x320899F, 0x32089B1, 0x0, 0x3208995, 0x3208997, 0x32089AD, 0x0, + 0x32090F2, 0x320899F, 0x32089B1, 0x0, 0x32090EE, 0x3208997, 0x32089AD, 0x0, + 0x320911A, 0x320899F, 0x32089B1, 0x0, 0x3209116, 0x3208997, 0x32089AD, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_1[] = { + 0x32089AA, 0x32089A0, 0x32089B2, 0x0, 0x32089A6, 0x3208998, 0x32089AE, 0x0, + 0x320899E, 0x32089A0, 0x32089B2, 0x0, 0x3208996, 0x3208998, 0x32089AE, 0x0, + 0x32090F3, 0x32089A0, 0x32089B2, 0x0, 0x32090EF, 0x3208998, 0x32089AE, 0x0, + 0x320911B, 0x32089A0, 0x32089B2, 0x0, 0x3209117, 0x3208998, 0x32089AE, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_2[] = { + 0x32089AC, 0x32089A4, 0x32089B4, 0x0, 0x32089A8, 0x320899C, 0x32089B0, 0x0, + 0x32089A2, 0x32089A4, 0x32089B4, 0x0, 0x320899A, 0x320899C, 0x32089B0, 0x0, + 0x32090F5, 0x32089A4, 0x32089B4, 0x0, 0x32090F1, 0x320899C, 0x32089B0, 0x0, + 0x320911D, 0x32089A4, 0x32089B4, 0x0, 0x3209119, 0x320899C, 0x32089B0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_3[] = { + 0x32089AB, 0x32089A3, 0x32089B3, 0x0, 0x32089A7, 0x320899B, 0x32089AF, 0x0, + 0x32089A1, 0x32089A3, 0x32089B3, 0x0, 0x3208999, 0x320899B, 0x32089AF, 0x0, + 0x32090F4, 0x32089A3, 0x32089B3, 0x0, 0x32090F0, 0x320899B, 0x32089AF, 0x0, + 0x320911C, 0x32089A3, 0x32089B3, 0x0, 0x3209118, 0x320899B, 0x32089AF, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_4[] = { + 0x32089B6, 0x32089BA, 0x32089BC, 0x0, 0x32089B5, 0x32089B9, 0x32089BB, 0x0, + 0x32089B8, 0x32089BA, 0x32089BC, 0x0, 0x32089B7, 0x32089B9, 0x32089BB, 0x0, + 0x32090F7, 0x32089BA, 0x32089BC, 0x0, 0x32090F6, 0x32089B9, 0x32089BB, 0x0, + 0x320911F, 0x32089BA, 0x32089BC, 0x0, 0x320911E, 0x32089B9, 0x32089BB, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_5[] = { + 0x32089BD, 0x32089C1, 0x0, 0x0, 0x32089BE, 0x32089C2, 0x0, 0x0, + 0x32089BF, 0x32089C1, 0x0, 0x0, 0x32089C0, 0x32089C2, 0x0, 0x0, + 0x32090F8, 0x32089C1, 0x0, 0x0, 0x32090F9, 0x32089C2, 0x0, 0x0, + 0x3209120, 0x32089C1, 0x0, 0x0, 0x3209121, 0x32089C2, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_3_poles[] = { + SPR_OPENTTD_BASE + 36 + 0x3208000, + SPR_OPENTTD_BASE + 37 + 0x3208000, + SPR_OPENTTD_BASE + 37 + 0x3208000, + SPR_OPENTTD_BASE + 36 + 0x3208000, + SPR_OPENTTD_BASE + 38 + 0x3208000, + 0x0, + + SPR_OPENTTD_BASE + 33 + 0x3208000, + SPR_OPENTTD_BASE + 34 + 0x3208000, + SPR_OPENTTD_BASE + 34 + 0x3208000, + SPR_OPENTTD_BASE + 33 + 0x3208000, + SPR_OPENTTD_BASE + 35 + 0x3208000, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_1_1[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x320898E, 0x3208990, 0x320898D, 0x320898F, 0x3208992, 0x3208994, 0x3208991, 0x3208993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_1_poles[] = { + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 37 + 6*3, + SPR_OPENTTD_BASE + 37 + 6*3, + SPR_OPENTTD_BASE + 36 + 6*3, + SPR_OPENTTD_BASE + 38 + 6*3, + 0x0, + + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 34 + 6*3, + SPR_OPENTTD_BASE + 34 + 6*3, + SPR_OPENTTD_BASE + 33 + 6*3, + SPR_OPENTTD_BASE + 35 + 6*3, + 0x0, + + 0x0, + 0x0, +}; + + +static const PalSpriteID _bridge_sprite_table_6_0[] = { + 0x9CD, 0x9D9, 0x0, 0x0, 0x9CE, 0x9DA, 0x0, 0x0, + 0x9D3, 0x9D9, 0x0, 0x0, 0x9D4, 0x9DA, 0x0, 0x0, + 0x10FC, 0x9D9, 0x0, 0x0, 0x10FD, 0x9DA, 0x0, 0x0, + 0x1124, 0x9D9, 0x0, 0x0, 0x1125, 0x9DA, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_6_1[] = { + 0x9CB, 0x9D7, 0x9DD, 0x0, 0x9D0, 0x9DC, 0x9E0, 0x0, + 0x9D1, 0x9D7, 0x9DD, 0x0, 0x9D6, 0x9DC, 0x9E0, 0x0, + 0x10FA, 0x9D7, 0x9DD, 0x0, 0x10FF, 0x9DC, 0x9E0, 0x0, + 0x1122, 0x9D7, 0x9DD, 0x0, 0x1127, 0x9DC, 0x9E0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_6_2[] = { + 0x9CC, 0x9D8, 0x9DE, 0x0, 0x9CF, 0x9DB, 0x9DF, 0x0, + 0x9D2, 0x9D8, 0x9DE, 0x0, 0x9D5, 0x9DB, 0x9DF, 0x0, + 0x10FB, 0x9D8, 0x9DE, 0x0, 0x10FE, 0x9DB, 0x9DF, 0x0, + 0x1123, 0x9D8, 0x9DE, 0x0, 0x1126, 0x9DB, 0x9DF, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_6_3[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x98E, 0x990, 0x98D, 0x98F, 0x992, 0x994, 0x991, 0x993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_6_poles[] = { + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 2526, + 2528, +}; + + +static const PalSpriteID _bridge_sprite_table_7_0[] = { + 0x31C89CD, 0x31C89D9, 0x0, 0x0, 0x31C89CE, 0x31C89DA, 0x0, 0x0, + 0x31C89D3, 0x31C89D9, 0x0, 0x0, 0x31C89D4, 0x31C89DA, 0x0, 0x0, + 0x31C90FC, 0x31C89D9, 0x0, 0x0, 0x31C90FD, 0x31C89DA, 0x0, 0x0, + 0x31C9124, 0x31C89D9, 0x0, 0x0, 0x31C9125, 0x31C89DA, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_7_1[] = { + 0x31C89CB, 0x31C89D7, 0x31C89DD, 0x0, 0x31C89D0, 0x31C89DC, 0x31C89E0, 0x0, + 0x31C89D1, 0x31C89D7, 0x31C89DD, 0x0, 0x31C89D6, 0x31C89DC, 0x31C89E0, 0x0, + 0x31C90FA, 0x31C89D7, 0x31C89DD, 0x0, 0x31C90FF, 0x31C89DC, 0x31C89E0, 0x0, + 0x31C9122, 0x31C89D7, 0x31C89DD, 0x0, 0x31C9127, 0x31C89DC, 0x31C89E0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_7_2[] = { + 0x31C89CC, 0x31C89D8, 0x31C89DE, 0x0, 0x31C89CF, 0x31C89DB, 0x31C89DF, 0x0, + 0x31C89D2, 0x31C89D8, 0x31C89DE, 0x0, 0x31C89D5, 0x31C89DB, 0x31C89DF, 0x0, + 0x31C90FB, 0x31C89D8, 0x31C89DE, 0x0, 0x31C90FE, 0x31C89DB, 0x31C89DF, 0x0, + 0x31C9123, 0x31C89D8, 0x31C89DE, 0x0, 0x31C9126, 0x31C89DB, 0x31C89DF, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_7_3[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x31C898E, 0x31C8990, 0x31C898D, 0x31C898F, 0x31C8992, 0x31C8994, 0x31C8991, 0x31C8993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_7_poles[] = { + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 2526, + 2528, +}; + +static const PalSpriteID _bridge_sprite_table_8_0[] = { + 0x31E89CD, 0x31E89D9, 0x0, 0x0, 0x31E89CE, 0x31E89DA, 0x0, 0x0, + 0x31E89D3, 0x31E89D9, 0x0, 0x0, 0x31E89D4, 0x31E89DA, 0x0, 0x0, + 0x31E90FC, 0x31E89D9, 0x0, 0x0, 0x31E90FD, 0x31E89DA, 0x0, 0x0, + 0x31E9124, 0x31E89D9, 0x0, 0x0, 0x31E9125, 0x31E89DA, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_8_1[] = { + 0x31E89CB, 0x31E89D7, 0x31E89DD, 0x0, 0x31E89D0, 0x31E89DC, 0x31E89E0, 0x0, + 0x31E89D1, 0x31E89D7, 0x31E89DD, 0x0, 0x31E89D6, 0x31E89DC, 0x31E89E0, 0x0, + 0x31E90FA, 0x31E89D7, 0x31E89DD, 0x0, 0x31E90FF, 0x31E89DC, 0x31E89E0, 0x0, + 0x31E9122, 0x31E89D7, 0x31E89DD, 0x0, 0x31E9127, 0x31E89DC, 0x31E89E0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_8_2[] = { + 0x31E89CC, 0x31E89D8, 0x31E89DE, 0x0, 0x31E89CF, 0x31E89DB, 0x31E89DF, 0x0, + 0x31E89D2, 0x31E89D8, 0x31E89DE, 0x0, 0x31E89D5, 0x31E89DB, 0x31E89DF, 0x0, + 0x31E90FB, 0x31E89D8, 0x31E89DE, 0x0, 0x31E90FE, 0x31E89DB, 0x31E89DF, 0x0, + 0x31E9123, 0x31E89D8, 0x31E89DE, 0x0, 0x31E9126, 0x31E89DB, 0x31E89DF, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_8_3[] = { + 0x986, 0x988, 0x985, 0x987, 0x98A, 0x98C, 0x989, 0x98B, + 0x31E898E, 0x31E8990, 0x31E898D, 0x31E898F, 0x31E8992, 0x31E8994, 0x31E8991, 0x31E8993, + 0x10E7, 0x10E9, 0x10E6, 0x10E8, 0x10EB, 0x10ED, 0x10EA, 0x10EC, + 0x110F, 0x1111, 0x110E, 0x1110, 0x1113, 0x1115, 0x1112, 0x1114, +}; + +static const PalSpriteID _bridge_sprite_table_8_poles[] = { + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + + 2526, + 2528, +}; + +static const PalSpriteID _bridge_sprite_table_0_0[] = { + 0x9F2, 0x9F6, 0x9F8, 0x0, 0x9F1, 0x9F5, 0x9F7, 0x0, + 0x9F4, 0x9F6, 0x9F8, 0x0, 0x9F3, 0x9F5, 0x9F7, 0x0, + 0x1109, 0x9F6, 0x9F8, 0x0, 0x1108, 0x9F5, 0x9F7, 0x0, + 0x1131, 0x9F6, 0x9F8, 0x0, 0x1130, 0x9F5, 0x9F7, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_0_1[] = { + 0x9EE, 0x9ED, 0x9F0, 0x9EF, 0x9EA, 0x9E9, 0x9EB, 0x9EC, + 0x9E6, 0x9E5, 0x9E8, 0x9E7, 0x9E2, 0x9E1, 0x9E3, 0x9E4, + 0x1105, 0x1104, 0x1107, 0x1106, 0x1101, 0x1100, 0x1102, 0x1103, + 0x112D, 0x112C, 0x112F, 0x112E, 0x1129, 0x1128, 0x112A, 0x112B, +}; + +static const PalSpriteID _bridge_sprite_table_0_poles[] = { + SPR_OPENTTD_BASE + 42, + SPR_OPENTTD_BASE + 42, + SPR_OPENTTD_BASE + 42, + SPR_OPENTTD_BASE + 42, + SPR_OPENTTD_BASE + 44, + 0x0, + + SPR_OPENTTD_BASE + 39, + SPR_OPENTTD_BASE + 39, + SPR_OPENTTD_BASE + 39, + SPR_OPENTTD_BASE + 39, + SPR_OPENTTD_BASE + 41, + 0x0, + + 0x0, + 0x0, +}; + + +static const PalSpriteID _bridge_sprite_table_1_0[] = { + 0x31E89BD, 0x31E89C1, 0x9C9, 0x0, 0x31E89BE, 0x31E89C2, 0x9CA, 0x0, + 0x31E89BF, 0x31E89C1, 0x9C9, 0x0, 0x31E89C0, 0x31E89C2, 0x9CA, 0x0, + 0x31E90F8, 0x31E89C1, 0x9C9, 0x0, 0x31E90F9, 0x31E89C2, 0x9CA, 0x0, + 0x31E9120, 0x31E89C1, 0x9C9, 0x0, 0x31E9121, 0x31E89C2, 0x9CA, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_9_0[] = { + 0x9F9, 0x9FD, 0x9C9, 0x0, 0x9FA, 0x9FE, 0x9CA, 0x0, + 0x9FB, 0x9FD, 0x9C9, 0x0, 0x9FC, 0x9FE, 0x9CA, 0x0, + 0x110A, 0x9FD, 0x9C9, 0x0, 0x110B, 0x9FE, 0x9CA, 0x0, + 0x1132, 0x9FD, 0x9C9, 0x0, 0x1133, 0x9FE, 0x9CA, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_10_0[] = { + 0xA0B, 0xA01, 0x0, 0x0, 0xA0C, 0xA02, 0x0, 0x0, + 0xA11, 0xA01, 0x0, 0x0, 0xA12, 0xA02, 0x0, 0x0, + 0xA17, 0xA01, 0x0, 0x0, 0xA18, 0xA02, 0x0, 0x0, + 0xA1D, 0xA01, 0x0, 0x0, 0xA1E, 0xA02, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_10_1[] = { + 0xA09, 0x9FF, 0xA05, 0x0, 0xA0E, 0xA04, 0xA08, 0x0, + 0xA0F, 0x9FF, 0xA05, 0x0, 0xA14, 0xA04, 0xA08, 0x0, + 0xA15, 0x9FF, 0xA05, 0x0, 0xA1A, 0xA04, 0xA08, 0x0, + 0xA1B, 0x9FF, 0xA05, 0x0, 0xA20, 0xA04, 0xA08, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_10_2[] = { + 0xA0A, 0xA00, 0xA06, 0x0, 0xA0D, 0xA03, 0xA07, 0x0, + 0xA10, 0xA00, 0xA06, 0x0, 0xA13, 0xA03, 0xA07, 0x0, + 0xA16, 0xA00, 0xA06, 0x0, 0xA19, 0xA03, 0xA07, 0x0, + 0xA1C, 0xA00, 0xA06, 0x0, 0xA1F, 0xA03, 0xA07, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_10_poles[] = { + SPR_OPENTTD_BASE + 36 + 2*6, + SPR_OPENTTD_BASE + 36 + 2*6, + SPR_OPENTTD_BASE + 36 + 2*6, + SPR_OPENTTD_BASE + 36 + 2*6, + SPR_OPENTTD_BASE + 38 + 2*6, + 0x0, + + SPR_OPENTTD_BASE + 33 + 2*6, + SPR_OPENTTD_BASE + 33 + 2*6, + SPR_OPENTTD_BASE + 33 + 2*6, + SPR_OPENTTD_BASE + 33 + 2*6, + SPR_OPENTTD_BASE + 35 + 2*6, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_11_0[] = { + 0x3218A0B, 0x3218A01, 0x0, 0x0, 0x3218A0C, 0x3218A02, 0x0, 0x0, + 0x3218A11, 0x3218A01, 0x0, 0x0, 0x3218A12, 0x3218A02, 0x0, 0x0, + 0x3218A17, 0x3218A01, 0x0, 0x0, 0x3218A18, 0x3218A02, 0x0, 0x0, + 0x3218A1D, 0x3218A01, 0x0, 0x0, 0x3218A1E, 0x3218A02, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_11_1[] = { + 0x3218A09, 0x32189FF, 0x3218A05, 0x0, 0x3218A0E, 0x3218A04, 0x3218A08, 0x0, + 0x3218A0F, 0x32189FF, 0x3218A05, 0x0, 0x3218A14, 0x3218A04, 0x3218A08, 0x0, + 0x3218A15, 0x32189FF, 0x3218A05, 0x0, 0x3218A1A, 0x3218A04, 0x3218A08, 0x0, + 0x3218A1B, 0x32189FF, 0x3218A05, 0x0, 0x3218A20, 0x3218A04, 0x3218A08, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_11_2[] = { + 0x3218A0A, 0x3218A00, 0x3218A06, 0x0, 0x3218A0D, 0x3218A03, 0x3218A07, 0x0, + 0x3218A10, 0x3218A00, 0x3218A06, 0x0, 0x3218A13, 0x3218A03, 0x3218A07, 0x0, + 0x3218A16, 0x3218A00, 0x3218A06, 0x0, 0x3218A19, 0x3218A03, 0x3218A07, 0x0, + 0x3218A1C, 0x3218A00, 0x3218A06, 0x0, 0x3218A1F, 0x3218A03, 0x3218A07, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_11_poles[] = { + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 38 + 2*6 + 0x3218000, + 0x0, + + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3218000, + SPR_OPENTTD_BASE + 35 + 2*6 + 0x3218000, + 0x0, + + 0x0, + 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_12_0[] = { + 0x3238A0B, 0x3238A01, 0x0, 0x0, 0x3238A0C, 0x3238A02, 0x0, 0x0, + 0x3238A11, 0x3238A01, 0x0, 0x0, 0x3238A12, 0x3238A02, 0x0, 0x0, + 0x3238A17, 0x3238A01, 0x0, 0x0, 0x3238A18, 0x3238A02, 0x0, 0x0, + 0x3238A1D, 0x3238A01, 0x0, 0x0, 0x3238A1E, 0x3238A02, 0x0, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_12_1[] = { + 0x3238A09, 0x32389FF, 0x3238A05, 0x0, 0x3238A0E, 0x3238A04, 0x3238A08, 0x0, + 0x3238A0F, 0x32389FF, 0x3238A05, 0x0, 0x3238A14, 0x3238A04, 0x3238A08, 0x0, + 0x3238A15, 0x32389FF, 0x3238A05, 0x0, 0x3238A1A, 0x3238A04, 0x3238A08, 0x0, + 0x3238A1B, 0x32389FF, 0x3238A05, 0x0, 0x3238A20, 0x3238A04, 0x3238A08, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_12_2[] = { + 0x3238A0A, 0x3238A00, 0x3238A06, 0x0, 0x3238A0D, 0x3238A03, 0x3238A07, 0x0, + 0x3238A10, 0x3238A00, 0x3238A06, 0x0, 0x3238A13, 0x3238A03, 0x3238A07, 0x0, + 0x3238A16, 0x3238A00, 0x3238A06, 0x0, 0x3238A19, 0x3238A03, 0x3238A07, 0x0, + 0x3238A1C, 0x3238A00, 0x3238A06, 0x0, 0x3238A1F, 0x3238A03, 0x3238A07, 0x0, +}; + +static const PalSpriteID _bridge_sprite_table_12_poles[] = { + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 36 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 38 + 2*6 + 0x3238000, + 0x0, + + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 33 + 2*6 + 0x3238000, + SPR_OPENTTD_BASE + 35 + 2*6 + 0x3238000, + 0x0, + + 0x0, + 0x0, +}; + +static const uint32 * const _bridge_sprite_table_2[] = { + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_0, + _bridge_sprite_table_2_1, +}; + +static const uint32 * const _bridge_sprite_table_4[] = { + _bridge_sprite_table_4_0, + _bridge_sprite_table_4_1, + _bridge_sprite_table_4_2, + _bridge_sprite_table_4_3, + _bridge_sprite_table_4_4, + _bridge_sprite_table_4_5, + _bridge_sprite_table_4_6, +}; + +static const uint32 * const _bridge_sprite_table_5[] = { + _bridge_sprite_table_5_0, + _bridge_sprite_table_5_1, + _bridge_sprite_table_5_2, + _bridge_sprite_table_5_3, + _bridge_sprite_table_5_4, + _bridge_sprite_table_5_5, + _bridge_sprite_table_5_6, +}; + +static const uint32 * const _bridge_sprite_table_3[] = { + _bridge_sprite_table_3_0, + _bridge_sprite_table_3_1, + _bridge_sprite_table_3_2, + _bridge_sprite_table_3_3, + _bridge_sprite_table_3_4, + _bridge_sprite_table_3_5, + _bridge_sprite_table_1_1, +}; + +static const uint32 * const _bridge_sprite_table_6[] = { + _bridge_sprite_table_6_0, + _bridge_sprite_table_6_1, + _bridge_sprite_table_6_2, + _bridge_sprite_table_6_2, + _bridge_sprite_table_6_2, + _bridge_sprite_table_6_2, + _bridge_sprite_table_6_3, +}; + +static const uint32 * const _bridge_sprite_table_7[] = { + _bridge_sprite_table_7_0, + _bridge_sprite_table_7_1, + _bridge_sprite_table_7_2, + _bridge_sprite_table_7_2, + _bridge_sprite_table_7_2, + _bridge_sprite_table_7_2, + _bridge_sprite_table_7_3, +}; + +static const uint32 * const _bridge_sprite_table_8[] = { + _bridge_sprite_table_8_0, + _bridge_sprite_table_8_1, + _bridge_sprite_table_8_2, + _bridge_sprite_table_8_2, + _bridge_sprite_table_8_2, + _bridge_sprite_table_8_2, + _bridge_sprite_table_8_3, +}; + +static const uint32 * const _bridge_sprite_table_0[] = { + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_0, + _bridge_sprite_table_0_1, +}; + +static const uint32 * const _bridge_sprite_table_1[] = { + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_0, + _bridge_sprite_table_1_1, +}; + +static const uint32 * const _bridge_sprite_table_9[] = { + _bridge_sprite_table_9_0, + _bridge_sprite_table_9_0, + _bridge_sprite_table_9_0, + _bridge_sprite_table_9_0, + _bridge_sprite_table_9_0, + _bridge_sprite_table_9_0, + _bridge_sprite_table_4_6, +}; + +static const uint32 * const _bridge_sprite_table_10[] = { + _bridge_sprite_table_10_0, + _bridge_sprite_table_10_1, + _bridge_sprite_table_10_2, + _bridge_sprite_table_10_2, + _bridge_sprite_table_10_2, + _bridge_sprite_table_10_2, + _bridge_sprite_table_6_3, +}; + +static const uint32 * const _bridge_sprite_table_11[] = { + _bridge_sprite_table_11_0, + _bridge_sprite_table_11_1, + _bridge_sprite_table_11_2, + _bridge_sprite_table_11_2, + _bridge_sprite_table_11_2, + _bridge_sprite_table_11_2, + _bridge_sprite_table_6_3, +}; + +static const uint32 * const _bridge_sprite_table_12[] = { + _bridge_sprite_table_12_0, + _bridge_sprite_table_12_1, + _bridge_sprite_table_12_2, + _bridge_sprite_table_12_2, + _bridge_sprite_table_12_2, + _bridge_sprite_table_12_2, + _bridge_sprite_table_6_3, +}; + +static const uint32 * const * const _bridge_sprite_table[] = { + _bridge_sprite_table_0, + _bridge_sprite_table_1, + _bridge_sprite_table_2, + _bridge_sprite_table_3, + _bridge_sprite_table_4, + _bridge_sprite_table_5, + _bridge_sprite_table_6, + _bridge_sprite_table_7, + _bridge_sprite_table_8, + _bridge_sprite_table_9, + _bridge_sprite_table_10, + _bridge_sprite_table_11, + _bridge_sprite_table_12 +}; + +static const uint32 * const _bridge_poles_table[] = { + _bridge_sprite_table_0_poles, + _bridge_sprite_table_1_poles, + _bridge_sprite_table_2_poles, + _bridge_sprite_table_3_poles, + _bridge_sprite_table_4_poles, + _bridge_sprite_table_5_poles, + _bridge_sprite_table_6_poles, + _bridge_sprite_table_7_poles, + _bridge_sprite_table_8_poles, + _bridge_sprite_table_2_poles, + _bridge_sprite_table_10_poles, + _bridge_sprite_table_11_poles, + _bridge_sprite_table_12_poles +}; + + diff --git a/table/unmovable_land.h b/table/unmovable_land.h new file mode 100644 --- /dev/null +++ b/table/unmovable_land.h @@ -0,0 +1,141 @@ +#define TILE_SEQ_BEGIN(x) ADD_WORD(x), +#define TILE_SEQ_LINE(a,b,c,d,e,f,g) a,b,c,d,e,f,ADD_WORD(g), +#define TILE_SEQ_END() 0x80 + +static const DrawTileUnmovableStruct _draw_tile_unmovable_data[] = { + {0xA29, 7,7, 2,2, 70}, + {0xA2A, 4,4, 7,7, 61}, +}; + +static const byte _unmovable_display_datas_0[] = { + TILE_SEQ_BEGIN(0x8A2B) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_1[] = { + TILE_SEQ_BEGIN(0x8A2C) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_2[] = { + TILE_SEQ_BEGIN(0x8A2D) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_3[] = { + TILE_SEQ_BEGIN(0x8A2E) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_4[] = { + TILE_SEQ_BEGIN(0x8A2F) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_5[] = { + TILE_SEQ_BEGIN(0x8A30) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_6[] = { + TILE_SEQ_BEGIN(0x8A31) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_7[] = { + TILE_SEQ_BEGIN(0x8A32) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_8[] = { + TILE_SEQ_BEGIN(0x8A33) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 20, 0x8A34) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_9[] = { + TILE_SEQ_BEGIN(0x8A35) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 20, 0x8A36) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_10[] = { + TILE_SEQ_BEGIN(0x8A37) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 20, 0x8A38) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_11[] = { + TILE_SEQ_BEGIN(0x8A39) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_12[] = { + TILE_SEQ_BEGIN(0x8A3A) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 50, 0x8A3B) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_13[] = { + TILE_SEQ_BEGIN(0x8A3C) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 50, 0x8A3D) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_14[] = { + TILE_SEQ_BEGIN(0x8A3E) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 50, 0x8A3F) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_15[] = { + TILE_SEQ_BEGIN(0x8A40) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_16[] = { + TILE_SEQ_BEGIN(0x8A41) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 60, 0x8A42) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_17[] = { + TILE_SEQ_BEGIN(0x8A43) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 60, 0x8A44) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_18[] = { + TILE_SEQ_BEGIN(0x8A45) + TILE_SEQ_LINE( 0, 0, 0, 16, 16, 60, 0x8A46) + TILE_SEQ_END() +}; + +static const byte _unmovable_display_datas_19[] = { + TILE_SEQ_BEGIN(0x8A47) + TILE_SEQ_END() +}; + +static const byte * const _unmovable_display_datas[] = { + _unmovable_display_datas_0, + _unmovable_display_datas_1, + _unmovable_display_datas_2, + _unmovable_display_datas_3, + _unmovable_display_datas_4, + _unmovable_display_datas_5, + _unmovable_display_datas_6, + _unmovable_display_datas_7, + _unmovable_display_datas_8, + _unmovable_display_datas_9, + _unmovable_display_datas_10, + _unmovable_display_datas_11, + _unmovable_display_datas_12, + _unmovable_display_datas_13, + _unmovable_display_datas_14, + _unmovable_display_datas_15, + _unmovable_display_datas_16, + _unmovable_display_datas_17, + _unmovable_display_datas_18, + _unmovable_display_datas_19, +}; + diff --git a/table/water_land.h b/table/water_land.h new file mode 100644 --- /dev/null +++ b/table/water_land.h @@ -0,0 +1,147 @@ +static const byte _shipdepot_display_seq_1[] = { + ADD_WORD(0xFDD), + + 0,15,0,16,1,0x14, + ADD_WORD(0x8FE8), + + 0x80 +}; + +static const byte _shipdepot_display_seq_2[] = { + ADD_WORD(0xFDD), + + 0,0,0,16,1,0x14, ADD_WORD(0xFEA), + 0,15,0,16,1,0x14, ADD_WORD(0x8FE6), + + 0x80 +}; + +static const byte _shipdepot_display_seq_3[] = { + ADD_WORD(0xFDD), + + 15,0,0,1,0x10,0x14,ADD_WORD(0x8FE9), + + 0x80 +}; + +static const byte _shipdepot_display_seq_4[] = { + ADD_WORD(0xFDD), + + 0,0,0,1,16,0x14, ADD_WORD(0xFEB), + 15,0,0,1,16,0x14, ADD_WORD(0x8FE7), + + 0x80 +}; + +static const byte * const _shipdepot_display_seq[] = { + _shipdepot_display_seq_1, + _shipdepot_display_seq_2, + _shipdepot_display_seq_3, + _shipdepot_display_seq_4, +}; + +static const byte _shiplift_display_seq_0[] = { + ADD_WORD(SPR_CANALS_BASE + 6), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 0 + 1), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 4 + 1), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_1[] = { + ADD_WORD(SPR_CANALS_BASE + 5), + 0, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 0), + 0xF, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 4), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_2[] = { + ADD_WORD(SPR_CANALS_BASE + 7), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 0 + 2), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 4 + 2), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_3[] = { + ADD_WORD(SPR_CANALS_BASE + 8), + 0, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 0 + 3), + 0xF, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 4 + 3), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_0b[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 8 + 1), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 12 + 1), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_1b[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 8), + 0xF, 0, 0, 0x1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 12), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_2b[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 8 + 2), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 12 + 2), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_3b[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 8 + 3), + 0xF, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 12 + 3), + 0x80, 0 +}; + +static const byte _shiplift_display_seq_0t[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 16 + 1), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 20 + 1), + 0x80, 8 +}; + +static const byte _shiplift_display_seq_1t[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 16), + 0xF, 0, 0, 0x1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 20), + 0x80, 8 +}; + +static const byte _shiplift_display_seq_2t[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 16 + 2), + 0, 0xF, 0, 0x10, 1, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 20 + 2), + 0x80, 8 +}; + +static const byte _shiplift_display_seq_3t[] = { + ADD_WORD(0xFDD), + 0, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 16 + 3), + 0xF, 0, 0, 1, 0x10, 0x14, ADD_WORD(SPR_CANALS_BASE + 9 + 20 + 3), + 0x80, 8 +}; + +static const byte * const _shiplift_display_seq[] = { + _shiplift_display_seq_0, + _shiplift_display_seq_1, + _shiplift_display_seq_2, + _shiplift_display_seq_3, + + _shiplift_display_seq_0b, + _shiplift_display_seq_1b, + _shiplift_display_seq_2b, + _shiplift_display_seq_3b, + + _shiplift_display_seq_0t, + _shiplift_display_seq_1t, + _shiplift_display_seq_2t, + _shiplift_display_seq_3t, +}; + + +static const SpriteID _water_shore_sprites[15] = { + 0, 0xFDF, 0xFE0, 0xFE4, 0xFDE, 0, 0xFE2, 0, 0xFE1, 0xFE5, 0, 0, 0xFE3, 0, 0 +}; diff --git a/terraform_gui.c b/terraform_gui.c new file mode 100644 --- /dev/null +++ b/terraform_gui.c @@ -0,0 +1,215 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "viewport.h" +#include "gfx.h" +#include "command.h" +#include "vehicle.h" + + +static void CcTerraform(bool success, uint tile, uint32 p1, uint32 p2) +{ + if (success) { + SndPlayTileFx(0x1D, tile); + } else { + SetRedErrorSquare(_terraform_err_tile); + } +} + +static void GenericRaiseLowerLand(uint tile, int mode) +{ + if (mode) { + DoCommandP(tile, 8, (uint32)mode, CcTerraform, CMD_TERRAFORM_LAND | CMD_AUTO | CMD_MSG(STR_0808_CAN_T_RAISE_LAND_HERE)); + } else { + DoCommandP(tile, 8, (uint32)mode, CcTerraform, CMD_TERRAFORM_LAND | CMD_AUTO | CMD_MSG(STR_0809_CAN_T_LOWER_LAND_HERE)); + } +} + + +typedef void OnButtonClick(Window *w); + +static const uint16 _terraform_keycodes[] = { + '1', + '2', + '3', + '4', + '5', + '6', + '7', +}; + +void PlaceProc_DemolishArea(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_AND_Y); +} + +void PlaceProc_RaiseLand(uint tile) +{ + GenericRaiseLowerLand(tile, 1); +} + +void PlaceProc_LowerLand(uint tile) +{ + GenericRaiseLowerLand(tile, 0); +} + +void PlaceProc_LevelLand(uint tile) +{ + VpStartPlaceSizing(tile, VPM_X_AND_Y | (2<<4)); +} + +void PlaceProc_PlantTree(uint tile) +{ +} + + + + +static void TerraformClick_Dynamite(Window *w) +{ + HandlePlacePushButton(w, 2, ANIMCURSOR_DEMOLISH, 1, PlaceProc_DemolishArea); +} + +static void TerraformClick_Lower(Window *w) +{ + HandlePlacePushButton(w, 3, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerLand); +} + +static void TerraformClick_Raise(Window *w) +{ + HandlePlacePushButton(w, 4, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseLand); +} + +static void TerraformClick_Level(Window *w) +{ + HandlePlacePushButton(w, 5, SPR_OPENTTD_BASE+69, 2, PlaceProc_LevelLand); +} + +static void TerraformClick_BuyLand(Window *w) +{ + HandlePlacePushButton(w, 6, 4792, 1, PlaceProc_BuyLand); +} + +static void TerraformClick_Trees(Window *w) +{ + if (HandlePlacePushButton(w, 8, 0, 1, PlaceProc_PlantTree)) ShowBuildTreesToolbar(); +} + +static void TerraformClick_PlaceSign(Window *w) +{ + HandlePlacePushButton(w, 9, 722, 1, PlaceProc_Sign); +} + + +static OnButtonClick * const _terraform_button_proc[] = { + TerraformClick_Dynamite, + TerraformClick_Lower, + TerraformClick_Raise, + TerraformClick_Level, + TerraformClick_BuyLand, + 0, + TerraformClick_Trees, + TerraformClick_PlaceSign, +}; + + + +static void TerraformToolbWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawWindowWidgets(w); + break; + case WE_CLICK: + if (e->click.widget >= 2 && e->click.widget != 7) { + _terraform_button_proc[e->click.widget - 2](w); + } + break; + + case WE_KEYPRESS: + { + int i; + for(i=0; i!=lengthof(_terraform_keycodes); i++) + if (e->keypress.keycode == _terraform_keycodes[i]) { + e->keypress.cont = false; + _terraform_button_proc[i](w); + break; + } + } + break; + + case WE_PLACE_OBJ: + _place_proc(e->place.tile); + return; + + case WE_PLACE_DRAG: + VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata & 0xF); + break; + + case WE_PLACE_MOUSEUP: + if (e->click.pt.x != -1) { + uint start_tile = e->place.starttile; + uint end_tile = e->place.tile; + + if (e->place.userdata == VPM_X_AND_Y) { + DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); + } else if (e->place.userdata == (VPM_X_AND_Y | (2<<4))) { + DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO); + } else if (e->place.userdata == VPM_X_AND_Y_LIMITED) { +// if (e->click.pt.x != -1) { +// DoCommandP(e->place.tile, _tree_to_plant, e->place.starttile, NULL, +// CMD_PLANT_TREE | CMD_AUTO | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE)); + } else { + assert(true); + } + } + break; + + case WE_ABORT_PLACE_OBJ: + w->click_state = 0; + 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: { + } break; + } +} + +static const Widget _terraform_widgets[] = { +{ WWT_CLOSEBOX, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 7, 11, 157, 0, 13, STR_LANDSCAPING_TOOLBAR, STR_018C_WINDOW_TITLE_DRAG_THIS}, + + +{ WWT_PANEL, 7, 0, 21, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC}, +{ WWT_PANEL, 7, 22, 43, 14, 35, 695, STR_018E_LOWER_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 44, 65, 14, 35, 694, STR_018F_RAISE_A_CORNER_OF_LAND}, +{ WWT_PANEL, 7, 66, 87, 14, 35, SPR_OPENTTD_BASE+68, STR_LEVEL_LAND_TOOLTIP}, +{ WWT_PANEL, 7, 88, 109, 14, 35, 4791, STR_0329_PURCHASE_LAND_FOR_FUTURE}, +{ WWT_PANEL, 7, 110, 113, 14, 35, 0, 0x0}, +{ WWT_PANEL, 7, 114, 135, 14, 35, 742, STR_0185_PLANT_TREES_PLACE_SIGNS}, +{ WWT_PANEL, 7, 136, 157, 14, 35, SPR_OPENTTD_BASE+70, STR_0289_PLACE_SIGN}, + +{ WWT_LAST}, +}; + +static const WindowDesc _terraform_desc = { + 640-158, 22+36, 158, 36, + WC_SCEN_LAND_GEN,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _terraform_widgets, + TerraformToolbWndProc +}; + + + +void ShowTerraformToolbar() +{ + AllocateWindowDescFront(&_terraform_desc, 0); +} diff --git a/texteff.c b/texteff.c new file mode 100644 --- /dev/null +++ b/texteff.c @@ -0,0 +1,178 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gfx.h" +#include "viewport.h" +#include "saveload.h" + +typedef struct TextEffect { + StringID string_id; + int16 x,y,right,bottom; + uint16 duration; + uint32 params_1; + uint32 params_2; +} TextEffect; + +static TextEffect _text_effect_list[30]; +TileIndex _animated_tile_list[256]; + +static void MarkTextEffectAreaDirty(TextEffect *te) +{ + MarkAllViewportsDirty( + te->x, + te->y - 1, + (te->right - te->x)*2 + te->x + 1, + (te->bottom - (te->y - 1)) * 2 + (te->y - 1) + 1 + ); +} + +void AddTextEffect(StringID msg, int x, int y, uint16 duration) +{ + TextEffect *te; + int w; + char buffer[100]; + + if (_game_mode == GM_MENU) + return; + + for (te = _text_effect_list; te->string_id != 0xFFFF; ) { + if (++te == endof(_text_effect_list)) + return; + } + + te->string_id = msg; + te->duration = duration; + te->y = y - 5; + te->bottom = y + 5; + te->params_1 = GET_DPARAM32(0); + te->params_2 = GET_DPARAM32(4); + + GetString(buffer, msg); + w = GetStringWidth(buffer); + + te->x = x - (w >> 1); + te->right = x + (w >> 1) - 1; + MarkTextEffectAreaDirty(te); +} + +static void MoveTextEffect(TextEffect *te) +{ + if (te->duration < 8) { + te->string_id = 0xFFFF; + } else { + te->duration-=8; + te->y--; + te->bottom--; + } + MarkTextEffectAreaDirty(te); +} + +void MoveAllTextEffects() +{ + TextEffect *te; + + for (te = _text_effect_list; te != endof(_text_effect_list); te++ ) { + if (te->string_id != 0xFFFF) + MoveTextEffect(te); + } +} + +void InitTextEffects() +{ + TextEffect *te; + + for (te = _text_effect_list; te != endof(_text_effect_list); te++ ) { + te->string_id = 0xFFFF; + } +} + +void DrawTextEffects(DrawPixelInfo *dpi) +{ + TextEffect *te; + + if (dpi->zoom < 1) { + for (te = _text_effect_list; te != endof(_text_effect_list); te++ ) { + if (te->string_id == 0xFFFF) + continue; + + /* intersection? */ + if ((int16)dpi->left > te->right || + (int16)dpi->top > te->bottom || + (int16)(dpi->left + dpi->width) <= te->x || + (int16)(dpi->top + dpi->height) <= te->y) + continue; + AddStringToDraw(te->x, te->y, te->string_id, te->params_1, te->params_2); + } + } else if (dpi->zoom == 1) { + for (te = _text_effect_list; te != endof(_text_effect_list); te++ ) { + if (te->string_id == 0xFFFF) + continue; + + /* intersection? */ + if (dpi->left > te->right*2 - te->x || + dpi->top > te->bottom*2 - te->y || + (dpi->left + dpi->width) <= te->x || + (dpi->top + dpi->height) <= te->y) + continue; + AddStringToDraw(te->x, te->y, (StringID)(te->string_id-1), te->params_1, te->params_2); + } + + } +} + +void DeleteAnimatedTile(uint tile) +{ + TileIndex *ti; + + for(ti=_animated_tile_list; ti!=endof(_animated_tile_list); ti++) { + if ( (TileIndex)tile == *ti) { + /* remove the hole */ + memcpy_overlapping(ti, ti+1, endof(_animated_tile_list) - 1 - ti); + /* and clear last item */ + endof(_animated_tile_list)[-1] = 0; + MarkTileDirtyByTile(tile); + return; + } + } +} + +bool AddAnimatedTile(uint tile) +{ + TileIndex *ti; + + for(ti=_animated_tile_list; ti!=endof(_animated_tile_list); ti++) { + if ( (TileIndex)tile == *ti || *ti == 0) { + *ti = tile; + MarkTileDirtyByTile(tile); + return true; + } + } + + return false; +} + +void AnimateAnimatedTiles() +{ + TileIndex *ti; + uint tile; + + for(ti=_animated_tile_list; ti!=endof(_animated_tile_list) && (tile=*ti) != 0; ti++) { + AnimateTile(tile); + } +} + +void InitializeAnimatedTiles() +{ + memset(_animated_tile_list, 0, sizeof(_animated_tile_list)); +} + +static void SaveLoad_ANIT() +{ + SlArray(_animated_tile_list, lengthof(_animated_tile_list), SLE_UINT16); +} + + +const ChunkHandler _animated_tile_chunk_handlers[] = { + { 'ANIT', SaveLoad_ANIT, SaveLoad_ANIT, CH_RIFF | CH_LAST}, +}; + + diff --git a/town.h b/town.h new file mode 100644 --- /dev/null +++ b/town.h @@ -0,0 +1,103 @@ +#ifndef TOWN_H +#define TOWN_H + +#include "player.h" + +struct Town { + TileIndex xy; + + // Current population of people and amount of houses. + uint16 num_houses; + uint32 population; + + // Town name + uint16 townnametype; + uint32 townnameparts; + + // NOSAVE: Location of name sign, UpdateTownVirtCoord updates this. + ViewportSign sign; + + // Makes sure we don't build certain house types twice. + byte flags12; + + // Which players have a statue? + byte statues; + + // Sort index in listings + byte sort_index_obsolete; + + // Player ratings as well as a mask that determines which players have a rating. + byte have_ratings; + uint8 unwanted[MAX_PLAYERS]; // how many months companies aren't wanted by towns (bribe) + int16 ratings[MAX_PLAYERS]; + + // Maximum amount of passengers and mail that can be transported. + uint16 max_pass; + uint16 max_mail; + uint16 new_max_pass; + uint16 new_max_mail; + uint16 act_pass; + uint16 act_mail; + uint16 new_act_pass; + uint16 new_act_mail; + + // Amount of passengers that were transported. + byte pct_pass_transported; + byte pct_mail_transported; + + // Amount of food and paper that was transported. Actually a bit mask would be enough. + uint16 act_food; + uint16 act_paper; + uint16 new_act_food; + uint16 new_act_paper; + + // Time until we rebuild a house. + byte time_until_rebuild; + + // When to grow town next time. + byte grow_counter; + byte growth_rate; + + // Fund buildings program in action? + byte fund_buildings_months; + + // Fund road reconstruction in action? + byte road_build_months; + + // Index in town array + byte index; + + // NOSAVE: UpdateTownRadius updates this given the house count. + uint16 radius[5]; +}; + + +void InitializeTown(); +void ShowTownViewWindow(uint town); +void DeleteTown(Town *t); +void ExpandTown(Town *t); +bool GrowTown(Town *t); +Town *CreateRandomTown(); + +enum { + ROAD_REMOVE = 0, + UNMOVEABLE_REMOVE = 1, + TUNNELBRIDGE_REMOVE = 1, + INDUSTRY_REMOVE = 2 +}; + +bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type); + +#define DEREF_TOWN(i) (&_towns[i]) +#define FOR_ALL_TOWNS(c) for(c=_towns; c != endof(_towns); c++) + +VARDEF Town _towns[70]; +VARDEF int _total_towns; // For the AI: the amount of towns active + +VARDEF bool _town_sort_dirty; +VARDEF byte _town_sort_order; + +VARDEF Town *_cleared_town; +VARDEF int _cleared_town_rating; + +#endif /* TOWN_H */ diff --git a/town_cmd.c b/town_cmd.c new file mode 100644 --- /dev/null +++ b/town_cmd.c @@ -0,0 +1,1867 @@ +#include "stdafx.h" +#include "ttd.h" +#include "viewport.h" +#include "town.h" +#include "command.h" +#include "pathfind.h" +#include "gfx.h" +#include "industry.h" +#include "station.h" +#include "player.h" +#include "news.h" +#include "saveload.h" +#include "economy.h" +#include "gui.h" + +// Local +static int _grow_town_result; + +static bool BuildTownHouse(Town *t, uint tile); +static void ClearTownHouse(Town *t, uint tile); +static void DoBuildTownHouse(Town *t, uint tile); + +typedef struct DrawTownTileStruct { + uint32 sprite_1; + uint32 sprite_2; + + byte subtile_xy; + byte width_height; + byte dz; + byte proc; +} DrawTownTileStruct; + +#include "table/town_land.h" + + +static void TownDrawTileProc1(TileInfo *ti) +{ + AddChildSpriteScreen(0x5A3, 0xE, 0x3C - (_map_owner[ti->tile]&0x7F)); +} + +typedef void TownDrawTileProc(TileInfo *ti); +static TownDrawTileProc * const _town_draw_tile_procs[1] = { + TownDrawTileProc1 +}; + + +static void DrawTile_Town(TileInfo *ti) +{ + const DrawTownTileStruct *dcts; + byte z; + uint32 image; + + /* Retrieve pointer to the draw town tile struct */ + { + uint hash, t; + hash = ti->x >> 4; + hash ^= hash>>2; + hash ^= (t=(ti->y >> 4)); + hash -= t>>2; + dcts = &_town_draw_tile_data[((_map2[ti->tile]<<4)|(_map3_lo[ti->tile]>>6)|((hash&3)<<2))]; + } + + z = ti->z; + + /* Add bricks below the house? */ + if (ti->tileh) { + AddSortableSpriteToDraw(0x3DD + ti->tileh, ti->x, ti->y, 16, 16, 7, z); + AddChildSpriteScreen(dcts->sprite_1, 0x1F, 1); + z += 8; + } else { + /* Else draw regular ground */ + DrawGroundSprite(dcts->sprite_1); + } + + /* Add a house on top of the ground? */ + if ((image = dcts->sprite_2) != 0) { + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + + AddSortableSpriteToDraw(image, + ti->x | (dcts->subtile_xy>>4), + ti->y | (dcts->subtile_xy&0xF), + (dcts->width_height>>4)+1, + (dcts->width_height&0xF)+1, + dcts->dz, + z); + + if (!(_display_opt & DO_TRANS_BUILDINGS)) + return; + } + + { + int proc; + if ((proc=dcts->proc-1) >= 0 ) + _town_draw_tile_procs[proc](ti); + } +} + +static uint GetSlopeZ_Town(TileInfo *ti) +{ + uint z = GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; + if (ti->tileh != 0) z = (z & ~7) + 4; + return (uint16) z; +} + +static void AnimateTile_Town(uint tile) +{ + int old; + int i; + int a,b; + + if (_tick_counter & 3) + return; + + if (_map2[tile] != 4 && _map2[tile] != 5) + return; + + if (!((old=_map_owner[tile])&0x80)) { + _map_owner[tile] |= 0x80; + + do { + i = (Random()&7) - 1; + } while (i < 0 || i == 1 || i*6==old); + + _map5[tile] = (_map5[tile] & ~0x3F) | i; + } + + a = _map_owner[tile]&0x7F; + b = (_map5[tile]&0x3F) * 6; + a += (a < b) ? 1 : -1; + _map_owner[tile] = (_map_owner[tile]&0x80)|a; + + if (a == b) { + _map5[tile] &= 0x40; + _map_owner[tile] &= 0x7F; + DeleteAnimatedTile(tile); + } + + MarkTileDirtyByTile(tile); +} + +static void UpdateTownRadius(Town *t); + +static bool IsCloseToTown(uint tile, uint dist) +{ + Town *t; + + FOR_ALL_TOWNS(t) { + if (t->xy != 0 && GetTileDist(tile, t->xy) < dist) + return true; + } + return false; +} + + +static void ChangePopulation(Town *t, int mod) +{ + t->population += mod; + InvalidateWindow(WC_TOWN_VIEW, t->index); + + if (_town_sort_order & 2) _town_sort_dirty = true; +} + +static void MakeSingleHouseBigger(uint tile) +{ + byte b; + + assert(IS_TILETYPE(tile, MP_HOUSE)); + + b = _map5[tile]; + if (b & 0x80) + return; + + _map5[tile] = (b & 0xC0) | ((b+1)&7); + + if ((_map5[tile]&7) != 0) + return; + + _map3_lo[tile] = _map3_lo[tile] + 0x40; + + if ( (_map3_lo[tile] & 0xC0) == 0xC0) { + Town *t = ClosestTownFromTile(tile, (uint)-1); + ChangePopulation(t, _housetype_population[_map2[tile]]); + } + MarkTileDirtyByTile(tile); +} + +static void MakeTownHouseBigger(uint tile) +{ + uint flags = _house_more_flags[_map2[tile]]; + if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); + if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); + if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); + if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); +} + +static void TileLoop_Town(uint tile) +{ + int house; + Town *t; + uint32 r; + + if ((_map3_lo[tile] & 0xC0) != 0xC0) { + MakeTownHouseBigger(tile); + return; + } + + house = _map2[tile]; + if (_housetype_extra_flags[house] & 0x20 && + !(_map5[tile] & 0x80) && + CHANCE16(1,2) && + AddAnimatedTile(tile)) { + _map5[tile] = (_map5[tile] & 0x40)|0x80; + } + + t = ClosestTownFromTile(tile, (uint)-1); + + r = Random(); + + if ( (byte)r < _housetype_population[house] ) { + uint amt = ((byte)r >> 3) + 1, moved; + if (_economy.fluct <= 0) amt = (amt + 1) >> 1; + t->new_max_pass += amt; + moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); + t->new_act_pass += moved; + } + + if ( (byte)(r>>8) < _housetype_mailamount[house] ) { + uint amt = ((byte)(r>>8) >> 3) + 1, moved; + if (_economy.fluct <= 0) amt = (amt + 1) >> 1; + t->new_max_mail += amt; + moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt); + t->new_act_mail += moved; + } + + if (_house_more_flags[house]&8 && (t->flags12&1) && --t->time_until_rebuild == 0) { + r>>=16; + t->time_until_rebuild = (r & 63) + 130; + + _current_player = OWNER_TOWN; + + ClearTownHouse(t, tile); + + // rebuild with another house? + if ( (byte) (r >> 8) >= 12) { + DoBuildTownHouse(t, tile); + } + } +} + +static void ClickTile_Town(uint tile) +{ + /* not used */ +} + +static int32 ClearTile_Town(uint tile, byte flags) +{ + int house, rating; + int32 cost; + Town *t; + + // safety checks + if (!EnsureNoVehicle(tile)) return CMD_ERROR; + if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); + + house = _map2[tile]; + cost = _price.remove_house * _housetype_remove_cost[house] >> 8; + + rating = _housetype_remove_ratingmod[house]; + _cleared_town_rating += rating; + _cleared_town = t = ClosestTownFromTile(tile, (uint)-1); + + if (_current_player < MAX_PLAYERS) { + if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) { + SET_DPARAM16(0, t->index); + return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); + } + } + + if (flags & DC_EXEC) { + ChangeTownRating(t, -rating, -1000); + ClearTownHouse(t, tile); + } + + return cost; +} + +static void GetAcceptedCargo_Town(uint tile, AcceptedCargo *ac) +{ + int type = _map2[tile]; + + ac->type_1 = CT_PASSENGERS; + ac->amount_1 = _housetype_cargo_passengers[type]; + + ac->type_2 = CT_GOODS; + ac->amount_2 = _housetype_cargo_goods[type]; + if (ac->amount_2 & 0x80) { + ac->amount_2 &= 0x7F; + ac->type_2 = CT_FOOD; + } + + ac->type_3 = CT_MAIL; + ac->amount_3 = _housetype_cargo_mail[type]; +} + +static void GetTileDesc_Town(uint tile, TileDesc *td) +{ + td->str = _town_tile_names[_map2[tile]]; + if ((_map3_lo[tile] & 0xC0) != 0xC0) { + SET_DPARAMX16(td->dparam, 0, td->str); + td->str = STR_2058_UNDER_CONSTRUCTION; + } + + td->owner = OWNER_TOWN; +} + +static uint32 GetTileTrackStatus_Town(uint tile, int mode) +{ + /* not used */ + return 0; +} + +static void ChangeTileOwner_Town(uint tile, byte old_player, byte new_player) +{ + /* not used */ +} + + +static const TileIndexDiff _roadblock_tileadd[4+3] = { + TILE_XY(0,-1), + TILE_XY(1,0), + TILE_XY(0,1), + TILE_XY(-1,0), + + // Store the first 3 elements again. + // Lets us rotate without using &3. + TILE_XY(0,-1), + TILE_XY(1,0), + TILE_XY(0,1), +}; + +static void TownTickHandler(Town *t) +{ + if (t->flags12&1) { + int i = t->grow_counter - 1; + if (i < 0) { + if (GrowTown(t)) { + i = t->growth_rate; + } else { + i = 0; + } + } + t->grow_counter = i; + } + + UpdateTownRadius(t); +} + +void OnTick_Town() +{ + uint i; + Town *t; + + if (_game_mode == GM_EDITOR) + return; + + i = _cur_town_ctr; + t = DEREF_TOWN(i); + if (++i == lengthof(_towns)) i = 0; + _cur_town_ctr = i; + + if (t->xy != 0) + TownTickHandler(t); + +} + +static byte GetTownRoadMask(TileIndex tile) +{ + byte b = GetRoadBitsByTile(tile); + byte r=0; + if (b&1) r|=10; + if (b&2) r|=5; + if (b&4) r|=9; + if (b&8) r|=6; + if (b&16) r|=3; + if (b&32) r|=12; + return r; +} + +static bool IsRoadAllowedHere(uint tile, int dir) +{ + uint k; + uint slope; + + // If this assertion fails, it might be because the world contains + // land at the edges. This is not ok. + TILE_ASSERT(tile); + + for(;;) { + // Check if there already is a road at this point? + if (GetRoadBitsByTile(tile) == 0) { + // No, try to build one in the direction. + // if that fails clear the land, and if that fails exit. + // This is to make sure that we can build a road here later. + if (DoCommandByTile(tile, (dir&1)?0xA:0x5, 0, DC_AUTO, CMD_BUILD_ROAD) == CMD_ERROR && + DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return false; + } + + slope = GetTileSlope(tile, NULL); + if (slope == 0) { + // Tile has no slope + // Disallow the road if any neighboring tile has a road. + if (HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1])), dir^2) || + HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3])), dir^2) || + HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1] + _roadblock_tileadd[dir+2])), dir) || + HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3] + _roadblock_tileadd[dir+2])), dir)) + return false; + + // Otherwise allow + return true; + } + + // If the tile is not a slope in the right direction, then + // maybe terraform some. + if ((k = (dir&1)?0xC:0x9) != slope && (k^0xF) != slope) { + uint32 r = Random(); + + if (CHANCE16I(1,8, r) && !_generating_world) { + if (CHANCE16I(1,16,r)) + DoCommandByTile(tile, slope, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); + else + DoCommandByTile(tile, slope^0xF, 1, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); + } + return false; + } + + tile = TILE_ADD(tile, _roadblock_tileadd[dir]); + } +} + +static bool TerraformTownTile(uint tile, int edges, int dir) +{ + int32 r; + + TILE_ASSERT(tile); + + r = DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); + if (r == CMD_ERROR || r >= 126*16) + return false; + DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND); + return true; +} + +static void LevelTownLand(uint tile) +{ + TileInfo ti; + + TILE_ASSERT(tile); + + // Don't terraform if land is plain or if there's a house there. + FindLandscapeHeightByTile(&ti, tile); + if (ti.tileh == 0 || ti.type == MP_HOUSE) + return; + + // First try up, then down + if (!TerraformTownTile(tile, ~ti.tileh & 0xF, 1)) { + TerraformTownTile(tile, ti.tileh & 0xF, 0); + } +} + +#define IS_WATER_TILE(t) (IS_TILETYPE((t), MP_WATER) && _map5[(t)] == 0) + +static void GrowTownInTile(uint *tile_ptr, uint mask, int block, Town *t1) +{ + Town *t2; + uint16 r; + int a,b,rcmd; + uint tmptile; + TileInfo ti; + int i; + int j; + uint tile = *tile_ptr; + + TILE_ASSERT(tile); + + if (mask == 0) { + // Tile has no road. First reset the status counter + // to say that this is the last iteration. + _grow_town_result = 0; + + // Then check if the tile we are at belongs to the town, + // if not, bail out. + t2 = ClosestTownFromTile(tile, (uint)-1); + if (t2 != t1) + return; + + // Remove hills etc + LevelTownLand(tile); + + // Is a road allowed here? + if (!IsRoadAllowedHere(tile, block)) + return; + + // Randomize new road block numbers + a = block; + b = block ^ 2; + r = (uint16)Random(); + if (r <= 0x4000) do { + a = (int)Random() & 3; + } while(a == b); + + if (!IsRoadAllowedHere(TILE_ADD(tile,_roadblock_tileadd[a]), a)) { + // A road is not allowed to continue the randomized road, + // return if the road we're trying to build is curved. + if ( a != (b^2)) + return; + + // Return if neither side of the new road is a house + if (!IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+1]), MP_HOUSE) && + !IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+3]), MP_HOUSE)) + return; + + // That means that the road is only allowed if there is a house + // at any side of the new road. + } + rcmd = (1 << a) + (1 << b); + + } else if (block < 5 && !HASBIT(mask,block^2)) { + // Continue building on a partial road. + // Always OK. + _grow_town_result = 0; + rcmd = 1 << (block^2); + } else { + + // Reached a tunnel? Then continue at the other side of it. + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile]&~3)==4) { + FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, _map5[tile]&3, 2); + *tile_ptr = flotr.tile; + return; + } + + // For any other kind of tunnel/bridge, bail out. + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) + return; + + // Possibly extend the road in a direction. + // Randomize a direction and if it has a road, bail out. + i = (int)Random() & 3; + if (HASBIT(mask, i)) + return; + + // This is the tile we will reach if we extend to this direction. + tmptile = TILE_ADD(tile,_roadblock_tileadd[i]); + + // Don't do it if it reaches to water. + if (IS_WATER_TILE(tmptile)) + return; + + // If the new tile belongs to another town, + // then stop the search altogether. + if (ClosestTownFromTile(tmptile, (uint)-1) != t1) { + _grow_town_result = 0; + return; + } + + // Build a house at the edge. 60% chance or + // always ok if no road allowed. + if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6,10)) { + // But not if there already is a house there. + if (!IS_TILETYPE(tmptile, MP_HOUSE)) { + // Level the land if possible + LevelTownLand(tmptile); + + // And build a house. + // Set result to -1 if we managed to build it. + if (BuildTownHouse(t1, tmptile)) + _grow_town_result = -1; + } + return; + } + + _grow_town_result = 0; + rcmd = 1 << i; + } + + FindLandscapeHeightByTile(&ti, tile); + + // Return if a water tile + if (ti.type == MP_WATER && ti.map5==0) + return; + + // Determine direction of slope, + // and build a road if not a special slope. + if ((i=0,ti.tileh != 3) && + (i++,ti.tileh != 9) && + (i++,ti.tileh != 12) && + (i++,ti.tileh != 6)) { +build_road_and_exit: + if (DoCommandByTile(tile, rcmd, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD) != CMD_ERROR) + _grow_town_result = -1; + return; + } + + tmptile = tile; + + // Now it contains the direction of the slope + j = -11; // max 11 tile long bridges + do { + if (++j == 0) + goto build_road_and_exit; + tmptile = TILE_MASK(tmptile + _tileoffs_by_dir[i]); + } while (IS_WATER_TILE(tmptile)); + + // no water tiles in between? + if (j == -10) + goto build_road_and_exit; + + // Quit if it selecting an appropiate bridge type fails a large number of times. + j = 22; + { + int32 bridge_len = GetBridgeLength(tile, tmptile); + do { + byte bridge_type = RandomRange(MAX_BRIDGES - 1); + if (CheckBridge_Stuff(bridge_type, bridge_len)) { + if (DoCommandByTile(tile, tmptile, 0x8000 + bridge_type, DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE) != CMD_ERROR) + _grow_town_result = -1; + + // obviously, if building any bridge would fail, there is no need to try other bridge-types + return; + } + } while(--j != 0); + } +} +#undef IS_WATER_TILE + + +// Returns true if a house was built, or no if the build failed. +static int GrowTownAtRoad(Town *t, uint tile) +{ + uint mask; + int block = 5; // special case + + TILE_ASSERT(tile); + + // Number of times to search. + _grow_town_result = 20; + + do { + // Get a bitmask of the road blocks on a tile + mask = GetTownRoadMask(tile); + + // Try to grow the town from this point + GrowTownInTile(&tile,mask,block,t); + + // Exclude the source position from the bitmask + // and return if no more road blocks available + CLRBIT(mask, (block ^ 2)); + if (mask == 0) + return _grow_town_result; + + // Select a random bit from the blockmask, walk a step + // and continue the search from there. + do block = Random() & 3; while (!HASBIT(mask,block)); + tile += _roadblock_tileadd[block]; + + // Max number of times is checked. + } while (--_grow_town_result >= 0); + + return (_grow_town_result == -2); +} + +// Generate a random road block +// The probability of a straight road +// is somewhat higher than a curved. +static int GenRandomRoadBits() +{ + uint32 r = Random(); + int a = r&3, b = (r >> 8) & 3; + if (a == b) b ^= 2; + return (1<xy; + ptr = _town_coord_mod; + do { + if (GetRoadBitsByTile(tile) != 0) { + return GrowTownAtRoad(t, tile); + } + offs = *ptr++; + + tile = TILE_ADD(tile, offs); + } while (offs); + + // No road available, try to build a random road block by + // clearing some land and then building a road there. + tile = t->xy; + ptr = _town_coord_mod; + do { + FindLandscapeHeightByTile(&ti, tile); + + // Only work with plain land that not already has a house with map5=0 + if (ti.tileh == 0 && !(ti.type==MP_HOUSE && ti.map5==0)) { + if (DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) { + DoCommandByTile(tile, GenRandomRoadBits(), 0, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); + return true; + } + } + offs = *ptr++; + tile = TILE_ADD(tile, offs); + } while (offs != 0); + + return false; +} + +static void UpdateTownRadius(Town *t) +{ + static const uint16 _town_radius_data[23][5] = { + { 4, 0, 0, 0, 0}, + {16, 0, 0, 0, 0}, + {25, 0, 0, 0, 0}, + {36, 0, 0, 0, 0}, + {49, 0, 4, 0, 0}, + {64, 0, 4, 0, 0}, + {64, 0, 9, 0, 1}, + {64, 0, 9, 0, 4}, + {64, 0, 16, 0, 4}, + {81, 0, 16, 0, 4}, + {81, 0, 16, 0, 4}, + {81, 0, 25, 0, 9}, + {81, 36, 25, 0, 9}, + {81, 36, 25, 16, 9}, + {81, 49, 0, 25, 9}, + {81, 64, 0, 25, 9}, + {81, 64, 0, 36, 9}, + {81, 64, 0, 36, 16}, + { 0, 81, 0, 49, 16}, + { 0, 81, 0, 49, 25}, + { 0,100, 0, 49, 25}, + { 0,100, 0, 64, 25}, + { 0,100, 0, 64, 36}, + }; + int i = min(t->num_houses, 88) >> 2; + memcpy(t->radius, _town_radius_data[i], sizeof(t->radius)); +} + +static void UpdateTownVirtCoord(Town *t) +{ + Point pt = RemapCoords2(GET_TILE_X(t->xy)*16, GET_TILE_Y(t->xy)*16); + SET_DPARAM32(0, t->townnameparts); + UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, t->townnametype); +} + +static void CreateTownName(Town *t1) +{ + Town *t2; + char buf1[64]; + char buf2[64]; + uint32 r; + + t1->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name; + + for(;;) { +restart: + r = Random(); + + SET_DPARAM32(0, r); + GetString(buf1, t1->townnametype); + + // Check size and width + if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130) + continue; + + FOR_ALL_TOWNS(t2) { + if (t2->xy != 0) { + SET_DPARAM32(0, t2->townnameparts); + GetString(buf2, t2->townnametype); + if (str_eq(buf1, buf2)) + goto restart; + } + } + t1->townnameparts = r; + + return; + } +} + +static void UpdateTownMaxPass(Town *t) +{ + t->max_pass = t->population >> 3; + t->max_mail = t->population >> 4; +} + +static void DoCreateTown(Town *t, TileIndex tile) +{ + int x, i; + + // clear the town struct + i = t->index; + memset(t, 0, sizeof(Town)); + t->index = i; + + t->xy = tile; + t->num_houses = 0; + t->time_until_rebuild = 10; + UpdateTownRadius(t); + t->flags12 = 0; + t->population = 0; + t->grow_counter = 0; + t->growth_rate = 250; + t->new_max_pass = 0; + t->new_max_mail = 0; + t->new_act_pass = 0; + t->new_act_mail = 0; + t->max_pass = 0; + t->max_mail = 0; + t->act_pass = 0; + t->act_mail = 0; + + t->pct_pass_transported = 0; + t->pct_mail_transported = 0; + t->fund_buildings_months = 0; + t->new_act_food = 0; + t->new_act_paper = 0; + t->act_food = 0; + t->act_paper = 0; + + for(i = 0; i != MAX_PLAYERS; i++) + t->ratings[i] = 500; + + t->have_ratings = 0; + t->statues = 0; + + CreateTownName(t); + + UpdateTownVirtCoord(t); + _town_sort_dirty = true; + + x = (Random() & 0xF) + 8; + if (_game_mode == GM_EDITOR) + x = _new_town_size * 16 + 3; + + t->num_houses += x; + UpdateTownRadius(t); + + i = x * 4; + do { + GrowTown(t); + } while (--i); + + t->num_houses -= x; + UpdateTownRadius(t); + UpdateTownMaxPass(t); +} + +static Town *AllocateTown() +{ + Town *t; + FOR_ALL_TOWNS(t) { + if (t->xy == 0) { + _total_towns++; + return t; + } + } + return NULL; +} + +int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + TileInfo ti; + Town *t; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + + // Check if too close to the edge of map + if (!CheckDistanceFromEdge(tile, 12)) + return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); + + // Can only build on clear flat areas. + FindLandscapeHeightByTile(&ti, tile); + if (ti.type != MP_CLEAR || ti.tileh != 0) + return_cmd_error(STR_0239_SITE_UNSUITABLE); + + // Check distance to all other towns. + if (IsCloseToTown(tile, 20)) + return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN); + + // Allocate town struct + t = AllocateTown(); + if (t == NULL) + return_cmd_error(STR_023A_TOO_MANY_TOWNS); + + // Create the town + if (flags & DC_EXEC) { + _generating_world = true; + DoCreateTown(t, tile); + _generating_world = false; + } + return 0; +} + +Town *CreateRandomTown() +{ + uint tile; + TileInfo ti; + Town *t; + int n; + + // Try 20 times. + n = 20; + do { + // Generate a tile index not too close from the edge + tile = TILE_MASK(Random()); + if (!CheckDistanceFromEdge(tile, 20)) + continue; + + // Make sure the tile is plain + FindLandscapeHeightByTile(&ti, tile); + if (ti.type != MP_CLEAR || ti.tileh != 0) + continue; + + // Check not too close to a town + if (IsCloseToTown(tile, 20)) + continue; + + // Allocate a town struct + t = AllocateTown(); + if (t == NULL) + break; + + DoCreateTown(t, tile); + return t; + } while (--n); + return NULL; +} + +static const byte _num_initial_towns[3] = { + 11, 23, 46 +}; + +void GenerateTowns() +{ + uint n; + n = _num_initial_towns[_opt.diff.number_towns] + (Random()&7); + do CreateRandomTown(); while (--n); +} + +static bool CheckBuildHouseMode(Town *t1, uint tile, uint tileh, int mode) { + Town *t2 = ClosestTownFromTile(tile, (uint)-1); + int b; + uint slope; + + static const byte _masks[8] = { + 0xC,0x3,0x9,0x6, + 0x3,0xC,0x6,0x9, + }; + + if (t2 != t1) + return false; + + slope = GetTileSlope(tile, NULL); + if (slope & 0x10) + return false; + + b = 0; + if ((slope & 0xF && ~slope & _masks[mode])) b = ~b; + if ((tileh & 0xF && ~tileh & _masks[mode+4])) b = ~b; + if (b) + return false; + + return DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR) != CMD_ERROR; +} + +int GetTownRadiusGroup(Town *t, uint tile) +{ + uint dist; + int i,smallest; + + dist = GetTileDistAdv(tile, t->xy); + if (t->fund_buildings_months && dist <= 25) + return 4; + + smallest = 0; + for(i=0; i!=lengthof(t->radius); i++) { + if (dist < t->radius[i]) + smallest = i; + } + + return smallest; +} + +static bool CheckFree2x2Area(Town *t1, uint tile) +{ + Town *t; + int i; + + static const TileIndexDiff _tile_add[4] = { + TILE_XY(0,0), + TILE_XY(0,1) - TILE_XY(0,0), + TILE_XY(1,0) - TILE_XY(0,1), + TILE_XY(1,1) - TILE_XY(1,0), + }; + + for(i=0; i!=4; i++) { + tile += _tile_add[i]; + + t = ClosestTownFromTile(tile, (uint)-1); + if (t1 != t) + return false; + + if (GetTileSlope(tile, NULL)) + return false; + + if (DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_FORCETEST, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + return false; + } + + return true; +} + +static void DoBuildTownHouse(Town *t, uint tile) +{ + int i; + uint bitmask; + int house; + uint slope; + int z; + uint oneof; + + // Above snow? + slope = GetTileSlope(tile, &z); + + // Get the town zone type + { + uint rad = GetTownRadiusGroup(t, tile); + + int land = _opt.landscape; + if (land == LT_HILLY && z >= _opt.snow_line) + land = -1; + + bitmask = (1 << rad) + (1 << (land + 12)); + } + + // bits 0-4 are used + // bits 11-15 are used + // bits 5-10 are not used. + { + byte houses[lengthof(_housetype_flags)]; + int num = 0; + + // Generate a list of all possible houses that can be built. + for(i=0; i!=lengthof(_housetype_flags); i++) { + if ((~_housetype_flags[i] & bitmask) == 0) + houses[num++] = (byte)i; + } + + for(;;) { + house = houses[RandomRange(num)]; + + if (_cur_year < _housetype_years[house].min || _cur_year > _housetype_years[house].max) + continue; + + // Special houses that there can be only one of. + oneof = 0; + if (house == 0x5B || house == 0x53 || house == 3 || house == 0x3C || house == 0x3D) + oneof = 2; + else if (house == 0x20 || house == 0x14) + oneof = 4; + + if (t->flags12 & oneof) + continue; + + // Make sure there is no slope? + if (_housetype_extra_flags[house]&0x12 && slope) + continue; + + if (_housetype_extra_flags[house]&0x10) { + if (CheckFree2x2Area(t,tile) || + CheckFree2x2Area(t,(tile+=TILE_XY(-1,0))) || + CheckFree2x2Area(t,(tile+=TILE_XY(0,-1))) || + CheckFree2x2Area(t,(tile+=TILE_XY(1,0)))) + break; + tile += TILE_XY(0,1); + } else if (_housetype_extra_flags[house]&4) { + if (CheckBuildHouseMode(t, tile+TILE_XY(1,0), slope, 0)) + break; + + if (CheckBuildHouseMode(t, tile+TILE_XY(-1,0), slope, 1)) { + tile += TILE_XY(-1,0); + break; + } + } else if (_housetype_extra_flags[house]&8) { + if (CheckBuildHouseMode(t, tile+TILE_XY(0,1), slope, 2)) + break; + + if (CheckBuildHouseMode(t, tile+TILE_XY(0,-1), slope, 3)) { + tile += TILE_XY(0,-1); + break; + } + } else + break; + } + } + + t->num_houses++; + + // Special houses that there can be only one of. + t->flags12 |= oneof; + + { + int m3lo,m5,eflags; + + // ENDING_2 + m3lo = 0; + m5 = 0; + if (_generating_world) { + uint32 r = Random(); + + // Value for map3lo + m3lo = 0xC0; + if ((byte)r >= 220) m3lo &= (r>>8); + + if (m3lo == 0xC0) + ChangePopulation(t, _housetype_population[house]); + + // Initial value for map5. + m5 = (r >> 16) & 0x3F; + } + + assert(IS_TILETYPE(tile, MP_CLEAR)); + + ModifyTile(tile, + MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, + house, /* map2 */ + m3lo, /* map3_lo */ + 0, /* map_owner */ + m5 /* map5 */ + ); + + eflags = _housetype_extra_flags[house]; + + if (eflags&0x18) { + assert(IS_TILETYPE(tile + TILE_XY(0,1), MP_CLEAR)); + ModifyTile(tile + TILE_XY(0,1), + MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, + ++house, /* map2 */ + m3lo, /* map3_lo */ + 0, /* map_owner */ + m5 /* map5 */ + ); + } + + if (eflags&0x14) { + assert(IS_TILETYPE(tile + TILE_XY(1,0), MP_CLEAR)); + ModifyTile(tile + TILE_XY(1,0), + MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, + ++house, /* map2 */ + m3lo, /* map3_lo */ + 0, /* map_owner */ + m5 /* map5 */ + ); + } + + if (eflags&0x10) { + assert(IS_TILETYPE(tile + TILE_XY(1,1), MP_CLEAR)); + ModifyTile(tile + TILE_XY(1,1), + MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, + ++house, /* map2 */ + m3lo, /* map3_lo */ + 0, /* map_owner */ + m5 /* map5 */ + ); + } + } + + // ENDING +} + +static bool BuildTownHouse(Town *t, uint tile) +{ + int32 r; + + // make sure it's possible + if (!EnsureNoVehicle(tile)) return false; + if (GetTileSlope(tile, NULL) & 0x10) return false; + + r = DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); + if (r == CMD_ERROR) return false; + + DoBuildTownHouse(t, tile); + return true; +} + + +static void DoClearTownHouseHelper(uint tile) +{ + assert(IS_TILETYPE(tile, MP_HOUSE)); + DoClearSquare(tile); + DeleteAnimatedTile(tile); +} + +static void ClearTownHouse(Town *t, uint tile) { + uint house = _map2[tile]; + uint eflags; + + assert(IS_TILETYPE(tile, MP_HOUSE)); + + // need to align the tile to point to the upper left corner of the house + if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks. + if (_housetype_extra_flags[house-1] & 0x04) { + house--; + tile += TILE_XY(-1,0); + } else if (_housetype_extra_flags[house-1] & 0x18) { + house--; + tile += TILE_XY(0,-1); + } else if (_housetype_extra_flags[house-2] & 0x10) { + house-=2; + tile += TILE_XY(-1,0); + } else if (_housetype_extra_flags[house-3] & 0x10) { + house-=3; + tile += TILE_XY(-1,-1); + } + } + + // Remove population from the town if the + // house is finished. + if ((~_map3_lo[tile] & 0xC0) == 0) { + ChangePopulation(t, -_housetype_population[house]); + } + + t->num_houses--; + + // Clear flags for houses that only may exist once/town. + if (house == 0x5B || house == 0x53 || house == 0x3C || + house == 0x3D || house == 0x03) + t->flags12 &= ~2; + if (house == 0x14 || house == 0x20) + t->flags12 &= ~4; + + // Do the actual clearing of tiles + eflags = _housetype_extra_flags[house]; + DoClearTownHouseHelper(tile); + if (eflags & 0x14) DoClearTownHouseHelper(tile + TILE_XY(1,0)); + if (eflags & 0x18) DoClearTownHouseHelper(tile + TILE_XY(0,1)); + if (eflags & 0x10) DoClearTownHouseHelper(tile + TILE_XY(1,1)); +} + +int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + StringID str; + Town *t = DEREF_TOWN(p1); + + str = AllocateName((byte*)_decode_parameters, 4); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + StringID old_str = t->townnametype; + t->townnametype = str; + DeleteName(old_str); + + UpdateTownVirtCoord(t); + _town_sort_dirty = true; + UpdateAllStationVirtCoord(); + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + return 0; +} + +// Called from GUI +void DeleteTown(Town *t) +{ + Industry *i; + uint tile; + + // Delete town authority window + // and remove from list of sorted towns + DeleteWindowById(WC_TOWN_VIEW, t->index); + _town_sort_dirty = true; + + // Delete all industries belonging to the town + for(i=_industries; i != endof(_industries); i++) { + if (i->xy && i->town == t) + DeleteIndustry(i); + } + + // Go through all tiles and delete those belonging to the town + tile = 0; + do { + if (IS_TILETYPE(tile, MP_HOUSE)) { + if (ClosestTownFromTile(tile, (uint)-1) == t) { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) || IS_TILETYPE(tile, MP_STREET)) { + if (_map_owner[tile] == OWNER_TOWN && ClosestTownFromTile(tile, (uint)-1) == t) { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + } + } while (++tile != TILES_X * TILES_Y); + + t->xy = 0; + DeleteName(t->townnametype); + + MarkWholeScreenDirty(); +} + +// Called from GUI +void ExpandTown(Town *t) +{ + int amount, n; + + _generating_world = true; + + amount = ((int)Random()&3) + 3; + t->num_houses += amount; + UpdateTownRadius(t); + + n = amount * 4; + do GrowTown(t); while (--n); + + t->num_houses -= amount; + UpdateTownRadius(t); + + UpdateTownMaxPass(t); + _generating_world = false; +} + +const byte _town_action_costs[8] = { + 2, 4, 9, 35, 48, 53, 117, 175 +}; + +typedef void TownActionProc(Town *t, int action); + +static void TownActionAdvertise(Town *t, int action) +{ + static const byte _advertising_amount[3] = {0x40, 0x70, 0xA0}; + static const byte _advertising_radius[3] = {10,15,20}; + ModifyStationRatingAround(t->xy, _current_player, + _advertising_amount[action], + _advertising_radius[action]); +} + +static void TownActionRoadRebuild(Town *t, int action) +{ + Player *p; + + t->road_build_months = 6; + + SET_DPARAM16(0, t->index); + + p = DEREF_PLAYER(_current_player); + SET_DPARAM16(1, p->name_1); + SET_DPARAM32(2, p->name_2); + + AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING, + NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_GENERAL, 0), t->xy, 0); +} + +static bool DoBuildStatueOfCompany(uint tile) +{ + TileInfo ti; + byte old; + int32 r; + + FindLandscapeHeightByTile(&ti, tile); + if (ti.tileh != 0) + return false; + + if (ti.type != MP_HOUSE && ti.type != MP_CLEAR && ti.type != MP_TREES) + return false; + + + old = _current_player; + _current_player = OWNER_NONE; + r = DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + _current_player = old; + + if (r == CMD_ERROR) + return false; + + ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, + 2 /* map5 */ + ); + + return true; +} + +static void TownActionBuildStatue(Town *t, int action) +{ + // Layouted as an outward spiral + static const TileIndexDiff _statue_tiles[] = { + TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), + TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), + TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), + TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), + TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), + TILE_XY(0,1), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), + TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), + TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), + TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), + TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), + TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), + TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), + TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), + 0, + }; + int offs; + uint tile = t->xy; + const TileIndexDiff *p = _statue_tiles; + + SETBIT(t->statues, _current_player); + + do { + if (DoBuildStatueOfCompany(tile)) + return; + offs = *p++; + tile = TILE_ADD(tile, offs); + } while (offs); +} + +static void TownActionFundBuildings(Town *t, int action) +{ + t->grow_counter = 1; + t->flags12 |= 1; + t->fund_buildings_months = 3; +} + +static void TownActionBuyRights(Town *t, int action) +{ + Station *st; + + FOR_ALL_STATIONS(st) { + if (st->xy && st->town == t && st->owner < 8 && + st->owner != _current_player) + st->blocked_months = 12; + } + + ModifyStationRatingAround(t->xy, _current_player, 130, 17); +} + +static void TownActionBribe(Town *t, int action) +{ + if (!RandomRange(15)) { + GoodsEntry *ge; + Station *st; + int i, rating; + + // set as unwanted for 6 months + t->unwanted[_current_player] = 6; + + // set all close by station ratings to 0 + FOR_ALL_STATIONS(st) { + if (st->town == t && st->owner == _current_player) { + for (i=0, ge = st->goods; i != NUM_CARGO; i++, ge++) + ge->rating = 0; + } + } + + // only show errormessage to the executing player. All errors are handled command.c + // but this is special, because it can only 'fail' on a DC_EXEC + if (!_networking || (_current_player == _local_player)) + ShowErrorMessage(STR_BRIBE_FAILED_2, STR_BRIBE_FAILED, 0, 0); + + /* decrease by a lot! + * ChangeTownRating is only for stuff in demolishing. Bribe failure should + * be independent of any cheat settings + * ChangeTownRating(c, -1000, -50); + */ + rating = t->ratings[_current_player]; + if (rating > -50) + t->ratings[_current_player] = -50; + } else { + ChangeTownRating(t, 200, 800); + } +} + +static TownActionProc * const _town_action_proc[] = { + TownActionAdvertise, + TownActionAdvertise, + TownActionAdvertise, + TownActionRoadRebuild, + TownActionBuildStatue, + TownActionFundBuildings, + TownActionBuyRights, + TownActionBribe +}; + +// p1 = town +// p2 = action +int32 CmdDoTownAction(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int32 cost; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + + cost = (_price.build_industry >> 8) * _town_action_costs[p2]; + + if (flags & DC_EXEC) { + _town_action_proc[p2](DEREF_TOWN(p1), p2); + InvalidateWindow(WC_TOWN_AUTHORITY, p1); + } + + return cost; +} + +static void UpdateTownGrowRate(Town *t) +{ + int n; + Station *st; + byte m; + Player *p; + + // Reset player ratings if they're low + FOR_ALL_PLAYERS(p) { + if (p->is_active && t->ratings[p->index] <= 200) { + t->ratings[p->index] += 5; + } + } + + n = 0; + FOR_ALL_STATIONS(st) { + if (GetTileDistAdv(st->xy, t->xy) <= t->radius[0]) { + if (st->time_since_load <= 20 || st->time_since_unload <= 20) { + n++; + if (st->owner < MAX_PLAYERS && t->ratings[st->owner] <= 1000-12) + t->ratings[st->owner] += 12; + } else { + if (st->owner < MAX_PLAYERS && t->ratings[st->owner] >= -1000+15) + t->ratings[st->owner] -= 15; + } + } + } + + t->flags12 &= ~1; + + if (t->fund_buildings_months != 0) { + t->fund_buildings_months--; + m = 60; + } else if (n == 0) { + m = 160; + if (!CHANCE16(1, 12)) + return; + } else { + static const byte _grow_count_values[5] = { + 210, 150, 110, 80, 50 + }; + m = _grow_count_values[min(n, 5) - 1]; + } + + if (_opt.landscape == LT_HILLY) { + if (GET_TILEHEIGHT(t->xy) >= _opt.snow_line && t->act_food == 0) + return; + } else if (_opt.landscape == LT_DESERT) { + if (GetMapExtraBits(t->xy) == 1 && (t->act_food==0 || t->act_paper==0)) + return; + } + + t->growth_rate = m; + if (m <= t->grow_counter) + t->grow_counter = m; + + t->flags12 |= 1; +} + +static void UpdateTownAmounts(Town *t) +{ + // Using +1 here to prevent overflow and division by zero + t->pct_pass_transported = t->new_act_pass * 256 / (t->new_max_pass + 1); + + t->max_pass = t->new_max_pass; t->new_max_pass = 0; + t->act_pass = t->new_act_pass; t->new_act_pass = 0; + t->act_food = t->new_act_food; t->new_act_food = 0; + t->act_paper = t->new_act_paper; t->new_act_paper = 0; + + // Using +1 here to prevent overflow and division by zero + t->pct_mail_transported = t->new_act_mail * 256 / (t->new_max_mail + 1); + t->max_mail = t->new_max_mail; t->new_max_mail = 0; + t->act_mail = t->new_act_mail; t->new_act_mail = 0; + + InvalidateWindow(WC_TOWN_VIEW, t->index); +} + +static void UpdateTownUnwanted(Town *t) +{ + Player *p; + + FOR_ALL_PLAYERS(p) { + if (t->unwanted[p->index] > 0) + t->unwanted[p->index]--; + } +} + +bool CheckIfAuthorityAllows(uint tile) +{ + Town *t; + + if (_current_player >= MAX_PLAYERS) + return true; + + t = ClosestTownFromTile(tile, _patches.dist_local_authority); + if (t == NULL) + return true; + + if (t->ratings[_current_player] > -200) + return true; + + _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; + SET_DPARAM16(0, t->index); + + return false; +} + + +Town *ClosestTownFromTile(uint tile, uint threshold) +{ + Town *t; + uint dist, best = threshold; + Town *best_town = NULL; + + FOR_ALL_TOWNS(t) { + if (t->xy != 0) { + dist = GetTileDist(tile, t->xy); + if (dist < best) { + best = dist; + best_town = t; + } + } + } + + return best_town; +} + +void ChangeTownRating(Town *t, int add, int max) +{ + int rating; + + // if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff + if (t == NULL || _current_player >= MAX_PLAYERS || (_cheats.magic_bulldozer.value && add < 0) ) + return; + + SETBIT(t->have_ratings, _current_player); + + rating = t->ratings[_current_player]; + + if (add < 0) { + if (rating > max) { + rating += add; + if (rating < max) rating = max; + } + } else { + if (rating < max) { + rating += add; + if (rating > max) rating = max; + } + } + t->ratings[_current_player] = rating; +} + +/* penalty for removing town-owned stuff */ +static const int _default_rating_settings [3][3] = { + // ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE + { 0, 128, 384}, // Permissive + { 48, 192, 480}, // Neutral + { 96, 384, 768}, // Hostile +}; + +bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type) +{ + int modemod; + + // if magic_bulldozer cheat is active, town doesn't restrict your destructive actions + if (t == NULL || _current_player >= MAX_PLAYERS || _cheats.magic_bulldozer.value) + return true; + + /* check if you're allowed to remove the street/bridge/tunnel/industry + * owned by a town no removal if rating is lower than ... depends now on + * difficulty setting. Minimum town rating selected by difficulty level + */ + modemod = _default_rating_settings[_opt_mod_ptr->diff.town_council_tolerance][type]; + + if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { + SET_DPARAM16(0, t->index); + _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; + return false; + } + + return true; +} + +void TownsMonthlyLoop() +{ + Town *t; + + FOR_ALL_TOWNS(t) if (t->xy != 0) { + if (t->road_build_months != 0) + t->road_build_months--; + + UpdateTownGrowRate(t); + UpdateTownAmounts(t); + UpdateTownUnwanted(t); + } +} + +void InitializeTowns() +{ + Subsidy *s; + int i; + + memset(_towns, 0, sizeof(_towns)); + for(i=0; i!=lengthof(_towns); i++) + _towns[i].index = i; + + memset(_subsidies, 0, sizeof(_subsidies)); + for (s=_subsidies; s != endof(_subsidies); s++) + s->cargo_type = 0xFF; + + _cur_town_ctr = 0; + _town_sort_dirty = true; + _total_towns = 0; +} + +const TileTypeProcs _tile_type_town_procs = { + DrawTile_Town, /* draw_tile_proc */ + GetSlopeZ_Town, /* get_slope_z_proc */ + ClearTile_Town, /* clear_tile_proc */ + GetAcceptedCargo_Town, /* get_accepted_cargo_proc */ + GetTileDesc_Town, /* get_tile_desc_proc */ + GetTileTrackStatus_Town, /* get_tile_track_status_proc */ + ClickTile_Town, /* click_tile_proc */ + AnimateTile_Town, /* animate_tile_proc */ + TileLoop_Town, /* tile_loop_clear */ + ChangeTileOwner_Town, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + NULL, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; + + +// Save and load of towns. +static const byte _town_desc[] = { + SLE_VAR(Town,xy, SLE_UINT16), + + SLE_CONDVAR(Town,population, SLE_FILE_U16 | SLE_VAR_U32, 0, 2), + SLE_CONDVAR(Town,population, SLE_UINT32, 3, 255), + + + SLE_VAR(Town,num_houses, SLE_UINT16), + SLE_VAR(Town,townnametype,SLE_UINT16), + SLE_VAR(Town,townnameparts,SLE_UINT32), + + SLE_VAR(Town,flags12, SLE_UINT8), + SLE_VAR(Town,statues, SLE_UINT8), + + // sort_index_obsolete was stored here in savegame format 0 - 1 + SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 1, 0, 1), + + SLE_VAR(Town,have_ratings,SLE_UINT8), + SLE_ARR(Town,ratings, SLE_INT16, 8), + // failed bribe attempts are stored since savegame format 4 + SLE_CONDARR(Town,unwanted, SLE_INT8, 8, 4,255), + + SLE_VAR(Town,max_pass, SLE_UINT16), + SLE_VAR(Town,max_mail, SLE_UINT16), + SLE_VAR(Town,new_max_pass,SLE_UINT16), + SLE_VAR(Town,new_max_mail,SLE_UINT16), + SLE_VAR(Town,act_pass, SLE_UINT16), + SLE_VAR(Town,act_mail, SLE_UINT16), + SLE_VAR(Town,new_act_pass,SLE_UINT16), + SLE_VAR(Town,new_act_mail,SLE_UINT16), + + SLE_VAR(Town,pct_pass_transported,SLE_UINT8), + SLE_VAR(Town,pct_mail_transported,SLE_UINT8), + + SLE_VAR(Town,act_food, SLE_UINT16), + SLE_VAR(Town,act_paper, SLE_UINT16), + SLE_VAR(Town,new_act_food,SLE_UINT16), + SLE_VAR(Town,new_act_paper,SLE_UINT16), + + SLE_VAR(Town,time_until_rebuild, SLE_UINT8), + SLE_VAR(Town,grow_counter, SLE_UINT8), + SLE_VAR(Town,growth_rate, SLE_UINT8), + SLE_VAR(Town,fund_buildings_months, SLE_UINT8), + SLE_VAR(Town,road_build_months, SLE_UINT8), + + // reserve extra space in savegame here. (currently 32 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 4, 2, 255), + + SLE_END() +}; + +static void Save_TOWN() +{ + Town *t; + + FOR_ALL_TOWNS(t) if (t->xy != 0) { + SlSetArrayIndex(t->index); + SlObject(t, _town_desc); + } +} + +static void Load_TOWN() +{ + int index; + while ((index = SlIterateArray()) != -1) { + Town *t = DEREF_TOWN(index); + SlObject(t, _town_desc); + _total_towns++; + } +} + +void AfterLoadTown() +{ + Town *t; + FOR_ALL_TOWNS(t) { + if (t->xy != 0) { + UpdateTownRadius(t); + UpdateTownVirtCoord(t); + } + } + _town_sort_dirty = true; +} + + +const ChunkHandler _town_chunk_handlers[] = { + { 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST}, +}; + + diff --git a/town_gui.c b/town_gui.c new file mode 100644 --- /dev/null +++ b/town_gui.c @@ -0,0 +1,481 @@ +#include "stdafx.h" +#include "ttd.h" +#include "town.h" +#include "window.h" +#include "gfx.h" +#include "viewport.h" +#include "gui.h" +#include "command.h" +#include "player.h" + +static const Widget _town_authority_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 316, 0, 13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 0, 316, 14, 105, 0x0, 0}, +{ WWT_IMGBTN, 13, 0, 305, 106, 157, 0x0, STR_2043_LIST_OF_THINGS_TO_DO_AT}, +{ WWT_SCROLLBAR, 13, 306, 316, 106, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_IMGBTN, 13, 0, 316, 158, 209, 0x0, 0}, +{ WWT_PUSHTXTBTN, 13, 0, 316, 210, 221, STR_2042_DO_IT, STR_2044_CARRY_OUT_THE_HIGHLIGHTED}, +{ WWT_LAST}, +}; + +extern const byte _town_action_costs[8]; +extern void DrawPlayerIcon(int p, int x, int y); + +static uint GetMaskOfTownActions(int *nump, Town *t) +{ + int32 avail, ref; + int i, num; + uint avail_buttons = 0x7F; // by default all buttons except bribe are enabled. + uint buttons; + + if (_local_player != 0xff) { + // bribe option enabled? + if (_patches.bribe) { + // if unwanted, disable everything. + if (t->unwanted[_local_player]) { + avail_buttons = 0; + } else if (t->ratings[_local_player] < 600) + avail_buttons |= (1 << 7); // only bribe if less than excellent + } + + // Things worth more than this are not shown + avail = DEREF_PLAYER(_local_player)->player_money + _price.station_value * 200; + ref = _price.build_industry >> 8; + + for(i=0,buttons=0,num=0; i != lengthof(_town_action_costs); i++,avail_buttons>>=1) { + if (avail_buttons&1 && avail >= _town_action_costs[i] * ref) { + SETBIT(buttons, i); + num++; + } + } + + // Disable build statue if already built + if(HASBIT(t->statues, _local_player)) + { + CLRBIT(buttons, 4); + num--; + } + + } else { + // no actions available for spectator + buttons = 0; + num = 0; + } + + if (nump) *nump = num; + return buttons; +} + +static int GetNthSetBit(uint32 bits, int n) +{ + int i = 0; + if (n >= 0) { + do { + if (bits&1 && --n < 0) return i; + i++; + } while (bits>>=1); + } + return -1; +} + +static void TownAuthorityWndProc(Window *w, WindowEvent *e) +{ + uint buttons; + int numact; + Town *t = DEREF_TOWN(w->window_number); + + switch(e->event) { + case WE_PAINT: + buttons = GetMaskOfTownActions(&numact, t); + SetVScrollCount(w, numact + 1); + + if (WP(w,def_d).data_1 != -1 && !HASBIT(buttons, WP(w,def_d).data_1)) + WP(w,def_d).data_1 = -1; + + w->disabled_state = (WP(w,def_d).data_1 == -1) ? (1 << 6) : 0; + + { + int y; + Player *p; + int r; + StringID str; + + SET_DPARAM16(0, w->window_number); + DrawWindowWidgets(w); + + DrawString(2, 15, STR_2023_TRANSPORT_COMPANY_RATINGS, 0); + + // Draw list of players + y = 25; + FOR_ALL_PLAYERS(p) { + if (p->is_active && HASBIT(t->have_ratings, p->index)) { + DrawPlayerIcon(p->index, 2, y); + + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, GetPlayerNameString(p->index)); + + r = t->ratings[p->index]; + (str = STR_3035_APPALLING, r <= -400) || // Apalling + (str++, r <= -200) || // Very Poor + (str++, r <= 0) || // Poor + (str++, r <= 200) || // Mediocore + (str++, r <= 400) || // Good + (str++, r <= 600) || // Very Good + (str++, r <= 800) || // Excellent + (str++, true); // Outstanding + + SET_DPARAM16(3, str); + DrawString(19, y, STR_2024, 0); + y+=10; + } + } + } + + // Draw actions list + { + int y = 107, i; + int pos = w->vscroll.pos; + + if (--pos < 0) { + DrawString(2, y, STR_2045_ACTIONS_AVAILABLE, 0); + y+=10; + } + for(i=0; buttons; i++,buttons>>=1) { + if (pos <= -5) + break; + + if (buttons&1 && --pos < 0) { + DrawString(3, y, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i, 6); + y += 10; + } + } + } + + { + int i; + if ((i=WP(w,def_d).data_1) != -1) { + SET_DPARAM32(1, (_price.build_industry >> 8) * _town_action_costs[i]); + SET_DPARAM16(0, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i); + DrawStringMultiLine(2, 159, STR_204D_INITIATE_A_SMALL_LOCAL + i, 313); + } + } + + break; + + case WE_CLICK: + switch(e->click.widget) { + case 3: { /* listbox */ + int y = (e->click.pt.y - 0x6B) / 10; + if (!IS_INT_INSIDE(y, 0, 5)) + return; + + y = GetNthSetBit(GetMaskOfTownActions(NULL, t), y + w->vscroll.pos - 1); + if (y >= 0) { + WP(w,def_d).data_1 = y; + SetWindowDirty(w); + } + break; + } + + case 6: { /* carry out the action */ + DoCommandP(t->xy, w->window_number, WP(w,def_d).data_1, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_2054_CAN_T_DO_THIS)); + break; + } + } + break; + + case WE_4: + SetWindowDirty(w); + break; + } +} + +static const WindowDesc _town_authority_desc = { + -1, -1, 317, 222, + WC_TOWN_AUTHORITY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _town_authority_widgets, + TownAuthorityWndProc +}; + +void ShowTownAuthorityWindow(uint town) +{ + Window *w; + + w = AllocateWindowDescFront(&_town_authority_desc, town); + if (w) { + w->vscroll.cap = 5; + WP(w,def_d).data_1 = -1; + } +} + +static void TownViewWndProc(Window *w, WindowEvent *e) +{ + Town *t = DEREF_TOWN(w->window_number); + + switch(e->event) { + case WE_PAINT: + SET_DPARAM16(0, t->index); + DrawWindowWidgets(w); + + SET_DPARAM32(0, t->population); + SET_DPARAM32(1, t->num_houses); + DrawString(2,107,STR_2006_POPULATION,0); + + SET_DPARAM16(0, t->act_pass); + SET_DPARAM16(1, t->max_pass); + DrawString(2,117,STR_200D_PASSENGERS_LAST_MONTH_MAX,0); + + SET_DPARAM16(0, t->act_mail); + SET_DPARAM16(1, t->max_mail); + DrawString(2,127,STR_200E_MAIL_LAST_MONTH_MAX,0); + + DrawWindowViewport(w); + break; + + case WE_CLICK: + switch(e->click.widget) { + case 5: /* scroll to location */ + ScrollMainWindowToTile(t->xy); + break; + case 6: /* town authority */ + ShowTownAuthorityWindow(w->window_number); + break; + case 7: /* rename */ + SET_DPARAM32(0, t->townnameparts); + ShowQueryString(t->townnametype, STR_2007_RENAME_TOWN, 31, 130, w->window_class, w->window_number); + break; + case 8: /* expand town */ + ExpandTown(t); + break; + case 9: /* delete town */ + DeleteTown(t); + break; + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, w->window_number, 0, NULL, CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN)); + } break; + } +} + + +static const Widget _town_view_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 259, 0, 13, STR_2005, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 0, 259, 14, 105, 0x0, 0}, +{ WWT_6, 13, 2, 257, 16, 103, 0x0, 0}, +{ WWT_IMGBTN, 13, 0, 259, 106, 137, 0x0, 0}, +{ WWT_PUSHTXTBTN, 13, 0, 85, 138, 149, STR_00E4_LOCATION, STR_200B_CENTER_THE_MAIN_VIEW_ON}, +{ WWT_PUSHTXTBTN, 13, 86, 171, 138, 149, STR_2020_LOCAL_AUTHORITY, STR_2021_SHOW_INFORMATION_ON_LOCAL}, +{ WWT_PUSHTXTBTN, 13, 172, 259, 138, 149, STR_0130_RENAME, STR_200C_CHANGE_TOWN_NAME}, +{ WWT_LAST}, +}; + +static const WindowDesc _town_view_desc = { + -1, -1, 260, 150, + WC_TOWN_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _town_view_widgets, + TownViewWndProc +}; + +static const Widget _town_view_scen_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 184, 0, 13, STR_2005, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 13, 0, 259, 14, 105, 0x0}, +{ WWT_6, 13, 2, 257, 16, 103, 0x0}, +{ WWT_IMGBTN, 13, 0, 259, 106, 137, 0x0}, +{ WWT_PUSHTXTBTN, 13, 0, 85, 138, 149, STR_00E4_LOCATION, STR_200B_CENTER_THE_MAIN_VIEW_ON}, +{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0}, +{ WWT_PUSHTXTBTN, 13, 185, 259, 0, 13, STR_0130_RENAME, STR_200C_CHANGE_TOWN_NAME}, +{ WWT_PUSHTXTBTN, 13, 86, 171, 138, 149, STR_023C_EXPAND, STR_023B_INCREASE_SIZE_OF_TOWN}, +{ WWT_PUSHTXTBTN, 13, 172, 259, 138, 149, STR_0290_DELETE, STR_0291_DELETE_THIS_TOWN_COMPLETELY}, +{ WWT_LAST}, +}; + +static const WindowDesc _town_view_scen_desc = { + -1, -1, 260, 150, + WC_TOWN_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _town_view_scen_widgets, + TownViewWndProc +}; + +void ShowTownViewWindow(uint town) +{ + Window *w; + Town *t; + + if (_game_mode != GM_EDITOR) { + w = AllocateWindowDescFront(&_town_view_desc, town); + } else { + w = AllocateWindowDescFront(&_town_view_scen_desc, town); + } + + if (w) { + w->flags4 |= WF_DISABLE_VP_SCROLL; + t = DEREF_TOWN(w->window_number); + AssignWindowViewport(w, 3, 17, 0xFE, 0x56, t->xy, 1); + } +} + +static const Widget _town_directory_widgets[] = { +{ WWT_TEXTBTN, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 13, 11, 207, 0, 13, STR_2000_TOWNS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 13, 0, 98, 14, 25, STR_SORT_BY_NAME, STR_SORT_TIP}, +{ WWT_PUSHTXTBTN, 13, 99, 196, 14, 25, STR_SORT_BY_POPULATION,STR_SORT_TIP}, +{ WWT_IMGBTN, 13, 0, 196, 26, 189, 0x0, STR_200A_TOWN_NAMES_CLICK_ON_NAME}, +{ WWT_SCROLLBAR, 13, 197, 207, 14, 189, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + + +// used to get a sorted list of the towns +static byte _town_sort[lengthof(_towns)]; +static uint _num_town_sort; + +static char _bufcache[64]; +static byte _last_town_idx; + +static int CDECL TownSorterByName(const void *a, const void *b) +{ + char buf1[64]; + Town *t; + byte val; + int r; + + t = DEREF_TOWN(*(byte*)a); + SET_DPARAM32(0, t->townnameparts); + GetString(buf1, t->townnametype); + + if ( (val=*(byte*)b) != _last_town_idx) { + _last_town_idx = val; + t = DEREF_TOWN(val); + SET_DPARAM32(0, t->townnameparts); + GetString(_bufcache, t->townnametype); + } + + r = strcmp(buf1, _bufcache); + if (_town_sort_order & 1) r = -r; + return r; +} + +static int CDECL TownSorterByPop(const void *a, const void *b) +{ + Town *ta = DEREF_TOWN(*(byte*)a); + Town *tb = DEREF_TOWN(*(byte*)b); + int r = tb->population - ta->population; + if (_town_sort_order & 1) r = -r; + return r; +} + +static void MakeSortedTownList() +{ + Town *t; + int n = 0; + FOR_ALL_TOWNS(t) if(t->xy) _town_sort[n++] = t->index; + _num_town_sort = n; + + _last_town_idx = 255; // used for "cache" + qsort(_town_sort, n, 1, _town_sort_order & 2 ? TownSorterByPop : TownSorterByName); +} + + +static void TownDirectoryWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + int n; + uint p; + Town *t; + + if (_town_sort_dirty) { + _town_sort_dirty = false; + MakeSortedTownList(); + } + + w->vscroll.count = _num_town_sort; + + DrawWindowWidgets(w); + DoDrawString(_town_sort_order & 1 ? "\xAA" : "\xA0", _town_sort_order <= 1 ? 88 : 187, 15, 0x10); + + p = w->vscroll.pos; + n = 0; + + while (p < _num_town_sort) { + t = DEREF_TOWN(_town_sort[p]); + SET_DPARAM16(0, t->index); + SET_DPARAM32(1, t->population); + DrawString(2, 28+n*10, STR_2057, 0); + p++; + if (++n == 16) + break; + } + } break; + + case WE_CLICK: + switch(e->click.widget) { + case 2: { + _town_sort_order = _town_sort_order==0 ? 1 : 0; + _town_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 3: { + _town_sort_order = _town_sort_order==2 ? 3 : 2; + _town_sort_dirty = true; + SetWindowDirty(w); + } break; + + case 4: { + int y = (e->click.pt.y - 28) / 10; + byte p; + Town *t; + + if (!IS_INT_INSIDE(y, 0, 16)) + return; + p = y + w->vscroll.pos; + if (p < _num_town_sort) { + t = DEREF_TOWN(_town_sort[p]); + ScrollMainWindowToTile(t->xy); + } + break; + } + } + break; + + + case WE_4: + SetWindowDirty(w); + break; + } +} + +static const WindowDesc _town_directory_desc = { + -1, -1, 208, 190, + WC_TOWN_DIRECTORY,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _town_directory_widgets, + TownDirectoryWndProc +}; + + +void ShowTownDirectory() +{ + Window *w; + + w = AllocateWindowDescFront(&_town_directory_desc, 0); + if (w) { + w->vscroll.cap = 16; + } +} + + diff --git a/train_cmd.c b/train_cmd.c new file mode 100644 --- /dev/null +++ b/train_cmd.c @@ -0,0 +1,2645 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "command.h" +#include "pathfind.h" +#include "station.h" +#include "table/train_cmd.h" +#include "gfx.h" +#include "news.h" +#include "engine.h" +#include "player.h" + + +#define is_firsthead_sprite(spritenum) \ + (is_custom_sprite(spritenum) \ + ? is_custom_firsthead_sprite(spritenum) \ + : _engine_sprite_add[spritenum] == 0) + + +static const byte _vehicle_initial_x_fract[4] = {10,8,4,8}; +static const byte _vehicle_initial_y_fract[4] = {8,4,8,10}; +static const byte _state_dir_table[4] = { 0x20, 8, 0x10, 4 }; + +static const byte _signal_onedir[14] = { + 0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0, + 0x40, 0x40, 0x40, 0x10, 0x80, 0x20 +}; + +static const byte _signal_otherdir[14] = { + 0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0, + 0x80, 0x80, 0x80, 0x20, 0x40, 0x10 +}; + +void UpdateTrainAcceleration(Vehicle *v) +{ + uint acc, power=0, max_speed=5000, weight=0; + Vehicle *u = v; + + assert(v->subtype == 0); + + // compute stuff like max speed, power, and weight. + do { + const RailVehicleInfo *rvi = &_rail_vehicle_info[u->engine_type]; + + // power is sum of the power for all engines + power += rvi->power; + + // limit the max speed to the speed of the slowest vehicle. + if (rvi->max_speed && rvi->max_speed <= max_speed) max_speed = rvi->max_speed; + + // weight is the sum of the weight of the wagon and the weight of the cargo. + weight += rvi->weight; + weight += (_cargoc.weights[u->cargo_type] * u->cargo_count) >> 4; + + } while ( (u=u->next) != NULL); + + // these are shown in the UI + v->u.rail.cached_weight = weight; + v->u.rail.cached_power = power; + v->max_speed = max_speed; + + assert(weight != 0); + + // compute acceleration + acc = power / weight * 4; + + if (acc >= 255) acc=255; + if (acc == 0) acc++; + + v->acceleration = (byte)acc; +} + +#define F_GRAV 9.82f +#define F_THETA 0.05f + +#define F_HP_KW 0.74569f +#define F_KPH_MS 0.27778f +#define F_MU 0.3f + +#define F_COEF_FRIC 0.04f +#define F_COEF_ROLL 0.18f + +#define F_CURVE_FACTOR (1/96.f) + +bool IsTunnelTile(TileIndex tile); + +static int GetRealisticAcceleration(Vehicle *v) +{ + uint emass = 0; + Vehicle *u = v; + float f = 0.0f, spd; + int curves = 0; + + assert(v->subtype == 0); + + // compute inclination force and number of curves. + do { + const RailVehicleInfo *rvi = &_rail_vehicle_info[u->engine_type]; + uint mass = rvi->weight + ((_cargoc.weights[u->cargo_type] * u->cargo_count) >> 4); + if (rvi->power) emass += mass; + + if (u->u.rail.flags & VRF_GOINGUP) { + f += (float)mass * ( -F_GRAV * F_THETA); + } else if (u->u.rail.flags & VRF_GOINGDOWN) { + f += (float)mass * ( F_GRAV * F_THETA); + } + + // compute curve penalty.. + if (u->next != NULL) { + uint diff = (u->direction - u->next->direction) & 7; + if (diff) { + curves += (diff == 1 || diff == 7) ? 1 : 3; + } + } + } while ((u = u->next) != NULL); + + spd = (float)(v->cur_speed ? v->cur_speed : 1); + + // compute tractive effort + { + float te = (float)v->u.rail.cached_power * (F_HP_KW/F_KPH_MS) / spd; + float te2 = (float)emass * (F_MU * F_GRAV); + if (te > te2) te = te2; + f += te; + } + + // add air resistance + { + float cx = 1.0f; // NOT DONE + + // air resistance is doubled in tunnels. + if (v->vehstatus == 0x40) cx *= 2; + + f -= cx * spd * spd * (F_KPH_MS * F_KPH_MS * 0.001f); + } + + // after this f contains the acceleration. + f /= (float)v->u.rail.cached_weight; + + // add friction to sum of forces (avoid mul by weight). (0.001 because we want kN) + f -= (F_COEF_FRIC * F_GRAV * 0.001f + (F_COEF_ROLL * F_KPH_MS * F_GRAV * 0.001f) * spd); + + // penalty for curves? + if (curves) + f -= (float)min(curves, 8) * F_CURVE_FACTOR; + + return (int)(f * (1.0/(F_KPH_MS * 0.015f)) + 0.5f); +} + + +int GetTrainImage(Vehicle *v, byte direction) +{ + int img = v->spritenum; + int base; + + if (is_custom_sprite(img)) { + base = GetCustomVehicleSprite(v, direction + 4 * is_custom_secondhead_sprite(img)); + if (base) return base; + img = _engine_original_sprites[v->engine_type]; + } + + base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]); + + if (v->cargo_count >= (v->cargo_cap >> 1)) + base += _wagon_full_adder[img]; + return base; +} + +void DrawTrainEngine(int x, int y, int engine, uint32 image_ormod) +{ + const RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; + + int img = rvi->image_index; + uint32 image = 0; + + if (is_custom_sprite(img)) { + image = GetCustomEngineSprite(engine, -1, CID_PURCHASE, 0, 0, 6); + if (!image) img = _engine_original_sprites[engine]; + } + if (!image) { + image = (6 & _engine_sprite_and[img]) + _engine_sprite_base[img]; + } + + if (rvi->flags & RVI_MULTIHEAD) { + DrawSprite(image | image_ormod, x-14, y); + x += 15; + image = 0; + if (is_custom_sprite(img)) { + image = GetCustomEngineSprite(engine, -1, CID_PURCHASE, 0, 0, 2); + if (!image) img = _engine_original_sprites[engine]; + } + if (!image) { + image = ((6 + _engine_sprite_add[img+1]) & _engine_sprite_and[img+1]) + _engine_sprite_base[img+1]; + } + } + DrawSprite(image | image_ormod, x, y); +} + +void DrawTrainEngineInfo(int engine, int x, int y, int maxw) +{ + const RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; + int cap; + uint multihead = ((rvi->flags & RVI_MULTIHEAD) ? 1 : 0); + + SET_DPARAM32(0, ((_price.build_railvehicle >> 3) * rvi->base_cost) >> 5); + SET_DPARAM16(2, rvi->max_speed * 10 >> 4); + SET_DPARAM16(3, rvi->power << multihead); + SET_DPARAM16(1, rvi->weight << multihead); + + SET_DPARAM32(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead); + + cap = rvi->capacity; + SET_DPARAM16(5, STR_8838_N_A); + if (cap != 0) { + SET_DPARAM16(6, cap << multihead); + SET_DPARAM16(5, _cargoc.names_long_p[rvi->cargo_type]); + } + DrawStringMultiCenter(x, y, STR_885B_COST_WEIGHT_T_SPEED_POWER, maxw); +} + + +int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags) +{ + int32 value; + Vehicle *v; + const RailVehicleInfo *rvi; + int dir; + const Engine *e; + int x,y; + + rvi = &_rail_vehicle_info[engine]; + value = (rvi->base_cost * _price.build_railwagon) >> 8; + + if (!(flags & DC_QUERY_COST)) { + _error_message = STR_00E1_TOO_MANY_VEHICLES_IN_GAME; + + v = AllocateVehicle(); + if (v == NULL) + return CMD_ERROR; + + if (flags & DC_EXEC) { + byte img = rvi->image_index; + Vehicle *u; + + v->spritenum = img; + + u = _vehicles; + for(;;) { + if (u->type == VEH_Train && u->tile == (TileIndex)tile && + u->subtype == 4 && u->engine_type == engine) { + u = GetLastVehicleInChain(u); + break; + } + + if (++u == endof(_vehicles)) { + u = NULL; + break; + } + } + + v->engine_type = engine; + + dir = _map5[tile] & 3; + + v->direction = (byte)(dir*2+1); + v->tile = (TileIndex)tile; + + x = GET_TILE_X(tile)*16 | _vehicle_initial_x_fract[dir]; + y = GET_TILE_Y(tile)*16 | _vehicle_initial_y_fract[dir]; + + v->x_pos = x; + v->y_pos = y; + v->z_pos = GetSlopeZ(x,y); + v->owner = _current_player; + v->z_height = 6; + v->u.rail.track = 0x80; + v->vehstatus = VS_HIDDEN | VS_DEFPAL; + + v->subtype = 4; + if (u != NULL) { + u->next = v; + v->subtype = 2; + v->u.rail.first_engine = u->u.rail.first_engine; + if (v->u.rail.first_engine == 0xffff && u->subtype == 0) + v->u.rail.first_engine = u->engine_type; + } else { + v->u.rail.first_engine = 0xffff; + } + + v->cargo_type = rvi->cargo_type; + v->cargo_cap = rvi->capacity; + v->value = value; +// v->day_counter = 0; + + e = &_engines[engine]; + v->u.rail.railtype = e->railtype; + + v->build_year = _cur_year; + v->type = VEH_Train; + v->cur_image = 0xAC2; + + _new_wagon_id = v->index; + + VehiclePositionChanged(v); + + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + } + } + + return value; +} + +// Move all free vehicles in the depot to the train +static void NormalizeTrainVehInDepot(Vehicle *u) +{ + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype==4 && + v->tile == u->tile && + v->u.rail.track == 0x80) { + if (DoCommandByTile(0,v->index | (u->index<<16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE) == CMD_ERROR) + break; + } + } +} + +static const byte _railveh_unk1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static const byte _railveh_score[] = { + 1, 4, 7, 19, 20, 30, 31, 19, + 20, 21, 22, 10, 11, 30, 31, 32, + 33, 34, 35, 29, 45, 32, 50, 40, + 41, 51, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 60, 62, + 63, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 71, 72, 73, + 74, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + + +static int32 EstimateTrainCost(const RailVehicleInfo *rvi) +{ + return (rvi->base_cost * (_price.build_railvehicle >> 3)) >> 5; +} + +/* Build a railroad vehicle + * p1 = vehicle type id + */ + +int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + const RailVehicleInfo *rvi; + int value,dir; + Vehicle *v, *u; + byte unit_num; + Engine *e; + uint tile; + + _cmd_build_rail_veh_var1 = 0; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + tile = TILE_FROM_XY(x,y); + rvi = &_rail_vehicle_info[p1]; + + if (rvi->flags & RVI_WAGON) { + return CmdBuildRailWagon(p1, tile, flags); + } + + value = EstimateTrainCost(rvi); + + if (!(flags & DC_QUERY_COST)) { + v = AllocateVehicle(); + if (v == NULL || _ptr_to_next_order >= endof(_order_array)) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + unit_num = GetFreeUnitNumber(VEH_Train); + if (unit_num > _patches.max_trains) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + if (flags & DC_EXEC) { + v->unitnumber = unit_num; + + dir = _map5[tile] & 3; + + v->direction = (byte)(dir*2+1); + v->tile = (TileIndex)tile; + v->owner = _current_player; + v->x_pos = (x |= _vehicle_initial_x_fract[dir]); + v->y_pos = (y |= _vehicle_initial_y_fract[dir]); + v->z_pos = GetSlopeZ(x,y); + v->z_height = 6; + v->u.rail.track = 0x80; + v->u.rail.first_engine = 0xffff; + v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; +// v->subtype = 0; + v->spritenum = rvi->image_index; + v->cargo_type = rvi->cargo_type; + v->cargo_cap = rvi->capacity; + v->max_speed = rvi->max_speed; +// v->cargo_count = 0; + v->value = value; +// v->day_counter = 0; +// v->next_order = 0; +// v->next_station = 0; +// v->load_unload_time_rem = 0; +// v->progress = 0; +// v->targetairport = 0; +// v->crash_anim_pos = 0; + v->last_station_visited = 0xff; + v->dest_tile = 0; +// v->profit_last_year = 0; +// v->profit_this_year = 0; + + v->engine_type = (byte)p1; + e = &_engines[p1]; + + v->reliability = e->reliability; + v->reliability_spd_dec = e->reliability_spd_dec; + v->max_age = e->lifelength * 366; + + v->string_id = STR_SV_TRAIN_NAME; +// v->cur_speed = 0; +// v->subspeed = 0; + v->u.rail.railtype = e->railtype; + _new_train_id = v->index; +// v->cur_order_index = 0; +// v->num_orders = 0; + + *(v->schedule_ptr = _ptr_to_next_order++) = 0; +// v->next_in_chain = 0xffff; +// v->next = NULL; + + v->service_interval = _patches.servint_trains; +// v->breakdown_ctr = 0; +// v->breakdowns_since_last_service = 0; +// v->unk4D = 0; + v->date_of_last_service = _date; + v->build_year = _cur_year; + v->type = VEH_Train; + v->cur_image = 0xAC2; + + VehiclePositionChanged(v); + + if (rvi->flags&RVI_MULTIHEAD && (u=AllocateVehicle()) != NULL) { + u->direction = v->direction; + u->owner = v->owner; + u->tile = v->tile; + u->x_pos = v->x_pos; + u->y_pos = v->y_pos; + u->z_pos = v->z_pos; + u->z_height = 6; + u->u.rail.track = 0x80; + v->u.rail.first_engine = 0xffff; + u->vehstatus = VS_HIDDEN | VS_DEFPAL; + u->subtype = 2; + u->spritenum = v->spritenum + 1; + u->cargo_type = v->cargo_type; + u->cargo_cap = v->cargo_cap; + u->u.rail.railtype = v->u.rail.railtype; +// u->next_in_chain = 0xffff; + v->next = u; + u->engine_type = v->engine_type; + u->build_year = v->build_year; + v->value = u->value = v->value >> 1; +// u->day_counter = 0; + u->type = VEH_Train; + u->cur_image = 0xAC2; + VehiclePositionChanged(u); + } + + UpdateTrainAcceleration(v); + NormalizeTrainVehInDepot(v); + + InvalidateWindow(WC_VEHICLE_DEPOT, tile); + InvalidateWindow(WC_TRAINS_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + } + } + _cmd_build_rail_veh_var1 = _railveh_unk1[p1]; + _cmd_build_rail_veh_score = _railveh_score[p1]; + return value; +} + + +bool IsTrainDepotTile(TileIndex tile) +{ + return IS_TILETYPE(tile, MP_RAILWAY) && + (_map5[tile] & 0xFC) == 0xC0; +} + +bool IsTunnelTile(TileIndex tile) +{ + return IS_TILETYPE(tile, MP_TUNNELBRIDGE) && + (_map5[tile]&0x80) == 0; +} + + +int CheckStoppedInDepot(Vehicle *v) +{ + int count; + TileIndex tile = v->tile; + + /* check if stopped in a depot */ + if (!IsTrainDepotTile(tile) || v->cur_speed != 0) { +errmsg: + _error_message = STR_881A_TRAINS_CAN_ONLY_BE_ALTERED; + return -1; + } + + count = 0; + do { + count++; + if (v->u.rail.track != 0x80 || v->tile != (TileIndex)tile || + (v->subtype==0 && !(v->vehstatus&VS_STOPPED))) + goto errmsg; + } while ( (v=v->next) != NULL); + + return count; +} + +// unlink a rail wagon from the linked list. +// returns the new value of first +static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first) +{ + // unlinking the first vehicle of the chain? + v->u.rail.first_engine = 0xffff; + if (v == first) { + Vehicle *u; + if ((v=v->next) == NULL) return NULL; + for (u=v; u; u=u->next) u->u.rail.first_engine = v->engine_type; + v->subtype = 4; + return v; + } else { + Vehicle *u; + for(u=first; u->next!=v; u=u->next) {} + u->next = v->next; + return first; + } +} + +static Vehicle *FindGoodVehiclePos(Vehicle *src) +{ + Vehicle *dst; + uint16 eng = src->engine_type; + TileIndex tile = src->tile; + + FOR_ALL_VEHICLES(dst) { + if (dst->type==VEH_Train && dst->subtype==4 && dst->tile==tile) { + // check so all vehicles in the line have the same engine. + Vehicle *v = dst; + while (v->engine_type == eng) { + if ((v = v->next) == NULL) return dst; + } + } + } + + return NULL; +} + +/* p1 & 0xffff= source vehicle index + p1 & 0xffff0000 = what wagon to put the wagon AFTER, 0xffff0000 to make a new line + p2 & 1 = move all vehicles following the vehicle.. + */ + +int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *src, *dst, *src_head, *dst_head; + bool is_loco; + + src = &_vehicles[p1 & 0xffff]; + if (src->type != VEH_Train) return CMD_ERROR; + + is_loco = !(_rail_vehicle_info[src->engine_type].flags & RVI_WAGON) + && is_firsthead_sprite(src->spritenum); + + // if nothing is selected as destination, try and find a matching vehicle to drag to. + if (((int32)p1 >> 16) == -1) { + dst = NULL; + if (!is_loco) dst = FindGoodVehiclePos(src); + } else { + dst = &_vehicles[((int32)p1 >> 16)]; + } + + // don't move the same vehicle.. + if (src == dst) + return 0; + + /* the player must be the owner */ + if (!CheckOwnership(src->owner) || (dst!=NULL && !CheckOwnership(dst->owner))) + return CMD_ERROR; + + /* locate the head of the two chains */ + src_head = GetFirstVehicleInChain(src); + dst_head = NULL; + if (dst != NULL) dst_head = GetFirstVehicleInChain(dst); + + /* check if all vehicles in the source train are stopped */ + if (CheckStoppedInDepot(src_head) < 0) + return CMD_ERROR; + + /* check if all the vehicles in the dest train are stopped, + * and that the length of the dest train is no longer than XXX vehicles */ + if (dst_head != NULL) { + int num = CheckStoppedInDepot(dst_head); + if (num < 0) + return CMD_ERROR; + + if (num > (_patches.mammoth_trains ? 100 : 9) && dst_head->subtype==0) + return_cmd_error(STR_8819_TRAIN_TOO_LONG); + + // if it's a multiheaded vehicle we're dragging to, drag to the vehicle before.. + while (is_custom_secondhead_sprite(dst->spritenum) + || (!is_custom_sprite(dst->spritenum) && _engine_sprite_add[dst->spritenum] != 0)) { + Vehicle *v = GetPrevVehicleInChain(dst); + if (!v || src == v) break; + dst = v; + } + + assert(dst_head->tile == src_head->tile); + } + + // when moving all wagons, we can't have the same src_head and dst_head + if (p2 & 1 && src_head == dst_head) + return 0; + + // moving a loco to a new line?, then we need to assign a unitnumber. + if (dst == NULL && src->subtype != 0 && is_loco) { + uint unit_num = GetFreeUnitNumber(VEH_Train); + if (unit_num > _patches.max_trains) + return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); + + if (flags & DC_EXEC) + src->unitnumber = unit_num; + } + + + /* do it? */ + if (flags & DC_EXEC) { + if (p2 & 1) { + // unlink ALL wagons + if (src != src_head) { + Vehicle *v = src_head; + while (v->next != src) v=v->next; + v->next = NULL; + } + } else { + // unlink single wagon from linked list + UnlinkWagon(src, src_head); + src->next = NULL; + } + + if (dst == NULL) { + // move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4. + if (is_loco) { + if (src->subtype != 0) { + // setting the type to 0 also involves setting up the schedule_ptr field. + src->subtype = 0; + assert(src->schedule_ptr == NULL); + *(src->schedule_ptr = _ptr_to_next_order++) = 0; + src->num_orders = 0; + } + dst_head = src; + } else { + src->subtype = 4; + } + src->u.rail.first_engine = 0xffff; + } else { + if (src->subtype == 0) { + // the vehicle was previously a loco. need to free the schedule list and delete vehicle windows etc. + DeleteWindowById(WC_VEHICLE_VIEW, src->index); + DeleteVehicleSchedule(src); + } + + src->subtype = 2; + src->unitnumber = 0; // doesn't occupy a unitnumber anymore. + + // setup first_engine + src->u.rail.first_engine = dst->u.rail.first_engine; + if (src->u.rail.first_engine == 0xffff && dst->subtype == 0) + src->u.rail.first_engine = dst->engine_type; + + // link in the wagon(s) in the chain. + { + Vehicle *v = src; + while (v->next != NULL) { + v->next->u.rail.first_engine = v->u.rail.first_engine; + v = v->next; + } + v->next = dst->next; + } + dst->next = src; + } + + if (src_head->subtype == 0) + UpdateTrainAcceleration(src_head); + InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index); + + if (dst_head) { + if (dst_head->subtype == 0) + UpdateTrainAcceleration(dst_head); + InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index); + } + + InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile); + InvalidateWindow(WC_TRAINS_LIST, _current_player); + } + + return 0; +} + +/* p1 = train to start / stop */ +int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->u.rail.days_since_order_progr = 0; + v->vehstatus ^= VS_STOPPED; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + } + return 0; +} + +// p1 = wagon/loco index +// p2 = mode +// 0: sell just the vehicle +// 1: sell the vehicle and all vehicles that follow it in the chain +// 2: when selling attached locos, rearrange all vehicles after it to separate lines. +int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v, *first,*last; + int32 cost; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + // get first vehicle in chain + first = v; + if (first->subtype != 0) { + first = GetFirstVehicleInChain(first); + last = NULL; + } else { + if (p2 != 1) { + // sell last part of multiheaded? + last = GetLastVehicleInChain(v); + if (is_firsthead_sprite(last->spritenum)) + last = NULL; + } else { + last = NULL; + } + } + + // make sure the vehicle is stopped in the depot + if (CheckStoppedInDepot(first) < 0) + return CMD_ERROR; + + + if (flags & DC_EXEC) { + // always redraw the depot. maybe redraw train list + InvalidateWindow(WC_VEHICLE_DEPOT, first->tile); + if (first->subtype == 0) InvalidateWindow(WC_TRAINS_LIST, first->owner); + // when selling an attached locomotive. we need to delete its window. + if (v->subtype == 0) { + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + + // rearrange all vehicles that follow to separate lines. + if (p2 == 2) { + Vehicle *u,*tmp; + u = v->next; + while (u != last) { + tmp = u; + u = u->next; + DoCommandByTile(tmp->tile, tmp->index | ((-1)<<16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); + } + } + } + + // delete the vehicles + cost = 0; + for(;;) { + Vehicle *tmp; + + assert(first); + first = UnlinkWagon(v, first); + cost -= v->value; + tmp = v; + v = v->next; + DeleteVehicle(tmp); + if (v == NULL || p2 != 1) break; + } + + // delete last vehicle of multiheaded train? + if (last) { + first = UnlinkWagon(last, first); + cost -= last->value; + DeleteVehicle(last); + } + + // an attached train changed? + if (first && first->subtype == 0) { + UpdateTrainAcceleration(first); + InvalidateWindow(WC_VEHICLE_DETAILS, first->index); + } + } else { + cost = 0; + for(;;) { + cost -= v->value; + if ((v=v->next) == NULL || p2 != 1) break; + } + if (last) cost -= last->value; + } + + return cost; +} + +static void UpdateTrainDeltaXY(Vehicle *v, int direction) +{ +#define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) + static const uint32 _delta_xy_table[8] = { + MKIT(3, 3, -1, -1), + MKIT(3, 7, -1, -3), + MKIT(3, 3, -1, -1), + MKIT(7, 3, -3, -1), + MKIT(3, 3, -1, -1), + MKIT(3, 7, -1, -3), + MKIT(3, 3, -1, -1), + MKIT(7, 3, -3, -1), + }; +#undef MKIT + + uint32 x = _delta_xy_table[direction]; + + v->x_offs = (byte)x; + v->y_offs = (byte)(x>>=8); + v->sprite_width = (byte)(x>>=8); + v->sprite_height = (byte)(x>>=8); +} + +static void UpdateVarsAfterSwap(Vehicle *v) +{ + UpdateTrainDeltaXY(v, v->direction); + v->cur_image = GetTrainImage(v, v->direction); + BeginVehicleMove(v); + VehiclePositionChanged(v); + EndVehicleMove(v); +} + +static void SetLastSpeed(Vehicle *v, int spd) { + int old = v->u.rail.last_speed; + if (spd != old) { + v->u.rail.last_speed = spd; + if (_patches.vehicle_speed || !old != !spd) + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } +} + +static void ReverseTrainSwapVeh(Vehicle *v, int l, int r) +{ + Vehicle *a, *b; + + /* locate vehicles to swap */ + for(a=v; l!=0; l--) { a = a->next; } + for(b=v; r!=0; r--) { b = b->next; } + + if (a != b) { + /* swap the hidden bits */ + { + uint16 tmp = (a->vehstatus & ~VS_HIDDEN) | (b->vehstatus&VS_HIDDEN); + b->vehstatus = (b->vehstatus & ~VS_HIDDEN) | (a->vehstatus&VS_HIDDEN); + a->vehstatus = tmp; + } + + /* swap variables */ + swap_byte(&a->u.rail.track, &b->u.rail.track); + swap_byte(&a->direction, &b->direction); + + /* toggle direction */ + if (!(a->u.rail.track & 0x80)) a->direction ^= 4; + if (!(b->u.rail.track & 0x80)) b->direction ^= 4; + + /* swap more variables */ + swap_int16(&a->x_pos, &b->x_pos); + swap_int16(&a->y_pos, &b->y_pos); + swap_tile(&a->tile, &b->tile); + swap_byte(&a->z_pos, &b->z_pos); + + /* update other vars */ + UpdateVarsAfterSwap(a); + UpdateVarsAfterSwap(b); + } else { + if (!(a->u.rail.track & 0x80)) a->direction ^= 4; + UpdateVarsAfterSwap(a); + } +} + +static void ReverseTrainDirection(Vehicle *v) +{ + int l = 0, r = -1; + Vehicle *u; + + if (IsTrainDepotTile(v->tile)) + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + + // count number of vehicles + u = v; + do r++; while ( (u = u->next) != NULL ); + + /* swap start<>end, start+1<>end-1, ... */ + do { + ReverseTrainSwapVeh(v, l++, r--); + } while (l <= r); + + if (IsTrainDepotTile(v->tile)) + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + + v->u.rail.flags &= ~VRF_REVERSING; +} + +/* p1 = vehicle */ +int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + _error_message = STR_EMPTY; + +// if (v->u.rail.track & 0x80 || IsTrainDepotTile(v->tile)) +// return CMD_ERROR; + + if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_patches.realistic_acceleration && v->cur_speed != 0) { + v->u.rail.flags ^= VRF_REVERSING; + } else { + v->cur_speed = 0; + SetLastSpeed(v, 0); + ReverseTrainDirection(v); + } + } + return 0; +} + +int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) + v->u.rail.force_proceed = 0x50; + + return 0; +} + +// p1 = vehicle to refit +// p2 = new cargo + +int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + int32 cost; + uint num; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + + v = &_vehicles[p1]; + if (!CheckOwnership(v->owner) || CheckStoppedInDepot(v) < 0) + return CMD_ERROR; + + cost = 0; + num = 0; + + do { + if (!(_rail_vehicle_info[v->engine_type].flags & RVI_WAGON) && (byte)p2 != v->cargo_type && v->cargo_cap != 0) { + cost += (_price.ship_base >> 7); + num += v->cargo_cap; + if (flags & DC_EXEC) { + v->cargo_count = 0; + v->cargo_type = (byte)p2; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } + } while ( (v=v->next) != NULL); + + _returned_refit_amount = num; + + return cost; +} + +int GetDepotByTile(uint tile) +{ + Depot *d; + int i=0; + for(d=_depots; d->xy != (TileIndex)tile; d++) { i++; } + return i; +} + +typedef struct TrainFindDepotData { + uint best_length; + uint tile; + byte owner; +} TrainFindDepotData; + +static bool TrainFindDepotEnumProc(uint tile, TrainFindDepotData *tfdd, int track, uint length, byte *state) +{ + if (IS_TILETYPE(tile, MP_RAILWAY) && _map_owner[tile] == tfdd->owner) { + if ((_map5[tile] & ~0x3) == 0xC0) { + if (length < tfdd->best_length) { + tfdd->best_length = length; + tfdd->tile = tile; + } + return true; + } + + // make sure the train doesn't run against a oneway signal + if ((_map5[tile] & 0xC0) == 0x40) { + if (!(_map3_lo[tile] & _signal_onedir[track]) && _map3_lo[tile] & _signal_otherdir[track]) + return true; + } + } + + // stop searching if we've found a destination that is closer already. + return length >= tfdd->best_length; +} + +// returns the tile of a depot to goto to +static uint FindClosestTrainDepot(Vehicle *v) +{ + int i; + TrainFindDepotData tfdd; + uint tile = v->tile; + + if (IsTrainDepotTile(tile)) + return tile; + + if (v->u.rail.track == 0x40) { tile = GetVehicleOutOfTunnelTile(v); } + + tfdd.owner = v->owner; + tfdd.best_length = (uint)-1; + + if (!_patches.new_depot_finding) { + // search in all directions + for(i=0; i!=4; i++) + NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); + if (tfdd.best_length != (uint)-1) + return tfdd.tile; + } else { + // search in the forward direction first. + i = v->direction >> 1; + if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; } + NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); + if (tfdd.best_length != (uint)-1) + return tfdd.tile; + + // search in backwards direction + i = (v->direction^4) >> 1; + if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; } + NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL); + if (tfdd.best_length != (uint)-1) + return tfdd.tile; + } + + return (uint)-1; +} + +int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1]; + uint depot_tile; + + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + if (flags & DC_EXEC) { + if (v->next_order & OF_UNLOAD) { + v->u.rail.days_since_order_progr = 0; + v->cur_order_index++; + } + + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + return 0; + } + + depot_tile = FindClosestTrainDepot(v); + if (depot_tile == (uint)-1) + return_cmd_error(STR_883A_UNABLE_TO_FIND_ROUTE_TO); + + if (flags & DC_EXEC) { + v->dest_tile = depot_tile; + v->next_order = OF_NON_STOP | OF_FULL_LOAD | OT_GOTO_DEPOT; + v->next_order_param = GetDepotByTile(depot_tile); + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + + return 0; +} + +/* p1 = vehicle + * p2 = new service int + */ +int32 CmdChangeTrainServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + v->service_interval = (uint16)p2; + InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 8); + } + + return 0; +} + +void OnTick_Train() +{ + _age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1); +} + +static const int8 _vehicle_smoke_pos[16] = { + -4, -4, -4, 0, 4, 4, 4, 0, + -4, 0, 4, 4, 4, 0,-4,-4, +}; + +static void HandleLocomotiveSmokeCloud(Vehicle *v) +{ + Vehicle *u; + + if (v->vehstatus & VS_TRAIN_SLOWING || v->load_unload_time_rem != 0 || v->cur_speed < 2) + return; + + u = v; + + do { + int engtype = v->engine_type; + + // no smoke? + if (_rail_vehicle_info[engtype].flags & 2 + || _engines[engtype].railtype > 0 + || (v->vehstatus&VS_HIDDEN) || (v->u.rail.track & 0xC0) ) + continue; + + switch (_rail_vehicle_info[engtype].engclass) { + case 0: + // steam smoke. + if ( (v->tick_counter&0xF) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile)) { + CreateEffectVehicleRel(v, + (_vehicle_smoke_pos[v->direction]), + (_vehicle_smoke_pos[v->direction+8]), + 10, + EV_STEAM_SMOKE); + } + break; + + case 1: + // diesel smoke + if (u->cur_speed <= 40 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) { + CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_3); + } + break; + + case 2: + // blue spark + if ( (v->tick_counter&0x3) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) { + CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_2); + } + break; + } + } while ( (v = v->next) != NULL ); + +} + +static void TrainPlayLeaveStationSound(Vehicle *v) +{ + static const byte sfx[3] = { 0x2, 0x8, 0x8 }; + int engtype = v->engine_type; + + switch (_engines[engtype].railtype) { + case 0: SndPlayVehicleFx(sfx[_rail_vehicle_info[engtype].engclass], v); break; + case 1: SndPlayVehicleFx(0x41, v); break; + case 2: SndPlayVehicleFx(0x47, v); break; + } +} + +static bool CheckTrainStayInDepot(Vehicle *v) +{ + Vehicle *u; + if (v->u.rail.track != 0x80) // first wagon (eg engine) in depot + return false; + + // make sure that all vehicles are in the depot + u = GetLastVehicleInChain(v); + if (u->u.rail.track != 0x80) + return false; + + // fix hung train if both ends are in depots (when here first wagon and last wagon is in depot) + // both first and last should be in the same depot, eg on the same tile + if (v->tile != u->tile) + return false; + + if (v->u.rail.force_proceed == 0) { + if (++v->load_unload_time_rem < 37) + return true; + v->load_unload_time_rem = 0; + + if (UpdateSignalsOnSegment(v->tile, v->direction)) + return true; + } + + TrainPlayLeaveStationSound(v); + + v->u.rail.track = 1; + if (v->direction & 2) + v->u.rail.track = 2; + + v->vehstatus &= ~VS_HIDDEN; + v->cur_speed = 0; + + UpdateTrainDeltaXY(v, v->direction); + v->cur_image = GetTrainImage(v, v->direction); + VehiclePositionChanged(v); + UpdateSignalsOnSegment(v->tile, v->direction); + UpdateTrainAcceleration(v); + InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); + + return false; +} + +typedef struct TrainTrackFollowerData { + TileIndex dest_coords; + int station_index; // station index we're heading for + uint best_bird_dist; + uint best_track_dist; + byte best_track; +} TrainTrackFollowerData; + +static bool TrainTrackFollower(uint tile, TrainTrackFollowerData *ttfd, int track, uint length, byte *state){ + if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile]&0xC0) == 0x40) { + // the tile has a signal + byte m3 = _map3_lo[tile]; + if (!(m3 & _signal_onedir[track])) { + // if one way signal not pointing towards us, stop going in this direction. + if (m3 & _signal_otherdir[track]) + return true; + } else if (_map2[tile] & _signal_onedir[track]) { + // green signal in our direction. either one way or two way. + *state = true; + } else if (m3 & _signal_otherdir[track]) { + // two way signal. unless we passed another green signal on the way, + // stop going in this direction. + if (!*state) return true; + } + } + + // heading for nowhere? + if (ttfd->dest_coords == 0) + return false; + + // did we reach the final station? + if (tile == ttfd->dest_coords || + (IS_TILETYPE(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0, 8) && _map2[tile] == ttfd->station_index)) { + // found station + ttfd->best_bird_dist = 0; + if (length < ttfd->best_track_dist) { + ttfd->best_track_dist = length; + ttfd->best_track = state[1]; + } + return true; + } else { + uint dist; + + // we've actually found the destination already. no point searching in directions longer than this. + if (ttfd->best_track_dist != (uint)-1) + return length >= ttfd->best_track_dist; + + // didn't find station + dist = GetTileDist(tile, ttfd->dest_coords); + if (dist < ttfd->best_bird_dist) { + ttfd->best_bird_dist = dist; + ttfd->best_track = state[1]; + } + return false; + } +} + +static void FillWithStationData(TrainTrackFollowerData *fd, Vehicle *v) +{ + uint tile; + + fd->dest_coords = tile = v->dest_tile; + fd->station_index = -1; + + if (IS_TILETYPE(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0, 8) ) + fd->station_index = _map2[tile]; +} + +static const byte _initial_tile_subcoord[6][4][3] = { +{{ 15, 8, 1 },{ 0, 0, 0 },{ 0, 8, 5 },{ 0, 0, 0 }}, +{{ 0, 0, 0 },{ 8, 0, 3 },{ 0, 0, 0 },{ 8,15, 7 }}, +{{ 0, 0, 0 },{ 7, 0, 2 },{ 0, 7, 6 },{ 0, 0, 0 }}, +{{ 15, 8, 2 },{ 0, 0, 0 },{ 0, 0, 0 },{ 8,15, 6 }}, +{{ 15, 7, 0 },{ 8, 0, 4 },{ 0, 0, 0 },{ 0, 0, 0 }}, +{{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 8, 4 },{ 7,15, 0 }}, +}; + +static const uint32 _reachable_tracks[4] = { + 0x10091009, + 0x00160016, + 0x05200520, + 0x2A002A00, +}; + +static const byte _search_directions[6][4] = { + { 0, 9, 2, 9 }, // track 1 + { 9, 1, 9, 3 }, // track 2 + { 9, 0, 3, 9 }, // track upper + { 1, 9, 9, 2 }, // track lower + { 3, 2, 9, 9 }, // track left + { 9, 9, 1, 0 }, // track right +}; + +static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0}; + +/* choose a track */ +static byte ChooseTrainTrack(Vehicle *v, uint tile, int direction, byte trackbits) +{ + TrainTrackFollowerData fd; + int bits = trackbits; + uint best_track; +#if 0 + int time = rdtsc(); + static float f; +#endif + + assert( (bits & ~0x3F) == 0); + + /* quick return in case only one possible direction is available */ + if (KILL_FIRST_BIT(bits) == 0) + return FIND_FIRST_BIT(bits); + + FillWithStationData(&fd, v); + + if (_patches.new_pathfinding) { + fd.best_bird_dist = (uint)-1; + fd.best_track_dist = (uint)-1; + fd.best_track = 0xFF; + NewTrainPathfind(tile - _tileoffs_by_dir[direction], direction, (TPFEnumProc*)TrainTrackFollower, &fd, NULL); + +// printf("Train %d %s\n", v->unitnumber, fd.best_track_dist == -1 ? "NOTFOUND" : "FOUND"); + + if (fd.best_track == 0xff) { + // blaha + best_track = FIND_FIRST_BIT(bits); + } else { + best_track = fd.best_track & 7; + } + } else { + int i, r; + uint best_bird_dist = 0; + uint best_track_dist = 0; + byte train_dir = v->direction & 3; + + + best_track = -1; + + do { + i = FIND_FIRST_BIT(bits); + bits = KILL_FIRST_BIT(bits); + + fd.best_bird_dist = (uint)-1; + fd.best_track_dist = (uint)-1; + + NewTrainPathfind(tile, _search_directions[i][direction], (TPFEnumProc*)TrainTrackFollower, &fd, NULL); + if (best_track != -1) { + if (best_track_dist == -1) { + if (fd.best_track_dist == -1) { + /* neither reached the destination, pick the one with the smallest bird dist */ + if (fd.best_bird_dist > best_bird_dist) goto bad; + if (fd.best_bird_dist < best_bird_dist) goto good; + } else { + /* we found the destination for the first time */ + goto good; + } + } else { + if (fd.best_track_dist == -1) { + /* didn't find destination, but we've found the destination previously */ + goto bad; + } else { + /* both old & new reached the destination, compare track length */ + if (fd.best_track_dist > best_track_dist) goto bad; + if (fd.best_track_dist < best_track_dist) goto good; + } + } + + /* if we reach this position, there's two paths of equal value so far. + * pick one randomly. */ + r = (byte)Random(); + if (_pick_track_table[i] == train_dir) r += 80; + if (_pick_track_table[best_track] == train_dir) r -= 80; + + if (r <= 127) goto bad; + } + good:; + best_track = i; + best_bird_dist = fd.best_bird_dist; + best_track_dist = fd.best_track_dist; + bad:; + } while (bits != 0); +// printf("Train %d %s\n", v->unitnumber, best_track_dist == -1 ? "NOTFOUND" : "FOUND"); + assert(best_track != -1); + } + +#if 0 + time = rdtsc() - time; + f = f * 0.99 + 0.01 * time; + printf("PF time = %d %f\n", time, f); +#endif + + return best_track; +} + + +static bool CheckReverseTrain(Vehicle *v) +{ + TrainTrackFollowerData fd; + int i, r; + int best_track; + uint best_bird_dist = 0; + uint best_track_dist = 0; + uint reverse, reverse_best; + + if (_opt.diff.line_reverse_mode != 0 || + v->u.rail.track & 0xC0 || + !(v->direction & 1)) + return false; + + FillWithStationData(&fd, v); + + best_track = -1; + reverse_best = reverse = 0; + + assert(v->u.rail.track); + + i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][v->direction>>1]; + + while(true) { + fd.best_bird_dist = (uint)-1; + fd.best_track_dist = (uint)-1; + + NewTrainPathfind(v->tile, reverse ^ i, (TPFEnumProc*)TrainTrackFollower, &fd, NULL); + + if (best_track != -1) { + if (best_bird_dist != 0) { + if (fd.best_bird_dist != 0) { + /* neither reached the destination, pick the one with the smallest bird dist */ + if (fd.best_bird_dist > best_bird_dist) goto bad; + if (fd.best_bird_dist < best_bird_dist) goto good; + } else { + /* we found the destination for the first time */ + goto good; + } + } else { + if (fd.best_bird_dist != 0) { + /* didn't find destination, but we've found the destination previously */ + goto bad; + } else { + /* both old & new reached the destination, compare track length */ + if (fd.best_track_dist > best_track_dist) goto bad; + if (fd.best_track_dist < best_track_dist) goto good; + } + } + + /* if we reach this position, there's two paths of equal value so far. + * pick one randomly. */ + r = (byte)Random(); + if (_pick_track_table[i] == (v->direction & 3)) r += 80; + if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80; + if (r <= 127) goto bad; + } +good:; + best_track = i; + best_bird_dist = fd.best_bird_dist; + best_track_dist = fd.best_track_dist; + reverse_best = reverse; +bad:; + if (reverse != 0) + break; + reverse = 2; + } + + return reverse_best != 0; +} + +static bool ProcessTrainOrder(Vehicle *v) +{ + uint order; + bool result; + + // These are un-interruptible + if ((v->next_order & OT_MASK) >= OT_GOTO_DEPOT && (v->next_order & OT_MASK) <= OT_LEAVESTATION) { + + // Let a depot order in the schedule interrupt. + if ((v->next_order & (OT_MASK|OF_UNLOAD)) != (OT_GOTO_DEPOT|OF_UNLOAD)) + return false; + } + + if ((v->next_order & (OT_MASK|OF_UNLOAD|OF_FULL_LOAD)) == (OT_GOTO_DEPOT|OF_UNLOAD|OF_FULL_LOAD) && + v->date_of_last_service+v->service_interval > _date) { + v->cur_order_index++; + } + + // check if we've reached the checkpoint? + if ((v->next_order & OT_MASK) == OT_GOTO_CHECKPOINT && v->tile == v->dest_tile) { + v->cur_order_index++; + } + + // check if we've reached a non-stop station while TTDPatch nonstop is enabled.. + if (_patches.new_nonstop && (v->next_order & OF_NON_STOP) && v->next_order_param == _map2[v->tile]) { + v->cur_order_index++; + } + + // Get the current order + if (v->cur_order_index >= v->num_orders) + v->cur_order_index = 0; + order = v->schedule_ptr[v->cur_order_index]; + + // If no order, do nothing. + if (order == 0) { + v->next_order = OT_NOTHING; + v->dest_tile = 0; + return false; + } + + // If it is unchanged, keep it. + if (order == (uint)((v->next_order | (v->next_order_param<<8)))) + return false; + + // Otherwise set it, and determine the destination tile. + v->next_order = (byte)order; + v->next_order_param = (byte)(order >> 8); + + v->dest_tile = 0; + + result = false; + if ((order & OT_MASK) == OT_GOTO_STATION) { + if ( (byte)(order >> 8) == v->last_station_visited) + v->last_station_visited = 0xFF; + v->dest_tile = DEREF_STATION(order >> 8)->xy; + result = CheckReverseTrain(v); + } else if ((order & OT_MASK) == OT_GOTO_DEPOT) { + v->dest_tile = _depots[order >> 8].xy; + result = CheckReverseTrain(v); + } else if ((order & OT_MASK) == OT_GOTO_CHECKPOINT) { + v->dest_tile = _checkpoints[order >> 8].xy; + result = CheckReverseTrain(v); + } + + InvalidateVehicleOrderWidget(v); + + return result; +} + +static void MarkTrainDirty(Vehicle *v) +{ + do { + v->cur_image = GetTrainImage(v, v->direction); + MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); + } while ( (v=v->next) != NULL); +} + +static void HandleTrainLoading(Vehicle *v, bool mode) +{ + if (v->next_order == OT_NOTHING) + return; + + if (v->next_order != OT_DUMMY) { + if ((v->next_order&OT_MASK) != OT_LOADING) + return; + + if (mode) + return; + + // don't mark the train as lost if we're loading on the final station. + if (v->next_order & OF_NON_STOP) + v->u.rail.days_since_order_progr = 0; + + if (--v->load_unload_time_rem) + return; + + if (v->next_order&OF_FULL_LOAD && CanFillVehicle(v)) { + SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); + if (LoadUnloadVehicle(v)) { + InvalidateWindow(WC_TRAINS_LIST, v->owner); + MarkTrainDirty(v); + + // need to update acceleration since the goods on the train changed. + UpdateTrainAcceleration(v); + } + return; + } + + TrainPlayLeaveStationSound(v); + + { + byte b = v->next_order; + v->next_order = OT_LEAVESTATION; + + // If this was not the final order, don't remove it from the list. + if (!(b & OF_NON_STOP)) + return; + } + } + + v->u.rail.days_since_order_progr = 0; + v->cur_order_index++; + InvalidateVehicleOrderWidget(v); +} + +static int UpdateTrainSpeed(Vehicle *v) +{ + uint spd; + uint accel; + + if (v->vehstatus & VS_STOPPED || v->u.rail.flags & VRF_REVERSING) { + accel = -v->acceleration * 2; + } else { + accel = v->acceleration; + if (_patches.realistic_acceleration) { + accel = GetRealisticAcceleration(v); + } + } + + spd = v->subspeed + accel * 2; + v->subspeed = (byte)spd; + v->cur_speed = spd = clamp(v->cur_speed + ((int)spd >> 8), 0, v->max_speed); + + if (!(v->direction & 1)) spd = spd * 3 >> 2; + + spd += v->progress; + v->progress = (byte)spd; + return (spd >> 8); +} + +static void TrainEnterStation(Vehicle *v, int station) +{ + Station *st; + uint32 flags; + + v->last_station_visited = station; + + /* check if a train ever visited this station before */ + st = DEREF_STATION(station); + if (!(st->had_vehicle_of_type & HVOT_TRAIN)) { + st->had_vehicle_of_type |= HVOT_TRAIN; + SET_DPARAM16(0, st->index); + flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); + AddNewsItem( + STR_8801_CITIZENS_CELEBRATE_FIRST, + flags, + v->index, + 0); + } + + // Did we reach the final destination? + if ((v->next_order&OT_MASK) == OT_GOTO_STATION && v->next_order_param == (byte)station) { + // Yeah, keep the load/unload flags + // Non Stop now means if the order should be increased. + v->next_order = (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) | OF_NON_STOP | OT_LOADING; + } else { + // No, just do a simple load + v->next_order = OT_LOADING; + } + v->next_order_param = 0; + + SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); + if (LoadUnloadVehicle(v) != 0) { + InvalidateWindow(WC_TRAINS_LIST, v->owner); + MarkTrainDirty(v); + UpdateTrainAcceleration(v); + } + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); +} + +static byte AfterSetTrainPos(Vehicle *v) +{ + byte new_z, old_z; + + // need this hint so it returns the right z coordinate on bridges. + _get_z_hint = v->z_pos; + new_z = GetSlopeZ(v->x_pos, v->y_pos); + _get_z_hint = 0; + + old_z = v->z_pos; + v->z_pos = new_z; + + v->u.rail.flags &= ~(VRF_GOINGUP | VRF_GOINGDOWN); + + if (new_z != old_z) { + v->u.rail.flags |= (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN; + } + + VehiclePositionChanged(v); + EndVehicleMove(v); + return old_z; +} + +static const byte _new_vehicle_direction_table[11] = { + 0, 7, 6, 0, + 1, 0, 5, 0, + 2, 3, 4, +}; + +static int GetNewVehicleDirectionByTile(uint new_tile, uint old_tile) +{ + uint offs = (GET_TILE_Y(new_tile) - GET_TILE_Y(old_tile) + 1) * 4 + + GET_TILE_X(new_tile) - GET_TILE_X(old_tile) + 1; + assert(offs < 11); + return _new_vehicle_direction_table[offs]; +} + +static int GetNewVehicleDirection(Vehicle *v, int x, int y) +{ + uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1); + assert(offs < 11); + return _new_vehicle_direction_table[offs]; +} + +static int GetDirectionToVehicle(Vehicle *v, int x, int y) +{ + byte offs; + + x -= v->x_pos; + if (x >= 0) { + offs = (x > 2) ? 0 : 1; + } else { + offs = (x < -2) ? 2 : 1; + } + + y -= v->y_pos; + if (y >= 0) { + offs += ((y > 2) ? 0 : 1) * 4; + } else { + offs += ((y < -2) ? 2 : 1) * 4; + } + + assert(offs < 11); + return _new_vehicle_direction_table[offs]; +} + +/* Check if the vehicle is compatible with the specified tile */ +static bool CheckCompatibleRail(Vehicle *v, uint tile) +{ + if (IS_TILETYPE(tile, MP_RAILWAY) || + IS_TILETYPE(tile, MP_STATION)) { + + } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + if ((_map5[tile] & 0xC0) == 0xC0) {// is bridge middle part? + TileInfo ti; + FindLandscapeHeightByTile(&ti, tile); + + // correct Z position of a train going under a bridge on slopes + if (CORRECT_Z(ti.tileh)) + ti.z += 8; + + if(v->z_pos != ti.z) // train is going over bridge + return true; + } + } else + return true; + + if (_map_owner[tile] != v->owner || + (v->subtype == 0 && (_map3_lo[tile] & 0xF) != v->u.rail.railtype)) + return false; + + return true; +} + +typedef struct { + byte small_turn, large_turn; + byte z_up; // fraction to remove when moving up + byte z_down; // fraction to remove when moving down +} RailtypeSlowdownParams; + +static const RailtypeSlowdownParams _railtype_slowdown[3] = { + // normal accel + {256/4, 256/2, 256/4, 2}, // normal + {256/4, 256/2, 256/4, 2}, // monorail + {0, 256/2, 256/4, 2}, // maglev +}; + +/* Modify the speed of the vehicle due to a turn */ +static void AffectSpeedByDirChange(Vehicle *v, byte new_dir) +{ + byte diff; + const RailtypeSlowdownParams *rsp; + + if (_patches.realistic_acceleration || (diff = (v->direction - new_dir) & 7) == 0) + return; + + rsp = &_railtype_slowdown[v->u.rail.railtype]; + v->cur_speed -= ((diff == 1 || diff == 7) ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8; +} + +/* Modify the speed of the vehicle due to a change in altitude */ +static void AffectSpeedByZChange(Vehicle *v, byte old_z) +{ + const RailtypeSlowdownParams *rsp; + if (old_z == v->z_pos || _patches.realistic_acceleration) + return; + + rsp = &_railtype_slowdown[v->u.rail.railtype]; + + if (old_z < v->z_pos) { + v->cur_speed -= (v->cur_speed * rsp->z_up >> 8); + } else { + uint16 spd = v->cur_speed + rsp->z_down; + if (spd <= v->max_speed) + v->cur_speed = spd; + } +} + +static const byte _otherside_signal_directions[14] = { + 1, 3, 1, 3, 5, 3, 0, 0, + 5, 7, 7, 5, 7, 1, +}; + +static void TrainMovedChangeSignals(uint tile, int dir) +{ + int i; + if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile]&0xC0)==0x40) { + i = FindFirstBit2x64((_map5[tile]+(_map5[tile]<<8)) & _reachable_tracks[dir]); + UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]); + } +} + + +typedef struct TrainCollideChecker { + Vehicle *v, *v_skip; + +} TrainCollideChecker; + +void *FindTrainCollideEnum(Vehicle *v, TrainCollideChecker *tcc) +{ + if (v == tcc->v || v == tcc->v_skip || v->type != VEH_Train || v->u.rail.track==0x80) + return 0; + + if ( myabs(v->z_pos - tcc->v->z_pos) > 6 || + myabs(v->x_pos - tcc->v->x_pos) >= 6 || + myabs(v->y_pos - tcc->v->y_pos) >= 6) + return NULL; + return v; +} + +static void SetVehicleCrashed(Vehicle *v) +{ + Vehicle *u; + + if (v->u.rail.crash_anim_pos != 0) + return; + + v->u.rail.crash_anim_pos++; + + u = v; + BEGIN_ENUM_WAGONS(v) + v->vehstatus |= VS_CRASHED; + END_ENUM_WAGONS(v) + + InvalidateWindowWidget(WC_VEHICLE_VIEW, u->index, 4); +} + +static int CountPassengersInTrain(Vehicle *v) +{ + int num = 0; + BEGIN_ENUM_WAGONS(v) + if (v->cargo_type == 0) num += v->cargo_count; + END_ENUM_WAGONS(v) + return num; +} + +static void CheckTrainCollision(Vehicle *v) +{ + TrainCollideChecker tcc; + Vehicle *coll; + int num; + + /* can't collide in depot */ + if (v->u.rail.track == 0x80) + return; + + assert((uint)TILE_FROM_XY(v->x_pos, v->y_pos) == v->tile); + + tcc.v = v; + tcc.v_skip = v->next; + + /* find colliding vehicle */ + coll = VehicleFromPos(v->tile, &tcc, (VehicleFromPosProc*)FindTrainCollideEnum); + if (coll == NULL) + return; + + coll = GetFirstVehicleInChain(coll); + + /* it can't collide with its own wagons */ + if (v == coll) + return; + + //two drivers + passangers killed in train v + num = 2 + CountPassengersInTrain(v); + if(!(coll->vehstatus&VS_CRASHED)) + //two drivers + passangers killed in train coll (if it was not crashed already) + num += 2 + CountPassengersInTrain(coll); + + SetVehicleCrashed(v); + if (coll->subtype == 0) + SetVehicleCrashed(coll); + + + SET_DPARAM16(0, num); + + AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL, + NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0), + v->index, + 0); + + ModifyStationRatingAround(v->tile, v->owner, -160, 30); + SndPlayVehicleFx(17, v); +} + +static void *CheckVehicleAtSignal(Vehicle *v, void *data) +{ + uint32 d = (uint32)data; + + if (v->type == VEH_Train && v->subtype == 0 && v->tile == (TileIndex)(d >> 8)) { + byte diff = (v->direction - (byte)d + 2) & 7; + if (diff == 2 || (v->cur_speed <= 5 && diff <= 4)) + return (void*)1; + } + return 0; +} + +static void TrainController(Vehicle *v) +{ + Vehicle *prev = NULL; + GetNewVehiclePosResult gp; + uint32 r, tracks,ts; + int dir, i; + byte chosen_dir; + byte chosen_track; + byte old_z; + + for(;;) { + BeginVehicleMove(v); + + if (v->u.rail.track != 0x40) { + if (GetNewVehiclePos(v, &gp)) { + /* Statying in the old tile */ + if (v->u.rail.track == 0x80) { + /* inside depot */ + gp.x = v->x_pos; + gp.y = v->y_pos; + } else { + /* isnot inside depot */ + r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); + if (r & 0x8) + goto invalid_rail; + if (r & 0x2) { + TrainEnterStation(v, r >> 8); + return; + } + + if (v->next_order == OT_LEAVESTATION) { + v->next_order = OT_NOTHING; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + } + } else { + /* A new tile is about to be entered. */ + + /* Determine what direction we're entering the new tile from */ + dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile); + assert(dir==1 || dir==3 || dir==5 || dir==7); + + /* Get the status of the tracks in the new tile and mask + * away the bits that aren't reachable. */ + ts = GetTileTrackStatus(gp.new_tile, 0) & _reachable_tracks[dir >> 1]; + + /* Combine the from & to directions. + * Now, the lower byte contains the track status, and the byte at bit 16 contains + * the signal status. */ + tracks = ts|(ts >> 8); + if ( (byte) tracks == 0) + goto invalid_rail; + + /* Check if the new tile contrains tracks that are compatible + * with the current train, if not, bail out. */ + if (!CheckCompatibleRail(v, gp.new_tile)) + goto invalid_rail; + + if (prev == NULL) { + /* Currently the locomotive is active. Determine which one of the + * available tracks to choose */ + chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, dir>>1, (byte)tracks); + + /* Check if it's a red signal and that force proceed is not clicked. */ + if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; + } else { + static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; + + /* The wagon is active, simply follow the prev vehicle. */ + chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & tracks); + } + + /* make sure chosen track is a valid track */ + assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); + + /* Update XY to reflect the entrance to the new tile, and select the direction to use */ + { + const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][dir>>1]; + gp.x = (gp.x & ~0xF) | b[0]; + gp.y = (gp.y & ~0xF) | b[1]; + chosen_dir = b[2]; + } + + /* Call the landscape function and tell it that the vehicle entered the tile */ + r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); + if (r&0x8) + goto invalid_rail; + + if (v->subtype == 0) v->load_unload_time_rem = 0; + + if (!(r&0x4)) { + v->tile = gp.new_tile; + v->u.rail.track = chosen_track; + } + + if (v->subtype == 0) + TrainMovedChangeSignals(gp.new_tile, dir>>1); + + if (v->next == NULL) + TrainMovedChangeSignals(gp.old_tile, (dir>>1) ^ 2); + + if (prev == NULL) { + AffectSpeedByDirChange(v, chosen_dir); + } + + v->direction = chosen_dir; + } + } else { + /* in tunnel */ + GetNewVehiclePos(v, &gp); + + if (IS_TILETYPE(gp.new_tile, MP_TUNNELBRIDGE) && + !(_map5[gp.new_tile] & 0xF0)) { + r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); + if (r & 0x4) goto common; + } + + v->x_pos = gp.x; + v->y_pos = gp.y; + VehiclePositionChanged(v); + goto next_vehicle; + } +common:; + + /* update image of train, as well as delta XY */ + dir = GetNewVehicleDirection(v, gp.x, gp.y); + UpdateTrainDeltaXY(v, dir); + v->cur_image = GetTrainImage(v, dir); + + v->x_pos = gp.x; + v->y_pos = gp.y; + + /* update the Z position of the vehicle */ + old_z = AfterSetTrainPos(v); + + if (prev == NULL) { + AffectSpeedByZChange(v, old_z); + CheckTrainCollision(v); + } + + /* continue with next vehicle */ +next_vehicle:; + prev = v; + if ((v=v->next) == NULL) + return; + } + +invalid_rail: + if (prev != NULL) { + error("!Disconnecting train"); + } + goto reverse_train_direction; + +red_light: { + /* find the first set bit in ts. need to do it in 2 steps, since + * FIND_FIRST_BIT only handles 6 bits at a time. */ + i = FindFirstBit2x64(ts); + + if (!(_map3_lo[gp.new_tile] & _signal_otherdir[i])) { + v->cur_speed = 0; + v->subspeed = 0; + v->progress = 255-100; + if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20) + return; + } else if (_map3_lo[gp.new_tile] & _signal_onedir[i]){ + v->cur_speed = 0; + v->subspeed = 0; + v->progress = 255-10; + if (++v->load_unload_time_rem < _patches.wait_twoway_signal * 73) { + uint o_tile = gp.new_tile + _tileoffs_by_dir[dir>>1]; + /* check if a train is waiting on the other side */ + if (VehicleFromPos(o_tile, (void*)( (o_tile<<8) | (dir^4)), (VehicleFromPosProc*)CheckVehicleAtSignal) == NULL) + return; + } + } + } + +reverse_train_direction: + v->load_unload_time_rem = 0; + v->cur_speed = 0; + v->subspeed = 0; + ReverseTrainDirection(v); + +} + +static void DeleteLastWagon(Vehicle *v) +{ + Vehicle *u = v; + int t; + + while (v->next != NULL) { + u = v; + v = v->next; + } + u->next = NULL; + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + DeleteWindowById(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_TRAINS_LIST, v->owner); + InvalidateWindow(WC_COMPANY, v->owner); + + BeginVehicleMove(v); + EndVehicleMove(v); + DeleteVehicle(v); + + if (!((t=v->u.rail.track) & 0xC0)) { + SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(t)); + } +} + +static void ChangeTrainDirRandomly(Vehicle *v) +{ + static int8 _random_dir_change[4] = { -1, 0, 0, 1}; + + do { + v->direction = (v->direction + _random_dir_change[Random()&3]) & 7; + if (!(v->vehstatus & VS_HIDDEN)) { + BeginVehicleMove(v); + UpdateTrainDeltaXY(v, v->direction); + v->cur_image = GetTrainImage(v, v->direction); + AfterSetTrainPos(v); + } + } while ( (v=v->next) != NULL); +} + +static void HandleCrashedTrain(Vehicle *v) +{ + int state = ++v->u.rail.crash_anim_pos, index; + uint32 r; + Vehicle *u; + + if (state == 4) { + CreateEffectVehicleRel(v, 4, 4, 8, EV_CRASHED_SMOKE); + } + + if (state <= 200 && (uint16)(r=Random()) <= 0x2492) { + index = (r * 10 >> 16); + + u = v; + do { + if (--index < 0) { + r = Random(); + + CreateEffectVehicleRel(u, + 2 + ((r>>8)&7), + 2 + ((r>>16)&7), + 5 + (r&7), + EV_DEMOLISH); + break; + } + } while ( (u=u->next) != NULL); + } + + if (state <= 240 && !(v->tick_counter&3)) { + ChangeTrainDirRandomly(v); + } + + if (state >= 4440 && !(v->tick_counter&0x1F)) + DeleteLastWagon(v); +} + +static void HandleBrokenTrain(Vehicle *v) +{ + if (v->breakdown_ctr != 1) { + v->breakdown_ctr = 1; + v->cur_speed = 0; + + if (v->breakdowns_since_last_service != 255) + v->breakdowns_since_last_service++; + + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? 0xE : 0x3A, v); + + if (!(v->vehstatus & VS_HIDDEN)) { + Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); + if (u) + u->u.special.unk0 = v->breakdown_delay * 2; + } + } + + if (!(v->tick_counter & 3)) { + if (!--v->breakdown_delay) { + v->breakdown_ctr = 0; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + } + } +} + +static const byte _breakdown_speeds[16] = { + 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15 +}; + +static void TrainCheckIfLineEnds(Vehicle *v) +{ + uint tile; + uint x,y; + int t; + uint32 ts; + + if ((uint)(t=v->breakdown_ctr) > 1) { + v->vehstatus |= VS_TRAIN_SLOWING; + + t = _breakdown_speeds[ ((~t) >> 4) & 0xF]; + if ((uint16)t <= v->cur_speed) + v->cur_speed = t; + } else { + v->vehstatus &= ~VS_TRAIN_SLOWING; + } + + // exit if inside a tunnel + if (v->u.rail.track & 0x40) + return; + + tile = v->tile; + + // tunnel entrance? + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && + (_map5[tile] & 0xF0) == 0 && (byte)((_map5[tile] & 3)*2+1) == v->direction) + return; + + // depot? + if (IS_TILETYPE(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0) + return; + + // determine the tracks on the next tile. + t = v->direction >> 1; + if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[t]) { + t = (t - 1) & 3; + } + tile += _tileoffs_by_dir[t]; + ts = GetTileTrackStatus(tile, 0) & _reachable_tracks[t]; + + x = v->x_pos & 0xF; + y = v->y_pos & 0xF; + + switch(v->direction) { + case 0: + x = (~x) + (~y) + 24; + break; + case 7: + x = y; + /* fall through */ + case 1: + x = (~x) + 16; + break; + case 2: + x = (~x) + y + 8; + break; + case 3: + x = y; + break; + case 4: + x = x + y - 8; + break; + case 6: + x = (~y) + x + 8; + break; + } + + if ( (uint16)ts != 0) { + if ((ts &= (ts >> 16)) == 0) { + // make a rail/road crossing red + if (IS_TILETYPE(tile, MP_STREET) && (_map5[tile] & 0xF0)==0x10) { + if (!(_map5[tile] & 4)) { + _map5[tile] |= 4; + SndPlayVehicleFx(12, v); + MarkTileDirtyByTile(tile); + } + } + return; + } + } else if (x + 4 > 15) { + v->cur_speed = 0; + ReverseTrainDirection(v); + return; + } + + // slow down + v->vehstatus |= VS_TRAIN_SLOWING; + t = _breakdown_speeds[x & 0xF]; + if (!(v->direction&1)) t>>=1; + if ((uint16)t < v->cur_speed) + v->cur_speed = t; +} + +static void TrainLocoHandler(Vehicle *v, bool mode) +{ + int j; + + /* train has crashed? */ + if (v->u.rail.crash_anim_pos != 0) { + if (!mode) HandleCrashedTrain(v); + return; + } + + if (v->u.rail.force_proceed != 0) + v->u.rail.force_proceed--; + + /* train is broken down? */ + if (v->breakdown_ctr != 0) { + if (v->breakdown_ctr <= 2) { + HandleBrokenTrain(v); + return; + } + v->breakdown_ctr--; + } + + if (v->u.rail.flags & VRF_REVERSING && v->cur_speed == 0) { + ReverseTrainDirection(v); + } + + /* exit if train is stopped */ + if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) + return; + + + if (ProcessTrainOrder(v)) { + v->load_unload_time_rem = 0; + v->cur_speed = 0; + v->subspeed = 0; + ReverseTrainDirection(v); + return; + } + + HandleTrainLoading(v, mode); + + if ((v->next_order & OT_MASK) == OT_LOADING) + return; + + if (CheckTrainStayInDepot(v)) + return; + + if (!mode) HandleLocomotiveSmokeCloud(v); + + j = UpdateTrainSpeed(v); + if (j == 0) { + // if the vehicle has speed 0, update the last_speed field. + if (v->cur_speed != 0) + return; + } else { + TrainCheckIfLineEnds(v); + + do { + TrainController(v); + if (v->cur_speed <= 0x100) + break; + } while (--j != 0); + } + + SetLastSpeed(v, v->cur_speed); +} + + +void Train_Tick(Vehicle *v) +{ + if (_age_cargo_skip_counter == 0 && v->cargo_days != 0xff) + v->cargo_days++; + + v->tick_counter++; + + if (v->subtype == 0) { + TrainLocoHandler(v, false); + + // make sure vehicle wasn't deleted. + if (v->type == VEH_Train && v->subtype == 0) + TrainLocoHandler(v, true); + } +} + + +static const byte _depot_track_ind[4] = {0,1,0,1}; + +void TrainEnterDepot(Vehicle *v, uint tile) +{ + byte t; + + SetSignalsOnBothDir(tile, _depot_track_ind[_map5[tile]&3]); + + if (v->subtype != 0) + v = GetFirstVehicleInChain(v); + + v->date_of_last_service = _date; + v->breakdowns_since_last_service = 0; + v->reliability = _engines[v->engine_type].reliability; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + v->load_unload_time_rem = 0; + v->cur_speed = 0; + + MaybeRenewVehicle(v, EstimateTrainCost(&_rail_vehicle_info[v->engine_type])); + + if ((v->next_order&OT_MASK) == OT_GOTO_DEPOT) { + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + + t = v->next_order; + v->next_order = OT_DUMMY; + + // Part of the schedule? + if (t & OF_UNLOAD) { v->u.rail.days_since_order_progr = 0; v->cur_order_index++; } + + // User initiated? + else if (t & OF_FULL_LOAD) { + v->vehstatus |= VS_STOPPED; + if (v->owner == _local_player) { + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_8814_TRAIN_IS_WAITING_IN_DEPOT, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + } + } +} + +static void CheckIfTrainNeedsService(Vehicle *v) +{ + uint tile; + byte depot; + + if (_patches.no_train_service && IS_HUMAN_PLAYER(v->owner)) + return; + + if (v->date_of_last_service + v->service_interval > _date) + return; + + if (v->vehstatus & VS_STOPPED) + return; + + if (_patches.gotodepot && IS_HUMAN_PLAYER(v->owner) && ScheduleHasDepotOrders(v->schedule_ptr)) + return; + + // Don't interfere with a depot visit scheduled by the user, or a + // depot visit by the order list. + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && + (v->next_order & (OF_FULL_LOAD|OF_UNLOAD)) != 0) + return; + + tile = FindClosestTrainDepot(v); + if (tile == (uint)-1 || GetTileDist(v->tile, tile) > 12) { + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT) { + v->next_order = OT_DUMMY; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + } + return; + } + + depot = GetDepotByTile(tile); + + if ((v->next_order & OT_MASK) == OT_GOTO_DEPOT && v->next_order_param != depot && !CHANCE16(3,16)) + return; + + v->next_order = OT_GOTO_DEPOT | OF_NON_STOP; + v->next_order_param = depot; + v->dest_tile = tile; + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); +} + +int32 GetTrainRunningCost(Vehicle *v) +{ + int32 cost = 0; + + do { + const RailVehicleInfo *rvi = &_rail_vehicle_info[v->engine_type]; + if (rvi->running_cost_base) + cost += rvi->running_cost_base * _price.running_rail[rvi->engclass]; + } while ( (v=v->next) != NULL ); + + return cost; +} + +void OnNewDay_Train(Vehicle *v) +{ + TileIndex tile; + + if ((++v->day_counter & 7) == 0) + DecreaseVehicleValue(v); + + if (v->subtype == 0) { + CheckVehicleBreakdown(v); + AgeVehicle(v); + + CheckIfTrainNeedsService(v); + + // check if train hasn't advanced in its order list for a set number of days + if (_patches.lost_train_days && v->num_orders && !(v->vehstatus & VS_STOPPED) && ++v->u.rail.days_since_order_progr >= _patches.lost_train_days && v->owner == _local_player) { + v->u.rail.days_since_order_progr = 0; + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_TRAIN_IS_LOST, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + + /* update destination */ + if ((v->next_order & OT_MASK) == OT_GOTO_STATION && + (tile=DEREF_STATION(v->next_order_param)->train_tile) != 0) + v->dest_tile = tile; + + if ((v->vehstatus & VS_STOPPED) == 0) { + /* running costs */ + int32 cost = GetTrainRunningCost(v) / 364; + + v->profit_this_year -= cost >> 8; + + SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN); + SubtractMoneyFromPlayerFract(v->owner, cost); + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + InvalidateWindow(WC_TRAINS_LIST, v->owner); + } + } +} + +void TrainsYearlyLoop() +{ + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype == 0) { + + // show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) + if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) { + SET_DPARAM32(1, v->profit_this_year); + SET_DPARAM16(0, v->unitnumber); + AddNewsItem( + STR_TRAIN_IS_UNPROFITABLE, + NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), + v->index, + 0); + } + + v->profit_last_year = v->profit_this_year; + v->profit_this_year = 0; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } + } +} + +extern void ShowTrainViewWindow(Vehicle *v); + +void HandleClickOnTrain(Vehicle *v) +{ + if (v->subtype != 0) v = GetFirstVehicleInChain(v); + ShowTrainViewWindow(v); +} + +void InitializeTrains() +{ + _age_cargo_skip_counter = 1; +} + +int ScheduleHasDepotOrders(uint16 *schedule) +{ + for (;*schedule!=0;schedule++) + if ((*schedule&OT_MASK) == OT_GOTO_DEPOT) + return true; + return false; +} diff --git a/train_gui.c b/train_gui.c new file mode 100644 --- /dev/null +++ b/train_gui.c @@ -0,0 +1,1319 @@ +#include "stdafx.h" +#include "ttd.h" + +#include "window.h" +#include "gui.h" +#include "gfx.h" +#include "vehicle.h" +#include "viewport.h" +#include "station.h" +#include "command.h" +#include "player.h" +//#include "town.h" +#include "engine.h" + +static Engine * const _rail_engines[3] = { + &_engines[0], + &_engines[NUM_NORMAL_RAIL_ENGINES], + &_engines[NUM_MONORAIL_ENGINES + NUM_NORMAL_RAIL_ENGINES], +}; + +const byte _rail_engines_count[3] = { + NUM_NORMAL_RAIL_ENGINES, + NUM_MONORAIL_ENGINES, + NUM_MAGLEV_ENGINES, +}; + +const byte _rail_engines_start[3] = { + 0, + NUM_NORMAL_RAIL_ENGINES, + NUM_MONORAIL_ENGINES + NUM_NORMAL_RAIL_ENGINES, +}; + +static void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2) +{ + Vehicle *v,*found; + + if (!success) + return; + + // find a locomotive in the depot. + found = NULL; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype==0 && + v->tile == tile && + v->u.rail.track == 0x80) { + if (found != NULL) // must be exactly one. + return; + found = v; + } + } + + // if we found a loco, + if (found != NULL) { + found = GetLastVehicleInChain(found); + // put the new wagon at the end of the loco. + DoCommandP(0, _new_wagon_id | (found->index<<16), 0, NULL, CMD_MOVE_RAIL_VEHICLE); + } +} + +static void CcBuildLoco(bool success, uint tile, uint32 p1, uint32 p2) +{ + Vehicle *v; + + if (!success) + return; + + v = &_vehicles[_new_train_id]; + if (tile == _backup_orders_tile) { + _backup_orders_tile = 0; + RestoreVehicleOrders(v, _backup_orders_data); + } + ShowTrainViewWindow(v); +} + +static void NewRailVehicleWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + + if (w->window_number == 0) + SETBIT(w->disabled_state, 5); + + { + int count = 0; + int num = _rail_engines_count[WP(w,buildtrain_d).railtype]; + Engine *e = _rail_engines[WP(w,buildtrain_d).railtype]; + do { + if (HASBIT(e->player_avail, _local_player)) + count++; + } while (++e,--num); + SetVScrollCount(w, count); + } + + SET_DPARAM16(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES); + DrawWindowWidgets(w); + + { + int num = _rail_engines_count[WP(w,buildtrain_d).railtype]; + Engine *e = _rail_engines[WP(w,buildtrain_d).railtype]; + int sel = WP(w,buildtrain_d).sel_index; + int pos = w->vscroll.pos; + int x = 1; + int y = 15; + int engine_id = _rail_engines_start[WP(w,buildtrain_d).railtype]; + int selected_id = -1; + + do { + if (HASBIT(e->player_avail, _local_player)) { + if (sel==0) selected_id = engine_id; + if (IS_INT_INSIDE(--pos, -8, 0)) { + DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel==0 ? 0xC : 0x10); + DrawTrainEngine(x+29, y+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player))); + y += 14; + } + sel--; + } + } while (++engine_id, ++e,--num); + + WP(w,buildtrain_d).sel_engine = selected_id; + + if (selected_id != -1) { + const RailVehicleInfo *rvi = &_rail_vehicle_info[selected_id]; + Engine *e; + YearMonthDay ymd; + + if (!(rvi->flags & RVI_WAGON)) { + /* it's an engine */ + int multihead = (rvi->flags&RVI_MULTIHEAD?1:0); + + SET_DPARAM32(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5); + SET_DPARAM16(2, rvi->max_speed * 10 >> 4); + SET_DPARAM16(3, rvi->power << multihead); + SET_DPARAM16(1, rvi->weight << multihead); + SET_DPARAM32(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead); + + SET_DPARAM16(5, STR_8838_N_A); + if (rvi->capacity != 0) { + SET_DPARAM16(6, rvi->capacity << multihead); + SET_DPARAM16(5, _cargoc.names_long_p[rvi->cargo_type]); + } + + e = &_engines[selected_id]; + + SET_DPARAM16(8, e->lifelength); + SET_DPARAM8(9, e->reliability * 100 >> 16); + ConvertDayToYMD(&ymd, e->intro_date); + SET_DPARAM16(7, ymd.year + 1920); + + DrawString(2, 0x7F, STR_8817_COST_WEIGHT_T_SPEED_POWER, 0); + } else { + /* it's a wagon */ + + SET_DPARAM32(0, + DoCommandByTile(w->window_number, selected_id, 0, DC_QUERY_COST, CMD_BUILD_RAIL_VEHICLE) + ); + SET_DPARAM16(4, rvi->capacity); + SET_DPARAM16(1, rvi->weight); + SET_DPARAM16(3, _cargoc.names_long_p[rvi->cargo_type]); + SET_DPARAM16(2, (_cargoc.weights[rvi->cargo_type] * rvi->capacity >> 4) + rvi->weight); + DrawString(2, 0x7F, STR_8821_COST_WEIGHT_T_T_CAPACITY, 0); + } + } + } + break; + + case WE_CLICK: { + switch(e->click.widget) { + case 2: { + uint i = (e->click.pt.y - 14) / 14; + if (i < 8) { + WP(w,buildtrain_d).sel_index = i + w->vscroll.pos; + SetWindowDirty(w); + } + } break; + case 5: { + int sel_eng; + sel_eng = WP(w,buildtrain_d).sel_engine; + if (sel_eng != -1) + DoCommandP(w->window_number, sel_eng, 0, (_rail_vehicle_info[sel_eng].flags & RVI_WAGON) ? CcBuildWagon : CcBuildLoco, CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE)); + } break; + case 6: + WP(w,buildtrain_d).rename_engine = WP(w,buildtrain_d).sel_engine; + ShowQueryString( + GetCustomEngineName(WP(w,buildtrain_d).sel_engine), + STR_886A_RENAME_TRAIN_VEHICLE_TYPE, + 31, + 160, + w->window_class, + w->window_number); + break; + } + } break; + + case WE_4: + if (w->window_number != 0 && !FindWindowById(WC_VEHICLE_DEPOT, w->window_number)) { + DeleteWindow(w); + } + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + + memcpy(_decode_parameters, b, 32); + DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_886B_CAN_T_RENAME_TRAIN_VEHICLE)); + } break; + } +} + +static const Widget _new_rail_vehicle_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 227, 0, 13, STR_0315, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 216, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION}, +{ WWT_SCROLLBAR, 14, 217, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PANEL, 14, 0, 227, 126, 187, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 113, 188, 199, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN}, +{ WWT_PUSHTXTBTN, 14, 114, 227, 188, 199, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE}, +{ WWT_LAST}, +}; + +static const WindowDesc _new_rail_vehicle_desc = { + -1, -1, 228, 200, + WC_BUILD_VEHICLE,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _new_rail_vehicle_widgets, + NewRailVehicleWndProc +}; + +static void ShowBuildTrainWindow(uint tile) +{ + Window *w; + + DeleteWindowById(WC_BUILD_VEHICLE, tile); + + w = AllocateWindowDesc(&_new_rail_vehicle_desc); + w->window_number = tile; + w->vscroll.cap = 8; + + if (tile != 0) { + w->caption_color = _map_owner[tile]; + WP(w,buildtrain_d).railtype = _map3_lo[tile] & 0xF; + } else { + w->caption_color = _local_player; + WP(w,buildtrain_d).railtype = DEREF_PLAYER(_local_player)->max_railtype - 1; + } +} + +static void DrawTrainImage(Vehicle *v, int x, int y, int count, int skip, VehicleID selection) +{ + do { + if (--skip < 0) { + int image = GetTrainImage(v, 6); + uint32 ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)); + if (v->vehstatus & VS_CRASHED) ormod = 0x3248000; + DrawSprite(image | ormod, x+14, y+6); + if (v->index == selection) DrawFrameRect(x-1, y-1, x+28, y+12, 15, 0x10); + x += 29; + count--; + } + + if (!(v = v->next)) + break; + } while (count); +} + +static void DrawTrainDepotWindow(Window *w) +{ + uint tile; + Vehicle *v, *u; + int num,x,y,i, hnum; + Depot *d; + + tile = w->window_number; + + /* setup disabled buttons */ + w->disabled_state = (_map_owner[tile]==_local_player) ? 0 : ((1<<3)|(1<<4)|(1<<6)); + + /* determine amount of items for scroller */ + num = 1; + hnum = 0; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && + (v->subtype == 0 || v->subtype == 4) && + v->tile == (TileIndex)tile && + v->u.rail.track == 0x80) { + num++; + // determine number of items in the X direction. + if (v->subtype == 0) { + i = -1; + u = v; + do i++; while ( (u=u->next) != NULL); + if (i > hnum) hnum = i; + } + } + } + SetVScrollCount(w, num); + SetHScrollCount(w, hnum); + + /* locate the depot struct */ + for(d=_depots; d->xy != (TileIndex)tile; d++) {} + + SET_DPARAM16(0,d->town_index); + DrawWindowWidgets(w); + + x = 2; + y = 15; + num = w->vscroll.pos; + + // draw all trains + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && + v->subtype == 0 && + v->tile == (TileIndex)tile && + v->u.rail.track == 0x80 && + --num < 0 && num >= -6) { + + DrawTrainImage(v, x+21, y, 10, w->hscroll.pos, WP(w,traindepot_d).sel); + SET_DPARAM16(0, v->unitnumber); + DrawString(x, y, (v->max_age - 366 < v->age) ? STR_00E3 : STR_00E2, 0); + DrawSprite(v->vehstatus&VS_STOPPED ? 0xC12 : 0xC13, x+15, y); + + y += 14; + } + } + + // draw all remaining vehicles + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && + v->subtype == 4 && + v->tile == (TileIndex)tile && + v->u.rail.track == 0x80 && + --num < 0 && num >= -6) { + + DrawTrainImage(v, x+50, y, 9, 0, WP(w,traindepot_d).sel); + DrawString(x, y+2, STR_8816, 0); + y += 14; + } + } +} + +typedef struct GetDepotVehiclePtData { + Vehicle *head; + Vehicle *wagon; +} GetDepotVehiclePtData; + +static int GetVehicleFromTrainDepotWndPt(Window *w, int x, int y, GetDepotVehiclePtData *d) +{ + int area_x; + int row; + Vehicle *v; + + x = x - 23; + if (x < 0) { + area_x = (x >= -10) ? -2 : -1; + } else { + area_x = x / 29; + } + + row = (y - 14) / 14; + if ( (uint) row >= 6) + return 1; /* means err */ + + row += w->vscroll.pos; + + /* go through all the locomotives */ + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && + v->subtype == 0 && + v->tile == w->window_number && + v->u.rail.track == 0x80 && + --row < 0) { + area_x += w->hscroll.pos; + goto found_it; + } + } + + area_x--; /* free wagons don't have an initial loco. */ + + /* and then the list of free wagons */ + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && + v->subtype == 4 && + v->tile == w->window_number && + v->u.rail.track == 0x80 && + --row < 0) + goto found_it; + } + + d->head = NULL; + d->wagon = NULL; + + /* didn't find anything, get out */ + return 0; + +found_it: + d->head = d->wagon = v; + + /* either pressed the flag or the number, but only when it's a loco */ + if (area_x < 0 && v->subtype==0) + return area_x; + + /* find the vehicle in this row that was clicked */ + while (--area_x >= 0) { + v = v->next; + if (v == NULL) break; + } + + d->wagon = v; + + return 0; +} + +static void TrainDepotMoveVehicle(Vehicle *wagon, int sel, Vehicle *head) +{ + Vehicle *v; + + v = &_vehicles[sel]; + + if (/*v->subtype == 0 ||*/ v == wagon) + return; + + if (wagon == NULL) { + if (head != NULL) + wagon = GetLastVehicleInChain(head); + } else { + wagon = GetPrevVehicleInChain(wagon); + if (wagon == NULL) + return; + } + + if (wagon == v) + return; + + DoCommandP(v->tile, v->index + ((wagon==NULL ? (uint32)-1 : wagon->index) << 16), _ctrl_pressed ? 1 : 0, NULL, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_8837_CAN_T_MOVE_VEHICLE)); +} + +static void TrainDepotClickTrain(Window *w, int x, int y) +{ + GetDepotVehiclePtData gdvp; + int mode, sel; + Vehicle *v; + + mode = GetVehicleFromTrainDepotWndPt(w, x, y, &gdvp); + + if (_thd.place_mode && mode <= 0) { _place_clicked_vehicle = gdvp.head; return; } + + v = gdvp.wagon; + + switch(mode) { + case 0: + sel = (int16)WP(w,traindepot_d).sel; + if (sel != -1) { + WP(w,traindepot_d).sel = INVALID_VEHICLE; + TrainDepotMoveVehicle(v, sel, gdvp.head); + } else if (v != NULL) { + WP(w,traindepot_d).sel = v->index; + SetObjectToPlaceWnd( SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)) + GetTrainImage(v, 6), 4, w); + SetWindowDirty(w); + } + break; + + case -1: + ShowTrainViewWindow(v); + break; + + case -2: + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_TRAIN | CMD_MSG(STR_883B_CAN_T_STOP_START_TRAIN)); + break; + } +} + +static void TrainDepotWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawTrainDepotWindow(w); + break; + + case WE_CLICK: { + switch(e->click.widget) { + case 6: + ShowBuildTrainWindow(w->window_number); + break; + case 7: + ScrollMainWindowToTile(w->window_number); + break; + case 2: + TrainDepotClickTrain(w, e->click.pt.x, e->click.pt.y); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + break; + + case WE_DRAGDROP: { + switch(e->click.widget) { + case 4: + case 3: { + Vehicle *v; + int sell_cmd; + + /* sell vehicle */ + if (w->disabled_state & (1 << e->click.widget)) + return; + + if (WP(w,traindepot_d).sel == INVALID_VEHICLE) + return; + + v = &_vehicles[WP(w,traindepot_d).sel]; + + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + + HandleButtonClick(w, e->click.widget); + + sell_cmd = (e->click.widget == 4 || _ctrl_pressed) ? 1 : 0; + + if (v->subtype != 0) { + DoCommandP(v->tile, v->index, sell_cmd, NULL, CMD_SELL_RAIL_WAGON | CMD_MSG(STR_8839_CAN_T_SELL_RAILROAD_VEHICLE)); + } else { + _backup_orders_tile = v->tile; + BackupVehicleOrders(v, _backup_orders_data); + if (!DoCommandP(v->tile, v->index, sell_cmd, NULL, CMD_SELL_RAIL_WAGON | CMD_MSG(STR_8839_CAN_T_SELL_RAILROAD_VEHICLE))) + _backup_orders_tile = 0; + } + } break; + + case 2: { + GetDepotVehiclePtData gdvp; + VehicleID sel = WP(w,traindepot_d).sel; + + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + + if (GetVehicleFromTrainDepotWndPt(w, e->dragdrop.pt.x, e->dragdrop.pt.y, &gdvp) == 0 && + sel != INVALID_VEHICLE) { + if (gdvp.wagon == NULL || gdvp.wagon->index != sel) { + TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head); + } else if (gdvp.head != NULL && gdvp.head->subtype==0) { + ShowTrainViewWindow(gdvp.head); + } + } + } break; + + default: + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); + break; + } + } break; + } +} + + +static const Widget _train_depot_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 348, 0, 13, STR_8800_TRAIN_DEPOT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 313, 14, 97, 0x601, STR_883F_TRAINS_CLICK_ON_TRAIN_FOR}, +//{ WWT_PANEL, 14, 314, 337, 14, 108, 0x2A9, STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE}, +{ WWT_PANEL, 14, 314, 337, 14, 54, 0x2A9, STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE}, +{ WWT_PANEL, 14, 314, 337, 55, 108, 0x2BF, STR_DRAG_WHOLE_TRAIN_TO_SELL_TIP}, + +{ WWT_SCROLLBAR, 14, 338, 348, 14, 108, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 173, 109, 120, STR_8815_NEW_VEHICLES, STR_8840_BUILD_NEW_TRAIN_VEHICLE}, +{ WWT_PUSHTXTBTN, 14, 174, 348, 109, 120, STR_00E4_LOCATION, STR_8842_CENTER_MAIN_VIEW_ON_TRAIN}, +{ WWT_HSCROLLBAR, 14, 0, 313, 98, 108, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _train_depot_desc = { + -1, -1, 349, 121, + WC_VEHICLE_DEPOT,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _train_depot_widgets, + TrainDepotWndProc +}; + + +void ShowTrainDepotWindow(uint tile) +{ + Window *w; + + w = AllocateWindowDescFront(&_train_depot_desc, tile); + if (w) { + w->caption_color = _map_owner[w->window_number]; + w->vscroll.cap = 6; + w->hscroll.cap = 9; + WP(w,traindepot_d).sel = INVALID_VEHICLE; + _backup_orders_tile = 0; + } +} + +const byte _rail_vehicle_refit_types[4][16] = { + { 0,1,2,4,5,6,7,8,9,10,0xFF }, // normal + { 0,1,4,5,6,7,9,11,10,0xFF }, // arctic + { 0,4,5,8,6,7,9,10,0xFF }, // desert + { 0,1,3,5,7,8,9,6,4,10,11,0xFF }// candy +}; + +static void RailVehicleRefitWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v = &_vehicles[w->window_number]; + const byte *b; + int sel; + int x,y; + byte color; + int cargo; + + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + DrawString(1, 15, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, 0); + + cargo = -1; + x = 6; + y = 25; + sel = WP(w,refit_d).sel; + b = _rail_vehicle_refit_types[_opt.landscape]; + do { + color = 16; + if (sel == 0) { + cargo = *b; + color = 12; + } + sel--; + DrawString(x,y,_cargoc.names_s[*b], color); + y += 10; + } while (*++b != 255); + + WP(w,refit_d).cargo = cargo; + + if (cargo != -1) { + int32 cost = DoCommandByTile(v->tile, v->index, cargo, 0, CMD_REFIT_RAIL_VEHICLE); + if (cost != CMD_ERROR) { + SET_DPARAM32(2, cost); + SET_DPARAM16(0, _cargoc.names_long_p[cargo]); + SET_DPARAM16(1, _returned_refit_amount); + DrawString(1, 137, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); + } + } + break; + } + + case WE_CLICK: + switch(e->click.widget) { + case 2: { /* listbox */ + int y = e->click.pt.y - 25; + if (y >= 0) { + WP(w,refit_d).sel = y / 10; + SetWindowDirty(w); + } + } break; + case 4: /* refit button */ + if (WP(w,refit_d).cargo != 0xFF) { + Vehicle *v = &_vehicles[w->window_number]; + if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE))) + DeleteWindow(w); + } + break; + } + break; + } +} + + +static const Widget _rail_vehicle_refit_widgets[] = { +{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 239, 0, 13, STR_983B_REFIT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_IMGBTN, 14, 0, 239, 14, 135, 0x0, STR_RAIL_SELECT_TYPE_OF_CARGO_FOR}, +{ WWT_IMGBTN, 14, 0, 239, 136, 157, 0x0}, +{ WWT_PUSHTXTBTN, 14, 0, 239, 158, 169, STR_RAIL_REFIT_VEHICLE, STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED}, +{ WWT_LAST}, +}; + +static const WindowDesc _rail_vehicle_refit_desc = { + -1,-1, 240, 170, + WC_VEHICLE_REFIT,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _rail_vehicle_refit_widgets, + RailVehicleRefitWndProc, +}; + +static void ShowRailVehicleRefitWindow(Vehicle *v) +{ + Window *w; + DeleteWindowById(WC_VEHICLE_REFIT, v->index); + _alloc_wnd_parent_num = v->index; + w = AllocateWindowDesc(&_rail_vehicle_refit_desc); + w->window_number = v->index; + w->caption_color = v->owner; + WP(w,refit_d).sel = -1; +} + + + + +static Widget _train_view_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 249, 0, 13, STR_882E, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PANEL, 14, 0, 231, 14, 121, 0x0, 0}, +{ WWT_6, 14, 2, 229, 16, 119, 0, 0}, +{ WWT_PUSHIMGBTN, 14, 0, 249, 122, 133, 0x0, STR_8846_CURRENT_TRAIN_ACTION_CLICK}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 14, 31, 0x2AB, STR_8848_CENTER_MAIN_VIEW_ON_TRAIN}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 32, 49, 0x2AD, STR_8849_SEND_TRAIN_TO_DEPOT}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 50, 67, 0x2B1, STR_884A_FORCE_TRAIN_TO_PROCEED}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 68, 85, 0x2CB, STR_884B_REVERSE_DIRECTION_OF_TRAIN}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 86, 103, 0x2B2, STR_8847_SHOW_TRAIN_S_ORDERS}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 104, 121, 0x2B3, STR_884C_SHOW_TRAIN_DETAILS}, +{ WWT_PUSHIMGBTN, 14, 232, 249, 68, 85, 0x2B4, STR_RAIL_REFIT_VEHICLE_TO_CARRY}, +{ WWT_LAST}, +}; + +static void TrainViewWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: { + Vehicle *v; + StringID str; + + v = &_vehicles[w->window_number]; + + w->disabled_state = (v->owner == _local_player) ? 0 : 0x1C0; + + + /* draw widgets & caption */ + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + /* draw the flag */ + DrawSprite( (v->vehstatus&VS_STOPPED) ? 0xC12 : 0xC13, 2, 123); + + if (v->u.rail.crash_anim_pos != 0) { + str = STR_8863_CRASHED; + } else if (v->breakdown_ctr == 1) { + str = STR_885C_BROKEN_DOWN; + } else if (v->vehstatus & VS_STOPPED) { + if (v->u.rail.last_speed == 0) { + str = STR_8861_STOPPED; + } else { + SET_DPARAM16(0, v->u.rail.last_speed * 10 >> 4); + str = STR_TRAIN_STOPPING + _patches.vehicle_speed; + } + } else { + switch(v->next_order & OT_MASK) { + case OT_GOTO_STATION: { + str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; + SET_DPARAM16(0, v->next_order_param); + SET_DPARAM16(1, v->u.rail.last_speed * 10 >> 4); + } break; + + case OT_GOTO_DEPOT: { + Depot *dep = &_depots[v->next_order_param]; + SET_DPARAM16(0, dep->town_index); + str = STR_HEADING_FOR_TRAIN_DEPOT + _patches.vehicle_speed; + SET_DPARAM16(1, v->u.rail.last_speed * 10 >> 4); + } break; + + case OT_LOADING: + case OT_LEAVESTATION: + str = STR_882F_LOADING_UNLOADING; + break; + + case OT_GOTO_CHECKPOINT: { + SET_DPARAM16(0, v->next_order_param); + str = STR_HEADING_FOR_CHECKPOINT + _patches.vehicle_speed; + SET_DPARAM16(1, v->u.rail.last_speed * 10 >> 4); + break; + } + + default: + if (v->num_orders == 0) { + str = STR_NO_ORDERS + _patches.vehicle_speed; + SET_DPARAM16(0, v->u.rail.last_speed * 10 >> 4); + } else + str = STR_EMPTY; + break; + } + } + + DrawStringCentered(125, 123, str, 0); + DrawWindowViewport(w); + } break; + + case WE_CLICK: { + int wid = e->click.widget; + Vehicle *v = &_vehicles[w->window_number]; + + switch(wid) { + case 4: /* start/stop train */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_TRAIN | CMD_MSG(STR_883B_CAN_T_STOP_START_TRAIN)); + break; + case 5: /* center main view */ + ScrollMainWindowTo(v->x_pos, v->y_pos); + break; + case 6: /* goto depot */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_TRAIN_GOTO_DEPOT | CMD_MSG(STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT)); + break; + case 7: /* force proceed */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL)); + break; + case 8: /* reverse direction */ + DoCommandP(v->tile, v->index, 0, NULL, CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_8869_CAN_T_REVERSE_DIRECTION)); + break; + case 9: /* show train orders */ + ShowOrdersWindow(v); + break; + case 10: /* show train details */ + ShowTrainDetailsWindow(v); + break; + case 11: + ShowRailVehicleRefitWindow(v); + break; + } + } break; + + case WE_DESTROY: + DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number); + DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number); + break; + + case WE_MOUSELOOP: { + Vehicle *v; + uint32 h; + + v = &_vehicles[w->window_number]; + assert(v->type == VEH_Train); + h = CheckStoppedInDepot(v) >= 0 ? (1 << 8) : (1 << 11); + if (h != w->hidden_state) { + w->hidden_state = h; + SetWindowDirty(w); + } + break; + } + + } +} + +static const WindowDesc _train_view_desc = { + -1,-1, 250, 134, + WC_VEHICLE_VIEW,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _train_view_widgets, + TrainViewWndProc +}; + +void ShowTrainViewWindow(Vehicle *v) +{ + Window *w; + + w = AllocateWindowDescFront(&_train_view_desc,v->index); + if (w) { + w->caption_color = v->owner; + AssignWindowViewport(w, 3, 17, 0xE2, 0x66, w->window_number | (1 << 31), 0); + } +} + +static void TrainDetailsCargoTab(Vehicle *v, int x, int y) +{ + int num; + StringID str; + + if (v->cargo_cap != 0) { + num = v->cargo_count; + str = STR_8812_EMPTY; + if (num != 0) { + SET_DPARAM8(0, v->cargo_type); + SET_DPARAM16(1, num); + SET_DPARAM16(2, v->cargo_source); + str = STR_8813_FROM; + } + DrawString(x, y, str, 0); + } +} + +static void TrainDetailsInfoTab(Vehicle *v, int x, int y) +{ + const RailVehicleInfo *rvi; + + rvi = &_rail_vehicle_info[v->engine_type]; + + if (!(rvi->flags & RVI_WAGON)) { + SET_DPARAM16(0, GetCustomEngineName(v->engine_type)); + SET_DPARAM16(1, v->build_year + 1920); + SET_DPARAM32(2, v->value); + DrawString(x, y, STR_882C_BUILT_VALUE, 0x10); + } else { + SET_DPARAM16(0, GetCustomEngineName(v->engine_type)); + SET_DPARAM32(1, v->value); + DrawString(x, y, STR_882D_VALUE, 0x10); + } +} + +static void TrainDetailsCapacityTab(Vehicle *v, int x, int y) +{ + if (v->cargo_cap != 0) { + SET_DPARAM16(1, v->cargo_cap); + SET_DPARAM16(0, _cargoc.names_long_p[v->cargo_type]); + DrawString(x, y, STR_013F_CAPACITY, 0); + } +} + +typedef void TrainDetailsDrawerProc(Vehicle *v, int x, int y); + +static TrainDetailsDrawerProc * const _train_details_drawer_proc[3] = { + TrainDetailsCargoTab, + TrainDetailsInfoTab, + TrainDetailsCapacityTab, +}; + +static void DrawTrainDetailsWindow(Window *w) +{ + Vehicle *v, *u; + uint16 tot_cargo[NUM_CARGO][2]; // count total cargo ([0]-actual cargo, [1]-total cargo) + int i,num,x,y,sel; + StringID str; + byte det_tab = WP(w, traindetails_d).tab; + + /* Count number of vehicles */ + num = 0; + + // det_tab == 3 <-- Total Cargo tab + if (det_tab == 3) // reset tot_cargo array to 0 values + memset(tot_cargo, 0, sizeof(tot_cargo)); + + u = v = &_vehicles[w->window_number]; + do { + if (det_tab != 3) + num++; + else { + tot_cargo[u->cargo_type][0] += u->cargo_count; + tot_cargo[u->cargo_type][1] += u->cargo_cap; + } + } while ( (u = u->next) != NULL); + + /* set scroll-amount seperately from counting, as to not + compute num double for more carriages of the same type + */ + if (det_tab == 3) { + for (i = 0; i != NUM_CARGO; i++) { + if (tot_cargo[i][1] > 0) // only count carriages that the train has + num++; + } + num++; // needs one more because first line is description string + } + + SetVScrollCount(w, num); + + w->disabled_state = 1 << (det_tab + 9); + if (v->owner != _local_player) + w->disabled_state |= (1 << 2); + + SET_DPARAM16(0, v->string_id); + SET_DPARAM16(1, v->unitnumber); + DrawWindowWidgets(w); + + num = v->age / 366; + SET_DPARAM16(1, num); + + x = 2; + + str = STR_0199_YEAR; + if (num != 1) { + str += STR_019A_YEARS - STR_0199_YEAR; + if ((uint16)(v->max_age - 366) < v->age) + str += STR_019B_YEARS - STR_019A_YEARS; + } + SET_DPARAM16(0, str); + SET_DPARAM16(2, v->max_age / 366); + SET_DPARAM32(3, GetTrainRunningCost(v) >> 8); + DrawString(x, 15, STR_885D_AGE_RUNNING_COST_YR, 0); + + SET_DPARAM16(2, v->max_speed * 10 >> 4); + SET_DPARAM32(1, v->u.rail.cached_power); + SET_DPARAM16(0, v->u.rail.cached_weight); + DrawString(x, 25, STR_885E_WEIGHT_T_POWER_HP_MAX_SPEED, 0); + + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(x, 35, STR_885F_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + SET_DPARAM8(0, 100 * (v->reliability>>8) >> 8); + SET_DPARAM16(1, v->breakdowns_since_last_service); + DrawString(x, 45, STR_8860_RELIABILITY_BREAKDOWNS, 0); + + SET_DPARAM16(0, v->service_interval); + SET_DPARAM16(1, v->date_of_last_service); + DrawString(x + 11, 141, STR_883C_SERVICING_INTERVAL_DAYS, 0); + + x = 1; + y = 57; + sel = w->vscroll.pos; + + // draw the first 3 details tabs + if (det_tab != 3) { + for(;;) { + if (--sel < 0 && sel >= -6) { + DrawTrainImage(v, x, y, 1, 0, INVALID_VEHICLE); + _train_details_drawer_proc[WP(w,traindetails_d).tab](v, x + 30, y + 2); + y += 14; + } + if ( (v=v->next) == NULL) + return; + } + } + else { // draw total cargo tab + i = 0; + DrawString(x, y + 2, STR_013F_TOTAL_CAPACITY_TEXT, 0); + do { + if (tot_cargo[i][1] > 0 && --sel < 0 && sel >= -5) { + y += 14; + // STR_013F_TOTAL_CAPACITY :{LTBLUE}- {CARGO} ({SHORTCARGO}) + SET_DPARAM8(0, i); // {CARGO} #1 + SET_DPARAM16(1, tot_cargo[i][0]); // {CARGO} #2 + SET_DPARAM8(2, i); // {SHORTCARGO} #1 + SET_DPARAM16(3, tot_cargo[i][1]); // {SHORTCARGO} #2 + DrawString(x, y, STR_013F_TOTAL_CAPACITY, 0); + } + } while (++i != NUM_CARGO); + } +} + +static void TrainDetailsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + DrawTrainDetailsWindow(w); + break; + case WE_CLICK: { + int mod; + Vehicle *v; + switch(e->click.widget) { + case 2: /* name train */ + v = &_vehicles[w->window_number]; + SET_DPARAM16(0, v->unitnumber); + ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number); + break; + case 6: /* inc serv interval */ + mod = 10; + goto do_change_service_int; + + case 7: /* dec serv interval */ + mod = -10; +do_change_service_int: + v = &_vehicles[w->window_number]; + mod += v->service_interval; + if (!IS_INT_INSIDE(mod, 30, 800+1)) + return; + + DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_TRAIN_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING)); + break; + /* details buttons*/ + case 9: // Cargo + case 10: // Information + case 11: // Capacities + case 12: // Total cargo + CLRBIT(w->disabled_state, 9); + CLRBIT(w->disabled_state, 10); + CLRBIT(w->disabled_state, 11); + CLRBIT(w->disabled_state, 12); + SETBIT(w->disabled_state, e->click.widget); + WP(w,traindetails_d).tab = e->click.widget - 9; + SetWindowDirty(w); + break; + } + } break; + + case WE_4: + if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL) + DeleteWindow(w); + break; + + case WE_ON_EDIT_TEXT: { + byte *b = e->edittext.str; + if (*b == 0) + return; + memcpy(_decode_parameters, b, 32); + DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_8866_CAN_T_NAME_TRAIN)); + } break; + } +} + +static const Widget _train_details_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 329, 0, 13, STR_8802_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 330, 369, 0, 13, STR_01AA_NAME, STR_8867_NAME_TRAIN}, +{ WWT_PANEL, 14, 0, 369, 14, 55, 0x0, 0}, +{ WWT_MATRIX, 14, 0, 358, 56, 139, 0x601, 0}, +{ WWT_SCROLLBAR, 14, 359, 369, 56, 139, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 140, 145, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL}, +{ WWT_PUSHTXTBTN, 14, 0, 10, 146, 151, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL}, +{ WWT_PANEL, 14, 11, 369, 140, 151, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 0, 92, 152, 163, STR_013C_CARGO, STR_884F_SHOW_DETAILS_OF_CARGO_CARRIED}, +{ WWT_PUSHTXTBTN, 14, 93, 184, 152, 163, STR_013D_INFORMATION, STR_8850_SHOW_DETAILS_OF_TRAIN_VEHICLES}, +{ WWT_PUSHTXTBTN, 14, 185, 277, 152, 163, STR_013E_CAPACITIES, STR_8851_SHOW_CAPACITIES_OF_EACH}, +{ WWT_PUSHTXTBTN, 14, 278, 369, 152, 163, STR_013E_TOTAL_CARGO, STR_8852_SHOW_TOTAL_CARGO}, +{ WWT_LAST}, +}; + + +static const WindowDesc _train_details_desc = { + -1,-1, 370, 164, + WC_VEHICLE_DETAILS,WC_VEHICLE_VIEW, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _train_details_widgets, + TrainDetailsWndProc +}; + + +void ShowTrainDetailsWindow(Vehicle *v) +{ + Window *w; + VehicleID veh = v->index; + + DeleteWindowById(WC_VEHICLE_ORDERS, veh); + DeleteWindowById(WC_VEHICLE_DETAILS, veh); + + _alloc_wnd_parent_num = veh; + w = AllocateWindowDesc(&_train_details_desc); + + w->window_number = veh; + w->caption_color = v->owner; + w->vscroll.cap = 6; + WP(w,traindetails_d).tab = 0; +} + +// draw the vehicle profit button in the vehicle list window. +void DrawVehicleProfitButton(Vehicle *v, int x, int y) +{ + uint32 ormod; + + // draw profit-based colored icons + if(v->age <= 365 * 2) + ormod = 0x3158000; // grey + else if(v->profit_last_year < 0) + ormod = 0x30b8000; //red + else if(v->profit_last_year < 10000) + ormod = 0x30a8000; // yellow + else + ormod = 0x30d8000; // green + DrawSprite((SPR_OPENTTD_BASE + 10) | ormod, x, y); +} + + +static const StringID _player_trains_tooltips[] = { + STR_018B_CLOSE_WINDOW, + STR_018C_WINDOW_TITLE_DRAG_THIS, + STR_883D_TRAINS_CLICK_ON_TRAIN_FOR, + STR_0190_SCROLL_BAR_SCROLLS_LIST, + STR_883E_BUILD_NEW_TRAINS_REQUIRES, + 0, +}; + +static void PlayerTrainsWndProc(Window *w, WindowEvent *e) +{ + switch(e->event) { + case WE_PAINT: + /* determine amount of items for scroller */ + { + Vehicle *v; + int num = 0; + byte owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype == 0 && v->owner == owner) + num++; + } + + SetVScrollCount(w, num); + } + + /* draw the widgets */ + { + Player *p = DEREF_PLAYER(w->window_number); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + DrawWindowWidgets(w); + } + + /* draw the trains */ + { + Vehicle *v; + int pos = w->vscroll.pos; + byte owner = (byte)w->window_number; + int x = 2; + int y = 15; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype == 0 && v->owner == owner && + --pos < 0 && pos >= -7) { + StringID str; + + DrawTrainImage(v, x + 21, y + 6, 10, 0, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y+13); + + SET_DPARAM16(0, v->unitnumber); + if (IsTrainDepotTile(v->tile)) { + str = STR_021F; + } else { + str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; + } + DrawString(x, y+2, str, 0); + + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(1, v->profit_last_year); + DrawString(x + 21, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + if (v->string_id != STR_SV_TRAIN_NAME) { + SET_DPARAM16(0, v->string_id); + DrawString(x+21, y, STR_01AB, 0); + } + + y += 26; + } + } + } + break; + + case WE_CLICK: { + switch(e->click.widget) { + case 2: { + int idx = (e->click.pt.y - 0xE) / 26; + Vehicle *v; + byte owner; + + if ((uint)idx >= 7) + break; + + idx += w->vscroll.pos; + + owner = (byte)w->window_number; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && v->subtype == 0 && v->owner == owner && + --idx < 0) { + ShowTrainViewWindow(v); + break; + } + } + } break; + + case 4: { + uint tile; + + tile = _last_built_train_depot_tile; + do { + if (_map_owner[tile] == _local_player && + IsTrainDepotTile(tile)) { + + ShowTrainDepotWindow(tile); + ShowBuildTrainWindow(tile); + return; + } + + tile = TILE_MASK(tile + 1); + } while(tile != _last_built_train_depot_tile); + + ShowBuildTrainWindow(0); + } break; + } + } break; + + } +} + +static const Widget _player_trains_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 313, 14, 195, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, +{ WWT_SCROLLBAR, 14, 314, 324, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 161, 196, 207, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES}, +{ WWT_PANEL, 14, 162, 324, 196, 207, 0x0, 0}, +{ WWT_LAST}, +}; + +static const WindowDesc _player_trains_desc = { + -1, -1, 325, 208, + WC_TRAINS_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _player_trains_widgets, + PlayerTrainsWndProc +}; + +static const Widget _other_player_trains_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_MATRIX, 14, 0, 313, 14, 195, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, +{ WWT_SCROLLBAR, 14, 314, 324, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_LAST}, +}; + +static const WindowDesc _other_player_trains_desc = { + -1, -1, 325, 196, + WC_TRAINS_LIST,0, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + _other_player_trains_widgets, + PlayerTrainsWndProc +}; + +void ShowPlayerTrains(int player) +{ + Window *w; + + if ( player == _local_player) { + w = AllocateWindowDescFront(&_player_trains_desc, player); + } else { + w = AllocateWindowDescFront(&_other_player_trains_desc, player); + } + if (w) { + w->caption_color = w->window_number; + w->vscroll.cap = 7; + } +} diff --git a/tree_cmd.c b/tree_cmd.c new file mode 100644 --- /dev/null +++ b/tree_cmd.c @@ -0,0 +1,647 @@ +#include "stdafx.h" +#include "ttd.h" +#include "viewport.h" +#include "command.h" +#include "town.h" + +static int GetRandomTreeType(uint tile, uint seed) +{ + byte i; + + if (_opt.landscape == LT_NORMAL) { + return seed * 12 >> 8; + } else if (_opt.landscape == LT_HILLY) { + return (seed >> 5) + 12; + } else if (_opt.landscape == LT_DESERT) { + i = GetMapExtraBits(tile); + if (i == 0) { + return (seed >> 6) + 28; + } else if (i == 1) { + if (seed > 12) + return -1; + return 27; + } else { + return (seed * 7 >> 8) + 20; + } + } else { + return (seed * 9 >> 8) + 32; + } +} + +static void PlaceTree(uint tile, uint32 r, byte m5_or) +{ + int tree = GetRandomTreeType(tile, (r >> 24)); + byte m5; + + if (tree >= 0) { + m5 = (byte)(r >> 16); + if(m5==7) m5--; + + _map5[tile] = m5 & 0x07; // growth state; + _map5[tile] |= m5 & 0xC0; // amount of trees + + _map3_lo[tile] = tree; // set type of tree + _map3_hi[tile] = 0; // no hedge + + // above snowline? + if( (_opt.landscape == LT_HILLY) && (GetTileZ(tile) - _opt.snow_line > 0) ) + { + _map2[tile] = 0xE0; // set land type to snow + _map2[tile] |= (byte)(r >> 24)&0x07; // randomize counter + } + else + { + _map2[tile] = (byte)(r >> 24)&0x1F; // randomize counter and ground + } + + + // make it tree class + _map_type_and_height[tile] |= MP_TREES << 4; + } +} + +static void DoPlaceMoreTrees(uint tile) +{ + int i = 1000; + int x,y; + uint cur_tile; + int dist; + + do { + uint32 r = Random(); + x = (r & 0x1F) - 16; + y = ((r>>8) & 0x1F) - 16; + + dist = myabs(x) + myabs(y); + + cur_tile=TILE_MASK(tile + TILE_XY(x,y)); + + if (dist <= 13 && IS_TILETYPE(cur_tile, MP_CLEAR)) { + PlaceTree(cur_tile, r, dist <= 6 ? 0xC0 : 0); + } + } while (--i); +} + +static void PlaceMoreTrees() +{ + int i = (Random() & 0x1F) + 25; + do { + DoPlaceMoreTrees(TILE_MASK(Random())); + } while (--i); +} + +void PlaceTreesRandomly() +{ + int i; + uint32 r; + uint tile; + + i = 1000; + do { + r = Random(); + tile = TILE_MASK(r); + if (IS_TILETYPE(tile, MP_CLEAR)) { + PlaceTree(tile, r, 0); + } + } while (--i); + + /* place extra trees at rainforest area */ + if (_opt.landscape == LT_DESERT) { + i = 15000; + + do { + r = Random(); + tile = TILE_MASK(r); + if (IS_TILETYPE(tile, MP_CLEAR) && GetMapExtraBits(tile) == 2) { + PlaceTree(tile, r, 0); + } + } while (--i); + } +} + +void GenerateTrees() +{ + int i; + + if (_opt.landscape != LT_CANDY) { + PlaceMoreTrees(); + } + + i = _opt.landscape == LT_HILLY ? 15 : 6; + do { + PlaceTreesRandomly(); + } while (--i); +} + +/* Plant a tree + * p1 = tree type, -1 means random. + * p2 = end tile + */ + +int32 CmdPlantTree(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti; + int32 cost; + int sx,sy,x,y; + int treetype; + + SET_EXPENSES_TYPE(EXPENSES_OTHER); + + // make sure sx,sy are smaller than ex,ey + sx = GET_TILE_X(p2)*16; + sy = GET_TILE_Y(p2)*16; + if (ex < sx) intswap(ex, sx); + if (ey < sy) intswap(ey, sy); + + cost = 0; // total cost + + for(x=sx; x<=ex; x+=16) { + for(y=sy; y<=ey; y+=16) { + FindLandscapeHeight(&ti, x, y); + if (!EnsureNoVehicle(ti.tile)) + continue; + + if (ti.type == MP_TREES) { + // no more space for trees? + if (_game_mode != GM_EDITOR && (ti.map5 & 0xC0) == 0xC0) { + _error_message = STR_2803_TREE_ALREADY_HERE; + continue; + } + + if (flags & DC_EXEC) { + _map5[ti.tile] = ti.map5 + 0x40; + MarkTileDirtyByTile(ti.tile); + } + // 2x as expensive to add more trees to an existing tile + cost += _price.build_trees * 2; + } else { + // don't allow building on rocks + if (ti.type != MP_CLEAR || _map_owner[ti.tile] != OWNER_NONE || (ti.map5 & 0x1C) == 8) { + _error_message = STR_2804_SITE_UNSUITABLE; + continue; + } + + // it's expensive to clear farmland + if ((ti.map5 & 0x1F) == 0xF) cost += _price.clear_3; + + if (flags & DC_EXEC) { + int m2; + + if (_game_mode != GM_EDITOR && _current_player < MAX_PLAYERS) { + Town *t = ClosestTownFromTile(ti.tile, _patches.dist_local_authority); + if (t != NULL) + ChangeTownRating(t, 7, 220); + } + m2 = 0; + if ( (ti.map5 & 0x1C) == 4 ) { + m2 = 16; + } else if ( (ti.map5 & 0x1C) == 16 ) { + m2 = (ti.map5 << 6) | 0x20; + } + + treetype = p1; + if (treetype == -1) { + treetype = GetRandomTreeType(ti.tile, Random()>>24); + if (treetype==-1) treetype=27; + } + + ModifyTile(ti.tile, + MP_SETTYPE(MP_TREES) | + MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5, + m2, /* map2 */ + treetype, /* map3lo */ + _game_mode == GM_EDITOR ? 3 : 0 /* map5 */ + ); + + if (_game_mode == GM_EDITOR && IS_BYTE_INSIDE(treetype, 0x14, 0x1B)) { + SetMapExtraBits(ti.tile, 2); + } + } + cost += _price.build_trees; + } + } + } + + if (cost == 0) return CMD_ERROR; + return cost; +} + +typedef struct TreeListEnt { + uint32 image; + byte x,y; +} TreeListEnt; + + +#include "table/tree_land.h" + + +static void DrawTile_Trees(TileInfo *ti) +{ + byte m2; + const uint32 *s; + const byte *d; + byte z; + TreeListEnt te[4]; + + m2 = _map2[ti->tile]; + + if ( (m2&0x30) == 0) { + DrawClearLandTile(ti, 3); + } else if ((m2&0x30) == 0x20) { + DrawGroundSprite(_tree_sprites_1[m2 >> 6] + _tileh_to_sprite[ti->tileh]); + } else { + DrawHillyLandTile(ti); + } + + DrawClearLandFence(ti, _map3_hi[ti->tile] >> 2); + + z = ti->z; + if (ti->tileh != 0) { + z += 4; + if (ti->tileh & 0x10) + z += 4; + } + + { + uint16 tmp = ti->x; + int index; + + tmp = (tmp >> 2) | (tmp << 14); + tmp -= ti->y; + tmp = (tmp >> 3) | (tmp << 13); + tmp -= ti->x; + tmp = (tmp >> 1) | (tmp << 15); + tmp += ti->y; + + d = _tree_layout_xy[(tmp & 0x30) >> 4]; + + index = ((tmp>>6)&3) + (_map3_lo[ti->tile]<<2); + + /* different tree styles above one of the grounds */ + if ((m2 & 0xB0) == 0xA0 && index >= 48 && index < 80) + index += 164 - 48; + + assert(index < lengthof(_tree_layout_sprite)); + s = _tree_layout_sprite[index]; + } + + StartSpriteCombine(); + + { + int i; + + /* put the trees to draw in a list */ + i = (ti->map5 >> 6) + 1; + do { + uint32 image = s[0] + (--i==0 ? (ti->map5 & 7) : 3); + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + te[i].image = image; + te[i].x = d[0]; + te[i].y = d[1]; + s++; + d+=2; + } while (i); + + /* draw them in a sorted way */ + for(;;) { + byte min = 0xFF; + TreeListEnt *tep = NULL; + + i = (ti->map5 >> 6) + 1; + do { + if (te[--i].image!=0 && (byte)(te[i].x + te[i].y) < min) { + min = te[i].x + te[i].y; + tep = &te[i]; + } + } while (i); + + if (tep == NULL) + break; + + AddSortableSpriteToDraw(tep->image, ti->x + tep->x, ti->y + tep->y, 5, 5, 0x10, z); + tep->image = 0; + } + } + + EndSpriteCombine(); +} + + +static uint GetSlopeZ_Trees(TileInfo *ti) { + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; +} + +static int32 ClearTile_Trees(uint tile, byte flags) { + int num; + + if (flags & DC_EXEC && _current_player < MAX_PLAYERS) { + Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + if (t != NULL) + ChangeTownRating(t, -35, -1000); + } + + num = (_map5[tile] >> 6) + 1; + if ( (byte)(_map3_lo[tile]-0x14) <= (0x1A-0x14)) + num <<= 2; + + if (flags & DC_EXEC) + DoClearSquare(tile); + + return num * _price.remove_trees; +} + +static void GetAcceptedCargo_Trees(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void GetTileDesc_Trees(uint tile, TileDesc *td) +{ + byte b; + StringID str; + + td->owner = _map_owner[tile]; + + b = _map3_lo[tile]; + (str=STR_2810_CACTUS_PLANTS, b==0x1B) || + (str=STR_280F_RAINFOREST, IS_BYTE_INSIDE(b, 0x14, 0x1A+1)) || + (str=STR_280E_TREES, true); + td->str = str; +} + +static void AnimateTile_Trees(uint tile) +{ + /* not used */ +} + +static byte _desert_sounds[] = { + 66,67,68,72 +}; + +static void TileLoopTreesDesert(uint tile) +{ + byte b; + + if ((b=GetMapExtraBits(tile)) == 2) { + uint32 r; + + if (CHANCE16I(1,200,r=Random())) { + SndPlayTileFx(_desert_sounds[(r >> 16) & 3], tile); + } + } else if (b == 1) { + if ((_map2[tile] & 0x30) != 0x20) { + _map2[tile] &= 0xF; + _map2[tile] |= 0xE0; + MarkTileDirtyByTile(tile); + } + } +} + +static void TileLoopTreesAlps(uint tile) +{ + byte tmp, m2; + int k; + + /* distance from snow line, in steps of 8 */ + k = GetTileZ(tile) - _opt.snow_line; + + tmp = _map5[tile] & 0xF0; + + if (k < -8) { + /* snow_m2_down */ + if ((tmp&0x30) != 0x20) + return; + m2 = 0; + } else if (k == -8) { + /* snow_m1 */ + m2 = 0x20; + if (tmp == m2) + return; + } else if (k < 8) { + /* snow_0 */ + m2 = 0x60; + if (tmp == m2) + return; + } else if (k == 8) { + /* snow_p1 */ + m2 = 0xA0; + if (tmp == m2) + return; + } else { + /* snow_p2_up */ + if (tmp == 0xC0) { + uint32 r; + if (CHANCE16I(1,200,r=Random())) { + SndPlayTileFx( (r&0x80000000) ? 57 : 52, tile); + } + return; + } else { + m2 = 0xE0; + } + } + + _map2[tile] &= 0xF; + _map2[tile] |= m2; + MarkTileDirtyByTile(tile); +} + +static void TileLoop_Trees(uint tile) +{ + byte m5, m2; + + static const TileIndexDiff _tileloop_trees_dir[] = { + TILE_XY(-1,-1), + TILE_XY(0,-1), + TILE_XY(1,-1), + TILE_XY(-1,0), + TILE_XY(1,0), + TILE_XY(-1,1), + TILE_XY(0,1), + TILE_XY(1,1), + }; + + if (_opt.landscape == LT_DESERT) { + TileLoopTreesDesert(tile); + } else if (_opt.landscape == LT_HILLY) { + TileLoopTreesAlps(tile); + } + + TileLoopClearHelper(tile); + + /* increase counter */ + { + byte m2 = _map2[tile]; + _map2[tile] = m2 = (m2 & 0xF0) | ((m2+1)&0xF); + if (m2 & 0xF) + return; + } + + m5 = _map5[tile]; + if ((m5&7) == 3) { + /* regular sized tree */ + if (_opt.landscape == LT_DESERT && _map3_lo[tile]!=0x1B && GetMapExtraBits(tile)==1) { + m5++; /* start destructing */ + } else { + switch(Random() & 0x7) { + case 0: /* start destructing */ + m5++; + break; + + case 1: /* add a tree */ + if (m5 < 0xC0) { + m5 = (m5 + 0x40) & ~7; + break; + } + /* fall through */ + + case 2: { /* add a neighbouring tree */ + byte m3 = _map3_lo[tile]; + + tile += _tileloop_trees_dir[Random() & 7]; + + if (!IS_TILETYPE(tile, MP_CLEAR)) + return; + + if ( (_map5[tile] & 0x1C) == 4) { + _map2[tile] = 0x10; + } else if ((_map5[tile] & 0x1C) == 16) { + _map2[tile] = (_map5[tile] << 6) | 0x20; + } else { + if ((_map5[tile] & 0x1F) != 3) + return; + _map2[tile] = 0; + } + + _map3_lo[tile] = m3; + _map3_hi[tile] = 0; + _map_type_and_height[tile] &= 0xF; + _map_type_and_height[tile] |= MP_TREES << 4; + + m5 = 0; + break; + } + + default: + return; + } + } + } else if ((m5&7) == 6) { + /* final stage of tree destruction */ + if (m5 & 0xC0) { + /* more than one tree, delete it? */ + m5 = ((m5 - 6) - 0x40) + 3; + } else { + /* just one tree, change type into MP_CLEAR */ + _map_type_and_height[tile] = (_map_type_and_height[tile]&~0xF0) | (MP_CLEAR<<4); + + m5 = 3; + m2 = _map2[tile]; + if ((m2&0x30) != 0) { + m5 = (m2 >> 6) | 0x10; + if (m2 != 0x20) + m5 = 7; + } + _map_owner[tile] = OWNER_NONE; + } + } else { + /* in the middle of a transition, change to next */ + m5++; + } + + _map5[tile] = m5; + MarkTileDirtyByTile(tile); +} + +void OnTick_Trees() +{ + uint32 r; + uint tile; + byte m; + int tree; + + /* place a tree at a random rainforest spot */ + if (_opt.landscape == LT_DESERT && + (r=Random(),tile=TILE_MASK(r),GetMapExtraBits(tile)==2) && + IS_TILETYPE(tile, MP_CLEAR) && + (m=_map5[tile]&0x1C, m<=4) && + (tree=GetRandomTreeType(tile, r>>24)) >= 0) { + + ModifyTile(tile, + MP_SETTYPE(MP_TREES) | + MP_MAP2 | MP_MAP3LO | MP_MAP3HI | MP_MAP5, + (m == 4 ? 0x10 : 0), + tree, + _map3_hi[tile] & ~3, + 0 + ); + } + + // byte underflow + if (--_trees_tick_ctr) + return; + + /* place a tree at a random spot */ + r = Random(); + tile = TILE_MASK(r); + if (IS_TILETYPE(tile, MP_CLEAR) && + (m=_map5[tile]&0x1C, m==0 || m==4 || m==0x10) && + (tree=GetRandomTreeType(tile, r>>24)) >= 0) { + int m2; + + if (m == 0) { + m2 = 0; + } else if (m == 4) { + m2 = 0x10; + } else { + m2 = (_map5[tile] << 6) | 0x20; + } + + ModifyTile(tile, + MP_SETTYPE(MP_TREES) | + MP_MAP2 | MP_MAP3LO | MP_MAP3HI | MP_MAP5, + m2, + tree, + _map3_hi[tile] & ~3, + 0 + ); + } +} + +static void ClickTile_Trees(uint tile) +{ + /* not used */ +} + +static uint32 GetTileTrackStatus_Trees(uint tile, int mode) +{ + return 0; +} + +static void ChangeTileOwner_Trees(uint tile, byte old_player, byte new_player) +{ + /* not used */ +} + +void InitializeTrees() +{ + memset(_sign_list, 0, sizeof(_sign_list)); + _trees_tick_ctr = 0; +} + + +const TileTypeProcs _tile_type_trees_procs = { + DrawTile_Trees, /* draw_tile_proc */ + GetSlopeZ_Trees, /* get_slope_z_proc */ + ClearTile_Trees, /* clear_tile_proc */ + GetAcceptedCargo_Trees, /* get_accepted_cargo_proc */ + GetTileDesc_Trees, /* get_tile_desc_proc */ + GetTileTrackStatus_Trees, /* get_tile_track_status_proc */ + ClickTile_Trees, /* click_tile_proc */ + AnimateTile_Trees, /* animate_tile_proc */ + TileLoop_Trees, /* tile_loop_clear */ + ChangeTileOwner_Trees, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + NULL, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; diff --git a/ttd.c b/ttd.c new file mode 100644 --- /dev/null +++ b/ttd.c @@ -0,0 +1,1107 @@ +#include "stdafx.h" + +#define VARDEF +#include "ttd.h" +#include "gfx.h" +#include "gui.h" +#include "station.h" +#include "vehicle.h" +#include "viewport.h" +#include "window.h" +#include "player.h" +#include "command.h" +#include "town.h" +#include "industry.h" +#include "news.h" +#include "engine.h" +#include "sound.h" +#include "economy.h" +#include "fileio.h" +#include "hal.h" +#include "airport.h" +#include "saveload.h" + +#include + +void GameLoop(); + +void IncreaseSpriteLRU(); +void InitializeGame(); +void GenerateWorld(int mode); +void CallLandscapeTick(); +void IncreaseDate(); +void RunOtherPlayersLoop(); +void DoPaletteAnimations(); +void MusicLoop(); +void ResetMusic(); +void InitializeStations(); +void DeleteAllPlayerStations(); + +extern void SetDifficultyLevel(int mode, GameOptions *gm_opt); +extern void DoStartupNewPlayer(bool is_ai); +extern void UpdateAllSignVirtCoords(); +extern void ShowOSErrorBox(const char *buf); + +void redsq_debug(int tile); +bool LoadSavegame(const char *filename); + +extern void HalGameLoop(); + +uint32 _pixels_redrawn; +bool _dbg_screen_rect; +bool disable_computer; + +void CDECL error(const char *s, ...) { + va_list va; + char buf[512]; + va_start(va, s); + vsprintf(buf, s, va); + va_end(va); + + ShowOSErrorBox(buf); + if (_video_driver) + _video_driver->stop(); + + assert(0); + exit(1); +} + +void CDECL debug(const char *s, ...) +{ + va_list va; + char buf[1024]; + va_start(va, s); + vsprintf(buf, s, va); + va_end(va); + + fprintf(stderr, "dbg: %s\n", buf); +} + +void CDECL ShowInfoF(const char *str, ...) +{ + va_list va; + char buf[1024]; + va_start(va, str); + vsprintf(buf, str, va); + va_end(va); + ShowInfo(buf); +} + +char * CDECL str_fmt(const char *str, ...) +{ + char buf[4096]; + va_list va; + int len; + char *p; + + va_start(va, str); + len = vsprintf(buf, str, va); + va_end(va); + p = malloc(len + 1); + if (p) + memcpy(p, buf, len + 1); + return p; +} + + +// NULL midi driver +static char *NullMidiStart(char **parm) { return NULL; } +static void NullMidiStop() {} +static void NullMidiPlaySong(const char *filename) {} +static void NullMidiStopSong() {} +static bool NullMidiIsSongPlaying() { return true; } +static void NullMidiSetVolume(byte vol) {} + +const HalMusicDriver _null_music_driver = { + NullMidiStart, + NullMidiStop, + NullMidiPlaySong, + NullMidiStopSong, + NullMidiIsSongPlaying, + NullMidiSetVolume, +}; + +// NULL video driver +static void *_null_video_mem; +static const char *NullVideoStart(char **parm) { + _screen.width = _screen.pitch = _cur_resolution[0]; + _screen.height = _cur_resolution[1]; + _null_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]); + return NULL; +} +static void NullVideoStop() { free(_null_video_mem); } +static void NullVideoMakeDirty(int left, int top, int width, int height) {} +static int NullVideoMainLoop() { + int i = 1000; + do { + GameLoop(); + _screen.dst_ptr = _null_video_mem; + UpdateWindows(); + } while (--i); + return ML_QUIT; +} + +static bool NullVideoChangeRes(int w, int h) { return false; } + + +const HalVideoDriver _null_video_driver = { + NullVideoStart, + NullVideoStop, + NullVideoMakeDirty, + NullVideoMainLoop, + NullVideoChangeRes, +}; + +// NULL sound driver +static char *NullSoundStart(char **parm) { return NULL; } +static void NullSoundStop() {} +const HalSoundDriver _null_sound_driver = { + NullSoundStart, + NullSoundStop, +}; + +enum { + DF_PRIORITY_MASK = 0xf, +}; + +typedef struct { + const DriverDesc *descs; + const char *name; + void *var; +} DriverClass; + +static DriverClass _driver_classes[] = { + {_video_driver_descs, "video", &_video_driver}, + {_sound_driver_descs, "sound", &_sound_driver}, + {_music_driver_descs, "music", &_music_driver}, +}; + +static const DriverDesc *GetDriverByName(const DriverDesc *dd, const char *name) +{ + do { + if (!strcmp(dd->name, name)) + return dd; + } while ((++dd)->name); + return NULL; +} + +static const DriverDesc *ChooseDefaultDriver(const DriverDesc *dd) +{ + const DriverDesc *best = NULL; + int best_pri = -1; + do { + if ((int)(dd->flags&DF_PRIORITY_MASK) > best_pri) { + best_pri = dd->flags&DF_PRIORITY_MASK; + best = dd; + } + } while ((++dd)->name); + return best; +} + +void ttd_strlcpy(char *dst, const char *src, size_t len) +{ + assert(len > 0); + while (--len && *src) + *dst++=*src++; + *dst = 0; +} + +char *strecpy(char *dst, const char *src) +{ + while ( (*dst++ = *src++) != 0) {} + return dst - 1; +} + +byte *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize) +{ + FILE *in; + void *mem; + size_t len; + + in = fopen(filename, "rb"); + if (in == NULL) + return NULL; + + fseek(in, 0, SEEK_END); + len = ftell(in); + fseek(in, 0, SEEK_SET); + if (len > maxsize || (mem=(byte*)malloc(len + 1)) == NULL) { + fclose(in); + return NULL; + } + ((byte*)mem)[len] = 0; + if (fread(mem, len, 1, in) != 1) { + fclose(in); + free(mem); + return NULL; + } + fclose(in); + + *lenp = len; + return mem; +} + +void LoadDriver(int driver, const char *name) +{ + const DriverClass *dc = &_driver_classes[driver]; + const DriverDesc *dd; + const void **var; + const void *drv; + const char *err; + char *parm; + char buffer[256]; + char *parms[32]; + + parms[0] = NULL; + + if (!*name) { + dd = ChooseDefaultDriver(dc->descs); + } else { + // Extract the driver name and put parameter list in parm + ttd_strlcpy(buffer, name, sizeof(buffer)); + parm = strchr(buffer, ':'); + if (parm) { + int 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); + } + var = dc->var; + if (*var != NULL) ((HalCommonDriver*)*var)->stop(); + *var = NULL; + drv = dd->drv; + if ((err=((HalCommonDriver*)drv)->start(parms)) != NULL) + error("Unable to load driver %s(%s). The error was: %s\n", dd->name, dd->longname, err); + *var = drv; +} + +void PrintDriverList() +{ +} + +static void showhelp() +{ + char buf[4096], *p; + const DriverClass *dc = _driver_classes; + const DriverDesc *dd; + int i; + + p = strecpy(buf, + "Command line options:\n" + " -v drv = Set video driver (see below)\n" + " -s drv = Set sound driver (see below)\n" + " -m drv = Set music driver (see below)\n" + " -r res = Set resolution (for instance 800x600)\n" + " -h = Display this help text\n" + " -t date= Set starting date\n" + " -d dbg = Debug mode\n" + " -l lng = Select Language\n" + " -e = Start Editor\n" + " -g = Start new game immediately (can optionally take a game to load)\n" + " -G seed= Set random seed\n" + ); + + for(i=0; i!=lengthof(_driver_classes); i++,dc++) { + p += sprintf(p, "List of %s drivers:\n", dc->name); + dd = dc->descs; + do { + p += sprintf(p, "%10s: %s\n", dd->name, dd->longname); + } while ((++dd)->name); + } + + ShowInfo(buf); +} + + +char *GetDriverParam(char **parm, const char *name) +{ + char *p; + int len = strlen(name); + while ((p = *parm++) != NULL) { + if (!strncmp(p,name,len)) { + if (p[len] == '=') return p + len + 1; + if (p[len] == 0) return p + len; + } + } + return NULL; +} + +bool GetDriverParamBool(char **parm, const char *name) +{ + char *p = GetDriverParam(parm, name); + return p != NULL; +} + +int GetDriverParamInt(char **parm, const char *name, int def) +{ + char *p = GetDriverParam(parm, name); + return p != NULL ? atoi(p) : def; +} + +typedef struct { + char *opt; + int numleft; + char **argv; + const char *options; + char *cont; +} MyGetOptData; + +static void MyGetOptInit(MyGetOptData *md, int argc, char **argv, const char *options) +{ + md->cont = NULL; + md->numleft = argc; + md->argv = argv; + md->options = options; +} + +static int MyGetOpt(MyGetOptData *md) +{ + char *s,*r,*t; + + if ((s=md->cont) != NULL) + goto md_continue_here; + + while(true) { + if (--md->numleft < 0) + return -1; + + s = *md->argv++; + if (*s == '-') { +md_continue_here:; + s++; + if (*s != 0) { + // Found argument, try to locate it in options. + if (*s == ':' || (r = strchr(md->options, *s)) == NULL) { + // ERROR! + return -2; + } + if (r[1] == ':') { + // Item wants an argument. Check if the argument follows, or if it comes as a separate arg. + if (!*(t = s + 1)) { + // It comes as a separate arg. Check if out of args? + if (--md->numleft < 0 || *(t = *md->argv) == '-') { + // Check if item is optional? + if (r[2] != ':') + return -2; + md->numleft++; + t = NULL; + } else { + md->argv++; + } + } + md->opt = t; + md->cont = NULL; + return *s; + } + md->opt = NULL; + md->cont = s; + return *s; + } + } else { + // This is currently not supported. + return -2; + } + } +} + +void SetDebugString(const char *s) +{ + int v; + char *end; + const char *t; + int *p; + + // global debugging level? + if (*s >= '0' && *s <= '9') { + v = strtoul(s, &end, 0); + s = end; + + _debug_spritecache_level = v; + _debug_misc_level = v; + } + + // individual levels + for(;;) { + // skip delimiters + while (*s == ' ' || *s == ',' || *s == '\t') s++; + if (*s == 0) break; + + t = s; + while (*s >= 'a' && *s <= 'z') s++; + +#define IS_LVL(x) (s - t == sizeof(x)-1 && !memcmp(t, x, sizeof(x)-1)) + // check debugging levels + if IS_LVL("misc") p = &_debug_misc_level; + else if IS_LVL("spritecache") p = &_debug_spritecache_level; + else { + ShowInfoF("Unknown debug level '%.*s'", s-t, t); + return; + } +#undef IS_LVL + if (*s == '=') s++; + v = strtoul(s, &end, 0); + s = end; + if (p) *p = v; + } +} + +void ParseResolution(int res[2], char *s) +{ + char *t = strchr(s, 'x'); + if (t == NULL) { + ShowInfoF("Invalid resolution '%s'", s); + return; + } + + res[0] = (strtoul(s, NULL, 0) + 7) & ~7; + res[1] = (strtoul(t+1, NULL, 0) + 7) & ~7; +} + +int ttd_main(int argc, char* argv[]) +{ + MyGetOptData mgo; + int i; + int network = 0; + char *network_conn = NULL; + char *language = NULL; + char musicdriver[32], sounddriver[32], videodriver[32]; + int resolution[2] = {0,0}; + uint startdate = -1; + _ignore_wrong_grf = false; + musicdriver[0] = sounddriver[0] = videodriver[0] = 0; + + _game_mode = GM_MENU; + _switch_mode = SM_MENU; + + MyGetOptInit(&mgo, argc-1, argv+1, "m:s:v:hn::l:eit:d::r:g::G:cp:"); + while ((i = MyGetOpt(&mgo)) != -1) { + switch(i) { + case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break; + case 's': ttd_strlcpy(sounddriver, mgo.opt, sizeof(sounddriver)); break; + case 'v': ttd_strlcpy(videodriver, mgo.opt, sizeof(videodriver)); break; + case 'n': network=1; if (mgo.opt) {network_conn = mgo.opt; network++;} break; + case 'r': ParseResolution(resolution, mgo.opt); break; + case 'l': { + language = mgo.opt; + } break; + case 't': { + startdate = atoi(mgo.opt); + } break; + case 'd': { +#if defined(WIN32) + CreateConsole(); +#endif + if (mgo.opt) + SetDebugString(mgo.opt); + } break; + case 'e': _switch_mode = SM_EDITOR; break; + case 'i': _ignore_wrong_grf = true; break; + case 'g': + if (mgo.opt) { + strcpy(_file_to_saveload.name, mgo.opt); + _switch_mode = SM_LOAD; + } else + _switch_mode = SM_NEWGAME; + break; + case 'G': + _random_seed_1 = atoi(mgo.opt); + break; + case 'p': { + int i = atoi(mgo.opt); + if (IS_INT_INSIDE(i, 0, 8)) _network_playas = i + 1; + break; + } + case -2: + case 'h': + showhelp(); + return 0; + } + } + + DeterminePaths(); + LoadFromConfig(); + + // override config? + if (musicdriver[0]) strcpy(_ini_musicdriver, musicdriver); + if (sounddriver[0]) strcpy(_ini_sounddriver, sounddriver); + if (videodriver[0]) strcpy(_ini_videodriver, videodriver); + if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; } + if (startdate != -1) _patches.starting_date = startdate; + + // enumerate language files + InitializeLanguagePacks(); + + // initialize screenshot formats + InitializeScreenshotFormats(); + + // initialize airport state machines + InitializeAirports(); + + // Sample catalogue + DEBUG(misc, 1) ("Loading sound effects..."); + MxInitialize(11025, "sample.cat"); + + // This must be done early, since functions use the InvalidateWindow* calls + InitWindowSystem(); + + GfxLoadSprites(); + LoadStringWidthTable(); + + DEBUG(misc, 1) ("Loading drivers..."); + LoadDriver(SOUND_DRIVER, _ini_sounddriver); + LoadDriver(MUSIC_DRIVER, _ini_musicdriver); + LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads + MusicLoop(); + + // Default difficulty level + _opt_mod_ptr = &_new_opt; + + // ugly hack, if diff_level is 9, it means we got no setting from the config file, so we load the default settings. + if (_opt_mod_ptr->diff_level == 9) + SetDifficultyLevel(0, _opt_mod_ptr); + + if (network) { + _networking = true; + + NetworkInitialize(); + if (network==1) { + DEBUG(misc, 1) ("Listening on port %d\n", _network_port); + NetworkListen(_network_port); + _networking_server = true; + } else { + DEBUG(misc, 1) ("Connecting to %s %d\n", network_conn, _network_port); + NetworkConnect(network_conn, _network_port); + } + } + + while (_video_driver->main_loop() == ML_SWITCHDRIVER) {} + + if (network) { + NetworkShutdown(); + } + + _video_driver->stop(); + _music_driver->stop(); + _sound_driver->stop(); + + SaveToConfig(); + + // uninitialize airport state machines + UnInitializeAirports(); + + return 0; +} + +static void ShowScreenshotResult(bool b) +{ + if (b) { + SET_DPARAM16(0, STR_SPEC_SCREENSHOT_NAME); + ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0); + } else { + ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0); + } + +} + +void LoadIntroGame() +{ + char filename[256]; + _game_mode = GM_MENU; + _display_opt |= DO_TRANS_BUILDINGS; // don't make buildings transparent in intro + + _opt_mod_ptr = &_new_opt; + GfxLoadSprites(); + LoadStringWidthTable(); + // Setup main window + InitWindowSystem(); + SetupColorsAndInitialWindow(); + + // Generate a world. + sprintf(filename, "%sopntitle.dat", _path.data_dir); + if (SaveOrLoad(filename, SL_LOAD) != SL_OK) + GenerateWorld(1); // if failed loading, make empty world. + + _opt.currency = _new_opt.currency; + + _pause = 0; + _local_player = 0; + MarkWholeScreenDirty(); + + // Play main theme + if (_music_driver->is_song_playing()) ResetMusic(); +} + +void MakeNewGame() +{ + _game_mode = GM_NORMAL; + + // Copy in game options + _opt_mod_ptr = &_opt; + memcpy(&_opt, &_new_opt, sizeof(_opt)); + + GfxLoadSprites(); + + // Reinitialize windows + InitWindowSystem(); + LoadStringWidthTable(); + + SetupColorsAndInitialWindow(); + + // Randomize world + GenerateWorld(0); + + // Create a single player + DoStartupNewPlayer(false); + + _local_player = 0; + + MarkWholeScreenDirty(); +} + +void MakeNewEditorWorld() +{ + _game_mode = GM_EDITOR; + + // Copy in game options + _opt_mod_ptr = &_opt; + memcpy(&_opt, &_new_opt, sizeof(_opt)); + + GfxLoadSprites(); + + // Re-init the windowing system + InitWindowSystem(); + + // Create toolbars + SetupColorsAndInitialWindow(); + + // Startup the game system + GenerateWorld(1); + + _local_player = OWNER_NONE; + MarkWholeScreenDirty(); +} + +void StartScenario() +{ + _game_mode = GM_NORMAL; + + // invalid type + if (_file_to_saveload.mode == SL_INVALID) { + printf("Savegame is obsolete or invalid format: %s\n", _file_to_saveload.name); + ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); + _game_mode = GM_MENU; + return; + } + + // Copy in game options + _opt_mod_ptr = &_opt; + memcpy(&_opt, &_new_opt, sizeof(_opt)); + + GfxLoadSprites(); + + // Reinitialize windows + InitWindowSystem(); + LoadStringWidthTable(); + + SetupColorsAndInitialWindow(); + + // Load game + if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode) != SL_OK) { + LoadIntroGame(); + ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); + } + + // Create a single player + DoStartupNewPlayer(false); + + _local_player = 0; + + MarkWholeScreenDirty(); +} + +bool SafeSaveOrLoad(const char *filename, int mode, int newgm) +{ + byte ogm = _game_mode; + int r; + + _game_mode = newgm; + r = SaveOrLoad(filename, mode); + if (r == SL_REINIT) { + if (ogm == GM_MENU) + LoadIntroGame(); + else if (ogm == GM_EDITOR) + MakeNewEditorWorld(); + else + MakeNewGame(); + return false; + } else if (r != SL_OK) { + _game_mode = ogm; + return false; + } else + return true; +} + +static void SwitchMode(int new_mode) +{ + _in_state_game_loop = true; + + switch(new_mode) { + case SM_EDITOR: // Switch to scenario editor + MakeNewEditorWorld(); + break; + + case SM_NEWGAME: + if (_networking) { NetworkStartSync(); } // UGLY HACK HACK HACK + MakeNewGame(); + break; + +normal_load: + case SM_LOAD: { // Load game + + if (_networking) { NetworkStartSync(); } // UGLY HACK HACK HACK + + _error_message = INVALID_STRING_ID; + if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) { + ShowErrorMessage(_error_message, STR_4009_GAME_LOAD_FAILED, 0, 0); + } else { + _opt_mod_ptr = &_opt; + _local_player = 0; + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // decrease pause counter (was increased from opening load dialog) + } + break; + } + + case SM_LOAD_SCENARIO: { + int i; + + if (_game_mode == GM_MENU) goto normal_load; + + if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) { + _opt_mod_ptr = &_opt; + + _local_player = OWNER_NONE; + _generating_world = true; + // delete all players. + for(i=0; i != MAX_PLAYERS; i++) { + ChangeOwnershipOfPlayerItems(i, 0xff); + _players[i].is_active = false; + } + _generating_world = false; + // delete all stations owned by a player + DeleteAllPlayerStations(); + } else + ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0); + + break; + } + + + case SM_MENU: // Switch to game menu + LoadIntroGame(); + break; + + case SM_SAVE: // Save game + if (SaveOrLoad(_file_to_saveload.name, SL_SAVE) != SL_OK) + ShowErrorMessage(INVALID_STRING_ID, STR_4007_GAME_SAVE_FAILED, 0, 0); + else + DeleteWindowById(WC_SAVELOAD, 0); + break; + + case SM_GENRANDLAND: + GenerateWorld(2); + // XXX: set date + _local_player = OWNER_NONE; + MarkWholeScreenDirty(); + break; + } + + _in_state_game_loop = false; +} + + +// State controlling game loop. +// The state must not be changed from anywhere +// but here. +// That check is enforced in DoCommand. +void StateGameLoop() +{ + _in_state_game_loop = true; + _frame_counter++; + + // store the random seed to be able to detect out of sync errors + _sync_seed_1 = _random_seed_1; + _sync_seed_2 = _random_seed_2; + + if (_savedump_path[0] && (uint)_frame_counter >= _savedump_first && (uint)(_frame_counter -_savedump_first) % _savedump_freq == 0 ) { + char buf[100]; + sprintf(buf, "%s%.5d.sav", _savedump_path, _frame_counter); + SaveOrLoad(buf, SL_SAVE); + if ((uint)_frame_counter >= _savedump_last) exit(1); + } + + if (_game_mode == GM_EDITOR) { + RunTileLoop(); + CallVehicleTicks(); + CallLandscapeTick(); + CallWindowTickEvent(); + NewsLoop(); + } else { + AnimateAnimatedTiles(); + IncreaseDate(); + RunTileLoop(); + CallVehicleTicks(); + CallLandscapeTick(); + + if (!disable_computer) + RunOtherPlayersLoop(); + + CallWindowTickEvent(); + NewsLoop(); + } + _in_state_game_loop = false; +} + +static void DoAutosave() +{ + char buf[200]; + + if (_patches.keep_all_autosave && _local_player != 255) { + Player *p; + char *s; + sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP); + p = DEREF_PLAYER(_local_player); + SET_DPARAM16(0, p->name_1); + SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, _date); + s= (char*)GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP) - 1, STR_4004); + strcpy(s, ".sav"); + } else { + int n = _autosave_ctr; + _autosave_ctr = (_autosave_ctr + 1) & 15; + sprintf(buf, "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, n); + } + + if (SaveOrLoad(buf, SL_SAVE) != SL_OK) + ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0); +} + +void GameLoop() +{ + int m; + + // autosave game? + if (_do_autosave) { + _do_autosave = false; + DoAutosave(); + RedrawAutosave(); + } + + // make a screenshot? + if ((m=_make_screenshot) != 0) { + _make_screenshot = 0; + switch(m) { + case 1: // make small screenshot + UndrawMouseCursor(); + ShowScreenshotResult(MakeScreenshot()); + break; + case 2: // make large screenshot + ShowScreenshotResult(MakeWorldScreenshot(-(TILE_X_MAX)*32, 0, TILE_X_MAX*32 + (TILE_X_MAX)*32, TILES_Y * 32, 0)); + break; + } + } + + // switch game mode? + if ((m=_switch_mode) != SM_NONE) { + _switch_mode = SM_NONE; + SwitchMode(m); + } + + IncreaseSpriteLRU(); + InteractiveRandom(); + + if (_scroller_click_timeout > 3) + _scroller_click_timeout -= 3; + else + _scroller_click_timeout = 0; + + _caret_timer += 3; + _timer_counter+=8; + CursorTick(); + + if (_networking) { + NetworkReceive(); + NetworkProcessCommands(); // to check if we got any new commands belonging to the current frame before we increase it. + } + + if (_networking_sync) { + // make sure client's time is synched to the server by running frames quickly up to where the server is. + if (!_networking_server) { + while (_frame_counter < _frame_counter_srv) { + StateGameLoop(); + NetworkProcessCommands(); // need to process queue to make sure that packets get executed. + } + } + // don't exceed the max count told by the server + if (_frame_counter < _frame_counter_max) { + StateGameLoop(); + NetworkProcessCommands(); + } + } else { + if (!_pause) + StateGameLoop(); + } + + if (!_pause && _display_opt&DO_FULL_ANIMATION) + DoPaletteAnimations(); + + if (!_pause || _patches.build_in_pause) + MoveAllTextEffects(); + + MouseLoop(); + + // send outgoing packets. + if (_networking) + NetworkSend(); + + if (_game_mode != GM_MENU) + MusicLoop(); +} + +void BeforeSaveGame() +{ + Window *w = FindWindowById(WC_MAIN_WINDOW, 0); + + _saved_scrollpos_x = WP(w,vp_d).scrollpos_x; + _saved_scrollpos_y = WP(w,vp_d).scrollpos_y; + _saved_scrollpos_zoom = w->viewport->zoom; +} + +void ConvertTownOwner() +{ + uint tile; + + for(tile=0; tile!=TILES_X * TILES_Y; tile++) { + if (IS_TILETYPE(tile, MP_STREET)) { + if ((_map5[tile] & 0xF0) == 0x10 && _map3_lo[tile] & 0x80) + _map3_lo[tile] = OWNER_TOWN; + + if (_map_owner[tile] & 0x80) + _map_owner[tile] = OWNER_TOWN; + } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + if (_map_owner[tile] & 0x80) + _map_owner[tile] = OWNER_TOWN; + } + } +} + +// before savegame version 4, the name of the company determined if it existed +void CheckIsPlayerActive() +{ + Player *p; + FOR_ALL_PLAYERS(p) { + if (p->name_1 != 0) { + p->is_active = true; + } + } +} + +extern void UpdateOldAircraft(); + +bool AfterLoadGame(uint version) +{ + Window *w; + ViewPort *vp; + + // in version 2.1 of the savegame, town owner was unified. + if (version <= 0x200) { + ConvertTownOwner(); + } + + // convert road side to my format. + if (_opt.road_side) _opt.road_side = 1; + + // Load the sprites + GfxLoadSprites(); + + // Update current year + SetDate(_date); + + // reinit the landscape variables (landscape might have changed) + InitializeLandscapeVariables(true); + + // Update all vehicles + AfterLoadVehicles(); + // in version 2.2 of the savegame, we have new airports + if (version <= 0x201) { + UpdateOldAircraft(); + } + + UpdateAllStationVirtCoord(); + + // Setup town coords + AfterLoadTown(); + UpdateAllSignVirtCoords(); + + // make sure there is a town in the game + if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, (uint)-1)) + { + _error_message = STR_NO_TOWN_IN_SCENARIO; + return false; + } + + // Initialize windows + InitWindowSystem(); + SetupColorsAndInitialWindow(); + + w = FindWindowById(WC_MAIN_WINDOW, 0); + + WP(w,vp_d).scrollpos_x = _saved_scrollpos_x; + WP(w,vp_d).scrollpos_y = _saved_scrollpos_y; + + vp = w->viewport; + vp->zoom = _saved_scrollpos_zoom; + vp->virtual_width = vp->width << vp->zoom; + vp->virtual_height = vp->height << vp->zoom; + + + // in version 4.0 of the savegame, is_active was introduced to determine + // if a player does exist, rather then checking name_1 + if (version <= 0x400) { + CheckIsPlayerActive(); + } + + // in case the player doesn't exist, create one (for scenario) + if (!_players[0].is_active) + DoStartupNewPlayer(false); + + DoZoomInOut(ZOOM_NONE); // update button status + MarkWholeScreenDirty(); + + return true; +} + + +void DebugProc(int i) +{ + switch(i) { + case 0: + *(byte*)0 = 0; + break; + case 1: + DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT); + break; + case 2: + UpdateAllStationVirtCoord(); + break; + } +} diff --git a/ttd.dsp b/ttd.dsp new file mode 100644 --- /dev/null +++ b/ttd.dsp @@ -0,0 +1,941 @@ +# Microsoft Developer Studio Project File - Name="ttd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ttd - Win32 Checked +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ttd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ttd.mak" CFG="ttd - Win32 Checked" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ttd - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ttd - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ttd - Win32 Checked" (based on "Win32 (x86) Console Application") +!MESSAGE "ttd - Win32 Release with PNG" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ttd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gr /Zp4 /W3 /Zi /Ox /Oa /Ow /Og /Oi /Os /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32_EXCEPTION_TRACKER" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /FAcs /FR /Yu"stdafx.h" /J /FD /c +# SUBTRACT CPP /WX /Ot +# ADD BASE RSC /l 0x41d /d "NDEBUG" +# ADD RSC /l 0x41d /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /map /machine:I386 /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ttd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WITH_SDL" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /D "WITH_PNG" /D "WITH_ZLIB" /YX"stdafx.h" /FD /GZ /c +# SUBTRACT CPP /WX /Fr +# ADD BASE RSC /l 0x41d /d "_DEBUG" +# ADD RSC /l 0x41d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib ws2_32.lib libpng.lib zlibstat.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ttd - Win32 Checked" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ttd___Win32_Checked" +# PROP BASE Intermediate_Dir "ttd___Win32_Checked" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Checked" +# PROP Intermediate_Dir "Checked" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WITH_SDL" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /YX"stdafx.h" /FD /GZ /c +# SUBTRACT BASE CPP /WX /Fr +# ADD CPP /nologo /Gr /Zp4 /ML /W3 /Gm /Zi /Ox /Oa /Ow /Og /Oi /Os /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WITH_SDL" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /YX"stdafx.h" /FD /c +# ADD BASE RSC /l 0x41d /d "_DEBUG" +# ADD RSC /l 0x41d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none /incremental:no + +!ELSEIF "$(CFG)" == "ttd - Win32 Release with PNG" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ttd___Win32_Release_with_PNG" +# PROP BASE Intermediate_Dir "ttd___Win32_Release_with_PNG" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleasePNG" +# PROP Intermediate_Dir "ReleasePNG" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /Gr /Zp4 /W3 /Zi /Ox /Oa /Ow /Og /Oi /Os /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32_EXCEPTION_TRACKER" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /FAcs /FR /Yu"stdafx.h" /J /FD /c +# SUBTRACT BASE CPP /WX /Ot +# ADD CPP /nologo /Gr /Zp4 /W3 /Zi /Ox /Oa /Ow /Og /Oi /Os /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32_EXCEPTION_TRACKER" /D "WIN32_ENABLE_DIRECTMUSIC_SUPPORT" /D "WITH_PNG" /D "WITH_ZLIB" /FAcs /FR /Yu"stdafx.h" /J /FD /c +# SUBTRACT CPP /WX /Ot +# ADD BASE RSC /l 0x41d /d "NDEBUG" +# ADD RSC /l 0x41d /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib libpng.lib zlibstat.lib /nologo /subsystem:windows /map /machine:I386 /opt:nowin98 +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib libpng.lib zlibstat.lib /nologo /subsystem:windows /map /machine:I386 /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "ttd - Win32 Release" +# Name "ttd - Win32 Debug" +# Name "ttd - Win32 Checked" +# Name "ttd - Win32 Release with PNG" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\ai.c +# End Source File +# Begin Source File + +SOURCE=.\airport.c +# End Source File +# Begin Source File + +SOURCE=.\command.c +# End Source File +# Begin Source File + +SOURCE=.\documentation.txt +# End Source File +# Begin Source File + +SOURCE=.\economy.c +# End Source File +# Begin Source File + +SOURCE=.\engine.c +# End Source File +# Begin Source File + +SOURCE=.\fileio.c +# End Source File +# Begin Source File + +SOURCE=.\gfx.c +# End Source File +# Begin Source File + +SOURCE=.\grfspecial.c +# End Source File +# Begin Source File + +SOURCE=.\landscape.c +# End Source File +# Begin Source File + +SOURCE=.\minilzo.c + +!IF "$(CFG)" == "ttd - Win32 Release" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ttd - Win32 Debug" + +# SUBTRACT CPP /YX + +!ELSEIF "$(CFG)" == "ttd - Win32 Checked" + +# SUBTRACT BASE CPP /YX +# SUBTRACT CPP /YX + +!ELSEIF "$(CFG)" == "ttd - Win32 Release with PNG" + +# SUBTRACT BASE CPP /YX /Yc /Yu +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\misc.c +# End Source File +# Begin Source File + +SOURCE=.\namegen.c +# End Source File +# Begin Source File + +SOURCE=.\network.c +# End Source File +# Begin Source File + +SOURCE=.\oldloader.c +# End Source File +# Begin Source File + +SOURCE=.\pathfind.c +# End Source File +# Begin Source File + +SOURCE=.\players.c +# End Source File +# Begin Source File + +SOURCE=.\saveload.c +# End Source File +# Begin Source File + +SOURCE=.\screenshot.c +# End Source File +# Begin Source File + +SOURCE=.\sdl.c +# End Source File +# Begin Source File + +SOURCE=.\settings.c +# End Source File +# Begin Source File + +SOURCE=.\sound.c +# End Source File +# Begin Source File + +SOURCE=.\spritecache.c +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.c + +!IF "$(CFG)" == "ttd - Win32 Release" + +# ADD CPP /Yc"stdafx.h" + +!ELSEIF "$(CFG)" == "ttd - Win32 Debug" + +!ELSEIF "$(CFG)" == "ttd - Win32 Checked" + +!ELSEIF "$(CFG)" == "ttd - Win32 Release with PNG" + +# ADD BASE CPP /Yc"stdafx.h" +# ADD CPP /Yc"stdafx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\strings.c +# End Source File +# Begin Source File + +SOURCE=.\texteff.c +# End Source File +# Begin Source File + +SOURCE=.\ttd.c +# End Source File +# Begin Source File + +SOURCE=.\ttd.rc +# End Source File +# Begin Source File + +SOURCE=.\unix.c + +!IF "$(CFG)" == "ttd - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ttd - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ttd - Win32 Checked" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ttd - Win32 Release with PNG" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\vehicle.c +# End Source File +# Begin Source File + +SOURCE=.\viewport.c +# End Source File +# Begin Source File + +SOURCE=.\w32dm.c +# End Source File +# Begin Source File + +SOURCE=.\w32dm2.cpp + +!IF "$(CFG)" == "ttd - Win32 Release" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ttd - Win32 Debug" + +!ELSEIF "$(CFG)" == "ttd - Win32 Checked" + +!ELSEIF "$(CFG)" == "ttd - Win32 Release with PNG" + +# SUBTRACT BASE CPP /YX /Yc /Yu +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\widget.c +# End Source File +# Begin Source File + +SOURCE=.\win32.c +# End Source File +# Begin Source File + +SOURCE=.\window.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\town.h +# End Source File +# Begin Source File + +SOURCE=.\command.h +# End Source File +# Begin Source File + +SOURCE=.\economy.h +# End Source File +# Begin Source File + +SOURCE=.\engine.h +# End Source File +# Begin Source File + +SOURCE=.\fileio.h +# End Source File +# Begin Source File + +SOURCE=.\functions.h +# End Source File +# Begin Source File + +SOURCE=.\gfx.h +# End Source File +# Begin Source File + +SOURCE=.\gui.h +# End Source File +# Begin Source File + +SOURCE=.\hal.h +# End Source File +# Begin Source File + +SOURCE=.\industry.h +# End Source File +# Begin Source File + +SOURCE=.\macros.h +# End Source File +# Begin Source File + +SOURCE=.\news.h +# End Source File +# Begin Source File + +SOURCE=.\pathfind.h +# End Source File +# Begin Source File + +SOURCE=.\player.h +# End Source File +# Begin Source File + +SOURCE=.\saveload.h +# End Source File +# Begin Source File + +SOURCE=.\sound.h +# End Source File +# Begin Source File + +SOURCE=.\station.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\ttd.h +# End Source File +# Begin Source File + +SOURCE=.\variables.h +# End Source File +# Begin Source File + +SOURCE=.\vehicle.h +# End Source File +# Begin Source File + +SOURCE=.\viewport.h +# End Source File +# Begin Source File + +SOURCE=.\window.h +# End Source File +# End Group +# Begin Group "Listings" + +# PROP Default_Filter "*.cod" +# Begin Source File + +SOURCE=.\Release\ai.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\aircraft_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\clear_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\command.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\depot_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\disaster_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\economy.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\engine.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\gfx.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\goods.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\graph_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\industry_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\industry_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\landscape.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\main_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\minilzo.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\misc.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\misc_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\news_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\player_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\player_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\players.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\rail_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\road_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\saveload.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\settings_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\ship_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\smallmap_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\sound.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\spritecache.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\station_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\strings.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\town_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\town_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\train_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\train_gui.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\tree_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\ttd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\vehicle.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\viewport.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\water_cmd.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\widget.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\win32.cod +# End Source File +# Begin Source File + +SOURCE=.\Release\window.cod +# End Source File +# End Group +# Begin Group "Gui Source codes" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\aircraft_gui.c +# End Source File +# Begin Source File + +SOURCE=.\airport_gui.c +# End Source File +# Begin Source File + +SOURCE=.\bridge_gui.c +# End Source File +# Begin Source File + +SOURCE=.\dock_gui.c +# End Source File +# Begin Source File + +SOURCE=.\engine_gui.c +# End Source File +# Begin Source File + +SOURCE=.\graph_gui.c +# End Source File +# Begin Source File + +SOURCE=.\industry_gui.c +# End Source File +# Begin Source File + +SOURCE=.\intro_gui.c +# End Source File +# Begin Source File + +SOURCE=.\main_gui.c +# End Source File +# Begin Source File + +SOURCE=.\misc_gui.c +# End Source File +# Begin Source File + +SOURCE=.\music_gui.c +# End Source File +# Begin Source File + +SOURCE=.\network_gui.c +# End Source File +# Begin Source File + +SOURCE=.\news_gui.c +# End Source File +# Begin Source File + +SOURCE=.\order_gui.c +# End Source File +# Begin Source File + +SOURCE=.\player_gui.c +# End Source File +# Begin Source File + +SOURCE=.\rail_gui.c +# End Source File +# Begin Source File + +SOURCE=.\road_gui.c +# End Source File +# Begin Source File + +SOURCE=.\roadveh_gui.c +# End Source File +# Begin Source File + +SOURCE=.\settings_gui.c +# End Source File +# Begin Source File + +SOURCE=.\ship_gui.c +# End Source File +# Begin Source File + +SOURCE=.\smallmap_gui.c +# End Source File +# Begin Source File + +SOURCE=.\station_gui.c +# End Source File +# Begin Source File + +SOURCE=.\subsidy_gui.c +# End Source File +# Begin Source File + +SOURCE=.\terraform_gui.c +# End Source File +# Begin Source File + +SOURCE=.\town_gui.c +# End Source File +# Begin Source File + +SOURCE=.\train_gui.c +# End Source File +# End Group +# Begin Group "Landscape" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\aircraft_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\clear_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\disaster_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\dummy_land.c +# End Source File +# Begin Source File + +SOURCE=.\industry_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\misc_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\order_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\rail_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\road_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\roadveh_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\ship_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\station_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\town_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\train_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\tree_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\tunnelbridge_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\unmovable_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\water_cmd.c +# End Source File +# End Group +# Begin Group "Tables" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\table\ai_rail.h +# End Source File +# Begin Source File + +SOURCE=.\table\allstrings.h +# End Source File +# Begin Source File + +SOURCE=.\table\animcursors.h +# End Source File +# Begin Source File + +SOURCE=.\table\build_industry.h +# End Source File +# Begin Source File + +SOURCE=.\table\town_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\clear_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\engines.h +# End Source File +# Begin Source File + +SOURCE=.\table\genland.h +# End Source File +# Begin Source File + +SOURCE=.\table\industry_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\landscape_const.h +# End Source File +# Begin Source File + +SOURCE=.\table\landscape_sprite.h +# End Source File +# Begin Source File + +SOURCE=.\table\palettes.h +# End Source File +# Begin Source File + +SOURCE=.\table\road_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\roadveh.h +# End Source File +# Begin Source File + +SOURCE=.\table\station_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\strings.h +# End Source File +# Begin Source File + +SOURCE=.\table\track_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\train_cmd.h +# End Source File +# Begin Source File + +SOURCE=.\table\tree_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\tunnel_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\unmovable_land.h +# End Source File +# Begin Source File + +SOURCE=.\table\water_land.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\changelog.txt +# End Source File +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# Begin Source File + +SOURCE=.\mainicon.ico +# End Source File +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/ttd.dsw b/ttd.dsw new file mode 100644 --- /dev/null +++ b/ttd.dsw @@ -0,0 +1,59 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "langs"=.\langs.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name strgen + End Project Dependency +}}} + +############################################################################### + +Project: "strgen"=.\strgen\strgen.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ttd"=.\ttd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name langs + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/ttd.h b/ttd.h new file mode 100644 --- /dev/null +++ b/ttd.h @@ -0,0 +1,491 @@ +#ifndef TTD_H +#define TTD_H + +// include strings +#include "table/strings.h" + +#ifndef VARDEF +#define VARDEF extern +#endif + +// use this on non static functions +#define PUBLIC + +typedef struct Rect { + int left,top,right,bottom; +} Rect; + +typedef struct SmallPoint { + int16 x,y; +} SmallPoint; + +typedef struct Point { + int x,y; +} Point; + +typedef struct Pair { + int a; + int b; +} Pair; + +typedef struct YearMonthDay { + int year, month, day; +} YearMonthDay; + +#include "macros.h" + +// Forward declarations of structs. +typedef struct Vehicle Vehicle; +typedef struct Depot Depot; +typedef struct Checkpoint Checkpoint; +typedef struct Window Window; +typedef struct Station Station; +typedef struct ViewPort ViewPort; +typedef struct Town Town; +typedef struct NewsItem NewsItem; +typedef struct Industry Industry; +typedef struct DrawPixelInfo DrawPixelInfo; +typedef uint16 VehicleID; +typedef uint16 StringID; +typedef uint16 SpriteID; +typedef uint32 PalSpriteID; + +typedef uint32 WindowNumber; +typedef byte WindowClass; + + +enum GameModes { + GM_MENU, + GM_NORMAL, + GM_EDITOR +}; + +enum SwitchModes { + SM_NONE = 0, + SM_NEWGAME = 1, + SM_EDITOR = 2, + SM_LOAD = 3, + SM_MENU = 4, + SM_SAVE = 5, + SM_GENRANDLAND = 6, + SM_LOAD_SCENARIO = 9, + +}; + +enum MapTileTypes { + MP_CLEAR, + MP_RAILWAY, + MP_STREET, + MP_HOUSE, + MP_TREES, + MP_STATION, + MP_WATER, + MP_STRANGE, + MP_INDUSTRY, + MP_TUNNELBRIDGE, + MP_UNMOVABLE +}; + +typedef struct TileInfo { + uint x; + uint y; + uint tileh; + uint type; + uint map5; + uint tile; + uint z; +} TileInfo; + +enum { + NG_EDGE = 1, +}; + +/* Display Options */ +enum { + DO_SHOW_TOWN_NAMES = 1, + DO_SHOW_STATION_NAMES = 2, + DO_SHOW_SIGNS = 4, + DO_FULL_ANIMATION = 8, + DO_TRANS_BUILDINGS = 0x10, + DO_FULL_DETAIL = 0x20, + DO_CHECKPOINTS = 0x40, +}; + +/* Landscape types */ +enum { + LT_NORMAL = 0, + LT_HILLY = 1, + LT_DESERT = 2, + LT_CANDY = 3, + + NUM_LANDSCAPE = 4, +}; + +enum { + NUM_PRICES = 49, +}; + +typedef struct Prices { + int32 station_value; + int32 build_rail; + int32 build_road; + int32 build_signals; + int32 build_bridge; + int32 build_train_depot; + int32 build_road_depot; + int32 build_ship_depot; + int32 build_tunnel; + int32 train_station_track; + int32 train_station_length; + int32 build_airport; + int32 build_bus_station; + int32 build_truck_station; + int32 build_dock; + int32 build_railvehicle; + int32 build_railwagon; + int32 aircraft_base; + int32 roadveh_base; + int32 ship_base; + int32 build_trees; + int32 terraform; + int32 clear_1; + int32 purchase_land; + int32 clear_2; + int32 clear_3; + int32 remove_trees; + int32 remove_rail; + int32 remove_signals; + int32 clear_bridge; + int32 remove_train_depot; + int32 remove_road_depot; + int32 remove_ship_depot; + int32 clear_tunnel; + int32 clear_water; + int32 remove_rail_station; + int32 remove_airport; + int32 remove_bus_station; + int32 remove_truck_station; + int32 remove_dock; + int32 remove_house; + int32 remove_road; + int32 running_rail[3]; + int32 aircraft_running; + int32 roadveh_running; + int32 ship_running; + int32 build_industry; +} Prices; + +#define GAME_DIFFICULTY_NUM 18 + +typedef struct GameDifficulty { + int max_no_competitors; + int competitor_start_time; + int number_towns; + int number_industries; + int max_loan; + int initial_interest; + int vehicle_costs; + int competitor_speed; + int competitor_intelligence; + int vehicle_breakdowns; + int subsidy_multiplier; + int construction_cost; + int terrain_type; + int quantity_sea_lakes; + int economy; + int line_reverse_mode; + int disasters; + int town_council_tolerance; // minimum required town ratings to be allowed to demolish stuff +} GameDifficulty; + +typedef struct AcceptedCargo { + int type_1, amount_1; + int type_2, amount_2; + int type_3, amount_3; +} AcceptedCargo; + +typedef struct TileDesc { + StringID str; + byte owner; + uint32 dparam[2]; +} TileDesc; + +typedef struct { + int16 left, top; + byte width_1, width_2; +} ViewportSign; + +typedef struct SignStruct { + StringID str; + ViewportSign sign; + int16 x,y; + byte z; +} SignStruct; + + +typedef int32 CommandProc(int x, int y, uint32 flags, uint32 p1, uint32 p2); + +typedef void DrawTileProc(TileInfo *ti); +typedef uint GetSlopeZProc(TileInfo *ti); +typedef int32 ClearTileProc(uint tile, byte flags); +typedef void GetAcceptedCargoProc(uint tile, AcceptedCargo *res); +typedef void GetTileDescProc(uint tile, TileDesc *td); +typedef uint32 GetTileTrackStatusProc(uint tile, int mode); +typedef void GetProducedCargoProc(uint tile, byte *b); +typedef void ClickTileProc(uint tile); +typedef void AnimateTileProc(uint tile); +typedef void TileLoopProc(uint tile); +typedef void ChangeTileOwnerProc(uint tile, byte old_player, byte new_player); +typedef uint32 VehicleEnterTileProc(Vehicle *v, uint tile, int x, int y); +typedef void VehicleLeaveTileProc(Vehicle *v, uint tile, int x, int y); + +typedef struct { + DrawTileProc *draw_tile_proc; + GetSlopeZProc *get_slope_z_proc; + ClearTileProc *clear_tile_proc; + GetAcceptedCargoProc *get_accepted_cargo_proc; + GetTileDescProc *get_tile_desc_proc; + GetTileTrackStatusProc *get_tile_track_status_proc; + ClickTileProc *click_tile_proc; + AnimateTileProc *animate_tile_proc; + TileLoopProc *tile_loop_proc; + ChangeTileOwnerProc *change_tile_owner_proc; + GetProducedCargoProc *get_produced_cargo_proc; + VehicleEnterTileProc *vehicle_enter_tile_proc; + VehicleLeaveTileProc *vehicle_leave_tile_proc; +} TileTypeProcs; + + + +#define MP_SETTYPE(x) ((x+1) << 8) + +enum { + MP_MAP2 = 1<<0, + MP_MAP3LO = 1<<1, + MP_MAP3HI = 1<<2, + MP_MAP5 = 1<<3, + MP_MAPOWNER_CURRENT = 1<<4, + MP_MAPOWNER = 1<<5, + + MP_TYPE_MASK = 0xF << 8, + + MP_MAP2_CLEAR = 1 << 12, + MP_MAP3LO_CLEAR = 1 << 13, + MP_MAP3HI_CLEAR = 1 << 14, + + MP_NODIRTY = 1<<15, +}; + +enum { + // Temperate + CT_PASSENGERS = 0, + CT_COAL = 1, + CT_MAIL = 2, + CT_OIL = 3, + CT_LIVESTOCK = 4, + CT_GOODS = 5, + CT_GRAIN = 6, + CT_WOOD = 7, + CT_IRON_ORE = 8, + CT_STEEL = 9, + CT_VALUABLES = 10, + CT_FOOD = 11, + + // Arctic + CT_HILLY_UNUSED = 8, + CT_PAPER = 9, + + // Tropic + CT_RUBBER = 1, + CT_FRUIT = 4, + CT_COPPER_ORE = 8, + CT_WATER = 9, + + // Toyland + CT_SUGAR = 1, + CT_TOYS = 3, + CT_BATTERIES = 4, + CT_CANDY = 5, + CT_TOFFEE = 6, + CT_COLA = 7, + CT_COTTON_CANDY = 8, + CT_BUBBLES = 9, + CT_PLASTIC = 10, + CT_FIZZY_DRINKS = 11, + + NUM_CARGO = 12, +}; + +enum { + WC_MAIN_WINDOW = 0x0, + WC_MAIN_TOOLBAR = 0x1, + WC_STATUS_BAR = 0x2, + WC_BUILD_TOOLBAR = 0x3, + WC_NEWS_WINDOW = 0x4, + WC_TOWN_DIRECTORY = 0x5, + WC_STATION_LIST = 0x6, + WC_TOWN_VIEW = 0x7, + WC_SMALLMAP = 0x8, + WC_TRAINS_LIST = 0x9, + WC_ROADVEH_LIST = 0xA, + WC_SHIPS_LIST = 0xB, + WC_AIRCRAFT_LIST = 0xC, + WC_VEHICLE_VIEW = 0xD, + WC_VEHICLE_DETAILS = 0xE, + WC_VEHICLE_REFIT = 0xF, + WC_VEHICLE_ORDERS = 0x10, + WC_STATION_VIEW = 0x11, + WC_VEHICLE_DEPOT = 0x12, + WC_BUILD_VEHICLE = 0x13, + WC_BUILD_BRIDGE = 0x14, + WC_ERRMSG = 0x15, + WC_ASK_ABANDON_GAME = 0x16, + WC_QUIT_GAME = 0x17, + WC_BUILD_STATION = 0x18, + WC_BUS_STATION = 0x19, + WC_TRUCK_STATION = 0x1A, + WC_BUILD_DEPOT = 0x1B, + WC_DEBUGGER = 0x1C, + WC_COMPANY = 0x1D, + WC_FINANCES = 0x1E, + WC_PLAYER_COLOR = 0x1F, + WC_QUERY_STRING = 0x20, + WC_SAVELOAD = 0x21, + WC_SELECT_GAME = 0x22, + WC_TOOLBAR_MENU = 0x24, + WC_INCOME_GRAPH = 0x25, + WC_OPERATING_PROFIT = 0x26, + WC_TOOLTIPS = 0x27, + WC_INDUSTRY_VIEW = 0x28, + WC_PLAYER_FACE = 0x29, + WC_LAND_INFO = 0x2A, + WC_TOWN_AUTHORITY = 0x2B, + WC_SUBSIDIES_LIST = 0x2C, + WC_GRAPH_LEGEND = 0x2D, + WC_DELIVERED_CARGO = 0x2E, + WC_PERFORMANCE_HISTORY = 0x2F, + WC_COMPANY_VALUE = 0x30, + WC_COMPANY_LEAGUE = 0x31, + WC_BUY_COMPANY = 0x32, + WC_PAYMENT_RATES = 0x33, + WC_SELECT_TUTORIAL = 0x34, + WC_ENGINE_PREVIEW = 0x35, + WC_MUSIC_WINDOW = 0x36, + WC_MUSIC_TRACK_SELECTION = 0x37, + WC_SCEN_LAND_GEN = 0x38, + WC_ASK_RESET_LANDSCAPE = 0x39, + WC_SCEN_TOWN_GEN = 0x3A, + WC_SCEN_INDUSTRY = 0x3B, + WC_SCEN_BUILD_ROAD = 0x3C, + WC_SCEN_BUILD_TREES = 0x3D, + WC_SEND_NETWORK_MSG = 0x3E, + WC_DROPDOWN_MENU = 0x3F, + WC_BUILD_INDUSTRY = 0x40, + WC_GAME_OPTIONS = 0x41, + WC_NETWORK_WINDOW = 0x42, + WC_INDUSTRY_DIRECTORY = 0x43, + WC_MESSAGE_HISTORY = 0x44, + WC_CHEATS = 0x45, +}; + + +enum { + EXPENSES_CONSTRUCTION = 0, + EXPENSES_NEW_VEHICLES = 1, + EXPENSES_TRAIN_RUN = 2, + EXPENSES_ROADVEH_RUN = 3, + EXPENSES_AIRCRAFT_RUN = 4, + EXPENSES_SHIP_RUN = 5, + EXPENSES_PROPERTY = 6, + EXPENSES_TRAIN_INC = 7, + EXPENSES_ROADVEH_INC = 8, + EXPENSES_AIRCRAFT_INC = 9, + EXPENSES_SHIP_INC = 10, + EXPENSES_LOAN_INT = 11, + EXPENSES_OTHER = 12, +}; + +// Tile type misc constants, don't know where to put these +enum { + TRACKTYPE_SPRITE_PITCH = 0x52, +}; + + +// special string constants +enum SpecialStrings { + + // special strings for town names. the town name is generated dynamically on request. + SPECSTR_TOWNNAME_START = 0x20C0, + SPECSTR_TOWNNAME_ENGLISH = SPECSTR_TOWNNAME_START, + SPECSTR_TOWNNAME_FRENCH, + SPECSTR_TOWNNAME_GERMAN, + SPECSTR_TOWNNAME_AMERICAN, + SPECSTR_TOWNNAME_LATIN, + SPECSTR_TOWNNAME_SILLY, + SPECSTR_TOWNNAME_SWEDISH, + SPECSTR_TOWNNAME_DUTCH, + SPECSTR_TOWNNAME_FINNISH, + SPECSTR_TOWNNAME_POLISH, + SPECSTR_TOWNNAME_SLOVAKISH, + SPECSTR_TOWNNAME_HUNGARIAN, + SPECSTR_TOWNNAME_AUSTRIAN, + SPECSTR_TOWNNAME_LAST = SPECSTR_TOWNNAME_AUSTRIAN, + + // special strings for player names on the form "TownName transport". + SPECSTR_PLAYERNAME_START = 0x70EA, + SPECSTR_PLAYERNAME_ENGLISH = SPECSTR_PLAYERNAME_START, + SPECSTR_PLAYERNAME_FRENCH, + SPECSTR_PLAYERNAME_GERMAN, + SPECSTR_PLAYERNAME_AMERICAN, + SPECSTR_PLAYERNAME_LATIN, + SPECSTR_PLAYERNAME_SILLY, + SPECSTR_PLAYERNAME_LAST = SPECSTR_PLAYERNAME_SILLY, + + SPECSTR_ANDCO_NAME = 0x70E6, + SPECSTR_PRESIDENT_NAME = 0x70E7, + SPECSTR_SONGNAME = 0x70E8, + + // reserve 32 strings for the *.lng files + SPECSTR_LANGUAGE_START = 0x7100, + SPECSTR_LANGUAGE_END = 0x711f, + + // reserve 32 strings for various screen resolutions + SPECSTR_RESOLUTION_START = 0x7120, + SPECSTR_RESOLUTION_END = 0x713f, + + // reserve 32 strings for screenshot formats + SPECSTR_SCREENSHOT_START = 0x7140, + SPECSTR_SCREENSHOT_END = 0x715F, + + STR_SPEC_SCREENSHOT_NAME = 0xF800, + STR_SPEC_USERSTRING = 0xF801, +}; + +typedef void PlaceProc(uint tile); + +enum Sprites { + SPR_OPENTTD_BASE = 0x1406, + SPR_CANALS_BASE = SPR_OPENTTD_BASE + 80, +}; + +enum MAP_OWNERS { + OWNER_TOWN = 0xf, // a town owns the tile + OWNER_NONE = 0x10,// nobody owns the tile + OWNER_WATER= 0x11,// "water" owns the tile +}; + +VARDEF bool _savegame_sort_dirty; +VARDEF byte _savegame_sort_order; + +#define INVALID_UINT_TILE (uint)0xFFFFFFFF +#define INVALID_STRING_ID 0xFFFF + +enum { + MAX_SCREEN_WIDTH = 2048, + MAX_SCREEN_HEIGHT = 1200, +}; + +#include "functions.h" +#include "variables.h" + +#endif /* TTD_H */ diff --git a/ttd.rc b/ttd.rc new file mode 100644 --- /dev/null +++ b/ttd.rc @@ -0,0 +1,157 @@ +//Microsoft Developer Studio generated resource script. +// +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "resource.h" +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +100 ICON DISCARDABLE "mainicon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +100 DIALOG DISCARDABLE 0, 0, 305, 70 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Fatal Application Failure" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&Close",12,7,49,50,14 + PUSHBUTTON "&Submit report",14,81,49,68,14 + PUSHBUTTON "&Emergency save",13,155,49,68,14 + PUSHBUTTON "",15,243,49,55,14 + EDITTEXT 11,7,70,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | + WS_HSCROLL | NOT WS_TABSTOP + LTEXT "",10,36,7,262,34 + ICON 100,IDC_STATIC,9,9,20,20 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,3,2,1 + PRODUCTVERSION 0,3,2,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "This program is licensed under the GNU General Public License.\0" + VALUE "CompanyName", "OpenTTD Developers\0" + VALUE "FileDescription", "OpenTTD\0" + VALUE "FileVersion", "0.3.2.1\0" + VALUE "InternalName", "openttd\0" + VALUE "LegalCopyright", "Copyright © OpenTTD Developers 2002-2004. All Rights Reserved.\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "openttd.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "OpenTTD\0" + VALUE "ProductVersion", "0.3.2.1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // !_MAC + +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Swedish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) +#ifdef _WIN32 +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resrc1.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""resource.h""\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Swedish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ttd.sln b/ttd.sln new file mode 100644 --- /dev/null +++ b/ttd.sln @@ -0,0 +1,50 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strgen", "strgen\strgen.vcproj", "{A133A442-BD0A-4ADE-B117-AD7545E4BDD1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ttd", "ttd.vcproj", "{668328A0-B40E-4CDB-BD72-D0064424414A}" + ProjectSection(ProjectDependencies) = postProject + {0F066B23-18DF-4284-8265-F4A5E7E3B966} = {0F066B23-18DF-4284-8265-F4A5E7E3B966} + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1} = {A133A442-BD0A-4ADE-B117-AD7545E4BDD1} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "langs", "langs.vcproj", "{0F066B23-18DF-4284-8265-F4A5E7E3B966}" + ProjectSection(ProjectDependencies) = postProject + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1} = {A133A442-BD0A-4ADE-B117-AD7545E4BDD1} + EndProjectSection +EndProject +Global + GlobalSection(DPCodeReviewSolutionGUID) = preSolution + DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000} + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + Checked = Checked + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Checked.ActiveCfg = Debug|Win32 + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Checked.Build.0 = Debug|Win32 + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Debug.ActiveCfg = Debug|Win32 + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Debug.Build.0 = Debug|Win32 + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Release.ActiveCfg = Debug|Win32 + {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}.Release.Build.0 = Debug|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Checked.ActiveCfg = Checked|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Checked.Build.0 = Checked|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Debug.ActiveCfg = Debug|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Debug.Build.0 = Debug|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Release.ActiveCfg = Release|Win32 + {668328A0-B40E-4CDB-BD72-D0064424414A}.Release.Build.0 = Release|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Checked.ActiveCfg = Debug|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Checked.Build.0 = Debug|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Debug.ActiveCfg = Debug|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Debug.Build.0 = Debug|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Release.ActiveCfg = Debug|Win32 + {0F066B23-18DF-4284-8265-F4A5E7E3B966}.Release.Build.0 = Debug|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/ttd.vcproj b/ttd.vcproj new file mode 100644 --- /dev/null +++ b/ttd.vcproj @@ -0,0 +1,2615 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c new file mode 100644 --- /dev/null +++ b/tunnelbridge_cmd.c @@ -0,0 +1,1475 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "viewport.h" +#include "command.h" +#include "player.h" +#include "town.h" + +extern void DrawCanalWater(uint tile); + +static const byte _bridge_available_year[MAX_BRIDGES] = { + 0, 0, 10, 0, 10, 10, 10, 10, 10, 10, 75, 85, 90 +}; + +static const byte _bridge_minlen[MAX_BRIDGES] = { + 0, 0, 0, 2, 3, 3, 3, 3, 3, 0, 2, 2, 2 +}; + +static const byte _bridge_maxlen[MAX_BRIDGES] = { + 16, 2, 5, 10, 16, 16, 7, 8, 9, 2, 16, 32, 32, +}; + +const uint16 _bridge_type_price_mod[MAX_BRIDGES] = { + 80, 112, 144, 168, 185, 192, 224, 232, 248, 240, 255, 380, 510, +}; + +const uint16 _bridge_speeds[MAX_BRIDGES] = { + 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x0A0, 0x0D0, 0x0F0, 0x100, 0x140, 0x200, 0x260 +}; + +const PalSpriteID _bridge_sprites[MAX_BRIDGES] = { + 0x0A24, 0x31E8A26, 0x0A25, 0x3208A22, + 0x0A22, 0x3218A22, 0x0A23, 0x31C8A23, + 0x31E8A23, 0x0A27, 0x0A28, 0x3218A28, + 0x3238A28, +}; + +const StringID _bridge_material[MAX_BRIDGES] = { + STR_5012_WOODEN, + STR_5013_CONCRETE, + STR_500F_GIRDER_STEEL, + STR_5011_SUSPENSION_CONCRETE, + STR_500E_SUSPENSION_STEEL, + STR_500E_SUSPENSION_STEEL, + STR_5010_CANTILEVER_STEEL, + STR_5010_CANTILEVER_STEEL, + STR_5010_CANTILEVER_STEEL, + STR_500F_GIRDER_STEEL, + STR_5014_TUBULAR_STEEL, + STR_5014_TUBULAR_STEEL, + STR_BRIDGE_TUBULAR_SILICON, +}; + +// calculate the price factor for building a long bridge. +// basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6, 7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8, +int CalcBridgeLenCostFactor(int x) +{ + int n,r; + if (x < 2) return x; + x -= 2; + for(n=0,r=2;;n++) { + if (x <= n) return r + x * n; + r += n * n; + x -= n; + } +} + +enum { + // foundation, whole tile is leveled up (tileh's 7, 11, 13, 14) --> 3 corners raised + BRIDGE_FULL_LEVELED_FOUNDATION = 1 << 7 | 1 << 11 | 1 << 13 | 1 << 14, + // foundation, tile is partly leveled up (tileh's 1, 2, 4, 8) --> 1 corner raised + BRIDGE_PARTLY_LEVELED_FOUNDATION = 1 << 1 | 1 << 2 | 1 << 4 | 1 << 8, + // no foundations (X,Y direction) (tileh's 0, 3, 6, 9, 12) + BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12, +}; + +/* check if bridge can be built on slope + * direction 0 = X-axis, direction 1 = Y-axis + * is_start_tile = false <-- end tile + * is_start_tile = true <-- start tile + */ +static uint32 CheckBridgeSlope(uint direction, uint tileh, bool is_start_tile) +{ + if (!(tileh & 0x10)) { // disable building on very steep slopes + + if (is_start_tile) { + /* check slope at start tile + - no extra cost + - direction X: tiles 0,12 + - direction Y: tiles 0, 9 + */ + if ((direction?0x201:0x1001) & (1 << tileh)) + return 0; + + // disallow certain start tiles to avoid certain crooked bridges + if (tileh == 2) + return CMD_ERROR; + + } + else { + /* check slope at end tile + - no extra cost + - direction X: tiles 0, 3 + - direction Y: tiles 0, 6 + */ + if ((direction?0x41:0x9) & (1 << tileh)) + return 0; + + // disallow certain end tiles to avoid certain crooked bridges + if (tileh == 8) + return CMD_ERROR; + + } + + /* disallow common start/end tiles to avoid certain crooked bridges e.g. + * start-tile: X 2,1 Y 2,4 (2 was disabled before) + * end-tile: X 8,4 Y 8,1 (8 was disabled before) + */ + if ( (tileh == 1 && (is_start_tile != (bool)direction)) || + (tileh == 4 && (is_start_tile == (bool)direction)) ) + return CMD_ERROR; + + // slope foundations + if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh) || BRIDGE_PARTLY_LEVELED_FOUNDATION & (1 << tileh)) + return _price.terraform; + } + + return CMD_ERROR; +} + +uint32 GetBridgeLength(TileIndex begin, TileIndex end) +{ + int x1, y1, x2, y2; // coordinates of starting and end tiles + x1 = GET_TILE_X(begin); + y1 = GET_TILE_Y(begin); + x2 = GET_TILE_X(end); + y2 = GET_TILE_Y(end); + + return abs((x2 + y2 - x1 - y1)) - 1; +} + +bool CheckBridge_Stuff(byte bridge_type, int bridge_len) +{ + int max; // max possible length of a bridge (with patch 100) + + if (_bridge_available_year[bridge_type] > _cur_year) + return false; + + max = _bridge_maxlen[bridge_type]; + if (max >= 16 && _patches.longbridges) + max = 100; + + if (bridge_len < _bridge_minlen[bridge_type] || bridge_len > max) + return false; + + return true; +} + +/* Build a Bridge + * x,y - end tile coord + * p1 - packed start tile coords (~ dx) + * p2&0xFF - bridge type (hi bh) + * p2>>8 - rail type. &0x80 means road bridge. + */ +int32 CmdBuildBridge(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + int bridge_type; + byte rail_or_road, railtype, m5; + int sx,sy; + TileInfo ti_start, ti_end, ti; /* OPT: only 2 of those are ever used */ + int bridge_len, odd_middle_part; + uint direction; + int i; + int32 cost, terraformcost, ret; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + /* unpack parameters */ + bridge_type = p2 & 0xFF; + railtype = (byte)(p2 >> 8); + + // type of bridge + if (railtype & 0x80) { + railtype = 0; + rail_or_road = 2; + } else { + rail_or_road = 0; + } + + sx = GET_TILE_X(p1) * 16; + sy = GET_TILE_Y(p1) * 16; + + direction = 0; + + /* check if valid, and make sure that (x,y) are smaller than (sx,sy) */ + if (x == sx) { + if (y == sy) + return_cmd_error(STR_5008_CANNOT_START_AND_END_ON); + direction = 1; + if (y > sy) { + intswap(y,sy); + intswap(x,sx); + } + } else if (y == sy) { + if (x > sx) { + intswap(y,sy); + intswap(x,sx); + } + } else + return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN); + + /* retrieve landscape height and ensure it's on land */ + if ( + ((FindLandscapeHeight(&ti_end, sx, sy), + ti_end.type == MP_WATER) && ti_end.map5 == 0) || + ((FindLandscapeHeight(&ti_start, x, y), + ti_start.type == MP_WATER) && ti_start.map5 == 0)) + return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH); + + if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << ti_start.tileh)) { + ti_start.z += 8; + ti_start.tileh = 0; + } + + if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << ti_end.tileh)) { + ti_end.z += 8; + ti_end.tileh = 0; + } + + if (ti_start.z != ti_end.z) + return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); + + _error_message = STR_500C; + + /* try and clear the start landscape */ + if ((ret=DoCommandByTile(ti_start.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR)) == CMD_ERROR) + return CMD_ERROR; + cost = ret; + + terraformcost = CheckBridgeSlope(direction, ti_start.tileh, true); // true - bridge-start-tile, false - bridge-end-tile + + // the AI and towns are not allowed to use bridges on slopes. + if (terraformcost == CMD_ERROR || + (terraformcost && (_is_ai_player || _current_player == OWNER_TOWN || !_patches.build_on_slopes))) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + cost += terraformcost; + + /* try and clear the end landscape */ + if ((ret=DoCommandByTile(ti_end.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR)) == CMD_ERROR) + return CMD_ERROR; + cost += ret; + + terraformcost = CheckBridgeSlope(direction, ti_end.tileh, false); // false - end tile slope check + + // the AI and towns are not allowed to use bridges on slopes. + if (terraformcost == CMD_ERROR || + (terraformcost && (_is_ai_player || _current_player == OWNER_TOWN || !_patches.build_on_slopes))) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + cost += terraformcost; + + /* do the drill? */ + if (flags & DC_EXEC) { + /* build the start tile */ + ModifyTile(ti_start.tile, + MP_SETTYPE(MP_TUNNELBRIDGE) | + MP_MAP2 | MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, + (bridge_type << 4), /* map2 */ + railtype, /* map3_lo */ + 0x80 | direction | rail_or_road /* map5 */ + ); + + /* build the end tile */ + ModifyTile(ti_end.tile, + MP_SETTYPE(MP_TUNNELBRIDGE) | + MP_MAP2 | MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, + (bridge_type << 4), /* map2 */ + railtype, /* map3_lo */ + 0x80 | 0x20 | direction | rail_or_road /* map5 */ + ); + } + + /* set various params */ + bridge_len = ((sx + sy - x - y) >> 4) - 1; + + //position of middle part of the odd bridge (larger than MAX(i) otherwise) + odd_middle_part=(bridge_len%2)?(bridge_len/2):bridge_len; + + for(i = 0; i != bridge_len; i++) { + if (direction != 0) + y+=16; + else + x+=16; + + FindLandscapeHeight(&ti, x, y); + + _error_message = STR_5009_LEVEL_LAND_OR_WATER_REQUIRED; + if (ti.tileh != 0 && ti.z >= ti_start.z) + return CMD_ERROR; + + // Find ship below + if ( ti.type == MP_WATER && !EnsureNoVehicle(ti.tile) ) + { + _error_message = STR_980E_SHIP_IN_THE_WAY; + return CMD_ERROR; + } + + if (ti.type == MP_WATER) { + if (ti.map5 != 0) goto not_valid_below; + m5 = 0xC8; + } else if (ti.type == MP_RAILWAY) { + if (direction == 0) { + if (ti.map5 != 2) goto not_valid_below; + } else { + if (ti.map5 != 1) goto not_valid_below; + } + m5 = 0xE0; + } else if (ti.type == MP_STREET) { + if (direction == 0) { + if (ti.map5 != 5) goto not_valid_below; + } else { + if (ti.map5 != 10) goto not_valid_below; + } + m5 = 0xE8; + } else { +not_valid_below:; + /* try and clear the middle landscape */ + if ((ret=DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR)) == CMD_ERROR) + return CMD_ERROR; + cost += ret; + m5 = 0xC0; + } + + /* do middle part of bridge */ + if (flags & DC_EXEC) { + _map5[ti.tile] = (byte)(m5 | direction | rail_or_road); + _map_type_and_height[ti.tile] &= ~0xF0; + _map_type_and_height[ti.tile] |= MP_TUNNELBRIDGE << 4; + + //bridges pieces sequence (middle parts) + // bridge len 1: 0 + // bridge len 2: 0 1 + // bridge len 3: 0 4 1 + // bridge len 4: 0 2 3 1 + // bridge len 5: 0 2 5 3 1 + // bridge len 6: 0 2 3 2 3 1 + // bridge len 7: 0 2 3 4 2 3 1 + // #0 - alwats as first, #1 - always as last (if len>1) + // #2,#3 are to pair in order + // for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0) + + if(i==0) //first tile + m5 = 0; + else if (i==bridge_len-1) //last tile + m5 = 1; + else if(i==odd_middle_part) //we are on the middle of odd bridge: #5 on even pos, #4 on odd + m5 = 5 - (i%2); + else { + // generate #2 and #3 in turns [i%2==0], after the middle of odd bridge + // this sequence swaps [... XOR (i>odd_middle_part)], + // for even bridges XOR does not apply as odd_middle_part==bridge_len + m5 = 2 + ((i%2==0)^(i>odd_middle_part)); + } + + _map2[ti.tile] = (bridge_type << 4) | m5; + _map3_lo[ti.tile] &= 0xF; + _map3_lo[ti.tile] |= (byte)(railtype << 4); + + MarkTileDirtyByTile(ti.tile); + } + } + + SetSignalsOnBothDir(ti_start.tile, (direction&1) ? 1 : 0); + + /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST) + It's unnecessary to execute this command every time for every bridge. So it is done only + and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated + */ + if (!(flags & DC_QUERY_COST)) { + bridge_len += 2; // begin and end tiles/ramps + + if (_current_player < MAX_PLAYERS && IS_HUMAN_PLAYER(_current_player)) + bridge_len = CalcBridgeLenCostFactor(bridge_len); + + cost += ((bridge_len * _price.build_bridge) * _bridge_type_price_mod[bridge_type]) >> 8; + } + + return cost; +} + +static bool DoCheckTunnelInWay(uint tile, uint z, uint dir) +{ + TileInfo ti; + int delta; + + delta = _tileoffs_by_dir[dir]; + + do { + tile -= delta; + FindLandscapeHeightByTile(&ti, tile); + } while (z < ti.z); + + if (z == ti.z && ti.type == MP_TUNNELBRIDGE && (ti.map5&0xF0) == 0 && (ti.map5&3) == dir) { + _error_message = STR_5003_ANOTHER_TUNNEL_IN_THE_WAY; + return false; + } + + return true; +} + +bool CheckTunnelInWay(uint tile, int z) +{ + return DoCheckTunnelInWay(tile,z,0) && + DoCheckTunnelInWay(tile,z,1) && + DoCheckTunnelInWay(tile,z,2) && + DoCheckTunnelInWay(tile,z,3); +} + +static byte _build_tunnel_bh; +static byte _build_tunnel_railtype; + +static int32 DoBuildTunnel(int x, int y, int x2, int y2, uint32 flags, uint exc_tile) +{ + uint end_tile; + int direction; + int32 cost, ret; + TileInfo ti; + uint z; + + if ( (uint) x > TILE_X_MAX * 16 - 1 || (uint) y > TILE_X_MAX * 16 - 1) + return CMD_ERROR; + + /* check if valid, and make sure that (x,y) is smaller than (x2,y2) */ + direction = 0; + if (x == x2) { + if (y == y2) + return_cmd_error(STR_5008_CANNOT_START_AND_END_ON); + direction++; + if (y > y2) { + intswap(y,y2); + intswap(x,x2); + exc_tile|=2; + } + } else if (y == y2) { + if (x > x2) { + intswap(y,y2); + intswap(x,x2); + exc_tile|=2; + } + } else + return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN); + + cost = 0; + + FindLandscapeHeight(&ti, x2, y2); + end_tile = ti.tile; + z = ti.z; + + if (exc_tile != 3) { + if ( (direction ? 9U : 12U) != ti.tileh) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) + return CMD_ERROR; + cost += ret; + } + cost += _price.build_tunnel; + + for(;;) { + if (direction) y2-=16; else x2-=16; + + if (x2 == x && y2 == y) + break; + + FindLandscapeHeight(&ti, x2, y2); + if (ti.z <= z) + return_cmd_error(STR_5002); + + if (!_cheats.crossing_tunnels.value && !CheckTunnelInWay(ti.tile, z)) + return CMD_ERROR; + + cost += _price.build_tunnel; + cost += (cost >> 3); + + if (cost >= 400000000) + cost = 400000000; + } + + FindLandscapeHeight(&ti, x2, y2); + if (ti.z != z) + return_cmd_error(STR_5004); + + if (exc_tile != 1) { + if ( (direction ? 6U : 3U) != ti.tileh) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) + return CMD_ERROR; + cost += ret; + } + + if (flags & DC_EXEC) { + ModifyTile(ti.tile, + MP_SETTYPE(MP_TUNNELBRIDGE) | + MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, + _build_tunnel_railtype, /* map3lo */ + ((_build_tunnel_bh << 1) | 2) - direction /* map5 */ + ); + + ModifyTile(end_tile, + MP_SETTYPE(MP_TUNNELBRIDGE) | + MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, + _build_tunnel_railtype, /* map3lo */ + (_build_tunnel_bh << 1) | (direction ? 3:0)/* map5 */ + ); + + UpdateSignalsOnSegment(end_tile, direction?7:1); + } + + return cost + _price.build_tunnel; +} + +/* Build Tunnel + * x,y - start tile coord + * p1 - railtype + * p2 - ptr to uint that recieves end tile + */ +int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + TileInfo ti, tiorg; + int direction; + uint z; + static const int8 _build_tunnel_coord_mod[4+1] = { -16, 0, 16, 0, -16 }; + static const byte _build_tunnel_tileh[4] = {3, 9, 12, 6}; + uint excavated_tile; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + _build_tunnel_railtype = (byte)(p1 & 0xFF); + _build_tunnel_bh = (byte)(p1 >> 8); + + _build_tunnel_endtile = 0; + excavated_tile = 0; + + FindLandscapeHeight(&tiorg, x, y); + + if (!EnsureNoVehicle(tiorg.tile)) + return CMD_ERROR; + + if (!(direction=0, tiorg.tileh==12) && + !(direction++, tiorg.tileh==6) && + !(direction++, tiorg.tileh==3) && + !(direction++, tiorg.tileh==9) ) + return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); + + z = tiorg.z; + do { + x += _build_tunnel_coord_mod[direction]; + y += _build_tunnel_coord_mod[direction+1]; + FindLandscapeHeight(&ti, x, y); + } while (z != ti.z); + _build_tunnel_endtile = ti.tile; + + + if (!EnsureNoVehicle(ti.tile)) + return CMD_ERROR; + + if (ti.tileh != _build_tunnel_tileh[direction]) { + if (DoCommandByTile(ti.tile, ti.tileh & ~_build_tunnel_tileh[direction], 0, flags, CMD_TERRAFORM_LAND) == CMD_ERROR) + return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); + excavated_tile = 1; + } + + if (flags & DC_EXEC && DoBuildTunnel(x,y,tiorg.x,tiorg.y,flags&~DC_EXEC,excavated_tile) == CMD_ERROR) + return CMD_ERROR; + + return DoBuildTunnel(x,y,tiorg.x, tiorg.y,flags,excavated_tile); +} + +static const byte _updsignals_tunnel_dir[4] = { 5, 7, 1, 3}; + +static uint CheckTunnelBusy(uint tile, int *length) +{ + int z = GetTileZ(tile); + byte m5 = _map5[tile]; + int delta = _tileoffs_by_dir[m5 & 3], len = 0; + uint starttile = tile; + Vehicle *v; + + do { tile += delta; len++; } while (!IS_TILETYPE(tile, MP_TUNNELBRIDGE) || _map5[tile]&0xF0 || (byte)(_map5[tile] ^ 2) != m5 || GetTileZ(tile) != z); + + if ((v=FindVehicleBetween(starttile, tile, z)) != NULL) { + _error_message = v->type == VEH_Train ? STR_5000_TRAIN_IN_TUNNEL : STR_5001_ROAD_VEHICLE_IN_TUNNEL; + return (uint)-1; + } + + if (length) *length = len; + return tile; +} + +static int32 DoClearTunnel(uint tile, uint32 flags) +{ + Town *t; + uint endtile; + int length; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + // in scenario editor you can always destroy tunnels + if (_game_mode != GM_EDITOR && !CheckTileOwnership(tile)) { + if (!(_patches.extra_dynamite || _cheats.magic_bulldozer.value) || _map_owner[tile] != OWNER_TOWN) + return CMD_ERROR; + } + + endtile = CheckTunnelBusy(tile, &length); + if (endtile == (uint)-1) return CMD_ERROR; + + _build_tunnel_endtile = endtile; + + t = ClosestTownFromTile(tile, (uint)-1); //needed for town rating penalty + // check if you're allowed to remove the tunnel owned by a town + // removal allowal depends on difficulty settings + if(_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR ) { + if (!CheckforTownRating(tile, flags, t, TUNNELBRIDGE_REMOVE)) { + SET_DPARAM16(0, t->index); + return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); + } + } + + if (flags & DC_EXEC) { + DoClearSquare(tile); + DoClearSquare(endtile); + UpdateSignalsOnSegment(tile, _updsignals_tunnel_dir[_map5[tile]&3]); + UpdateSignalsOnSegment(endtile, _updsignals_tunnel_dir[_map5[endtile]&3]); + if (_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR) + ChangeTownRating(t, -250, 0); + } + return _price.clear_tunnel * (length + 1); +} + +static uint FindEdgesOfBridge(uint tile, uint *endtile) +{ + int direction = _map5[tile] & 1; + uint start; + + // find start of bridge + for(;;) { + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile] & 0xE0) == 0x80) + break; + tile += direction ? TILE_XY(0,-1) : TILE_XY(-1,0); + } + + start = tile; + + // find end of bridge + for(;;) { + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile] & 0xE0) == 0xA0) + break; + tile += direction ? TILE_XY(0,1) : TILE_XY(1,0); + } + + *endtile = tile; + + return start; +} + +static int32 DoClearBridge(uint tile, uint32 flags) +{ + uint endtile; + Vehicle *v; + Town *t; + int direction; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + direction = _map5[tile]&1; + + /* delete stuff under the middle part if there's a transport route there..? */ + if ((_map5[tile] & 0xE0) == 0xE0) { + int32 cost; + + // check if we own the tile below the bridge.. + if (_current_player != OWNER_WATER && (!CheckTileOwnership(tile) || !EnsureNoVehicleZ(tile, GET_TILEHEIGHT(tile)) )) + return CMD_ERROR; + + cost = (_map5[tile] & 8) ? _price.remove_road * 2 : _price.remove_rail; + + if (flags & DC_EXEC) { + _map5[tile] = _map5[tile] & ~0x38; + _map_owner[tile] = OWNER_NONE; + MarkTileDirtyByTile(tile); + } + return cost; + + /* delete canal under bridge */ + } else if(_map5[tile]==0xC8 && GET_TILEHEIGHT(tile)!=0) { + int32 cost; + + // check for vehicles under bridge + if ( !EnsureNoVehicleZ(tile, GET_TILEHEIGHT(tile)) ) + return CMD_ERROR; + cost = _price.clear_water; + if (flags & DC_EXEC) { + _map5[tile] = _map5[tile] & ~0x38; + _map_owner[tile] = OWNER_NONE; + MarkTileDirtyByTile(tile); + } + return cost; + } + + tile = FindEdgesOfBridge(tile, &endtile); + + // floods, scenario editor can always destroy bridges + if (_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !CheckTileOwnership(tile)) { + if (!(_patches.extra_dynamite || _cheats.magic_bulldozer.value) || _map_owner[tile] != OWNER_TOWN) + return CMD_ERROR; + } + + if (!EnsureNoVehicle(tile) || !EnsureNoVehicle(endtile)) + return CMD_ERROR; + + /* Make sure there's no vehicle on the bridge + Omit tile and endtile, since these are already checked, thus solving the problem + of bridges over water, or higher bridges, where z is not increased, eg level bridge + */ + tile += direction ? TILE_XY(0, 1) : TILE_XY( 1,0); + endtile -= direction ? TILE_XY(0, 1) : TILE_XY( 1,0); + if ((v=FindVehicleBetween(tile, endtile, GET_TILEHEIGHT(tile) + 8)) != NULL) { + VehicleInTheWayErrMsg(v); + return CMD_ERROR; + } + + /* Put the tiles back to start/end position */ + tile -= direction ? TILE_XY(0, 1) : TILE_XY( 1,0); + endtile += direction ? TILE_XY(0, 1) : TILE_XY( 1,0); + + + t = ClosestTownFromTile(tile, (uint)-1); //needed for town rating penalty + // check if you're allowed to remove the bridge owned by a town. + // removal allowal depends on difficulty settings + if(_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR) { + if (!CheckforTownRating(tile, flags, t, TUNNELBRIDGE_REMOVE)) + return CMD_ERROR; + } + + if (flags & DC_EXEC) { + byte m5; + uint c = tile; + uint16 new_data; + + //checks if the owner is town then decrease town rating by 250 until + // you have a "Poor" (0) town rating + if (_map_owner[tile] == OWNER_TOWN && _game_mode != GM_EDITOR) + ChangeTownRating(t, -250, 0); + + do { + m5 = _map5[c]; + + if (m5 & 0x40) { + if (m5 & 0x20) { + static const uint16 _new_data_table[] = {0x1002, 0x1001, 0x2005, 0x200A, 0, 0, 0, 0}; + new_data = _new_data_table[((m5 & 0x18) >> 2) | (m5&1)]; + } else { + if (!(m5 & 0x18)) goto clear_it; + new_data = 0x6000; + } + + _map_type_and_height[c] &= 0x0F; + _map_type_and_height[c] |= new_data >> 8; + _map5[c] = (byte)new_data; + _map2[c] = 0; + + MarkTileDirtyByTile(c); + + } else { +clear_it:; + DoClearSquare(c); + } + c += direction ? TILE_XY(0,1) : TILE_XY(1,0); + } while (c <= endtile); + + SetSignalsOnBothDir(tile, direction); + SetSignalsOnBothDir(endtile, direction); + + } + + return ((((endtile - tile) >> (direction?8:0))&0xFF)+1) * _price.clear_bridge; +} + +static int32 ClearTile_TunnelBridge(uint tile, byte flags) { + int32 ret; + byte m5 = _map5[tile]; + + if ((m5 & 0xF0) == 0) { + if (flags & DC_AUTO) + return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST); + return DoClearTunnel(tile, flags); + } else if (m5 & 0x80) { + if (flags & DC_AUTO) + return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); + + ret = DoClearBridge(tile, flags); + if (ret == CMD_ERROR) + return CMD_ERROR; + + return ret; + } else { + return CMD_ERROR; + } +} + +int32 DoConvertTunnelBridgeRail(uint tile, uint totype, bool exec) +{ + uint endtile; + int length; + Vehicle *v; + + if ((_map5[tile] & 0xFC) == 0x00) { + // railway tunnel + if (!CheckTileOwnership(tile)) return CMD_ERROR; + + if ( (uint)(_map3_lo[tile] & 0xF) == totype) return CMD_ERROR; + + endtile = CheckTunnelBusy(tile, &length); + if (endtile == (uint)-1) return CMD_ERROR; + + if (exec) { + _map3_lo[tile] = (_map3_lo[tile] & 0xF0) + totype; + _map3_lo[endtile] = (_map3_lo[endtile] & 0xF0) + totype; + MarkTileDirtyByTile(tile); + MarkTileDirtyByTile(endtile); + } + return (length + 1) * (_price.build_rail >> 1); + } else if ((_map5[tile] & 0xF8) == 0xE0) { + // bridge middle part with rail below + // only check for train under bridge + if (!CheckTileOwnership(tile) || !EnsureNoVehicleZ(tile, GET_TILEHEIGHT(tile))) + return CMD_ERROR; + + // tile is already of requested type? + if ( (uint)(_map3_lo[tile] & 0xF) == totype) return CMD_ERROR; + // change type. + if (exec) { + _map3_lo[tile] = (_map3_lo[tile] & 0xF0) + totype; + MarkTileDirtyByTile(tile); + } + return _price.build_rail >> 1; + } else if ((_map5[tile]&0xC6) == 0x80) { + uint starttile; + int32 cost; + + if (!CheckTileOwnership(tile)) return CMD_ERROR; + + // railway bridge + starttile = tile = FindEdgesOfBridge(tile, &endtile); + // Make sure there's no vehicle on the bridge + if ((v=FindVehicleBetween(tile, endtile, 0xff)) != NULL) { + VehicleInTheWayErrMsg(v); + return CMD_ERROR; + } + + if ( (uint)(_map3_lo[tile] & 0xF) == totype) return CMD_ERROR; + cost = 0; + do { + if (exec) { + if (tile == starttile || tile == endtile) { + _map3_lo[tile] = (_map3_lo[tile] & 0xF0) + totype; + } else { + _map3_lo[tile] = (_map3_lo[tile] & 0x0F) + (totype << 4); + } + MarkTileDirtyByTile(tile); + } + cost += (_price.build_rail>>1); + tile += _map5[tile]&1 ? TILE_XY(0,1) : TILE_XY(1,0); + } while (tile <= endtile); + + return cost; + } else + return CMD_ERROR; +} + + +// fast routine for getting the height of a middle bridge tile. 'tile' MUST be a middle bridge tile. +static uint GetBridgeHeight(const TileInfo *ti) +{ + uint delta; + TileInfo ti_end; + uint tile = ti->tile; + uint z_correction = 0; + + // find the end tile of the bridge. + delta = (_map5[tile] & 1) ? TILE_XY(0,1) : TILE_XY(1,0); + do { + assert((_map5[tile] & 0xC0) == 0xC0); // bridge and middle part + tile += delta; + } while (_map5[tile] & 0x40); // while bridge middle parts + + // if the end of the bridge is on a tileh 7, the z coordinate is 1 tile too low + // correct it. + FindLandscapeHeightByTile(&ti_end, tile); + if (HASBIT(1 << 7, ti_end.tileh)) + z_correction += 8; + + // return the height there (the height of the NORTH CORNER) + return GET_TILEHEIGHT(tile) + z_correction; +} + +static const byte _bridge_foundations[2][16] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + {1,16,18,3,20,5,0,7,22,0,10,11,12,13,14}, + {1,15,17,0,19,5,6,7,21,9,10,11, 0,13,14}, +}; + +extern const byte _track_sloped_sprites[14]; +extern const byte _road_sloped_sprites[14]; + +#include "table/tunnel_land.h" + +static void DrawBridgePillars(TileInfo *ti, int x, int y, int z) +{ + const uint32 *b; + uint32 image; + int piece; + + b = _bridge_poles_table[_map2[ti->tile]>>4]; + + // Draw first piece + // (necessary for cantilever bridges) + image = b[12 + (ti->map5&0x01)]; + piece = _map2[ti->tile]&0xF; + if( image!=0 && piece!=0 ) + DrawGroundSpriteAt(image, x,y, z); + + image = b[(ti->map5&0x01)*6 + piece]; + if (!(_display_opt & DO_TRANS_BUILDINGS)) image = (image & 0x3FFF) | 0x03224000; + + if (image != 0) { + int back_height, front_height, i=z; + const byte *p; + + static const byte _tileh_bits[4][8] = { + {2,1,8,4, 16,11,0,9}, + {1,8,4,2, 11,16,9,0}, + {4,8,1,2, 16,11,0,9}, + {2,4,8,1, 11,16,9,0}, + }; + + p = _tileh_bits[(image & 1) * 2 + (ti->map5&0x01)]; + front_height = ti->z + ((ti->tileh & p[0])?8:0); + back_height = ti->z + ((ti->tileh & p[1])?8:0); + if (ti->tileh & 0x10) { + if (!(ti->tileh & p[2])) front_height += 8; + if (!(ti->tileh & p[3])) back_height += 8; + } + + for(; z>=front_height || z>=back_height; z=z-8) { + if (z>=front_height) AddSortableSpriteToDraw(image, x,y, p[4], p[5], 0x28, z); // front facing pillar + if (z>=back_height && ztile] & 0x80; + + // draw tunnel? + if ( (byte)(ti->map5&0xF0) == 0) { + /* railway type */ + image = (_map3_lo[ti->tile] & 0xF) * 8; + + /* ice? */ + if (ice) + image += 32; + + image += _draw_tunnel_table_1[(ti->map5 >> 2) & 0x3]; + image += (ti->map5 & 3) << 1; + DrawGroundSprite(image); + + AddSortableSpriteToDraw(image+1, ti->x + 15, ti->y + 15, 1, 1, 8, (byte)ti->z); + // draw bridge? + } else if ((byte)ti->map5 & 0x80) { + // get type of track on the bridge. + tmp = _map3_lo[ti->tile]; + if (ti->map5 & 0x40) tmp >>= 4; + tmp &= 0xF; + + // 0 = rail bridge + // 1 = road bridge + // 2 = monorail bridge + // 3 = maglev bridge + + // add direction and fix stuff. + if (tmp != 0) tmp++; + tmp = (ti->map5&3) + (tmp*2); + + if (!(ti->map5 & 0x40)) { // bridge ramps + + if (!(BRIDGE_NO_FOUNDATION & (1 << ti->tileh))) { // no foundations for 0, 3, 6, 9, 12 + int f = GetBridgeFoundation(ti->tileh, ti->map5 & 0x1); // pass direction + if (f) DrawFoundation(ti, f); + + // default sloped sprites.. + if (ti->tileh != 0) image = _track_sloped_sprites[ti->tileh - 1] + 0x3F3; + } + + // bridge ending. + b = _bridge_sprite_table[_map2[ti->tile]>>4][6]; + b += (tmp&(3<<1))*4; /* actually ((tmp>>2)&3)*8 */ + b += (tmp&1); // direction + if (ti->tileh == 0) b += 4; // sloped "entrance" ? + if (ti->map5 & 0x20) b += 2; // which side + + image = *b; + + if (!ice) { + DrawClearLandTile(ti, 3); + } else { + DrawGroundSprite(0x11C6 + _tileh_to_sprite[ti->tileh]); + } + + // draw ramp + if (!(_display_opt & DO_TRANS_BUILDINGS)) image = (image & 0x3FFF) | 0x03224000; + AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z); + } else { + // bridge middle part. + uint z; + int x,y; + + image = (ti->map5 >> 3) & 3; // type of stuff under bridge (only defined for 0,1) + assert(image <= 1); + + if (!(ti->map5 & 0x20)) { + // draw land under bridge + if (ice) image += 2; // ice too? + DrawGroundSprite(_bridge_land_below[image] + _tileh_to_sprite[ti->tileh]); + + // draw canal water? + if (ti->map5 & 8 && ti->z != 0) DrawCanalWater(ti->tile); + } else { + // draw transport route under bridge + + // draw foundation? + if (ti->tileh) { + int f = _bridge_foundations[ti->map5&1][ti->tileh]; + if (f) DrawFoundation(ti, f); + } + + if (!(image&1)) { + // railway + image = 0x3F3 + (ti->map5 & 1); + if (ti->tileh != 0) image = _track_sloped_sprites[ti->tileh - 1] + 0x3F3; + image += (_map3_lo[ti->tile] & 0xF) * TRACKTYPE_SPRITE_PITCH; + if (ice) image += 26; // ice? + } else { + // road + image = 1332 + (ti->map5 & 1); + if (ti->tileh != 0) image = _road_sloped_sprites[ti->tileh - 1] + 0x53F; + if (ice) image += 19; // ice? + } + DrawGroundSprite(image); + } + // get bridge sprites + b = _bridge_sprite_table[_map2[ti->tile]>>4][_map2[ti->tile]&0xF] + tmp * 4; + + z = GetBridgeHeight(ti) + 5; + + // draw rail + image = b[0]; + if (!(_display_opt & DO_TRANS_BUILDINGS)) image = (image & 0x3FFF) | 0x03224000; + AddSortableSpriteToDraw(image, ti->x, ti->y, (ti->map5&1)?11:16, (ti->map5&1)?16:11, 1, z); + + x = ti->x; + y = ti->y; + image = b[1]; + if (!(_display_opt & DO_TRANS_BUILDINGS)) image = (image & 0x3FFF) | 0x03224000; + + // draw roof + if (ti->map5&1) { + x += 12; + if (image&0x3FFF) AddSortableSpriteToDraw(image, x,y, 1, 16, 0x28, z); + } else { + y += 12; + if (image&0x3FFF) AddSortableSpriteToDraw(image, x,y, 16, 1, 0x28, z); + } + + if (ti->z + 5 == z ) { + // draw poles below for small bridges + image = b[2]; + if (image) { + if (!(_display_opt & DO_TRANS_BUILDINGS)) image = (image & 0x3FFF) | 0x03224000; + DrawGroundSpriteAt(image, x, y, z); + } + } else if (_patches.bridge_pillars) { + // draw pillars below for high bridges + DrawBridgePillars(ti, x, y, z); + } + } + } +} + +static uint GetSlopeZ_TunnelBridge(TileInfo *ti) { + uint z = ti->z; + uint x = ti->x & 0xF; + uint y = ti->y & 0xF; + + // swap directions if Y tunnel/bridge to let the code handle the X case only. + if (ti->map5 & 1) intswap(x,y); + + // to the side of the tunnel/bridge? + if (IS_INT_INSIDE(y, 5, 10+1)) { + // tunnel? + if ( (ti->map5 & 0xF0) == 0) + return z; + + // bridge? + if ( ti->map5 & 0x80 ) { + // bridge ending? + if (!(ti->map5 & 0x40)) { + if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << ti->tileh)) // 7, 11, 13, 14 + z += 8; + + // no ramp for bridge ending + if ((BRIDGE_PARTLY_LEVELED_FOUNDATION & (1 << ti->tileh) || BRIDGE_NO_FOUNDATION & (1 << ti->tileh)) && ti->tileh != 0) { + return z + 8; + + } else if (!(ti->map5 & 0x20)) { // northern / southern ending + // ramp + return (z + (x>>1) + 1); + } else { + // ramp in opposite dir + return (z + ((x^0xF)>>1)); + } + + // bridge middle part + } else { + // build on slopes? + if (ti->tileh) z+=8; + + // keep the same elevation because we're on the bridge? + if (_get_z_hint >= z + 8) + return _get_z_hint; + + // actually on the bridge, but not yet in the shared area. + if (!IS_INT_INSIDE(x, 5, 10+1)) + return GetBridgeHeight(ti) + 8; + + // in the shared area, assume that we're below the bridge, cause otherwise the hint would've caught it. + // if rail or road below then it means it's possibly build on slope below the bridge. + if (ti->map5 & 0x20) { + uint f = _bridge_foundations[ti->map5&1][ti->tileh]; + // make sure that the slope is not inclined foundation + if (IS_BYTE_INSIDE(f, 1, 15)) return z; + + // change foundation type? + if (f) ti->tileh = _inclined_tileh[f - 15]; + } + + // no transport route, fallback to default + } + } + } else { + // if it's a bridge middle with transport route below, then we need to compensate for build on slopes + if ( (ti->map5 & (0x80 + 0x40 + 0x20)) == (0x80 + 0x40 + 0x20)) { + uint f; + if (ti->tileh) z += 8; + f = _bridge_foundations[ti->map5&1][ti->tileh]; + if (IS_BYTE_INSIDE(f, 1, 15)) return z; + if (f) ti->tileh = _inclined_tileh[f - 15]; + } + } + + // default case + z = ti->z; + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + z; +} + +static void GetAcceptedCargo_TunnelBridge(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static const StringID _bridge_tile_str[(MAX_BRIDGES + 3) + (MAX_BRIDGES + 3)] = { + STR_501F_WOODEN_RAIL_BRIDGE, + STR_5020_CONCRETE_RAIL_BRIDGE, + STR_501C_STEEL_GIRDER_RAIL_BRIDGE, + STR_501E_REINFORCED_CONCRETE_SUSPENSION, + STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE, + STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE, + STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE, + STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE, + STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE, + STR_501C_STEEL_GIRDER_RAIL_BRIDGE, + STR_5027_TUBULAR_RAIL_BRIDGE, + STR_5027_TUBULAR_RAIL_BRIDGE, + STR_5027_TUBULAR_RAIL_BRIDGE, + 0,0,0, + + STR_5025_WOODEN_ROAD_BRIDGE, + STR_5026_CONCRETE_ROAD_BRIDGE, + STR_5022_STEEL_GIRDER_ROAD_BRIDGE, + STR_5024_REINFORCED_CONCRETE_SUSPENSION, + STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE, + STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE, + STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE, + STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE, + STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE, + STR_5022_STEEL_GIRDER_ROAD_BRIDGE, + STR_5028_TUBULAR_ROAD_BRIDGE, + STR_5028_TUBULAR_ROAD_BRIDGE, + STR_5028_TUBULAR_ROAD_BRIDGE, + 0,0,0, +}; + +static void GetTileDesc_TunnelBridge(uint tile, TileDesc *td) +{ + int delta; + + if ((_map5[tile] & 0x80) == 0) { + td->str = STR_5017_RAILROAD_TUNNEL + ((_map5[tile] >> 2) & 3); + } else { + td->str = _bridge_tile_str[ (_map2[tile] >> 4) + (((_map5[tile]>>1)&3)<<4) ]; + + /* scan to the end of the bridge, that's where the owner is stored */ + if (_map5[tile] & 0x40) { + delta = _map5[tile] & 1 ? TILE_XY(0,-1) : TILE_XY(-1,0); + do tile += delta; while (_map5[tile] & 0x40); + } + } + td->owner = _map_owner[tile]; +} + + +static void AnimateTile_TunnelBridge(uint tile) +{ + /* not used */ +} + +static void TileLoop_TunnelBridge(uint tile) +{ + if (_opt.landscape == LT_HILLY) { + if ( GetTileZ(tile) > _opt.snow_line) { + if (!(_map3_hi[tile] & 0x80)) { + _map3_hi[tile] |= 0x80; + MarkTileDirtyByTile(tile); + } + } else { + if (_map3_hi[tile] & 0x80) { + _map3_hi[tile] &= ~0x80; + MarkTileDirtyByTile(tile); + } + } + } else if (_opt.landscape == LT_DESERT) { + if (GetMapExtraBits(tile) == 1 && !(_map3_hi[tile]&0x80)) { + _map3_hi[tile] |= 0x80; + MarkTileDirtyByTile(tile); + } + } + + // if it's a bridge with water below, call tileloop_water on it. + if ((_map5[tile] & 0xF8) == 0xC8) TileLoop_Water(tile); +} + +static void ClickTile_TunnelBridge(uint tile) +{ + /* not used */ +} + + +static uint32 GetTileTrackStatus_TunnelBridge(uint tile, int mode) +{ + uint32 result; + byte t, m5 = _map5[tile]; + + if ((m5 & 0xF0) == 0) { + if (((m5 & 0xC) >> 1) == mode) { /* XXX: possible problem when switching mode constants */ + return m5&1 ? 0x202 : 0x101; + } + } else if (m5 & 0x80) { + result = 0; + if ((m5 & 6) == mode) { + result = m5&1 ? 0x202 : 0x101; + } + if (m5 & 0x40) { + t = m5; + if (!(t & 0x20)) { + if ((t &= 0x18) != 8) + return result; + t = (t&0xE7) | 0x30; + } + + if ((t & 0x18) >> 2 != mode) + return result; + + result ^= m5&1 ? 0x101 : 0x202; + } + return result; + } + return 0; +} + +static void ChangeTileOwner_TunnelBridge(uint tile, byte old_player, byte new_player) +{ + if (_map_owner[tile] != old_player) + return; + + if (new_player != 255) { + _map_owner[tile] = new_player; + } else { + if((_map5[tile] & 0xC0)==0xC0) { + // the stuff BELOW the middle part is owned by the deleted player. + if (!(_map5[tile] & (1 << 4 | 1 << 3))) { + // convert railway into grass. + _map5[tile] &= ~(1 << 5 | 1 << 4 | 1 << 3); // no transport route under bridge anymore.. + } else { + // for road, change the owner of the road to local authority + _map_owner[tile] = OWNER_NONE; + } + } else { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } + } +} + + +static const byte _tunnel_fractcoord_1[4] = {0x8E,0x18,0x81,0xE8}; +static const byte _tunnel_fractcoord_2[4] = {0x81,0x98,0x87,0x38}; +static const byte _tunnel_fractcoord_3[4] = {0x82,0x88,0x86,0x48}; +static const byte _exit_tunnel_track[4] = {1,2,1,2}; + +static const byte _road_exit_tunnel_state[4] = {8, 9, 0, 1}; +static const byte _road_exit_tunnel_frame[4] = {2, 7, 9, 4}; + +static const byte _tunnel_fractcoord_4[4] = {0x52, 0x85, 0x98, 0x29}; +static const byte _tunnel_fractcoord_5[4] = {0x92, 0x89, 0x58, 0x25}; +static const byte _tunnel_fractcoord_6[4] = {0x92, 0x89, 0x56, 0x45}; +static const byte _tunnel_fractcoord_7[4] = {0x52, 0x85, 0x96, 0x49}; + +static uint32 VehicleEnter_TunnelBridge(Vehicle *v, uint tile, int x, int y) +{ + int z; + int dir, vdir; + byte fc; + int h; + + if ((_map5[tile] & 0xF0) == 0) { + z = GetSlopeZ(x, y) - v->z_pos; + if (myabs(z) > 2) + return 8; + + if (v->type == VEH_Train) { + fc = (x&0xF)+(y<<4); + + dir = _map5[tile] & 3; + vdir = v->direction >> 1; + + if (v->u.rail.track != 0x40 && dir == vdir) { + if (v->subtype == 0 && fc == _tunnel_fractcoord_1[dir]) { + if (v->spritenum < 4) + SndPlayVehicleFx(3, v); + return 0; + } + if (fc == _tunnel_fractcoord_2[dir]) { + v->tile = tile; + v->u.rail.track = 0x40; + v->vehstatus |= VS_HIDDEN; + return 4; + } + } + + if (dir == (vdir^2) && fc == _tunnel_fractcoord_3[dir] && z == 0) { + v->tile = tile; + v->u.rail.track = _exit_tunnel_track[dir]; + v->vehstatus &= ~VS_HIDDEN; + return 4; + } + } else if (v->type == VEH_Road) { + fc = (x&0xF)+(y<<4); + dir = _map5[tile] & 3; + vdir = v->direction >> 1; + + // Enter tunnel? + if (v->u.road.state != 0xFF && dir == vdir) { + if (fc == _tunnel_fractcoord_4[dir] || + fc == _tunnel_fractcoord_5[dir]) { + + v->tile = tile; + v->u.road.state = 0xFF; + v->vehstatus |= VS_HIDDEN; + return 4; + } else { + return 0; + } + } + + if (dir == (vdir^2) && ( + fc == _tunnel_fractcoord_6[dir] || + fc == _tunnel_fractcoord_7[dir]) && + z == 0) { + v->tile = tile; + v->u.road.state = _road_exit_tunnel_state[dir]; + v->u.road.frame = _road_exit_tunnel_frame[dir]; + v->vehstatus &= ~VS_HIDDEN; + return 4; + } + } + } else if (_map5[tile] & 0x80) { + if (v->type == VEH_Road || (v->type == VEH_Train && v->subtype == 0)) { + if (GetTileSlope(tile, &h) != 0 || myabs(h - v->z_pos) > 2) { + /* modify speed of vehicle */ + uint16 spd = _bridge_speeds[_map2[tile] >> 4]; + if (v->type == VEH_Road) spd<<=1; + if (spd < v->cur_speed) + v->cur_speed = spd; + } + } + } + return 0; +} + +uint GetVehicleOutOfTunnelTile(Vehicle *v) +{ + uint tile = v->tile; + int delta_tile; + byte z; + + /* locate either ending of the tunnel */ + delta_tile = (v->direction&2) ? TILE_XY(0,1) : TILE_XY(1,0); + z = v->z_pos; + for(;;) { + TileInfo ti; + FindLandscapeHeightByTile(&ti, tile); + + if (ti.type == MP_TUNNELBRIDGE && (ti.map5 & 0xF0)==0 && (byte)ti.z == z) + break; + + tile += delta_tile; + } + return tile; +} + +const TileTypeProcs _tile_type_tunnelbridge_procs = { + DrawTile_TunnelBridge, /* draw_tile_proc */ + GetSlopeZ_TunnelBridge, /* get_slope_z_proc */ + ClearTile_TunnelBridge, /* clear_tile_proc */ + GetAcceptedCargo_TunnelBridge, /* get_accepted_cargo_proc */ + GetTileDesc_TunnelBridge, /* get_tile_desc_proc */ + GetTileTrackStatus_TunnelBridge,/* get_tile_track_status_proc */ + ClickTile_TunnelBridge, /* click_tile_proc */ + AnimateTile_TunnelBridge, /* animate_tile_proc */ + TileLoop_TunnelBridge, /* tile_loop_clear */ + ChangeTileOwner_TunnelBridge, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + VehicleEnter_TunnelBridge, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; diff --git a/unix.c b/unix.c new file mode 100644 --- /dev/null +++ b/unix.c @@ -0,0 +1,486 @@ +#include "stdafx.h" +#include "ttd.h" +#include "hal.h" + +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#endif + + +#if defined(WITH_SDL) +#include +#endif + +#ifdef __MORPHOS__ +#include +ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;) +#endif /* __MORPHOS__ */ + +static char *_fios_path; +static char *_fios_save_path; +static char *_fios_scn_path; +static FiosItem *_fios_items; +static int _fios_count, _fios_alloc; + +static FiosItem *FiosAlloc() +{ + if (_fios_count == _fios_alloc) { + _fios_alloc += 256; + _fios_items = realloc(_fios_items, _fios_alloc * sizeof(FiosItem)); + } + return &_fios_items[_fios_count++]; +} + +int compare_FiosItems (const void *a, const void *b) { + const FiosItem *da = (const FiosItem *) a; + const FiosItem *db = (const FiosItem *) b; + int r; + + if (_savegame_sort_order < 2) // sort by date + r = da->mtime < db->mtime ? 1 : -1; + else + r = strcmp(da->title[0] ? da->title : da->name, db->title[0] ? db->title : db->name); + + if (_savegame_sort_order & 1) r = -r; + return r; +} + + +// Get a list of savegames +FiosItem *FiosGetSavegameList(int *num, int mode) +{ + FiosItem *fios; + DIR *dir; + struct dirent *dirent; + struct stat sb; + int sort_start; + char filename[MAX_PATH]; + + if (_fios_save_path == NULL) { + _fios_save_path = malloc(MAX_PATH); + strcpy(_fios_save_path, _path.save_dir); + } + + if(_game_mode==GM_EDITOR) + _fios_path = _fios_scn_path; + else + _fios_path = _fios_save_path; + + // Parent directory, only if not in root already. + if (_fios_path[1] != 0) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_PARENT; + fios->mtime = 0; + sprintf(fios->title, ".. (Parent directory)"); + } + + // Show subdirectories first + dir = opendir(_fios_path[0] ? _fios_path : "/"); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + sprintf (filename, "%s/%s", _fios_path, dirent->d_name); + if (!stat(filename, &sb)) { + if (S_ISDIR(sb.st_mode)) { + if (dirent->d_name[0] != '.') { + fios = FiosAlloc(); + fios->mtime = 0; + fios->type = FIOS_TYPE_DIR; + fios->title[0] = 0; + sprintf(fios->name, "%s/ (Directory)", dirent->d_name); + } + } + } + } + closedir(dir); + } + + // this is where to start sorting + sort_start = _fios_count; + + /* Show savegame files + * .SAV OpenTTD saved game + * .SS1 Transport Tycoon Deluxe preset game + * .SV1 Transport Tycoon Deluxe (Patch) saved game + * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game + */ + dir = opendir(_fios_path[0] ? _fios_path : "/"); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + sprintf (filename, "%s/%s", _fios_path, dirent->d_name); + if (!stat(filename, &sb)) { + if (!S_ISDIR(sb.st_mode)) { + char *t = strrchr(dirent->d_name, '.'); + if (t && !strcmp(t, ".sav")) { // OpenTTD + *t = 0; // cut extension + fios = FiosAlloc(); + fios->type = FIOS_TYPE_FILE; + fios->mtime = sb.st_mtime; + fios->title[0] = 0; + ttd_strlcpy(fios->name, dirent->d_name, sizeof(fios->name)); + } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) { + int ext = 0; // start of savegame extensions in _old_extensions[] + if (t && ((ext++, !strcmp(t, ".ss1")) || (ext++, !strcmp(t, ".sv1")) || (ext++, !strcmp(t, ".sv2"))) ) { // TTDLX(Patch) + *t = 0; // cut extension + fios = FiosAlloc(); + fios->old_extension = ext-1; + fios->type = FIOS_TYPE_OLDFILE; + fios->mtime = sb.st_mtime; + ttd_strlcpy(fios->name, dirent->d_name, sizeof(fios->name)); + GetOldSaveGameName(fios->title, filename); + } + } + } + } + } + closedir(dir); + } + + *num = _fios_count; + qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); + return _fios_items; +} + +// Get a list of scenarios +FiosItem *FiosGetScenarioList(int *num, int mode) +{ + FiosItem *fios; + DIR *dir; + struct dirent *dirent; + struct stat sb; + int sort_start; + char filename[MAX_PATH]; + + if (_fios_scn_path == NULL) { + _fios_scn_path = malloc(MAX_PATH); + strcpy(_fios_scn_path, _path.scenario_dir); + } + _fios_path = _fios_scn_path; + + // Show subdirectories first + dir = opendir(_fios_path[0] ? _fios_path : "/"); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + sprintf (filename, "%s/%s", _fios_path, dirent->d_name); + if (!stat(filename, &sb)) { + if (S_ISDIR(sb.st_mode)) { + if (dirent->d_name[0] != '.') { + fios = FiosAlloc(); + fios->mtime = 0; + fios->type = FIOS_TYPE_DIR; + fios->title[0] = 0; + sprintf(fios->name, "%s/ (Directory)", dirent->d_name); + } + } + } + } + closedir(dir); + } + + // this is where to start sorting + sort_start = _fios_count; + + /* Show scenario files + * .SCN OpenTTD style scenario file + * .SV0 Transport Tycoon Deluxe (Patch) scenario + * .SS0 Transport Tycoon Deluxe preset scenario + */ + dir = opendir(_fios_path[0] ? _fios_path : "/"); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + sprintf (filename, "%s/%s", _fios_path, dirent->d_name); + if (!stat(filename, &sb)) { + if (!S_ISDIR(sb.st_mode)) { + char *t = strrchr(dirent->d_name, '.'); + if (t && !strcmp(t, ".scn")) { // OpenTTD + *t = 0; // cut extension + fios = FiosAlloc(); + fios->type = FIOS_TYPE_SCENARIO; + fios->mtime = sb.st_mtime; + fios->title[0] = 0; + ttd_strlcpy(fios->name, dirent->d_name, sizeof(fios->name)-3); + } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO || mode == SLD_NEW_GAME) { + int ext = 3; // start of scenario extensions in _old_extensions[] + if (t && ((ext++, !strcmp(t, ".sv0")) || (ext++, !strcmp(t, ".ss0"))) ) { // TTDLX(Patch) + *t = 0; // cut extension + fios = FiosAlloc(); + fios->old_extension = ext-1; + fios->type = FIOS_TYPE_OLD_SCENARIO; + fios->mtime = sb.st_mtime; + GetOldScenarioGameName(fios->title, filename); + ttd_strlcpy(fios->name, dirent->d_name, sizeof(fios->name)-3); + } + } + } + } + } + closedir(dir); + } + + *num = _fios_count; + qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); + return _fios_items; +} + + +// Free the list of savegames +void FiosFreeSavegameList() +{ + free(_fios_items); + _fios_items = NULL; + _fios_alloc = _fios_count = 0; +} + +// Browse to +char *FiosBrowseTo(const FiosItem *item) +{ + char *path = _fios_path; + char *s; + + switch(item->type) { + case FIOS_TYPE_PARENT: + s = strrchr(path, '/'); + if (s != NULL) *s = 0; + break; + + case FIOS_TYPE_DIR: + s = strchr((char*)item->name, '/'); + if (s) *s = 0; + while (*path) path++; + *path++ = '/'; + strcpy(path, item->name); + break; + + case FIOS_TYPE_FILE: + FiosMakeSavegameName(str_buffr, item->name); + return str_buffr; + + case FIOS_TYPE_OLDFILE: + sprintf(str_buffr, "%s/%s.%s", _fios_path, item->name, _old_extensions[item->old_extension]); + return str_buffr; + + case FIOS_TYPE_SCENARIO: + sprintf(str_buffr, "%s/%s.scn", path, item->name); + return str_buffr; + + case FIOS_TYPE_OLD_SCENARIO: + sprintf(str_buffr, "%s/%s.%s", path, item->name, _old_extensions[item->old_extension]); + return str_buffr; + } + + return NULL; +} + +// Get descriptive texts. +// Returns a path as well as a +// string describing the path. +StringID FiosGetDescText(char **path) +{ + *path = _fios_path[0] ? _fios_path : "/"; + +#if defined(__linux__) + { + struct statvfs s; + + if (statvfs(*path, &s) == 0) + { + uint64 tot = (uint64)s.f_bsize * s.f_bavail; + SET_DPARAM32(0, (uint32)(tot >> 20)); + return STR_4005_BYTES_FREE; + } + else + return STR_4006_UNABLE_TO_READ_DRIVE; + } +#else + SET_DPARAM32(0, 0); + return STR_4005_BYTES_FREE; +#endif +} + +void FiosMakeSavegameName(char *buf, const char *name) +{ + if(_game_mode==GM_EDITOR) + sprintf(buf, "%s/%s.scn", _fios_path, name); + else + sprintf(buf, "%s/%s.sav", _fios_path, name); +} + +void FiosDelete(const char *name) +{ + char *path = str_buffr; + FiosMakeSavegameName(path, name); + unlink(path); +} + +const DriverDesc _video_driver_descs[] = { + {"null", "Null Video Driver", &_null_video_driver, 0}, +#if defined(WITH_SDL) + {"sdl", "SDL Video Driver", &_sdl_video_driver, 1}, +#endif + {NULL} +}; + +const DriverDesc _sound_driver_descs[] = { + {"null", "Null Sound Driver", &_null_sound_driver, 0}, +#if defined(WITH_SDL) + {"sdl", "SDL Sound Driver", &_sdl_sound_driver, 1}, +#endif + {NULL} +}; + +#if defined(__APPLE__) +#define EXTMIDI_PRI 2 +#else +#define EXTMIDI_PRI 0 +#endif + +const DriverDesc _music_driver_descs[] = { +#ifndef __BEOS__ +#ifndef __MORPHOS__ +// MorphOS have no music support + {"extmidi", "External MIDI Driver", &_extmidi_music_driver, EXTMIDI_PRI}, +#endif +#endif +#ifdef __BEOS__ + {"bemidi", "BeOS MIDI Driver", &_bemidi_music_driver, 1}, +#endif + {"null", "Null Music Driver", &_null_music_driver, 1}, + {NULL} +}; + +bool FileExists(const char *filename) +{ + return access(filename, 0) == 0; +} + +static int LanguageCompareFunc(const void *a, const void *b) +{ + return strcmp(*(char**)a, *(char**)b); +} + +int GetLanguageList(char **languages, int max) +{ + DIR *dir; + struct dirent *dirent; + int num = 0; + + dir = opendir(_path.lang_dir); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + char *t = strrchr(dirent->d_name, '.'); + if (t && !strcmp(t, ".lng")) { + languages[num++] = strdup(dirent->d_name); + if (num == max) break; + } + } + closedir(dir); + } + + qsort(languages, num, sizeof(char*), LanguageCompareFunc); + return num; +} + +void ChangeWorkingDirectory(char *exe) +{ + char *s = strrchr(exe, '/'); + if (s != NULL) { + *s = 0; + chdir(exe); + *s = '/'; + } +} + +void ShowInfo(const char *str) +{ + puts(str); +} + +void ShowOSErrorBox(const char *buf) +{ + fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf); + +#if defined(__APPLE__) + // this opens the crash log opener script + system("./Crash_Log_Opener.app"); +#endif +} + +int CDECL main(int argc, char* argv[]) +{ + // change the working directory to enable doubleclicking in UIs +#if defined(__BEOS__) + ChangeWorkingDirectory(argv[0]); +#endif +#if defined(__linux__) + ChangeWorkingDirectory(argv[0]); +#endif + + _random_seed_2 = _random_seed_1 = time(NULL); + + + return ttd_main(argc, argv); +} + +void DeterminePaths() +{ + char *s; + + _path.game_data_dir = malloc( MAX_PATH ); + strcpy(_path.game_data_dir, GAME_DATA_DIR); + +#if defined(USE_HOMEDIR) + { + char *homedir; + homedir = getenv("HOME"); + + if(!homedir) { + struct passwd *pw = getpwuid(getuid()); + if (pw) homedir = pw->pw_dir; + } + + _path.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); + } + +#else /* not defined(USE_HOMEDIR) */ + + _path.personal_dir = malloc( MAX_PATH ); + strcpy(_path.personal_dir, PERSONAL_DIR); + + // check if absolute or relative path + s = strchr(_path.personal_dir, '/'); + + // add absolute path + if (s==NULL || _path.personal_dir != s) { + getcwd(_path.personal_dir, MAX_PATH); + s = strchr(_path.personal_dir, 0); + *s++ = '/'; + strcpy(s, PERSONAL_DIR); + } + +#endif /* defined(USE_HOMEDIR) */ + + s = strchr(_path.personal_dir, 0); + + // append a / ? + if (s[-1] != '/') { s[0] = '/'; s[1] = 0; } + + _path.save_dir = str_fmt("%ssave", _path.personal_dir); + _path.autosave_dir = str_fmt("%s/autosave", _path.save_dir); + _path.scenario_dir = str_fmt("%sscenario", _path.personal_dir); + _path.gm_dir = str_fmt("%sgm/", _path.game_data_dir); + _path.data_dir = str_fmt("%sdata/", _path.game_data_dir); + _path.lang_dir = str_fmt("%slang/", _path.game_data_dir); + + _config_file = str_fmt("%sopenttd.cfg", _path.personal_dir); + + // make (auto)save and scenario folder + mkdir(_path.save_dir, 0755); + mkdir(_path.autosave_dir, 0755); + mkdir(_path.scenario_dir, 0755); +} + diff --git a/unmovable_cmd.c b/unmovable_cmd.c new file mode 100644 --- /dev/null +++ b/unmovable_cmd.c @@ -0,0 +1,389 @@ +#include "stdafx.h" +#include "ttd.h" +#include "command.h" +#include "viewport.h" +#include "player.h" +#include "gui.h" +#include "economy.h" +#include "town.h" + +typedef struct DrawTileUnmovableStruct { + uint16 image; + byte subcoord_x; + byte subcoord_y; + byte width; + byte height; + byte z_size; + byte unused; +} DrawTileUnmovableStruct; + +typedef struct DrawTileSeqStruct { + int8 delta_x; + int8 delta_y; + int8 delta_z; + byte width,height; + byte unk; + SpriteID image; +} DrawTileSeqStruct; + +#include "table/unmovable_land.h" + +static void DrawTile_Unmovable(TileInfo *ti) +{ + uint32 image, ormod; + + if (!(ti->map5 & 0x80)) { + if (ti->map5 == 2) { + + // statue + DrawGroundSprite(0x58C); + + image = PLAYER_SPRITE_COLOR(_map_owner[ti->tile]); + image += 0x8A48; + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 25, ti->z); + } else if (ti->map5 == 3) { + + // "owned by" sign + DrawClearLandTile(ti, 0); + + AddSortableSpriteToDraw( + PLAYER_SPRITE_COLOR(_map_owner[ti->tile]) + 0x92B6, + ti->x+8, ti->y+8, + 1, 1, + 10, + GetSlopeZ(ti->x+8, ti->y+8) + ); + } else { + // lighthouse or transmitter + + const DrawTileUnmovableStruct *dtus; + + if (ti->tileh) DrawFoundation(ti, ti->tileh); + DrawClearLandTile(ti, 2); + + dtus = &_draw_tile_unmovable_data[ti->map5]; + + image = dtus->image; + if (!(_display_opt & DO_TRANS_BUILDINGS)) + image = (image & 0x3FFF) | 0x3224000; + + AddSortableSpriteToDraw(image, + ti->x | dtus->subcoord_x, + ti->y | dtus->subcoord_y, + dtus->width, dtus->height, + dtus->z_size, ti->z); + } + } else { + const DrawTileSeqStruct *dtss; + const byte *t; + + if (ti->tileh) DrawFoundation(ti, ti->tileh); + + ormod = PLAYER_SPRITE_COLOR(_map_owner[ti->tile]); + + t = _unmovable_display_datas[ti->map5 & 0x7F]; + DrawGroundSprite(*(uint16*)t | ormod); + + t += sizeof(uint16); + + for(dtss = (DrawTileSeqStruct *)t; (byte)dtss->delta_x != 0x80; dtss++) { + image = dtss->image; + if (_display_opt & DO_TRANS_BUILDINGS) { + image |= ormod; + } else { + image = (image & 0x3FFF) | 0x03224000; + } + AddSortableSpriteToDraw(image, ti->x + dtss->delta_x, ti->y + dtss->delta_y, + dtss->width, dtss->height, dtss->unk, ti->z + dtss->delta_z); + } + } +} + +static uint GetSlopeZ_Unmovable(TileInfo *ti) +{ + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; +} + +static int32 ClearTile_Unmovable(uint tile, byte flags) +{ + byte m5 = _map5[tile]; + //Town *t; + + if (m5 & 0x80) + return_cmd_error(STR_5804_COMPANY_HEADQUARTERS_IN); + + if (m5 == 3) // company owned land + return DoCommandByTile(tile, 0, 0, flags, CMD_SELL_LAND_AREA); + + //t = ClosestTownFromTile(tile, _patches.dist_local_authority + 20); // needed for town penalty + + // checks if you're allowed to remove unmovable things. no remove under rating "%difficulty setting" + if (_game_mode != GM_EDITOR) { + if (flags & DC_AUTO || !_cheats.magic_bulldozer.value) + return_cmd_error(STR_5800_OBJECT_IN_THE_WAY); + + /*if (!CheckforTownRating(tile, flags, t, UNMOVEABLE_REMOVE)) + return CMD_ERROR; + */ + + } + + if (flags & DC_EXEC) { + DoClearSquare(tile); + // decreases the town rating by 250; + /*if (_game_mode != GM_EDITOR) + ChangeTownRating(t, -250, -100); + */ + } + + // return _price.build_industry*0.34; + return 0; +} + +static void GetAcceptedCargo_Unmovable(uint tile, AcceptedCargo *ac) +{ + byte m5 = _map5[tile]; + uint level; // HQ level (depends on company performance) in the range 1..5. + + if (!(m5 & 0x80)) { + /* not used */ + return; + } + + /* HQ accepts passenger and mail; but we have to divide the values + * between 4 tiles it occupies! */ + + level = (m5 & ~0x80) / 4 + 1; + + // Top town building generates 10, so to make HQ interesting, the top + // type makes 20. + ac->type_1 = CT_PASSENGERS; + ac->amount_1 = level; + if (!ac->amount_1) ac->amount_1 = 1; + + // Top town building generates 4, HQ can make up to 8. The + // proportion passengers:mail is different because such a huge + // commercial building generates unusually high amount of mail + // correspondence per physical visitor. + ac->type_2 = CT_MAIL; + ac->amount_2 = level / 2; + if (!ac->amount_2) ac->amount_2 = 1; +} + +static const StringID _unmovable_tile_str[] = { + STR_5803_COMPANY_HEADQUARTERS, + STR_5801_TRANSMITTER, + STR_5802_LIGHTHOUSE, + STR_2016_STATUE, + STR_5805_COMPANY_OWNED_LAND, +}; + +static void GetTileDesc_Unmovable(uint tile, TileDesc *td) +{ + int i = _map5[tile]; + if (i & 0x80) i = -1; + td->str = _unmovable_tile_str[i + 1]; + td->owner = _map_owner[tile]; +} + +static void AnimateTile_Unmovable(uint tile) +{ + /* not used */ +} + +static void TileLoop_Unmovable(uint tile) +{ + byte m5 = _map5[tile]; + byte level; // HQ level (depends on company performance) in the range 1..5. + uint32 r; + + if (!(m5 & 0x80)) { + /* not used */ + return; + } + + /* HQ accepts passenger and mail; but we have to divide the values + * between 4 tiles it occupies! */ + + level = (m5 & ~0x80) / 4 + 1; + assert(level < 6); + + r = Random(); + // Top town buildings generate 250, so the top HQ type makes 256. + if ((byte) r < (256 / 4 / (6 - level))) { + uint amt = ((byte) r >> 3) / 4 + 1; + if (_economy.fluct <= 0) amt = (amt + 1) >> 1; + MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt); + } + + r >>= 8; + // Top town building generates 90, HQ can make up to 196. The + // proportion passengers:mail is about the same as in the acceptance + // equations. + if ((byte) r < (196 / 4 / (6 - level))) { + uint amt = ((byte) r >> 3) / 4 + 1; + if (_economy.fluct <= 0) amt = (amt + 1) >> 1; + MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt); + } +} + + +static uint32 GetTileTrackStatus_Unmovable(uint tile, int mode) +{ + return 0; +} + +static void ClickTile_Unmovable(uint tile) +{ + if (_map5[tile] & 0x80) { + ShowPlayerCompany(_map_owner[tile]); + } +} + +static const TileIndexDiff _tile_add[4] = { + TILE_XY(1,0), + TILE_XY(0,1), + TILE_XY(-1,0), + TILE_XY(0,-1), +}; + +/* checks, if a radio tower is within a 9x9 tile square around tile */ +bool checkRadioTowerNearby(uint tile) +{ + uint tile_s; + + tile_s = TILE_XY( (int) GET_TILE_X(tile)-4, (int) GET_TILE_Y(tile)-4 ); + + BEGIN_TILE_LOOP(tile, 9, 9, tile_s) + // already a radio tower here? + if (IS_TILETYPE(tile, MP_UNMOVABLE) && _map5[tile] == 0) + return false; + END_TILE_LOOP(tile, 9, 9, tile_s) + return true; +} + +void GenerateUnmovables() +{ + int i,j; + uint tile; + uint32 r; + int dir; + int h; + + if (_opt.landscape == LT_CANDY) + return; + + /* add radio tower */ + i = 1000; + j = 40; // limit of 40 radio towers per world. + do { + r = Random(); + tile = r % (TILES_X*TILES_Y); +// TILE_MASK seems to be not working correctly. Radio masts accumulate in one area. +// tile = TILE_MASK(r); + if (IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h >= 32) { + if(!checkRadioTowerNearby(tile)) + continue; + _map_type_and_height[tile] |= MP_UNMOVABLE << 4; + _map5[tile] = 0; + _map_owner[tile] = OWNER_NONE; + if (--j == 0) + break; + } + } while (--i); + + if (_opt.landscape == LT_DESERT) + return; + + /* add lighthouses */ + i = (Random()&3) + 7; + do { +restart: + r = Random(); + dir = r >> 30; + r = r%((dir==0 || dir== 2)?TILE_Y_MAX:TILE_X_MAX); + tile = + (dir==0)?TILE_XY(0,r):0 + // left + (dir==1)?TILE_XY(r,0):0 + // top + (dir==2)?TILE_XY(TILE_X_MAX,r):0 + // right + (dir==3)?TILE_XY(r,TILE_Y_MAX):0; // bottom + j = 20; + do { + if (--j == 0) + goto restart; + tile = TILE_MASK(tile + _tile_add[dir]); + } while (!(IS_TILETYPE(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h <= 16)); + + assert(tile == TILE_MASK(tile)); + + _map_type_and_height[tile] |= MP_UNMOVABLE << 4; + _map5[tile] = 1; + _map_owner[tile] = OWNER_NONE; + } while (--i); +} + +extern int32 CheckFlatLandBelow(uint tile, uint w, uint h, uint flags, uint invalid_dirs, int *); + +int32 CmdBuildCompanyHQ(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + + if (CheckFlatLandBelow(tile, 2, 2, flags, 0, NULL) == CMD_ERROR) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DEREF_PLAYER(_current_player)->location_of_house = tile; + + ModifyTile(tile + TILE_XY(0,0), + MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, + 0x80 + ); + + ModifyTile(tile + TILE_XY(0,1), + MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, + 0x81 + ); + + ModifyTile(tile + TILE_XY(1,0), + MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, + 0x82 + ); + + ModifyTile(tile + TILE_XY(1,1), + MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, + 0x83 + ); + } + + return 0; +} + +static void ChangeTileOwner_Unmovable(uint tile, byte old_player, byte new_player) +{ + if (_map_owner[tile] != old_player) + return; + + if (_map5[tile]==3 && new_player != 255) { + _map_owner[tile] = new_player; + } else { + DoClearSquare(tile); + } +} + +const TileTypeProcs _tile_type_unmovable_procs = { + DrawTile_Unmovable, /* draw_tile_proc */ + GetSlopeZ_Unmovable, /* get_slope_z_proc */ + ClearTile_Unmovable, /* clear_tile_proc */ + GetAcceptedCargo_Unmovable, /* get_accepted_cargo_proc */ + GetTileDesc_Unmovable, /* get_tile_desc_proc */ + GetTileTrackStatus_Unmovable, /* get_tile_track_status_proc */ + ClickTile_Unmovable, /* click_tile_proc */ + AnimateTile_Unmovable, /* animate_tile_proc */ + TileLoop_Unmovable, /* tile_loop_clear */ + ChangeTileOwner_Unmovable, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + NULL, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; diff --git a/variables.h b/variables.h new file mode 100644 --- /dev/null +++ b/variables.h @@ -0,0 +1,435 @@ +#ifndef VARIABLES_H +#define VARIABLES_H + +#include "player.h" +//enum { DPARAM_SIZE = 32 }; + + +// ********* START OF SAVE REGION + +#if !defined(MAX_PATH) +# define MAX_PATH 260 +#endif + +// Prices and also the fractional part. +VARDEF Prices _price; +VARDEF uint16 _price_frac[NUM_PRICES]; + +VARDEF uint32 _cargo_payment_rates[NUM_CARGO]; +VARDEF uint16 _cargo_payment_rates_frac[NUM_CARGO]; + +typedef struct { + GameDifficulty diff; + byte diff_level; + byte currency; + bool kilometers; + byte town_name; + byte landscape; + byte snow_line; + byte autosave; + byte road_side; +} GameOptions; + +// These are the options for the current game +VARDEF GameOptions _opt; + +// These are the options for the new game +VARDEF GameOptions _new_opt; + +// Current date +VARDEF uint16 _date; +VARDEF uint16 _date_fract; + +// Amount of game ticks +VARDEF uint16 _tick_counter; + +// Used when calling OnNewDay +VARDEF VehicleID _vehicle_id_ctr_day; + +// Skip aging of cargo? +VARDEF byte _age_cargo_skip_counter; + +// Available aircraft types +VARDEF byte _avail_aircraft; + +// Position in tile loop +VARDEF TileIndex _cur_tileloop_tile; + +// Also save scrollpos_x, scrollpos_y and zoom +VARDEF uint16 _disaster_delay; + +// Determines what station to operate on in the +// tick handler. +VARDEF uint16 _station_tick_ctr; + +VARDEF uint32 _random_seed_1, _random_seed_2; +// Iterator through all towns in OnTick_Town +VARDEF byte _cur_town_ctr; + +VARDEF uint _cur_player_tick_index; +VARDEF uint _next_competitor_start; + +// Determines how often to run the tree loop +VARDEF byte _trees_tick_ctr; + +// Keep track of current game position +VARDEF int _saved_scrollpos_x; +VARDEF int _saved_scrollpos_y; +VARDEF byte _saved_scrollpos_zoom; + +// ********* END OF SAVE REGION + +typedef struct Patches { + bool vehicle_speed; // show vehicle speed + bool build_on_slopes; // allow building on slopes + bool mammoth_trains; // allow very long trains + bool join_stations; // allow joining of train stations + bool full_load_any; // new full load calculation, any cargo must be full + byte station_spread; // amount a station may spread + bool inflation; // disable inflation + bool no_train_service; // never automatically send trains to service + bool selectgoods; // only send the goods to station if a train has been there + bool longbridges; // allow 100 tile long bridges + bool gotodepot; // allow goto depot in orders + bool build_rawmaterial_ind; // allow building raw material industries + bool multiple_industry_per_town; // allow many industries of the same type per town + bool same_industry_close; // allow same type industries to be built close to each other + uint16 lost_train_days; // if a train doesn't switch order in this amount of days, a train is lost warning is shown + bool train_income_warn; // if train is generating little income, show a warning + bool status_long_date; // always show long date in status bar + bool signal_side; // show signals on right side + bool show_finances; // show finances at end of year + bool new_nonstop; // ttdpatch compatible nonstop handling + bool roadveh_queue; // buggy road vehicle queueing + bool autoscroll; // scroll when moving mouse to the edge. + byte errmsg_duration; // duration of error message + byte snow_line_height; // a number 0-15 that configured snow line height + bool bribe; // enable bribing the local authority + bool new_depot_finding; // use new algorithm to find a depot. + bool nonuniform_stations;// allow nonuniform train stations + bool always_small_airport; // always allow small airports + bool realistic_acceleration; // realistic acceleration for trains + + byte max_trains; //max trains in game per player (these are 8bit because the unitnumber field can't hold more) + byte max_roadveh; //max trucks in game per player + byte max_aircraft; //max planes in game per player + byte max_ships; //max ships in game per player + + uint16 servint_trains; // service interval for trains + uint16 servint_roadveh; // service interval for road vehicles + uint16 servint_aircraft;// service interval for aircraft + uint16 servint_ships; // service interval for ships + + bool autorenew; + uint16 autorenew_months; + + bool new_pathfinding; // use optimized pathfinding algoritm for trains + byte pf_maxdepth; // maximum recursion depth when searching for a train route for new pathfinder + uint16 pf_maxlength; // maximum length when searching for a train route for new pathfinder + + bool build_in_pause; // build while in pause mode + bool bridge_pillars; // show bridge pillars for high bridges + + byte ai_disable_veh; // mask of vehicle types to disable for ai + uint32 starting_date; // starting date + uint32 colored_news_date; // when does newspaper become colored? + + bool keep_all_autosave; // name the autosave in a different way. + bool extra_dynamite; // extra dynamite + + bool never_expire_vehicles; // never expire vehicles + byte extend_vehicle_life; // extend vehicle life by this many years + + bool auto_euro; // automatically switch to euro in 2002 + bool serviceathelipad; // service helicopters at helipads automatically (no need to send to depot) + bool smooth_economy; // smooth economy + byte dist_local_authority; // distance for town local authority, default 20 + + byte wait_oneway_signal; //waitingtime in days before a oneway signal + byte wait_twoway_signal; //waitingtime in days before a twoway signal + +} Patches; + +enum { + DISABLE_TRAINS = 1<<0, + DISABLE_ROADVEH = 1 << 1, + DISABLE_AIRCRAFT = 1 << 2, + DISABLE_SHIPS = 1 << 3, +}; + +VARDEF Patches _patches; + + +typedef struct Cheat { + bool been_used; // has this cheat been used before? + byte value; // active? +} Cheat; + + +// WARNING! Do _not_ remove entries in Cheats struct or change the order +// of the existing ones! Would break downward compatibility. +// Only add new entries at the end of the struct! + +typedef struct Cheats { + Cheat magic_bulldozer; // dynamite industries, unmovables + Cheat switch_player; // change to another player + Cheat money; // get rich + Cheat crossing_tunnels; // allow tunnels that cross each other +} Cheats; + +VARDEF Cheats _cheats; + +typedef struct Paths { + char *personal_dir; // includes cfg file and save folder + char *game_data_dir; // includes data, gm, lang + char *data_dir; + char *gm_dir; + char *lang_dir; + char *save_dir; + char *autosave_dir; + char *scenario_dir; +} Paths; + +VARDEF Paths _path; + +// Which options struct does options modify? +VARDEF GameOptions *_opt_mod_ptr; + +// NOSAVE: Used in palette animations only, not really important. +VARDEF int _timer_counter; + + +// NOSAVE: can be determined from _date +VARDEF byte _cur_year; +VARDEF byte _cur_month; + +// NOSAVE: can be determined from player structs +VARDEF byte _player_colors[MAX_PLAYERS]; + +VARDEF bool _in_state_game_loop; +VARDEF int32 _frame_counter; + +VARDEF int32 _frame_counter_max; // for networking, this is the frame that we are not allowed to execute yet. +VARDEF int32 _frame_counter_srv; // for networking, this is the last known framecounter of the server. it is always less than frame_counter_max. + +// networking settings +VARDEF uint _network_port; +VARDEF uint _network_sync_freq; +VARDEF uint _network_ahead_frames; + +VARDEF uint32 _network_ip_list[10]; // Network IPs +VARDEF char * _network_detected_serverip; // UDP Broadcast detected Server +VARDEF uint32 _network_detected_serverport; // UDP Broadcast detected server-port + +VARDEF uint32 _sync_seed_1, _sync_seed_2; + +VARDEF bool _is_ai_player; // current player is an AI player? + +VARDEF bool _do_autosave; +VARDEF int _autosave_ctr; + +VARDEF byte _local_player; +VARDEF byte _display_opt; +VARDEF byte _pause; +VARDEF int _caret_timer; +VARDEF uint16 _news_display_opt; +VARDEF byte _game_mode; + +VARDEF StringID _error_message; +VARDEF StringID _error_message_2; +VARDEF int32 _additional_cash_required; + +VARDEF uint32 _decode_parameters[10]; +VARDEF byte _current_player; + +VARDEF int _docommand_recursive; + +VARDEF uint32 _pressed_key; // Low 8 bits = ASCII, High 16 bits = keycode +VARDEF bool _ctrl_pressed; // Is Ctrl pressed? +VARDEF bool _shift_pressed; // Is Alt pressed? +VARDEF byte _dirkeys; // 1=left, 2=up, 4=right, 8=down + +VARDEF bool _fullscreen; +VARDEF bool _double_size; +VARDEF uint _display_hz; +VARDEF bool _force_full_redraw; +VARDEF uint _fullscreen_bpp; +VARDEF bool _fast_forward; +VARDEF bool _rightclick_emulate; + +// IN/OUT parameters to commands +VARDEF byte _yearly_expenses_type; +VARDEF TileIndex _terraform_err_tile; +VARDEF uint _build_tunnel_endtile; +VARDEF bool _generating_world; +VARDEF int _new_town_size; +VARDEF uint _returned_refit_amount; + +// Deals with the type of the savegame, independent of extension +typedef struct { + int mode; // savegame/scenario type (old, new) + byte name[MAX_PATH]; // name +} SmallFiosItem; + +// Used when switching from the intro menu. +VARDEF byte _switch_mode; +VARDEF bool _exit_game; +VARDEF SmallFiosItem _file_to_saveload; +VARDEF byte _make_screenshot; + +VARDEF bool _networking; +VARDEF bool _networking_sync; // if we use network mode and the games must stay in sync. +VARDEF bool _networking_server; +VARDEF bool _networking_queuing; // queueing only? + +VARDEF byte _network_playas; // an id to play as.. + +VARDEF byte _get_z_hint; // used as a hint to getslopez to return the right height at a bridge. + +VARDEF char *_newgrf_files[32]; + + +VARDEF Vehicle *_place_clicked_vehicle; + +VARDEF char _ini_videodriver[16], _ini_musicdriver[16], _ini_sounddriver[16]; + +VARDEF bool _cache_sprites; + +// debug features +VARDEF char _savedump_path[64]; +VARDEF uint _savedump_first, _savedump_freq, _savedump_last; +// end of debug features + + +typedef struct { + char *name; + char *file; +} DynLangEnt; + +// Used for dynamic language support +typedef struct { + int num; // number of languages + int curr; // currently selected language index + char curr_file[32]; // currently selected language file + StringID dropdown[32 + 1]; // used in settings dialog + DynLangEnt ent[32]; +} DynamicLanguages; + +VARDEF DynamicLanguages _dynlang; + +VARDEF int _num_resolutions; +VARDEF uint16 _resolutions[32][2]; +VARDEF uint16 _cur_resolution[2]; + +VARDEF char _screenshot_format_name[8]; +VARDEF int _num_screenshot_formats, _cur_screenshot_format; + +VARDEF char _savegame_format[8]; + +VARDEF char *_config_file; + +// NOSAVE: These can be recalculated from InitializeLandscapeVariables +typedef struct { + StringID names_s[NUM_CARGO]; + StringID names_p[NUM_CARGO]; + StringID names_long_s[NUM_CARGO]; + StringID names_long_p[NUM_CARGO]; + StringID names_short[NUM_CARGO]; + byte weights[NUM_CARGO]; + SpriteID sprites[NUM_CARGO]; + byte transit_days_1[NUM_CARGO]; + byte transit_days_2[NUM_CARGO]; + byte ai_railwagon[3][NUM_CARGO]; + byte ai_roadveh_start[NUM_CARGO]; + byte ai_roadveh_count[NUM_CARGO]; +} CargoConst; + +VARDEF CargoConst _cargoc; + +typedef byte TownNameGenerator(byte *buf, uint32 seed); +extern TownNameGenerator * const _town_name_generators[]; + +#define SET_DPARAM32(n, v) (_decode_parameters[n] = (v)) +#define SET_DPARAMX32(s, n, v) ((s)[n] = (v)) +#define GET_DPARAM32(n) (_decode_parameters[n]) + +#define SET_DPARAM(n, v) (_decode_parameters[n] = (v)) +#define SET_DPARAMX(s, n, v) ((s)[n] = (v)) +#define GET_DPARAM(n) (_decode_parameters[n]) + +static void FORCEINLINE SET_DPARAM64(int n, int64 v) +{ + _decode_parameters[n] = (uint32)v; + _decode_parameters[n+1] = (uint32)((uint64)v >> 32); +} + +#if defined(TTD_LITTLE_ENDIAN) +#define SET_DPARAMX16(s, n, v) ( ((uint16*)(s+n))[0] = (v)) +#define SET_DPARAMX8(s, n, v) ( ((uint8*)(s+n))[0] = (v)) +#define GET_DPARAMX16(s, n) ( ((uint16*)(s+n))[0]) +#define GET_DPARAMX8(s, n) ( ((uint8*)(s+n))[0]) +#elif defined(TTD_BIG_ENDIAN) +#define SET_DPARAMX16(s, n, v) ( ((uint16*)(s+n))[1] = (v)) +#define SET_DPARAMX8(s, n, v) ( ((uint8*)(s+n))[3] = (v)) +#define GET_DPARAMX16(s, n) ( ((uint16*)(s+n))[1]) +#define GET_DPARAMX8(s, n) ( ((uint8*)(s+n))[3]) +#endif + +#define SET_DPARAM16(n, v) SET_DPARAMX16(_decode_parameters, n, v) +#define SET_DPARAM8(n, v) SET_DPARAMX8(_decode_parameters, n, v) +#define GET_DPARAM16(n) GET_DPARAMX16(_decode_parameters, n) +#define GET_DPARAM8(n) GET_DPARAMX8(_decode_parameters, n) + +#define COPY_IN_DPARAM(offs,src,num) memcpy(_decode_parameters + offs, src, sizeof(uint32) * (num)) +#define COPY_OUT_DPARAM(dst,offs,num) memcpy(dst,_decode_parameters + offs, sizeof(uint32) * (num)) + +#define INJECT_DPARAM(n) InjectDparam(n); + +#define SET_EXPENSES_TYPE(x) if (x) _yearly_expenses_type=x; + +/* landscape.c */ +extern const byte _tileh_to_sprite[32]; +extern byte _map_type_and_height[TILES_X * TILES_Y]; +extern byte _map5[TILES_X * TILES_Y]; +extern byte _map3_lo[TILES_X * TILES_Y]; +extern byte _map3_hi[TILES_X * TILES_Y]; +extern byte _map_owner[TILES_X * TILES_Y]; +extern byte _map2[TILES_X * TILES_Y]; +extern byte _map_extra_bits[TILES_X * TILES_Y/4]; + +static const byte _inclined_tileh[] = { + 3,9,3,6,12,6,12,9, +}; + +extern const TileTypeProcs * const _tile_type_procs[16]; + +/* station_cmd.c */ +// there are 5 types of airport (Country (3x4) , City(6x6), Metropolitan(6x6), International(7x7), Heliport(1x1) +// will become obsolete once airports are loaded from seperate file +extern const byte _airport_size_x[5]; +extern const byte _airport_size_y[5]; + +extern const TileIndexDiff _tileoffs_by_dir[4]; + +/* misc */ +VARDEF byte str_buffr[512]; +VARDEF char _screenshot_name[128]; +VARDEF char _userstring[128]; +VARDEF byte _vehicle_design_names; + +VARDEF SignStruct _sign_list[40]; +VARDEF SignStruct *_new_sign_struct; + +VARDEF bool _ignore_wrong_grf; + +/* tunnelbridge */ +#define MAX_BRIDGES 13 + +/* Debugging levels */ +VARDEF int _debug_spritecache_level; +VARDEF int _debug_misc_level; + +void CDECL debug(const char *s, ...); +#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug + +#endif /* VARIABLES_H */ diff --git a/vehicle.c b/vehicle.c new file mode 100644 --- /dev/null +++ b/vehicle.c @@ -0,0 +1,1819 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "gfx.h" +//#include "station.h" +#include "viewport.h" +#include "news.h" +#include "command.h" +#include "saveload.h" +#include "player.h" +#include "engine.h" + +#define INVALID_COORD (-0x8000) +#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0))) + + +void VehicleInTheWayErrMsg(Vehicle *v) +{ + StringID id; + + (id = STR_8803_TRAIN_IN_THE_WAY,v->type == VEH_Train) || + (id = STR_9000_ROAD_VEHICLE_IN_THE_WAY,v->type == VEH_Road) || + (id = STR_A015_AIRCRAFT_IN_THE_WAY,v->type == VEH_Aircraft) || + (id = STR_980E_SHIP_IN_THE_WAY, true); + + _error_message = id; +} + +static void *EnsureNoVehicleProc(Vehicle *v, void *data) +{ + if (v->tile != (TileIndex)(int)data || v->type == VEH_Disaster) + return NULL; + + VehicleInTheWayErrMsg(v); + return (void*)1; +} + +bool EnsureNoVehicle(TileIndex tile) +{ + return VehicleFromPos(tile, (void*)(int)tile, (VehicleFromPosProc*)EnsureNoVehicleProc) == NULL; +} + +static void *EnsureNoVehicleProcZ(Vehicle *v, void *data) +{ + uint32 d = (uint32)data; // max mapsize 4,096*4,096 if shifted 8 bits for byte + // with uint64 max mapsize is 2,6843,5456*2,6843,5456 :D + if (v->tile != (TileIndex)(d >> (sizeof(byte)*8)) || v->z_pos != (byte)d || v->type == VEH_Disaster) + return NULL; + + VehicleInTheWayErrMsg(v); + return (void*)1; +} + +bool EnsureNoVehicleZ(TileIndex tile, byte z) +{ + TileInfo ti; + FindLandscapeHeightByTile(&ti, tile); + // needs z correction for slope-type graphics that have the NORTHERN tile lowered + // 1, 2, 3, 4, 5, 6 and 7 + if (CORRECT_Z(ti.tileh)) + z += 8; + + return VehicleFromPos(tile, (void*)((TileIndex)tile << (sizeof(byte)*8) | (byte)z), (VehicleFromPosProc*)EnsureNoVehicleProcZ) == NULL; +} + +Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z) +{ + int x1 = GET_TILE_X(from); + int y1 = GET_TILE_Y(from); + int x2 = GET_TILE_X(to); + int y2 = GET_TILE_Y(to); + Vehicle *veh; + uint count; + + /* Make sure x1 < x2 or y1 < y2 */ + if (x1 > x2 || y1 > y2) { + intswap(x1,x2); + intswap(y1,y2); + } + for(veh = _vehicles, count=lengthof(_vehicles); count != 0; count--, veh++) { + if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) { + if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 && + (veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) { + return veh; + } + } + } + return NULL; +} + +void VehiclePositionChanged(Vehicle *v) +{ + int img = v->cur_image; + const SpriteDimension *sd; + Point pt = RemapCoords(v->x_pos + v->x_offs, v->y_pos + v->y_offs, v->z_pos); + + sd = GetSpriteDimension(img); + + pt.x += sd->xoffs; + pt.y += sd->yoffs; + + UpdateVehiclePosHash(v, pt.x, pt.y); + + v->left_coord = pt.x; + v->top_coord = pt.y; + v->right_coord = pt.x + sd->xsize + 2; + v->bottom_coord = pt.y + sd->ysize + 2; +} + +void UpdateCheckpointSign(Checkpoint *cp) +{ + Point pt = RemapCoords2(GET_TILE_X(cp->xy)*16, GET_TILE_Y(cp->xy)*16); + SET_DPARAM16(0, cp - _checkpoints); + UpdateViewportSignPos(&cp->sign, pt.x, pt.y - 0x20, STR_CHECKPOINT_VIEWPORT); +} + +void RedrawCheckpointSign(Checkpoint *cp) +{ + MarkAllViewportsDirty( + cp->sign.left - 6, + cp->sign.top, + cp->sign.left + (cp->sign.width_1 << 2) + 12, + cp->sign.top + 48); +} + +// Called after load to update coordinates +void AfterLoadVehicles() +{ + Vehicle *v; + Checkpoint *cp; + + FOR_ALL_VEHICLES(v) { + if (v->type != 0) { + v->left_coord = INVALID_COORD; + VehiclePositionChanged(v); + + if (v->type == VEH_Train) { + if (v->subtype == 0) + UpdateTrainAcceleration(v); + } + +#if defined(_DEBUG) + if (!(v->schedule_ptr == NULL || (v->schedule_ptr >= _order_array && v->schedule_ptr < _ptr_to_next_order))) + v->schedule_ptr = NULL; +#endif + } + } + + // update checkpoint signs + for(cp=_checkpoints; cp != endof(_checkpoints); cp++) if (cp->xy) UpdateCheckpointSign(cp); +} + + +static Vehicle *InitializeVehicle(Vehicle *v) +{ + VehicleID index = v->index; + memset(v, 0, sizeof(Vehicle)); + v->index = index; + + assert(v->schedule_ptr == NULL); + + v->left_coord = INVALID_COORD; + v->next = NULL; + v->next_hash = 0xffff; + v->string_id = 0; + return v; +} + +Vehicle *ForceAllocateSpecialVehicle() +{ + Vehicle *v; + for(v=_vehicles + NUM_NORMAL_VEHICLES; + v!=&_vehicles[NUM_NORMAL_VEHICLES+NUM_SPECIAL_VEHICLES]; v++) { + if (v->type == 0) + return InitializeVehicle(v); + } + return NULL; + +} + +Vehicle *ForceAllocateVehicle() +{ + Vehicle *v; + for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { + if (v->type == 0) + return InitializeVehicle(v); + } + return NULL; +} + +Vehicle *AllocateVehicle() +{ + Vehicle *v; + int num; + + if (IS_HUMAN_PLAYER(_current_player)) { + num = 0; + + for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { + if (v->type == 0) + num++; + } + + if (num <= 90) + return NULL; + } + + return ForceAllocateVehicle(); +} + +void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) +{ + int x,y,x2,y2; + VehicleID veh; + Point pt = RemapCoords(GET_TILE_X(tile) * 16, GET_TILE_Y(tile) * 16, 0); + + x2 = ((pt.x + 104) & 0x1F80) >> 7; + x = ((pt.x - 174) & 0x1F80) >> 7; + + y2 = ((pt.y + 56) & 0xFC0); + y = ((pt.y - 294) & 0xFC0); + + for(;;) { + int xb = x; + for(;;) { + veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; + while (veh != INVALID_VEHICLE) { + Vehicle *v = &_vehicles[veh]; + void *a; + + if ((a = proc(v, data)) != NULL) + return a; + veh = v->next_hash; + } + + if (x == x2) + break; + + x = (x + 1) & 0x3F; + } + x = xb; + + if (y == y2) + break; + + y = (y + 0x40) & ((0x3F) << 6); + } + return NULL; +} + + + +void UpdateVehiclePosHash(Vehicle *v, int x, int y) +{ + VehicleID *old_hash, *new_hash; + int old_x = v->left_coord; + int old_y = v->top_coord; + Vehicle *u; + + new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(x,y)]; + old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(old_x, old_y)]; + + if (old_hash == new_hash) + return; + + /* remove from hash table? */ + if (old_hash != NULL) { + Vehicle *last = NULL; + int idx = *old_hash; + while((u = &_vehicles[idx]) != v) { + idx = u->next_hash; + assert(idx != INVALID_VEHICLE); + last = u; + } + + if (last == NULL) + *old_hash = v->next_hash; + else + last->next_hash = v->next_hash; + } + + /* insert into hash table? */ + if (new_hash != NULL) { + v->next_hash = *new_hash; + *new_hash = v->index; + } +} + +void InitializeVehicles() +{ + Vehicle *v; + int i; + + // clear it... + memset(&_vehicles, 0, sizeof(_vehicles)); + memset(&_checkpoints, 0, sizeof(_checkpoints)); + memset(&_depots, 0, sizeof(_depots)); + + // setup indexes.. + i = 0; + FOR_ALL_VEHICLES(v) + v->index = i++; + + memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash)); + + _ptr_to_next_order = _order_array; +} + +Vehicle *GetLastVehicleInChain(Vehicle *v) +{ + while (v->next != NULL) v = v->next; + return v; +} + +Vehicle *GetPrevVehicleInChain(Vehicle *v) +{ + Vehicle *org = v; + + v = _vehicles; + while (v->type != VEH_Train || org != v->next) { + if (++v == endof(_vehicles)) + return NULL; + } + + return v; +} + +Vehicle *GetFirstVehicleInChain(Vehicle *v) +{ + for(;;) { + Vehicle *u = v; + v = _vehicles; + while (v->type != VEH_Train || u != v->next) { + if (++v == endof(_vehicles)) + return u; + } + } +} + +int CountVehiclesInChain(Vehicle *v) +{ + int count = 0; + do count++; while ( (v=v->next) != NULL); + return count; +} + + +Depot *AllocateDepot() +{ + Depot *dep, *free_dep = NULL; + int num_free = 0; + + for(dep = _depots; dep != endof(_depots); dep++) { + if (dep->xy == 0) { + num_free++; + if (free_dep==NULL) + free_dep = dep; + } + } + + if (free_dep == NULL || + (num_free < 30 && IS_HUMAN_PLAYER(_current_player))) { + _error_message = STR_1009_TOO_MANY_DEPOTS; + return NULL; + } + + return free_dep; +} + +Checkpoint *AllocateCheckpoint() +{ + Checkpoint *cp; + + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy == 0) + return cp; + } + + return NULL; +} + +uint GetCheckpointByTile(uint tile) +{ + Checkpoint *cp; + int i=0; + for(cp=_checkpoints; cp->xy != (TileIndex)tile; cp++) { i++; } + return i; +} + + +Vehicle *IsScheduleShared(Vehicle *u) +{ + uint16 *sched = u->schedule_ptr; + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->schedule_ptr == sched && u != v && v->type != 0) + return v; + } + return NULL; +} + +void DeleteVehicleSchedule(Vehicle *v) +{ + uint16 *sched, *cur; + int num; + Vehicle *u; + + // if the schedule is shared, don't delete it. + if ((u = IsScheduleShared(v)) != NULL) { + v->schedule_ptr = NULL; + InvalidateWindow(WC_VEHICLE_ORDERS, u->index); + return; + } + + sched = v->schedule_ptr; + v->schedule_ptr = NULL; + + num = v->num_orders + 1; + + _ptr_to_next_order -= num; + + cur = sched; + while (cur != _ptr_to_next_order) { + assert(cur < _ptr_to_next_order); + cur[0] = cur[num]; + cur++; + } + + FOR_ALL_VEHICLES(v) { + if (v->schedule_ptr != NULL && sched < v->schedule_ptr) { + v->schedule_ptr -= num; + } + } +} + +void DeleteCommandFromVehicleSchedule(uint cmd) +{ + Vehicle *v; + uint16 *sched; + uint order; + bool need_invalidate; + + FOR_ALL_VEHICLES(v) { + if (v->type != 0 && v->schedule_ptr != NULL) { + + // clear last station visited + if (v->last_station_visited == (cmd>>8) && (cmd & OT_MASK) == OT_GOTO_STATION) + v->last_station_visited = 0xFF; + + // check the next order + if ( (uint)((v->next_order&OT_MASK) | (v->next_order_param<<8)) == cmd) { + v->next_order = OT_DUMMY; + InvalidateWindow(WC_VEHICLE_VIEW, v->index); + } + + // clear the order list + need_invalidate = false; + sched = v->schedule_ptr; + while ((order=*sched++) != 0) { + if ( (order & (OT_MASK|0xFF00)) == cmd) { + sched[-1] = OT_DUMMY; + need_invalidate = true; + } + } + + if (need_invalidate) + InvalidateWindow(WC_VEHICLE_ORDERS, v->index); + } + } +} + +void DoDeleteDepot(uint tile) +{ + byte dep_index; + Depot *d; + + // Clear it + DoClearSquare(tile); + + // Nullify the depot struct + for(d=_depots,dep_index=0; d->xy != (TileIndex)tile; d++) {dep_index++;} + d->xy = 0; + + DeleteCommandFromVehicleSchedule((dep_index << 8) + OT_GOTO_DEPOT); + + // Delete the depot + DeleteWindowById(WC_VEHICLE_DEPOT, tile); +} + +void DeleteVehicle(Vehicle *v) +{ + DeleteName(v->string_id); + v->type = 0; + UpdateVehiclePosHash(v, INVALID_COORD, 0); + v->next_hash = 0xffff; + + if (v->schedule_ptr != NULL) + DeleteVehicleSchedule(v); +} + +void DeleteVehicleChain(Vehicle *v) +{ + do { + Vehicle *u = v; + v = v->next; + DeleteVehicle(u); + } while (v); +} + + +void Aircraft_Tick(Vehicle *v); +void RoadVeh_Tick(Vehicle *v); +void Ship_Tick(Vehicle *v); +void Train_Tick(Vehicle *v); +void EffectVehicle_Tick(Vehicle *v); +void DisasterVehicle_Tick(Vehicle *v); + +VehicleTickProc *_vehicle_tick_procs[] = { + Train_Tick, + RoadVeh_Tick, + Ship_Tick, + Aircraft_Tick, + EffectVehicle_Tick, + DisasterVehicle_Tick, +}; + +void CallVehicleTicks() +{ + Vehicle *v; + + FOR_ALL_VEHICLES(v) { + if (v->type != 0) + _vehicle_tick_procs[v->type - 0x10](v); + } +} + +static bool CanFillVehicle_FullLoadAny(Vehicle *v) +{ + uint32 full = 0, not_full = 0; + + // patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded. + do { + //Should never happen, but just in case future additions change this + assert(v->cargo_type<32); + + if (v->cargo_cap != 0) { + uint32 mask = 1 << v->cargo_type; + if (v->cargo_cap == v->cargo_count) full |= mask; else not_full |= mask; + } + } while ( (v=v->next) != NULL); + + // continue loading if there is a non full cargo type and no cargo type that is full + return not_full && (full & ~not_full) == 0; +} + +bool CanFillVehicle(Vehicle *v) +{ + byte *t = &_map_type_and_height[v->tile]; + + if (t[0] >> 4 == MP_STATION || + (v->type == VEH_Ship && + (t[TILE_XY(1,0)] >> 4 == MP_STATION || + t[TILE_XY(-1,0)] >> 4 == MP_STATION || + t[TILE_XY(0,1)] >> 4 == MP_STATION || + t[TILE_XY(0,-1)] >> 4 == MP_STATION || + t[TILE_XY(-2,0)] >> 4 == MP_STATION))) { + + // If patch is active, use alternative CanFillVehicle-function + if (_patches.full_load_any) + return CanFillVehicle_FullLoadAny(v); + + do { + if (v->cargo_count != v->cargo_cap) + return true; + } while ( (v=v->next) != NULL); + } + return false; +} + +static void DoDrawVehicle(Vehicle *v) +{ + uint32 image = v->cur_image; + + if (v->vehstatus & VS_DISASTER) { + image |= 0x3224000; + } else if (v->vehstatus & VS_DEFPAL) { + image |= (v->vehstatus & VS_CRASHED) ? 0x3248000 : SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner)); + } + + AddSortableSpriteToDraw(image, v->x_pos + v->x_offs, v->y_pos + v->y_offs, + v->sprite_width, v->sprite_height, v->z_height, v->z_pos); +} + +void ViewportAddVehicles(DrawPixelInfo *dpi) +{ + int x,xb, y, x2, y2; + VehicleID veh; + Vehicle *v; + + x = ((dpi->left - 70) & 0x1F80) >> 7; + x2 = ((dpi->left + dpi->width) & 0x1F80) >> 7; + + y = ((dpi->top - 70) & 0xFC0); + y2 = ((dpi->top + dpi->height) & 0xFC0); + + for(;;) { + xb = x; + for(;;) { + veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; + while (veh != INVALID_VEHICLE) { + v = &_vehicles[veh]; + + if (!(v->vehstatus & VS_HIDDEN) && + dpi->left <= v->right_coord && + dpi->top <= v->bottom_coord && + dpi->left + dpi->width >= v->left_coord && + dpi->top + dpi->height >= v->top_coord) { + DoDrawVehicle(v); + } + veh = v->next_hash; + } + + if (x == x2) + break; + x = (x + 1) & 0x3F; + } + x = xb; + + if (y == y2) + break; + y = (y + 0x40) & ((0x3F) << 6); + } +} + +static void EffectInit_0(Vehicle *v) +{ + uint32 r = Random(); + v->cur_image = (uint16)((r & 7) + 3701); + v->progress = (byte)((r >> 16)&7); +} + +static void EffectTick_0(Vehicle *v) +{ + uint tile; + uint img; + + if (--v->progress & 0x80) { + BeginVehicleMove(v); + + tile = TILE_FROM_XY(v->x_pos, v->y_pos); + if (!IS_TILETYPE(tile, MP_INDUSTRY)) { + EndVehicleMove(v); + DeleteVehicle(v); + return; + } + + img = v->cur_image + 1; + if (img > 3708) img = 3701; + v->cur_image = img; + v->progress = 7; + VehiclePositionChanged(v); + EndVehicleMove(v); + } +} + +static void EffectInit_1(Vehicle *v) +{ + v->cur_image = 3079; + v->progress = 12; +} + +static void EffectTick_1(Vehicle *v) +{ + bool moved; + + BeginVehicleMove(v); + + moved = false; + + if ((++v->progress & 7) == 0) { + v->z_pos++; + moved = true; + } + + if ((v->progress & 0xF)==4) { + if (++v->cur_image > 3083) { + EndVehicleMove(v); + DeleteVehicle(v); + return; + } + moved = true; + } + + if (moved) { + VehiclePositionChanged(v); + EndVehicleMove(v); + } +} + +static void EffectInit_2(Vehicle *v) +{ + v->cur_image = 3073; + v->progress = 0; +} + +static void EffectTick_2(Vehicle *v) +{ + if ((++v->progress & 3) == 0) { + BeginVehicleMove(v); + v->z_pos++; + VehiclePositionChanged(v); + EndVehicleMove(v); + } else if ((v->progress & 7) == 1) { + BeginVehicleMove(v); + if (++v->cur_image > 3078) { + EndVehicleMove(v); + DeleteVehicle(v); + } else { + VehiclePositionChanged(v); + EndVehicleMove(v); + } + } +} + +static void EffectInit_3(Vehicle *v) +{ + v->cur_image = 3084; + v->progress = 1; +} + +static void EffectTick_3(Vehicle *v) +{ + if (++v->progress > 2) { + v->progress = 0; + BeginVehicleMove(v); + if (++v->cur_image > 3089) { + EndVehicleMove(v); + DeleteVehicle(v); + } else { + VehiclePositionChanged(v); + EndVehicleMove(v); + } + } +} + +static void EffectInit_4(Vehicle *v) +{ + v->cur_image = 2040; + v->progress = 12; +} + +static void EffectTick_4(Vehicle *v) +{ + bool moved; + + BeginVehicleMove(v); + + moved = false; + + if ((++v->progress & 3) == 0) { + v->z_pos++; + moved = true; + } + + if ((v->progress & 0xF)==4) { + if (++v->cur_image > 2044) { + EndVehicleMove(v); + DeleteVehicle(v); + return; + } + moved = true; + } + + if (moved) { + VehiclePositionChanged(v); + EndVehicleMove(v); + } +} + +static void EffectInit_5(Vehicle *v) +{ + v->cur_image = 3709; + v->progress = 0; +} + +static void EffectTick_5(Vehicle *v) +{ + if (!(++v->progress & 3)) { + BeginVehicleMove(v); + if (++v->cur_image > 3724) { + EndVehicleMove(v); + DeleteVehicle(v); + } else { + VehiclePositionChanged(v); + EndVehicleMove(v); + } + } +} + +static void EffectInit_6(Vehicle *v) +{ + v->cur_image = 3737; + v->progress = 0; +} + +static void EffectTick_6(Vehicle *v) +{ + if (!(++v->progress & 7)) { + BeginVehicleMove(v); + if (++v->cur_image > 3740) v->cur_image = 3737; + VehiclePositionChanged(v); + EndVehicleMove(v); + } + + if (!--v->u.special.unk0) { + BeginVehicleMove(v); + EndVehicleMove(v); + DeleteVehicle(v); + } +} + +static void EffectInit_7(Vehicle *v) +{ + v->cur_image = 3725; + v->progress = 0; +} + +static void EffectTick_7(Vehicle *v) +{ + if (!(++v->progress & 3)) { + BeginVehicleMove(v); + if (++v->cur_image > 3736) { + EndVehicleMove(v); + DeleteVehicle(v); + } else { + VehiclePositionChanged(v); + EndVehicleMove(v); + } + } +} + +static void EffectInit_8(Vehicle *v) +{ + v->cur_image = 1416; + v->progress = 0; + v->u.special.unk0 = 0; + v->u.special.unk2 = 0; +} + +#define MK(imag,dir,dur) (imag<<6)+(dir<<4)+dur +static const byte _effecttick8_data[] = { + MK(0,0,4), + MK(3,3,4), + MK(2,2,7), + MK(0,2,7), + MK(1,1,3), + MK(2,2,7), + MK(0,2,7), + MK(1,1,3), + MK(2,2,7), + MK(0,2,7), + MK(3,3,6), + MK(2,2,6), + MK(1,1,7), + MK(3,1,7), + MK(0,0,3), + MK(1,1,7), + MK(3,1,7), + MK(0,0,3), + MK(1,1,7), + MK(3,1,7), + 255 +}; +#undef MK + +static const int8 _xy_inc_by_dir[5] = { + -1, 0, 1, 0, -1, +}; + +#define GET_X_INC_BY_DIR(d) _xy_inc_by_dir[d] +#define GET_Y_INC_BY_DIR(d) _xy_inc_by_dir[(d)+1] + +static void EffectTick_8(Vehicle *v) +{ + byte b; + + if (!(++v->progress & 7)) { + v->u.special.unk2++; + BeginVehicleMove(v); + + b = _effecttick8_data[v->u.special.unk0]; + + v->cur_image = 0x588 + (b>>6); + + v->x_pos += GET_X_INC_BY_DIR((b>>4)&3); + v->y_pos += GET_X_INC_BY_DIR((b>>4)&3); + + if (v->u.special.unk2 < (b & 7)) { + v->u.special.unk2 = 0; + v->u.special.unk0++; + if (_effecttick8_data[v->u.special.unk0] == 0xFF) { + EndVehicleMove(v); + DeleteVehicle(v); + return; + } + } + VehiclePositionChanged(v); + EndVehicleMove(v); + } +} + +static void EffectInit_9(Vehicle *v) +{ + v->cur_image = 4751; + v->spritenum = 0; + v->progress = 0; +} + +#define MK(x,y,z,i) (x+4)+(y+4)*16,(z+4)+i*16 + +/* -1,0,1,2 = 2*/ +/* -1,0,1 = 2*/ +/* */ +static const byte _effecttick9_data1[] = { + MK(0,0,1,0), + MK(1,0,1,1), + MK(0,0,1,0), + MK(1,0,1,2), + 0x81, +}; + + +static const byte _effecttick9_data2[] = { + MK(0,0,1,0), + MK(-1,0,1,1), + MK(0,0,1,0), + MK(-1,0,1,2), + 0x81, +}; + +static const byte _effecttick9_data3[] = { + MK(0,0,1,0), + MK(0,1,1,1), + MK(0,0,1,0), + MK(0,1,1,2), + 0x81, +}; + +static const byte _effecttick9_data4[] = { + MK(0,0,1,0), + MK(0,-1,1,1), + MK(0,0,1,0), + MK(0,-1,1,2), + 0x81, +}; + +static const byte _effecttick9_data5[] = { + MK(0,0,1,2), + MK(0,0,1,7), + MK(0,0,1,8), + MK(0,0,1,9), + 0x80, +}; + +static const byte _effecttick9_data6[] = { + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(0,0,1,0), + MK(0,0,1,2), + MK(0,0,1,0), + MK(0,0,1,1), + MK(2,1,3,0), + MK(1,1,3,1), + MK(2,1,3,0), + MK(1,1,3,2), + MK(2,1,3,0), + MK(1,1,3,1), + MK(2,1,3,0), + MK(1,0,1,2), + MK(0,0,1,0), + MK(1,0,1,1), + MK(0,0,1,0), + MK(1,0,1,2), + MK(0,0,1,0), + MK(1,0,1,1), + MK(0,0,1,0), + MK(1,0,1,2), + 0x82,0, + MK(0,0,0,0xA), + MK(0,0,0,0xB), + MK(0,0,0,0xC), + MK(0,0,0,0xD), + MK(0,0,0,0xE), + 0x80 +}; +#undef MK + +static const byte * const _effecttick9_data[6] = { + _effecttick9_data1, + _effecttick9_data2, + _effecttick9_data3, + _effecttick9_data4, + _effecttick9_data5, + _effecttick9_data6, +}; + +static void EffectTick_9(Vehicle *v) +{ + int et; + const byte *b; + + if (((++v->progress)&3) != 0) + return; + + BeginVehicleMove(v); + + et = v->engine_type + 1; + + if (v->spritenum == 0) { + if (++v->cur_image < 4754) { + VehiclePositionChanged(v); + EndVehicleMove(v); + return; + } + if (v->u.special.unk2 != 0) { + v->spritenum = (byte)((Random()&3)+1); + } else { + v->spritenum = 6; + } + et = 0; + } + +again: + v->engine_type = et; + b = &_effecttick9_data[v->spritenum - 1][et*2]; + + if (*b == 0x80) { + EndVehicleMove(v); + DeleteVehicle(v); + return; + } + + if (*b == 0x81) { + if (v->z_pos > 180 || CHANCE16(1,96)) { + v->spritenum = 5; + SndPlayVehicleFx(0x2F, v); + } + et = 0; + goto again; + } + + if (*b == 0x82) { + uint tile; + + et++; + SndPlayVehicleFx(0x31, v); + + tile = TILE_FROM_XY(v->x_pos, v->y_pos); + if (IS_TILETYPE(tile, MP_INDUSTRY) && + _map5[tile]==0xA2) { + AddAnimatedTile(tile); + } + goto again; + } + + v->x_pos += (b[0]&0xF) - 4; + v->y_pos += (b[0]>>4) - 4; + v->z_pos += (b[1]&0xF) - 4; + v->cur_image = 4748 + (b[1] >> 4); + + VehiclePositionChanged(v); + EndVehicleMove(v); +} + + +typedef void EffectInitProc(Vehicle *v); +typedef void EffectTickProc(Vehicle *v); + +static EffectInitProc * const _effect_init_procs[] = { + EffectInit_0, + EffectInit_1, + EffectInit_2, + EffectInit_3, + EffectInit_4, + EffectInit_5, + EffectInit_6, + EffectInit_7, + EffectInit_8, + EffectInit_9, +}; + +static EffectTickProc * const _effect_tick_procs[] = { + EffectTick_0, + EffectTick_1, + EffectTick_2, + EffectTick_3, + EffectTick_4, + EffectTick_5, + EffectTick_6, + EffectTick_7, + EffectTick_8, + EffectTick_9, +}; + + +Vehicle *CreateEffectVehicle(int x, int y, int z, int type) +{ + Vehicle *v; + + v = ForceAllocateSpecialVehicle(); + if (v != NULL) { + v->type = VEH_Special; + v->subtype = type; + v->x_pos = x; + v->y_pos = y; + v->z_pos = z; + v->z_height = v->sprite_width = v->sprite_height = 1; + v->x_offs = v->y_offs = 0; + v->tile = 0; + v->vehstatus = VS_UNCLICKABLE; + + _effect_init_procs[type](v); + + VehiclePositionChanged(v); + BeginVehicleMove(v); + EndVehicleMove(v); + } + return v; +} + +Vehicle *CreateEffectVehicleAbove(int x, int y, int z, int type) +{ + return CreateEffectVehicle(x, y, GetSlopeZ(x, y) + z, type); +} + +Vehicle *CreateEffectVehicleRel(Vehicle *v, int x, int y, int z, int type) +{ + return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type); +} + +void EffectVehicle_Tick(Vehicle *v) +{ + _effect_tick_procs[v->subtype](v); +} + +Vehicle *CheckClickOnVehicle(ViewPort *vp, int x, int y) +{ + Vehicle *found = NULL, *v; + uint dist, best_dist = (uint)-1; + + if ( (uint)(x -= vp->left) >= (uint)vp->width || + (uint)(y -= vp->top) >= (uint)vp->height) + return NULL; + + x = (x << vp->zoom) + vp->virtual_left; + y = (y << vp->zoom) + vp->virtual_top; + + FOR_ALL_VEHICLES(v) { + if (v->type != 0 && (v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0 && + x >= v->left_coord && x <= v->right_coord && + y >= v->top_coord && y <= v->bottom_coord) { + + dist = max( + myabs( ((v->left_coord + v->right_coord)>>1) - x ), + myabs( ((v->top_coord + v->bottom_coord)>>1) - y ) + ); + + if (dist < best_dist) { + found = v; + best_dist = dist; + } + } + } + + return found; +} + + +void DecreaseVehicleValue(Vehicle *v) +{ + v->value -= v->value >> 8; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); +} + +static const byte _breakdown_chance[64] = { + 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 11, 11, + 12, 13, 13, 13, 13, 14, 15, 16, + 17, 19, 21, 25, 28, 31, 34, 37, + 40, 44, 48, 52, 56, 60, 64, 68, + 72, 80, 90, 100, 110, 120, 130, 140, + 150, 170, 190, 210, 230, 250, 250, 250, +}; + +void CheckVehicleBreakdown(Vehicle *v) +{ + int rel, rel_old; + uint32 r; + int chance; + + /* decrease reliability */ + v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0); + if ((rel_old >> 8) != (rel >> 8)) + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) != 0 || + v->cur_speed < 5 || _game_mode == GM_MENU) + return; + + r = Random(); + + /* increase chance of failure */ + chance = v->breakdown_chance + 1; + if (CHANCE16I(1,25,r)) chance += 25; + v->breakdown_chance = min(255, chance); + + /* calculate reliability value to use in comparison */ + rel = v->reliability; + if (v->type == VEH_Ship) rel += 0x6666; + + /* disabled breakdowns? */ + if (_opt.diff.vehicle_breakdowns < 1) + return; + + /* reduced breakdowns? */ + if (_opt.diff.vehicle_breakdowns == 1) rel += 0x6666; + + /* check if to break down */ + if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) { + v->breakdown_ctr = (byte)(((r >> 16) & 0x3F) + 0x3F); + v->breakdown_delay = (byte)(((r >> 24) & 0x7F) | 0x80); + v->breakdown_chance = 0; + } +} + +static const StringID _vehicle_type_names[4] = { + STR_019F_TRAIN, + STR_019C_ROAD_VEHICLE, + STR_019E_SHIP, + STR_019D_AIRCRAFT, +}; + +static void ShowVehicleGettingOld(Vehicle *v, StringID msg) +{ + if (v->owner != _local_player) + return; + + SET_DPARAM16(0, _vehicle_type_names[v->type - 0x10]); + SET_DPARAM16(1, v->unitnumber); + AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); +} + +void AgeVehicle(Vehicle *v) +{ + int age; + + if (v->age < 65535) + v->age++; + + age = v->age - v->max_age; + if (age == 366*0 || age == 366*1 || age == 366*2 || age == 366*3 || age == 366*4) + v->reliability_spd_dec <<= 1; + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + + if (age == -366) { + ShowVehicleGettingOld(v, STR_01A0_IS_GETTING_OLD); + } else if (age == 0) { + ShowVehicleGettingOld(v, STR_01A1_IS_GETTING_VERY_OLD); + } else if (age == 366*1 || age == 366*2 || age == 366*3 || age == 366*4 || age == 366*5) { + ShowVehicleGettingOld(v, STR_01A2_IS_GETTING_VERY_OLD_AND); + } +} + +void MaybeRenewVehicle(Vehicle *v, int32 build_cost) +{ + Engine *e; + + // When automatically renewing a vehicle we want to prevent the + // "getting old" messages so we renew it if it won't enter the + // depot during the next service sooner than half a year before + // the vehicle getting old (that's one year before it reaches + // the max_age, see AgeVehicle). + if (!(_patches.autorenew && v->max_age - v->age < 366 + 183 + v->service_interval)) + return; + + e = &_engines[v->engine_type]; + v->reliability = e->reliability; + v->reliability_spd_dec = e->reliability_spd_dec; + v->age = 0; + + v->date_of_last_service = _date; + v->build_year = _cur_year; + + SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); + SubtractMoneyFromPlayer(build_cost - v->value); + v->value = build_cost; + + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); +} + + +int32 CmdNameVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + Vehicle *v; + StringID str; + + v = &_vehicles[p1]; + + if (!CheckOwnership(v->owner)) + return CMD_ERROR; + + str = AllocateName((byte*)_decode_parameters, 2); + if (str == 0) + return CMD_ERROR; + + if (flags & DC_EXEC) { + StringID old_str = v->string_id; + v->string_id = str; + DeleteName(old_str); + MarkWholeScreenDirty(); + } else { + DeleteName(str); + } + + return 0; +} + + + +static Rect _old_vehicle_coords; + +void BeginVehicleMove(Vehicle *v) { + _old_vehicle_coords.left = v->left_coord; + _old_vehicle_coords.top = v->top_coord; + _old_vehicle_coords.right = v->right_coord; + _old_vehicle_coords.bottom = v->bottom_coord; +} + +void EndVehicleMove(Vehicle *v) +{ + MarkAllViewportsDirty( + min(_old_vehicle_coords.left,v->left_coord), + min(_old_vehicle_coords.top,v->top_coord), + max(_old_vehicle_coords.right,v->right_coord)+1, + max(_old_vehicle_coords.bottom,v->bottom_coord)+1 + ); +} + +void InvalidateVehicleOrderWidget(Vehicle *v) +{ + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); + InvalidateWindowWidget(WC_VEHICLE_ORDERS, v->index, 2); +} + +/* returns true if staying in the same tile */ +bool GetNewVehiclePos(Vehicle *v, GetNewVehiclePosResult *gp) +{ + static const int8 _delta_coord[16] = { + -1,-1,-1, 0, 1, 1, 1, 0, /* x */ + -1, 0, 1, 1, 1, 0,-1,-1, /* y */ + }; + + int x = v->x_pos + _delta_coord[v->direction]; + int y = v->y_pos + _delta_coord[v->direction + 8]; + + gp->x = x; + gp->y = y; + gp->old_tile = v->tile; + gp->new_tile = TILE_FROM_XY(x,y); + return gp->old_tile == gp->new_tile; +} + +static const byte _new_direction_table[9] = { + 0, 7, 6, + 1, 3, 5, + 2, 3, 4, +}; + +byte GetDirectionTowards(Vehicle *v, int x, int y) +{ + byte dirdiff, dir; + int i = 0; + + if (y >= v->y_pos) { + if (y != v->y_pos) i+=3; + i+=3; + } + + if (x >= v->x_pos) { + if (x != v->x_pos) i++; + i++; + } + + dir = v->direction; + + dirdiff = _new_direction_table[i] - dir; + if (dirdiff == 0) + return dir; + return (dir+((dirdiff&7)<5?1:-1)) & 7; +} + +uint32 VehicleEnterTile(Vehicle *v, uint tile, int x, int y) +{ + uint old_tile = v->tile; + uint32 result = _tile_type_procs[GET_TILETYPE(tile)]->vehicle_enter_tile_proc(v, tile, x, y); + + if (!(result & 8) && old_tile != tile) { + VehicleLeaveTileProc *proc = _tile_type_procs[GET_TILETYPE(old_tile)]->vehicle_leave_tile_proc; + if (proc != NULL) + proc(v, old_tile, x, y); + } + return result; +} + +uint GetFreeUnitNumber(byte type) +{ + uint unit_num = 0; + Vehicle *u; + +restart: + unit_num++; + FOR_ALL_VEHICLES(u) { + if (u->type == type && u->owner == _current_player && + unit_num == u->unitnumber) + goto restart; + } + return unit_num; +} + + +// Save and load of vehicles +const byte _common_veh_desc[] = { + SLE_VAR(Vehicle,subtype, SLE_UINT8), + + SLE_VAR(Vehicle,next_in_chain_old, SLE_UINT16), + SLE_VAR(Vehicle,string_id, SLE_STRINGID), + SLE_VAR(Vehicle,unitnumber, SLE_UINT8), + SLE_VAR(Vehicle,owner, SLE_UINT8), + SLE_VAR(Vehicle,tile, SLE_UINT16), + SLE_VAR(Vehicle,dest_tile, SLE_UINT16), + + SLE_VAR(Vehicle,x_pos, SLE_INT16), + SLE_VAR(Vehicle,y_pos, SLE_INT16), + SLE_VAR(Vehicle,z_pos, SLE_UINT8), + SLE_VAR(Vehicle,direction, SLE_UINT8), + + SLE_VAR(Vehicle,cur_image, SLE_UINT16), + SLE_VAR(Vehicle,spritenum, SLE_UINT8), + SLE_VAR(Vehicle,sprite_width, SLE_UINT8), + SLE_VAR(Vehicle,sprite_height, SLE_UINT8), + SLE_VAR(Vehicle,z_height, SLE_UINT8), + SLE_VAR(Vehicle,x_offs, SLE_INT8), + SLE_VAR(Vehicle,y_offs, SLE_INT8), + SLE_VAR(Vehicle,engine_type, SLE_UINT16), + SLE_VAR(Vehicle,max_speed, SLE_UINT16), + SLE_VAR(Vehicle,cur_speed, SLE_UINT16), + SLE_VAR(Vehicle,subspeed, SLE_UINT8), + SLE_VAR(Vehicle,acceleration, SLE_UINT8), + SLE_VAR(Vehicle,progress, SLE_UINT8), + + SLE_VAR(Vehicle,vehstatus, SLE_UINT8), + SLE_VAR(Vehicle,last_station_visited,SLE_UINT8), + + SLE_VAR(Vehicle,cargo_type, SLE_UINT8), + SLE_VAR(Vehicle,cargo_days, SLE_UINT8), + SLE_VAR(Vehicle,cargo_source, SLE_UINT8), + SLE_VAR(Vehicle,cargo_cap, SLE_UINT16), + SLE_VAR(Vehicle,cargo_count, SLE_UINT16), + + SLE_VAR(Vehicle,day_counter, SLE_UINT8), + SLE_VAR(Vehicle,tick_counter, SLE_UINT8), + + SLE_VAR(Vehicle,cur_order_index, SLE_UINT8), + SLE_VAR(Vehicle,num_orders, SLE_UINT8), + SLE_VAR(Vehicle,next_order, SLE_UINT8), + SLE_VAR(Vehicle,next_order_param, SLE_UINT8), + SLE_REF(Vehicle,schedule_ptr, REF_SCHEDULE), + + SLE_VAR(Vehicle,age, SLE_UINT16), + SLE_VAR(Vehicle,max_age, SLE_UINT16), + SLE_VAR(Vehicle,date_of_last_service,SLE_UINT16), + SLE_VAR(Vehicle,service_interval, SLE_UINT16), + SLE_VAR(Vehicle,reliability, SLE_UINT16), + SLE_VAR(Vehicle,reliability_spd_dec,SLE_UINT16), + SLE_VAR(Vehicle,breakdown_ctr, SLE_UINT8), + SLE_VAR(Vehicle,breakdown_delay, SLE_UINT8), + SLE_VAR(Vehicle,breakdowns_since_last_service, SLE_UINT8), + SLE_VAR(Vehicle,breakdown_chance, SLE_UINT8), + SLE_VAR(Vehicle,build_year, SLE_UINT8), + + SLE_VAR(Vehicle,load_unload_time_rem, SLE_UINT16), + + SLE_VAR(Vehicle,profit_this_year, SLE_INT32), + SLE_VAR(Vehicle,profit_last_year, SLE_INT32), + SLE_VAR(Vehicle,value, SLE_UINT32), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + + +static const byte _train_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Train, 0), // Train type. VEH_Train in mem, 0 in file. + SLE_INCLUDEX(0, INC_VEHICLE_COMMON), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRail,crash_anim_pos), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRail,force_proceed), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRail,railtype), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRail,track), SLE_UINT8), + + SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,flags), SLE_UINT8, 2, 255), + SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,days_since_order_progr), SLE_UINT16, 2, 255), + + // reserve extra space in savegame here. (currently 13 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 13, 2, 255), + + SLE_END() +}; + +static const byte _roadveh_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Road, 1), // Road type. VEH_Road in mem, 1 in file. + SLE_INCLUDEX(0, INC_VEHICLE_COMMON), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,state), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,frame), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,unk2), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,overtaking), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,overtaking_ctr),SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,crashed_ctr), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,reverse_ctr), SLE_UINT8), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + +static const byte _ship_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Ship, 2), // Ship type. VEH_Ship in mem, 2 in file. + SLE_INCLUDEX(0, INC_VEHICLE_COMMON), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleShip,state), SLE_UINT8), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + +static const byte _aircraft_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Aircraft, 3), // Aircraft type. VEH_Aircraft in mem, 3 in file. + SLE_INCLUDEX(0, INC_VEHICLE_COMMON), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleAir,crashed_counter), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleAir,pos), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleAir,targetairport), SLE_UINT8), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleAir,state), SLE_UINT8), + + SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleAir,previous_pos), SLE_UINT8, 2, 255), + + // reserve extra space in savegame here. (currently 15 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 15, 2, 255), + + SLE_END() +}; + +static const byte _special_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Special, 4), + + SLE_VAR(Vehicle,subtype, SLE_UINT8), + + SLE_VAR(Vehicle,tile, SLE_UINT16), + + SLE_VAR(Vehicle,x_pos, SLE_INT16), + SLE_VAR(Vehicle,y_pos, SLE_INT16), + SLE_VAR(Vehicle,z_pos, SLE_UINT8), + + SLE_VAR(Vehicle,cur_image, SLE_UINT16), + SLE_VAR(Vehicle,sprite_width, SLE_UINT8), + SLE_VAR(Vehicle,sprite_height, SLE_UINT8), + SLE_VAR(Vehicle,z_height, SLE_UINT8), + SLE_VAR(Vehicle,x_offs, SLE_INT8), + SLE_VAR(Vehicle,y_offs, SLE_INT8), + SLE_VAR(Vehicle,progress, SLE_UINT8), + SLE_VAR(Vehicle,vehstatus, SLE_UINT8), + + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleSpecial,unk0), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleSpecial,unk2), SLE_UINT8), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + +static const byte _disaster_desc[] = { + SLE_WRITEBYTE(Vehicle,type,VEH_Disaster, 5), + + SLE_VAR(Vehicle,next_in_chain_old,SLE_UINT16), + + SLE_VAR(Vehicle,subtype, SLE_UINT8), + SLE_VAR(Vehicle,tile, SLE_UINT16), + SLE_VAR(Vehicle,dest_tile, SLE_UINT16), + + SLE_VAR(Vehicle,x_pos, SLE_INT16), + SLE_VAR(Vehicle,y_pos, SLE_INT16), + SLE_VAR(Vehicle,z_pos, SLE_UINT8), + SLE_VAR(Vehicle,direction, SLE_UINT8), + + SLE_VAR(Vehicle,x_offs, SLE_INT8), + SLE_VAR(Vehicle,y_offs, SLE_INT8), + SLE_VAR(Vehicle,sprite_width, SLE_UINT8), + SLE_VAR(Vehicle,sprite_height, SLE_UINT8), + SLE_VAR(Vehicle,z_height, SLE_UINT8), + SLE_VAR(Vehicle,owner, SLE_UINT8), + SLE_VAR(Vehicle,vehstatus, SLE_UINT8), + SLE_VAR(Vehicle,next_order, SLE_UINT8), + + SLE_VAR(Vehicle,cur_image, SLE_UINT16), + SLE_VAR(Vehicle,age, SLE_UINT16), + + SLE_VAR(Vehicle,tick_counter, SLE_UINT8), + + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleDisaster,image_override), SLE_UINT16), + SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleDisaster,unk2), SLE_UINT16), + + // reserve extra space in savegame here. (currently 16 bytes) + SLE_CONDARR(NullStruct,null,SLE_FILE_U64 | SLE_VAR_NULL, 2, 2, 255), + + SLE_END() +}; + + +static const void *_veh_descs[] = { + _train_desc, + _roadveh_desc, + _ship_desc, + _aircraft_desc, + _special_desc, + _disaster_desc, +}; + +// Will be called when the vehicles need to be saved. +static void Save_VEHS() +{ + Vehicle *v; + // Write the vehicles + FOR_ALL_VEHICLES(v) { + if (v->type != 0) { + SlSetArrayIndex(v->index); + v->next_in_chain_old = v->next ? v->next->index : INVALID_VEHICLE; + SlObject(v, _veh_descs[v->type - 0x10]); + } + } +} + +// Will be called when vehicles need to be loaded. +static void Load_VEHS() +{ + int index; + Vehicle *v; + + while ((index = SlIterateArray()) != -1) { + Vehicle *v = &_vehicles[index]; + v->next_in_chain_old = INVALID_VEHICLE; + SlObject(v, _veh_descs[SlReadByte()]); + v->next = v->next_in_chain_old == INVALID_VEHICLE ? NULL : &_vehicles[v->next_in_chain_old]; + if (v->type == VEH_Train) + v->u.rail.first_engine = 0xffff; + } + + // Iterate through trains and set first_engine appropriately. + FOR_ALL_VEHICLES(v) { + Vehicle *w; + + if (v->type != VEH_Train || v->subtype != 0) + continue; + + for (w = v->next; w; w = w->next) + w->u.rail.first_engine = v->engine_type; + } +} + +static const byte _depot_desc[] = { + SLE_VAR(Depot,xy, SLE_UINT16), + SLE_VAR(Depot,town_index, SLE_UINT16), + SLE_END() +}; + +static void Save_DEPT() +{ + Depot *d; + int i; + for(i=0,d=_depots; i!=lengthof(_depots); i++,d++) { + if (d->xy != 0) { + SlSetArrayIndex(i); + SlObject(d, _depot_desc); + } + } +} + +static void Load_DEPT() +{ + int index; + while ((index = SlIterateArray()) != -1) { + SlObject(&_depots[index], _depot_desc); + } +} + +static const byte _checkpoint_desc[] = { + SLE_VAR(Checkpoint,xy, SLE_UINT16), + SLE_VAR(Checkpoint,town_or_string, SLE_UINT16), + SLE_VAR(Checkpoint,deleted, SLE_UINT8), + + SLE_CONDVAR(Checkpoint, build_date, SLE_UINT16, 3, 255), + SLE_CONDVAR(Checkpoint, stat_id, SLE_UINT8, 3, 255), + + SLE_END() +}; + +static void Save_CHKP() +{ + Checkpoint *cp; + int i; + for(i=0,cp=_checkpoints; i!=lengthof(_checkpoints); i++,cp++) { + if (cp->xy != 0) { + SlSetArrayIndex(i); + SlObject(cp, _checkpoint_desc); + } + } +} + +static void Load_CHKP() +{ + int index; + while ((index = SlIterateArray()) != -1) { + SlObject(&_checkpoints[index], _checkpoint_desc); + } +} + + +static void Save_ORDR() +{ + uint len = _ptr_to_next_order - _order_array; + SlArray(_order_array, len, SLE_UINT16); +} + +static void Load_ORDR() +{ + uint len = SlGetFieldLength() >> 1; + _ptr_to_next_order = _order_array + len; + SlArray(_order_array, len, SLE_UINT16); +} + +const ChunkHandler _veh_chunk_handlers[] = { + { 'VEHS', Save_VEHS, Load_VEHS, CH_SPARSE_ARRAY}, + { 'ORDR', Save_ORDR, Load_ORDR, CH_RIFF}, + { 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY}, + { 'CHKP', Save_CHKP, Load_CHKP, CH_ARRAY | CH_LAST}, +}; + + diff --git a/vehicle.h b/vehicle.h new file mode 100644 --- /dev/null +++ b/vehicle.h @@ -0,0 +1,416 @@ +#ifndef VEHICLE_H +#define VEHICLE_H + +typedef struct VehicleRail { + uint16 last_speed; // NOSAVE: only used in UI + uint16 crash_anim_pos; + uint16 days_since_order_progr; + + uint16 cached_weight; // cached power and weight for the vehicle. + uint32 cached_power; // no need to save those, they are recomputed on load. + + // NOSAVE: for wagon override - id of the first engine in train + // 0xffff == not in train + uint16 first_engine; + + byte track; + byte force_proceed; + byte railtype; + + byte flags; +} VehicleRail; + +enum { + VRF_REVERSING = 1, + + // used to calculate if train is going up or down + VRF_GOINGUP = 2, + VRF_GOINGDOWN = 4, +}; + +typedef struct VehicleAir { + uint16 crashed_counter; + byte pos; + byte previous_pos; + byte targetairport; + byte state; +} VehicleAir; + +typedef struct VehicleRoad { + byte state; + byte frame; + uint16 unk2; + byte overtaking; + byte overtaking_ctr; + uint16 crashed_ctr; + byte reverse_ctr; +} VehicleRoad; + +typedef struct VehicleSpecial { + uint16 unk0; + byte unk2; +} VehicleSpecial; + +typedef struct VehicleDisaster { + uint16 image_override; + uint16 unk2; +} VehicleDisaster; + +typedef struct VehicleShip { + byte state; +} VehicleShip; + +// not used ATM +struct WorldSprite { + struct WorldSprite *next; // next sprite in hash chain + uint16 image; // sprite number for this vehicle + + // screen coordinates + int16 left, top, right, bottom; + + // world coordinates + int16 x; + int16 y; + byte z; + + int8 x_offs; // x offset for vehicle sprite + int8 y_offs; // y offset for vehicle sprite + + byte width; // width of vehicle sprite + byte height; // height of vehicle sprite + byte depth; // depth of vehicle sprite + + byte flags; // draw flags +}; + +struct Vehicle { + byte type; // type, ie roadven,train,ship,aircraft,special + byte subtype; // subtype + + uint16 index; // NOSAVE: Index in vehicle array + uint16 next_in_chain_old; // Next vehicle index for chained vehicles + + Vehicle *next; // next + + StringID string_id; // Displayed string + + byte unitnumber; // unit number, for display purposes only + byte owner; // which player owns the vehicle? + + TileIndex tile; // Current tile index + TileIndex dest_tile; // Heading for this tile + + int16 x_pos; // coordinates + int16 y_pos; + byte z_pos; + byte direction; // facing + + uint16 cur_image; // sprite number for this vehicle + byte spritenum; // currently displayed sprite index + // 0xfd == custom sprite, 0xfe == custom second head sprite + // 0xff == reserved for another custom sprite + byte sprite_width;// width of vehicle sprite + byte sprite_height;// height of vehicle sprite + byte z_height; // z-height of vehicle sprite + int8 x_offs; // x offset for vehicle sprite + int8 y_offs; // y offset for vehicle sprite + uint16 engine_type; + + uint16 max_speed; // maximum speed + uint16 cur_speed; // current speed + byte subspeed; // fractional speed + byte acceleration; // used by train & aircraft + byte progress; + + byte vehstatus; // Status + byte last_station_visited; + + byte cargo_type; // type of cargo this vehicle is carrying + byte cargo_days; // how many days have the pieces been in transit + byte cargo_source;// source of cargo + uint16 cargo_cap; // total capacity + uint16 cargo_count;// how many pieces are used + + byte day_counter; // increased by one for each day + byte tick_counter;// increased by one for each tick + + // related to the current order + byte cur_order_index; + byte num_orders; + byte next_order; + byte next_order_param; + uint16 *schedule_ptr; + + // Boundaries for the current position in the world and a next hash link. + // NOSAVE: All of those can be updated with VehiclePositionChanged() + int16 left_coord, top_coord, right_coord, bottom_coord; + uint16 next_hash; + + // Related to age and service time + uint16 age; // Age in days + uint16 max_age; // Maximum age + uint16 date_of_last_service; + uint16 service_interval; + uint16 reliability; + uint16 reliability_spd_dec; + byte breakdown_ctr; + byte breakdown_delay; + byte breakdowns_since_last_service; + byte breakdown_chance; + byte build_year; + + uint16 load_unload_time_rem; + + int32 profit_this_year; + int32 profit_last_year; + uint32 value; + + union { + VehicleRail rail; + VehicleAir air; + VehicleRoad road; + VehicleSpecial special; + VehicleDisaster disaster; + VehicleShip ship; + } u; +}; + +#define is_custom_sprite(x) (x >= 0xfd) +#define is_custom_firsthead_sprite(x) (x == 0xfd) +#define is_custom_secondhead_sprite(x) (x == 0xfe) + +struct Depot { + TileIndex xy; + uint16 town_index; +}; + +// train checkpoint +struct Checkpoint { + TileIndex xy; + uint16 town_or_string; // if this is 0xC000, it's a string id, otherwise a town. + ViewportSign sign; + uint16 build_date; + byte stat_id; + byte deleted; // this is a delete counter. when it reaches 0, the checkpoint struct is deleted. +}; + +enum { + VEH_Train = 0x10, + VEH_Road = 0x11, + VEH_Ship = 0x12, + VEH_Aircraft = 0x13, + VEH_Special = 0x14, + VEH_Disaster = 0x15, +}; + +/* Order types */ +enum { + OT_NOTHING = 0, + OT_GOTO_STATION = 1, + OT_GOTO_DEPOT = 2, + OT_LOADING = 3, + OT_LEAVESTATION = 4, + OT_DUMMY = 5, + OT_GOTO_CHECKPOINT = 6, + + OT_MASK = 0x1F, +}; + +/* Order flags */ +enum { + OF_UNLOAD = 0x20, + OF_FULL_LOAD = 0x40, // Also used when to force an aircraft into a depot. + OF_NON_STOP = 0x80, + OF_MASK = 0xE0, +}; + + +enum VehStatus { + VS_HIDDEN = 1, + VS_STOPPED = 2, + VS_UNCLICKABLE = 4, + VS_DEFPAL = 0x8, + VS_TRAIN_SLOWING = 0x10, + VS_DISASTER = 0x20, + VS_AIRCRAFT_BROKEN = 0x40, + VS_CRASHED = 0x80, +}; + + + +/* Effect vehicle types */ +enum { + EV_INDUSTRYSMOKE = 0, + EV_STEAM_SMOKE = 1, + + EV_SMOKE_1 = 2, + EV_SMOKE_2 = 3, + EV_SMOKE_3 = 4, + + EV_CRASHED_SMOKE = 5, + EV_BREAKDOWN_SMOKE = 6, + + EV_DEMOLISH = 7, + EV_ROADWORK = 8, + + EV_INDUSTRY_SMOKE = 9, + +}; + +typedef void VehicleTickProc(Vehicle *v); +typedef void *VehicleFromPosProc(Vehicle *v, void *data); + +typedef struct { + byte orderindex; + uint16 order[41]; + uint16 service_interval; + char name[32]; +} BackuppedOrders; + +void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order); +void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order); +Vehicle *AllocateVehicle(); +Vehicle *ForceAllocateVehicle(); +Vehicle *ForceAllocateSpecialVehicle(); +void UpdateVehiclePosHash(Vehicle *v, int x, int y); +void InitializeVehicles(); +void VehiclePositionChanged(Vehicle *v); +void AfterLoadVehicles(); +Vehicle *GetLastVehicleInChain(Vehicle *v); +Vehicle *GetPrevVehicleInChain(Vehicle *v); +Vehicle *GetFirstVehicleInChain(Vehicle *v); +int CountVehiclesInChain(Vehicle *v); +void DeleteVehicle(Vehicle *v); +void DeleteVehicleChain(Vehicle *v); +void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc); +void CallVehicleTicks(); +void DeleteVehicleSchedule(Vehicle *v); +Vehicle *IsScheduleShared(Vehicle *v); + +Depot *AllocateDepot(); +Checkpoint *AllocateCheckpoint(); +void UpdateCheckpointSign(Checkpoint *cp); +void RedrawCheckpointSign(Checkpoint *cp); + +void InitializeTrains(); +bool IsTrainDepotTile(TileIndex tile); +bool IsRoadDepotTile(TileIndex tile); + +bool CanFillVehicle(Vehicle *v); + +void ViewportAddVehicles(DrawPixelInfo *dpi); + +void TrainEnterDepot(Vehicle *v, uint tile); + +/* train_cmd.h */ +int GetTrainImage(Vehicle *v, byte direction); +int GetAircraftImage(Vehicle *v, byte direction); +int GetRoadVehImage(Vehicle *v, byte direction); +int GetShipImage(Vehicle *v, byte direction); + +Vehicle *CreateEffectVehicle(int x, int y, int z, int type); +Vehicle *CreateEffectVehicleAbove(int x, int y, int z, int type); +Vehicle *CreateEffectVehicleRel(Vehicle *v, int x, int y, int z, int type); + +uint32 VehicleEnterTile(Vehicle *v, uint tile, int x, int y); + +void VehicleInTheWayErrMsg(Vehicle *v); +Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z); +uint GetVehicleOutOfTunnelTile(Vehicle *v); + +bool UpdateSignalsOnSegment(uint tile, byte direction); +void SetSignalsOnBothDir(uint tile, byte track); + +Vehicle *CheckClickOnVehicle(ViewPort *vp, int x, int y); +//uint GetVehicleWeight(Vehicle *v); + +void DecreaseVehicleValue(Vehicle *v); +void CheckVehicleBreakdown(Vehicle *v); +void AgeVehicle(Vehicle *v); +void MaybeRenewVehicle(Vehicle *v, int32 build_cost); + +void DeleteCommandFromVehicleSchedule(uint cmd); + +void BeginVehicleMove(Vehicle *v); +void EndVehicleMove(Vehicle *v); + +bool IsAircraftHangarTile(TileIndex tile); +void ShowAircraftViewWindow(Vehicle *v); + +void InvalidateVehicleOrderWidget(Vehicle *v); + +bool IsShipDepotTile(TileIndex tile); +uint GetFreeUnitNumber(byte type); + +int LoadUnloadVehicle(Vehicle *v); +int GetDepotByTile(uint tile); +uint GetCheckpointByTile(uint tile); + +void DoDeleteDepot(uint tile); + +void UpdateTrainAcceleration(Vehicle *v); +int32 GetTrainRunningCost(Vehicle *v); + +int CheckStoppedInDepot(Vehicle *v); + +int ScheduleHasDepotOrders(uint16 *schedule); + +typedef struct GetNewVehiclePosResult { + int x,y; + uint old_tile; + uint new_tile; +} GetNewVehiclePosResult; + +/* returns true if staying in the same tile */ +bool GetNewVehiclePos(Vehicle *v, GetNewVehiclePosResult *gp); +byte GetDirectionTowards(Vehicle *v, int x, int y); + +#define BEGIN_ENUM_WAGONS(v) do { +#define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL); + +#define FOR_ALL_VEHICLES(v) for(v=_vehicles; v != endof(_vehicles); v++) + +/* vehicle.c */ +enum { + NUM_NORMAL_VEHICLES = 2048, + NUM_SPECIAL_VEHICLES = 512, + NUM_VEHICLES = NUM_NORMAL_VEHICLES + NUM_SPECIAL_VEHICLES +}; + +VARDEF Vehicle _vehicles[NUM_VEHICLES]; + +VARDEF uint16 _order_array[5000]; +VARDEF uint16 *_ptr_to_next_order; + +VARDEF Depot _depots[255]; + +// 128 checkpoints +VARDEF Checkpoint _checkpoints[128]; + +// NOSAVE: Can be regenerated by inspecting the vehicles. +VARDEF VehicleID _vehicle_position_hash[0x1000]; + +// NOSAVE: Return values from various commands. +VARDEF VehicleID _new_train_id; +VARDEF VehicleID _new_wagon_id; +VARDEF VehicleID _new_aircraft_id; +VARDEF VehicleID _new_ship_id; +VARDEF VehicleID _new_roadveh_id; +VARDEF uint16 _aircraft_refit_capacity; +VARDEF byte _cmd_build_rail_veh_score; +VARDEF byte _cmd_build_rail_veh_var1; + +// NOSAVE: Player specific info +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; +VARDEF TileIndex _backup_orders_tile; +VARDEF BackuppedOrders _backup_orders_data[1]; + +// for each player, for each vehicle type, keep a list of the vehicles. +//VARDEF Vehicle *_vehicle_arr[8][4]; + +#define INVALID_VEHICLE 0xffff + +#endif /* VEHICLE_H */ diff --git a/viewport.c b/viewport.c new file mode 100644 --- /dev/null +++ b/viewport.c @@ -0,0 +1,2040 @@ +#include "stdafx.h" +#include "ttd.h" +#include "viewport.h" +#include "window.h" +#include "vehicle.h" +#include "station.h" +#include "gfx.h" +#include "town.h" + +#define VIEWPORT_DRAW_MEM (65536) + +static bool _added_tile_sprite; +static bool _offset_ground_sprites; + +typedef struct StringSpriteToDraw { + uint16 string; + uint16 color; + struct StringSpriteToDraw *next; + int16 x; + int16 y; + uint32 params[2]; + uint16 width; +} StringSpriteToDraw; + +typedef struct TileSpriteToDraw { + uint32 image; + struct TileSpriteToDraw *next; + int16 x, y; + byte z; +} TileSpriteToDraw; + +typedef struct ChildScreenSpriteToDraw { + uint32 image; + int16 x,y; + struct ChildScreenSpriteToDraw *next; +} ChildScreenSpriteToDraw; + +typedef struct ParentSpriteToDraw { + uint32 image; + int16 left, top, right, bottom; + int16 tile_x, tile_y; + int16 tile_right, tile_bottom; + ChildScreenSpriteToDraw *child; + byte unk16; + byte tile_z; + byte tile_z_bottom; +} ParentSpriteToDraw; + +typedef struct ViewportDrawer { + DrawPixelInfo dpi; + + byte *spritelist_mem, *eof_spritelist_mem; + + StringSpriteToDraw **last_string, *first_string; + TileSpriteToDraw **last_tile, *first_tile; + + ChildScreenSpriteToDraw **last_child; + + ParentSpriteToDraw **parent_list; + + byte combine_sprites; + + int offs_x, offs_y; // used when drawing ground sprites relative + bool ground_child; +} ViewportDrawer; + +static ViewportDrawer *_cur_vd; + +TileHighlightData * const _thd_ptr = &_thd; +static TileInfo *_cur_ti; + + +Point MapXYZToViewport(ViewPort *vp, uint x, uint y, uint z) +{ + Point p = RemapCoords(x, y, z); + p.x -= (vp->virtual_width>>1); + p.y -= (vp->virtual_height>>1); + return p; +} + +void AssignWindowViewport(Window *w, int x, int y, + int width, int height, uint32 follow_flags, byte zoom) +{ + ViewPort *vp; + Point pt; + byte z; + uint32 bit; + + for(vp=_viewports,bit=1; ; vp++, bit<<=1) { + assert(vp!=endof(_viewports)); + if (vp->width == 0) + break; + } + _active_viewports |= bit; + + vp->left = x + w->left; + vp->top = y + w->top; + vp->width = width; + vp->height = height; + + vp->zoom = zoom; + + vp->virtual_width = width << zoom; + vp->virtual_height = height << zoom; + + if (follow_flags & 0x80000000) { + Vehicle *veh; + WP(w,vp_d).follow_vehicle = (VehicleID)(follow_flags & 0xFFFF); + veh = &_vehicles[WP(w,vp_d).follow_vehicle]; + pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); + } else { + int x = GET_TILE_X(follow_flags) * 16; + int y = GET_TILE_Y(follow_flags) * 16; + WP(w,vp_d).follow_vehicle = 0xFFFF; + z = GetSlopeZ(x,y); + pt = MapXYZToViewport(vp, x,y, z); + } + + WP(w,vp_d).scrollpos_x = pt.x; + WP(w,vp_d).scrollpos_y = pt.y; + w->viewport = vp; + vp->virtual_left = 0;//pt.x; + vp->virtual_top = 0;//pt.y; +} + +static Point _vp_move_offs; + +static void DoSetViewportPosition(Window *w, int left, int top, int width, int height) +{ + for (; w < _last_window; w++) { + if (left + width > w->left && + w->left+w->width > left && + top + height > w->top && + w->top+w->height > top) { + + if (left < w->left) { + DoSetViewportPosition(w, left, top, w->left - left, height); + DoSetViewportPosition(w, left + (w->left - left), top, width - (w->left - left), height); + return; + } + + if (left + width > w->left + w->width) { + DoSetViewportPosition(w, left, top, (w->left + w->width - left), height); + DoSetViewportPosition(w, left + (w->left + w->width - left), top, width - (w->left + w->width - left) , height); + return; + } + + if (top < w->top) { + DoSetViewportPosition(w, left, top, width, (w->top - top)); + DoSetViewportPosition(w, left, top + (w->top - top), width, height - (w->top - top)); + return; + } + + if (top + height > w->top + w->height) { + DoSetViewportPosition(w, left, top, width, (w->top + w->height - top)); + DoSetViewportPosition(w, left, top + (w->top + w->height - top), width , height - (w->top + w->height - top)); + return; + } + + return; + } + } + + { + int xo = _vp_move_offs.x; + int yo = _vp_move_offs.y; + + if (abs(xo) >= width || abs(yo) >= height) { + /* fully_outside */ + RedrawScreenRect(left, top, left+width, top+height); + return; + } + + GfxScroll(left, top, width, height, xo, yo); + + if (xo > 0) { + RedrawScreenRect(left, top, xo + left, top + height); + left += xo; + width -= xo; + } else if (xo < 0) { + RedrawScreenRect(left+width+xo, top, left+width, top + height); + width += xo; + } + + if (yo > 0) { + RedrawScreenRect(left, top, width+left, top + yo); + } else if (yo < 0) { + RedrawScreenRect(left, top + height + yo, width+left, top + height); + } + } +} + +void SetViewportPosition(Window *w, int x, int y) +{ + ViewPort *vp = w->viewport; + int old_left = vp->virtual_left; + int old_top = vp->virtual_top; + int i; + int left, top, width, height; + + vp->virtual_left = x; + vp->virtual_top = y; + + old_left >>= vp->zoom; + old_top >>= vp->zoom; + x >>= vp->zoom; + y >>= vp->zoom; + + old_left -= x; + old_top -= y; + + if (old_top == 0 && old_left == 0) + return; + + _vp_move_offs.x = old_left; + _vp_move_offs.y = old_top; + + left = vp->left; + top = vp->top; + width = vp->width; + height = vp->height; + + if (left < 0) { + width += left; + left = 0; + } + + if ( (i=(left + width - _screen.width)) >= 0) + width -= i; + + if (width > 0) { + if (top < 0) { + height += top; + top = 0; + } + + if ( (i=(top + height - _screen.height)) >= 0) { + height -= i; + } + + if (height > 0) + DoSetViewportPosition(w+1, left, top, width, height); + } +} + + +ViewPort *IsPtInWindowViewport(Window *w, int x, int y) +{ + ViewPort *vp = w->viewport; + if (vp != NULL && + IS_INT_INSIDE(x, vp->left, vp->left + vp->width) && + IS_INT_INSIDE(y, vp->top, vp->top + vp->height)) + return vp; + + return NULL; +} + +Point TranslateXYToTileCoord(ViewPort *vp, int x, int y) { + int z; + Point pt; + int a,b; + + if ( (uint)(x -= vp->left) >= (uint)vp->width || + (uint)(y -= vp->top) >= (uint)vp->height) { + Point pt = {-1, -1}; + return pt; + } + + x = ((x << vp->zoom) + vp->virtual_left) >> 2; + y = ((y << vp->zoom) + vp->virtual_top) >> 1; + +#if !defined(NEW_ROTATION) + a = y-x; + b = y+x; +#else + a = x+y; + b = x-y; +#endif + z = GetSlopeZ(a, b) >> 1; + z = GetSlopeZ(a+z, b+z) >> 1; + z = GetSlopeZ(a+z, b+z) >> 1; + z = GetSlopeZ(a+z, b+z) >> 1; + z = GetSlopeZ(a+z, b+z) >> 1; + + pt.x = a+z; + pt.y = b+z; + + if ((uint)pt.x >= TILE_X_MAX*16 || (uint)pt.y >= TILE_Y_MAX*16) { + pt.x = pt.y = -1; + } + + return pt; +} + +static Point GetTileFromScreenXY(int x, int y) +{ + Window *w; + ViewPort *vp; + Point pt; + + if ( (w = FindWindowFromPt(x, y)) != NULL && + (vp = IsPtInWindowViewport(w, x, y)) != NULL) + return TranslateXYToTileCoord(vp, x, y); + + pt.y = pt.x = -1; + return pt; +} + +Point GetTileBelowCursor() +{ + return GetTileFromScreenXY(_cursor.pos.x, _cursor.pos.y); +} + +Point GetTileZoomCenter(bool in) +{ + int x, y; + + if (in) { + x = (_cursor.pos.x >> 1) + (_screen.width >> 2); + y = (_cursor.pos.y >> 1) + (_screen.height >> 2); + } + else { + x = _screen.width - _cursor.pos.x; + y = _screen.height - _cursor.pos.y; + } + return GetTileFromScreenXY(x, y); +} + +void DrawGroundSpriteAt(uint32 image, int x, int y, byte z) +{ + ViewportDrawer *vd = _cur_vd; + TileSpriteToDraw *ts; + + assert( (image & 0x3fff) < NUM_SPRITES); + + ts = (TileSpriteToDraw*)vd->spritelist_mem; + if ((byte*)ts >= vd->eof_spritelist_mem) { + DEBUG(misc, 0) ("Out of sprite mem\n"); + return; + } + + vd->spritelist_mem += sizeof(TileSpriteToDraw); + + ts->image = image; + ts->next = NULL; + ts->x = x; + ts->y = y; + ts->z = z; + *vd->last_tile = ts; + vd->last_tile = &ts->next; +} + +void DrawGroundSprite(uint32 image) +{ + if (_offset_ground_sprites) { + // offset ground sprite because of foundation? + AddChildSpriteScreen(image, _cur_vd->offs_x, _cur_vd->offs_y); + } else { + _added_tile_sprite = true; + DrawGroundSpriteAt(image, _cur_ti->x, _cur_ti->y, _cur_ti->z); + } +} + + +void OffsetGroundSprite(int x, int y) +{ + _cur_vd->offs_x = x; + _cur_vd->offs_y = y; + _offset_ground_sprites = true; +} + +static void AddCombinedSprite(uint32 image, int x, int y, byte z) +{ + ViewportDrawer *vd = _cur_vd; + int t; + uint32 image_org = image; + const SpriteDimension *sd; + Point pt = RemapCoords(x, y, z); + + sd = GetSpriteDimension(image & 0x3FFF); + + if ((t = pt.x + sd->xoffs) >= vd->dpi.left + vd->dpi.width || + (t + sd->xsize) <= vd->dpi.left || + (t = pt.y + sd->yoffs) >= vd->dpi.top + vd->dpi.height || + (t + sd->ysize) <= vd->dpi.top) + return; + + AddChildSpriteScreen(image_org, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top); +} + + +void AddSortableSpriteToDraw(uint32 image, int x, int y, int w, int h, byte dz, byte z) +{ + ViewportDrawer *vd = _cur_vd; + ParentSpriteToDraw *ps; + const SpriteDimension *sd; + Point pt; + + assert( (image & 0x3fff) < NUM_SPRITES); + + if (vd->combine_sprites == 2) { + AddCombinedSprite(image, x, y, z); + return; + } + + vd->last_child = NULL; + + ps = (ParentSpriteToDraw*)vd->spritelist_mem; + if ((byte*)ps >= vd->eof_spritelist_mem) { + DEBUG(misc, 0) ("Out of sprite mem\n"); + return; + } + + ps->image = image; + ps->tile_x = x; + ps->tile_right = x + w - 1; + + ps->tile_y = y; + ps->tile_bottom = y + h - 1; + + ps->tile_z = z; + ps->tile_z_bottom = z + dz - 1; + + pt = RemapCoords(x, y, z); + + sd = GetSpriteDimension(image & 0x3FFF); + if ((ps->left = (pt.x += sd->xoffs)) >= vd->dpi.left + vd->dpi.width || + (ps->right = (pt.x + sd->xsize)) <= vd->dpi.left || + (ps->top = (pt.y += sd->yoffs)) >= vd->dpi.top + vd->dpi.height || + (ps->bottom = (pt.y + sd->ysize)) <= vd->dpi.top) { + return; + } + + ps->unk16 = 0; + ps->child = NULL; + vd->last_child = &ps->child; + + vd->spritelist_mem += sizeof(ParentSpriteToDraw); + *vd->parent_list++ = ps; + + if (vd->combine_sprites == 1) { + vd->combine_sprites = 2; + } +} + +void StartSpriteCombine() +{ + _cur_vd->combine_sprites = 1; +} + +void EndSpriteCombine() +{ + _cur_vd->combine_sprites = 0; +} + +void AddChildSpriteScreen(uint32 image, int x, int y) +{ + ViewportDrawer *vd = _cur_vd; + ChildScreenSpriteToDraw *cs; + + cs = (ChildScreenSpriteToDraw*) vd->spritelist_mem; + if ((byte*)cs >= vd->eof_spritelist_mem) { + DEBUG(misc,0) ("Out of sprite mem\n"); + return; + } + + if (vd->last_child == NULL) + return; + + *vd->last_child = cs; + vd->last_child = &cs->next; + + vd->spritelist_mem += sizeof(ChildScreenSpriteToDraw); + + cs->image = image; + cs->x = x; + cs->y = y; + cs->next = NULL; +} + +/* Returns a StringSpriteToDraw */ +void *AddStringToDraw(int x, int y, StringID string, uint32 params_1, uint32 params_2) +{ + ViewportDrawer *vd = _cur_vd; + StringSpriteToDraw *ss; + + ss = (StringSpriteToDraw*)vd->spritelist_mem; + if ((byte*)ss >= vd->eof_spritelist_mem) { + DEBUG(misc, 0) ("Out of sprite mem\n"); + return NULL; + } + + vd->spritelist_mem += sizeof(StringSpriteToDraw); + + ss->string = string; + ss->next = NULL; + ss->x = x; + ss->y = y; + ss->params[0] = params_1; + ss->params[1] = params_2; + ss->width = 0; + + *vd->last_string = ss; + vd->last_string = &ss->next; + + return ss; +} + +/* Debugging code */ + +#ifdef DEBUG_TILE_PUSH +static int _num_push; +static uint _pushed_tile[200]; +static int _pushed_track[200]; + +static uint _stored_tile[200]; +static int _stored_track[200]; +static int _num_stored; + +void dbg_store_path() +{ + memcpy(_stored_tile, _pushed_tile, sizeof(_stored_tile)); + memcpy(_stored_track, _pushed_track, sizeof(_stored_tile)); + _num_stored = _num_push; + MarkWholeScreenDirty(); +} + +void dbg_push_tile(uint tile, int track) +{ + _pushed_tile[_num_push] = tile; + _pushed_track[_num_push++] = track; + dbg_store_path(); +} + +void dbg_pop_tile() +{ + _num_push--; +} + +static const uint16 _dbg_track_sprite[] = { + 0x3F4, + 0x3F3, + 0x3F5, + 0x3F6, + 0x3F8, + 0x3F7, +}; + +int dbg_draw_pushed(const TileInfo *ti) +{ + int i; + if (ti->tile==0) + return 0; + for(i=0; i!=_num_stored; i++) + if (_stored_tile[i] == ti->tile) { + DrawGroundSpriteAt(_dbg_track_sprite[_stored_track[i]&7], ti->x, ti->y, ti->z); + } + return -1; +} + +#endif + +static void DrawSelectionSprite(uint32 image, const TileInfo *ti) +{ + if (_added_tile_sprite) { + DrawGroundSpriteAt(image, ti->x, ti->y, ti->z + 7); + } else { + AddSortableSpriteToDraw(image, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7); + } +} + +static bool IsPartOfAutoLine(int px, int py) +{ + const TileHighlightData *thd = _thd_ptr; + + px -= thd->selstart.x; + py -= thd->selstart.y; + + switch(thd->drawstyle) { + case HT_LINE | 0: return px == py || px == py + 16; + case HT_LINE | 1: return px == py || px == py - 16; + case HT_LINE | 2: return px == -py || px == -py + 16; + case HT_LINE | 3: return px == -py || px == -py - 16; + default: + NOT_REACHED(); + } + + /* useless, but avoids compiler warning this way */ + return 0; +} + +static void DrawTileSelection(const TileInfo *ti) +{ + uint32 image; + const TileHighlightData *thd = _thd_ptr; + +#ifdef DEBUG_TILE_PUSH + dbg_draw_pushed(ti); +#endif + + // Draw a red error square? + if (thd->redsq != 0 && thd->redsq == (TileIndex)ti->tile) { + DrawSelectionSprite(0x030382F0 | _tileh_to_sprite[ti->tileh], ti); + return; + } + + // no selection active? + if (thd->drawstyle == 0) + return; + + // Inside the inner area? + if (IS_INSIDE_1D(ti->x, thd->pos.x, thd->size.x) && IS_INSIDE_1D(ti->y, thd->pos.y, thd->size.y)) { + if (thd->drawstyle & HT_RECT) { + image = 0x2F0 + _tileh_to_sprite[ti->tileh]; + if (thd->make_square_red) image |= 0x3048000; + DrawSelectionSprite(image, ti); + } else if (thd->drawstyle & HT_POINT) { + // Figure out the Z coordinate for the single dot. + byte z = ti->z; + if (ti->tileh & 8) { + z += 8; + if (!(ti->tileh & 2) && (ti->tileh & 0x10)) { + z += 8; + } + } + DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? 0x306 : 0xFEE,ti->x, ti->y, z); + } else { + if (IsPartOfAutoLine(ti->x, ti->y)) { + image = 0x2F0 + _tileh_to_sprite[ti->tileh]; + if (thd->make_square_red) image |= 0x3048000; + DrawSelectionSprite(image, ti); + } + } + return; + } + + // Check if it's inside the outer area? + if (thd->outersize.x && + thd->size.x < thd->size.x + thd->outersize.x && + IS_INSIDE_1D(ti->x, thd->pos.x + thd->offs.x, thd->size.x + thd->outersize.x) && + IS_INSIDE_1D(ti->y, thd->pos.y + thd->offs.y, thd->size.y + thd->outersize.y)) { + // Draw a blue rect. + DrawSelectionSprite(0x30582F0 + _tileh_to_sprite[ti->tileh], ti); + return; + } +} + +void ViewportAddLandscape() +{ + ViewportDrawer *vd = _cur_vd; + int x, y, width, height; + TileInfo ti; + bool direction; + + _cur_ti = &ti; + + // Transform into tile coordinates and round to closest full tile +#if !defined(NEW_ROTATION) + x = ((vd->dpi.top >> 1) - (vd->dpi.left >> 2)) & ~0xF; + y = ((vd->dpi.top >> 1) + (vd->dpi.left >> 2) - 0x10) & ~0xF; +#else + x = ((vd->dpi.top >> 1) + (vd->dpi.left >> 2) - 0x10) & ~0xF; + y = ((vd->dpi.left >> 2) - (vd->dpi.top >> 1)) & ~0xF; +#endif + // determine size of area + { + Point pt = RemapCoords(x, y, 241); + width = (vd->dpi.left + vd->dpi.width - pt.x + 95) >> 6; + height = (vd->dpi.top + vd->dpi.height - pt.y) >> 5 << 1; + } + + assert(width > 0); + assert(height > 0); + + direction = false; + + do { + int width_cur = width; + int x_cur = x; + int y_cur = y; + + do { + FindLandscapeHeight(&ti, x_cur, y_cur); +#if !defined(NEW_ROTATION) + y_cur += 0x10; + x_cur -= 0x10; +#else + y_cur += 0x10; + x_cur += 0x10; +#endif + _added_tile_sprite = false; + _offset_ground_sprites = false; + + DrawTile(&ti); + DrawTileSelection(&ti); + } while (--width_cur); + +#if !defined(NEW_ROTATION) + if ( (direction^=1) != 0) + y += 0x10; + else + x += 0x10; +#else + if ( (direction^=1) != 0) + x += 0x10; + else + y -= 0x10; +#endif + } while (--height); +} + + +void ViewportAddTownNames(DrawPixelInfo *dpi) +{ + Town *t; + int left, top, right, bottom; + + if (!(_display_opt & DO_SHOW_TOWN_NAMES) || _game_mode == GM_MENU) + return; + + left = dpi->left; + top = dpi->top; + right = left + dpi->width; + bottom = top + dpi->height; + + if (dpi->zoom < 1) { + FOR_ALL_TOWNS(t) { + if (t->xy && + bottom > t->sign.top && + top < t->sign.top + 12 && + right > t->sign.left && + left < t->sign.left + t->sign.width_1) { + + AddStringToDraw(t->sign.left + 1, t->sign.top + 1, STR_2001, t->townnametype, t->townnameparts); + } + } + } else if (dpi->zoom == 1) { + right += 2; + bottom += 2; + + FOR_ALL_TOWNS(t) { + if (t->xy && + bottom > t->sign.top && + top < t->sign.top + 24 && + right > t->sign.left && + left < t->sign.left + t->sign.width_1*2) { + + AddStringToDraw(t->sign.left + 1, t->sign.top + 1, STR_2001, t->townnametype, t->townnameparts); + } + } + } else { + right += 4; + bottom += 5; + + assert(dpi->zoom == 2); + FOR_ALL_TOWNS(t) { + if (t->xy && + bottom > t->sign.top && + top < t->sign.top + 24 && + right > t->sign.left && + left < t->sign.left + t->sign.width_2*4) { + + AddStringToDraw(t->sign.left + 5, t->sign.top + 1, STR_2002, t->townnametype, t->townnameparts); + AddStringToDraw(t->sign.left + 1, t->sign.top - 3, STR_2003, t->townnametype, t->townnameparts); + } + } + } +} + +void ViewportAddStationNames(DrawPixelInfo *dpi) +{ + int left, top, right, bottom; + Station *st; + StringSpriteToDraw *sstd; + + if (!(_display_opt & DO_SHOW_STATION_NAMES) || _game_mode == GM_MENU) + return; + + left = dpi->left; + top = dpi->top; + right = left + dpi->width; + bottom = top + dpi->height; + + if (dpi->zoom < 1) { + FOR_ALL_STATIONS(st) { + if (st->xy && + bottom > st->sign.top && + top < st->sign.top + 12 && + right > st->sign.left && + left < st->sign.left + st->sign.width_1) { + + sstd=AddStringToDraw(st->sign.left + 1, st->sign.top + 1, STR_305C_0, st->index, st->facilities); + if (sstd != NULL) { + sstd->color = (st->owner == OWNER_NONE || !st->facilities) ? 0xE : _player_colors[st->owner]; + sstd->width = st->sign.width_1; + } + } + } + } else if (dpi->zoom == 1) { + right += 2; + bottom += 2; + + FOR_ALL_STATIONS(st) { + if (st->xy && + bottom > st->sign.top && + top < st->sign.top + 24 && + right > st->sign.left && + left < st->sign.left + st->sign.width_1*2) { + + sstd=AddStringToDraw(st->sign.left + 1, st->sign.top + 1, STR_305C_0, st->index, st->facilities); + if (sstd != NULL) { + sstd->color = (st->owner == OWNER_NONE || !st->facilities) ? 0xE : _player_colors[st->owner]; + sstd->width = st->sign.width_1; + } + } + } + + } else { + assert(dpi->zoom == 2); + + right += 4; + bottom += 5; + + FOR_ALL_STATIONS(st) { + if (st->xy && + bottom > st->sign.top && + top < st->sign.top + 24 && + right > st->sign.left && + left < st->sign.left + st->sign.width_2*4) { + + sstd=AddStringToDraw(st->sign.left + 1, st->sign.top + 1, STR_305D_0, st->index, st->facilities); + if (sstd != NULL) { + sstd->color = (st->owner == OWNER_NONE || !st->facilities) ? 0xE : _player_colors[st->owner]; + sstd->width = st->sign.width_2 | 0x8000; + } + } + } + } +} + +void ViewportAddSigns(DrawPixelInfo *dpi) +{ + SignStruct *ss; + int left, top, right, bottom; + StringSpriteToDraw *sstd; + + if (!(_display_opt & DO_SHOW_SIGNS)) + return; + + left = dpi->left; + top = dpi->top; + right = left + dpi->width; + bottom = top + dpi->height; + + if (dpi->zoom < 1) { + for(ss=_sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + bottom > ss->sign.top && + top < ss->sign.top + 12 && + right > ss->sign.left && + left < ss->sign.left + ss->sign.width_1) { + + sstd=AddStringToDraw(ss->sign.left + 1, ss->sign.top + 1, STR_2806, ss->str, 0); + if (sstd != NULL) { + sstd->width = ss->sign.width_1; + sstd->color = 14; + } + } + } + } else if (dpi->zoom == 1) { + right += 2; + bottom += 2; + for(ss=_sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + bottom > ss->sign.top && + top < ss->sign.top + 24 && + right > ss->sign.left && + left < ss->sign.left + ss->sign.width_1*2) { + + sstd=AddStringToDraw(ss->sign.left + 1, ss->sign.top + 1, STR_2806, ss->str, 0); + if (sstd != NULL) { + sstd->width = ss->sign.width_1; + sstd->color = 14; + } + } + } + } else { + right += 4; + bottom += 5; + + for(ss=_sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + bottom > ss->sign.top && + top < ss->sign.top + 24 && + right > ss->sign.left && + left < ss->sign.left + ss->sign.width_2*4) { + + sstd=AddStringToDraw(ss->sign.left + 1, ss->sign.top + 1, STR_2807, ss->str, 0); + if (sstd != NULL) { + sstd->width = ss->sign.width_2 | 0x8000; + sstd->color = 14; + } + } + } + } +} + +void ViewportAddCheckpoints(DrawPixelInfo *dpi) +{ + Checkpoint *cp; + + int left, top, right, bottom; + StringSpriteToDraw *sstd; + + if (!(_display_opt & DO_CHECKPOINTS)) + return; + + left = dpi->left; + top = dpi->top; + right = left + dpi->width; + bottom = top + dpi->height; + + if (dpi->zoom < 1) { + for(cp=_checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + bottom > cp->sign.top && + top < cp->sign.top + 12 && + right > cp->sign.left && + left < cp->sign.left + cp->sign.width_1) { + + sstd=AddStringToDraw(cp->sign.left + 1, cp->sign.top + 1, STR_CHECKPOINT_VIEWPORT, cp - _checkpoints, 0); + if (sstd != NULL) { + sstd->width = cp->sign.width_1; + sstd->color = (cp->deleted ? 0xE : 11); + } + } + } + } else if (dpi->zoom == 1) { + right += 2; + bottom += 2; + for(cp=_checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + bottom > cp->sign.top && + top < cp->sign.top + 24 && + right > cp->sign.left && + left < cp->sign.left + cp->sign.width_1*2) { + + sstd=AddStringToDraw(cp->sign.left + 1, cp->sign.top + 1, STR_CHECKPOINT_VIEWPORT, cp - _checkpoints, 0); + if (sstd != NULL) { + sstd->width = cp->sign.width_1; + sstd->color = (cp->deleted ? 0xE : 11); + } + } + } + } else { + right += 4; + bottom += 5; + + for(cp=_checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + bottom > cp->sign.top && + top < cp->sign.top + 24 && + right > cp->sign.left && + left < cp->sign.left + cp->sign.width_2*4) { + + sstd=AddStringToDraw(cp->sign.left + 1, cp->sign.top + 1, STR_CHECKPOINT_VIEWPORT_TINY, cp - _checkpoints, 0); + if (sstd != NULL) { + sstd->width = cp->sign.width_2 | 0x8000; + sstd->color = (cp->deleted ? 0xE : 11); + } + } + } + } +} + +void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str) +{ + char buffer[128]; + int w; + + sign->top = top; + + GetString(buffer, str); + w = GetStringWidth(buffer) + 3; + sign->width_1 = w; + sign->left = left - (w >> 1); + + _stringwidth_base = 0xE0; + w = GetStringWidth(buffer); + _stringwidth_base = 0; + sign->width_2 = w + 1; +} + + +void ViewportDrawTileSprites(TileSpriteToDraw *ts) +{ + do { + Point pt = RemapCoords(ts->x, ts->y, ts->z); + DrawSprite(ts->image, pt.x, pt.y); + } while ( (ts = ts->next) != NULL); +} + +void ViewportSortParentSprites(ParentSpriteToDraw **psd) +{ + ParentSpriteToDraw *ps, *ps2,*ps3, **psd2, **psd3; + + while((ps=*psd) != NULL) { + if (!(ps->unk16 & 1)) { + ps->unk16 |= 1; + psd2 = psd; + + while ( (ps2=*++psd2) != NULL) { + if (ps2->unk16 & 1) + continue; + + if (ps->tile_right >= ps2->tile_x && + ps->tile_bottom >= ps2->tile_y && + ps->tile_z_bottom >= ps2->tile_z && ( + ps->tile_x >= ps2->tile_right || + ps->tile_y >= ps2->tile_bottom || + ps->tile_z >= ps2->tile_z_bottom + )) { + psd3 = psd; + do { + ps3 = *psd3; + *psd3 = ps2; + ps2 = ps3; + + psd3++; + } while (psd3 <= psd2); + } + } + } else { + psd++; + } + } +} + +void ViewportDrawParentSprites(ParentSpriteToDraw **psd) +{ + ParentSpriteToDraw *ps; + ChildScreenSpriteToDraw *cs; + + for (;(ps=*psd) != NULL;psd++) { + Point pt = RemapCoords(ps->tile_x, ps->tile_y, ps->tile_z); + DrawSprite(ps->image, pt.x, pt.y); + + cs = ps->child; + while (cs) { + DrawSprite(cs->image, ps->left + cs->x, ps->top + cs->y); + cs = cs->next; + } + } +} + +void ViewportDrawStrings(DrawPixelInfo *dpi, StringSpriteToDraw *ss) +{ + DrawPixelInfo dp; + byte zoom; + + _cur_dpi = &dp; + dp = *dpi; + + zoom = (byte)dp.zoom; + dp.zoom = 0; + + dp.left >>= zoom; + dp.top >>= zoom; + dp.width >>= zoom; + dp.height >>= zoom; + + do { + if (ss->width != 0) { + int x, y, w, bottom; + + x = (ss->x >> zoom) - 1; + y = (ss->y >> zoom) - 1; + + bottom = y + 11; + + w = ss->width; + if (w & 0x8000) { + w &= ~0x8000; + y--; + bottom -= 6; + w -= 3; + } + + DrawFrameRect(x,y, x+w, bottom, ss->color, (_display_opt & DO_TRANS_BUILDINGS) ? 0 : 0x9); + } + + SET_DPARAM32(0, ss->params[0]); + SET_DPARAM32(1, ss->params[1]); + if (!(_display_opt & DO_TRANS_BUILDINGS) && ss->width != 0) { + /* This is such a frustrating mess - I need to convert + * from real color codes to string color codes and guess + * what, they are completely different. --pasky */ + static const byte ci2sci[17] = { + /* 0 */ 16, /* 1 */ 0, /* 2 */ 5, + /* 3X*/ 2, /* 4 */ 8, /* 5 */ 3, + /* 6X*/ 14, /* 7 */ 7, /* 8 */ 9, + /* 9 */ 13, /* 10 */ 10, /* 11 */ 15, + /* 12 */ 4, /* 13 */ 6, /* 14 */ 11, + /* 15 */ 1, /* 16 */ 12 + }; + byte color = ci2sci[ss->color + 1]; + + DrawString(ss->x >> zoom, (ss->y >> zoom) - (ss->width&0x8000?2:0), ss->string, color); + } else { + DrawString(ss->x >> zoom, (ss->y >> zoom) - (ss->width&0x8000?2:0), ss->string, 16); + } + } while ( (ss = ss->next) != NULL); + + _cur_dpi = dpi; +} + +void ViewportDoDraw(ViewPort *vp, int left, int top, int right, int bottom) +{ + ViewportDrawer vd; + int mask; + int x,y; + DrawPixelInfo *old_dpi; + + byte mem[VIEWPORT_DRAW_MEM]; + ParentSpriteToDraw *parent_list[750]; + + _cur_vd = &vd; + + old_dpi = _cur_dpi; + _cur_dpi = &vd.dpi; + + vd.dpi.zoom = vp->zoom; + mask = (-1) << vp->zoom; + + vd.combine_sprites = 0; + vd.ground_child = 0; + + vd.dpi.width = (right - left) & mask; + vd.dpi.height = (bottom - top) & mask; + vd.dpi.left = left & mask; + vd.dpi.top = top & mask; + vd.dpi.pitch = old_dpi->pitch; + + x = ((vd.dpi.left - (vp->virtual_left&mask)) >> vp->zoom) + vp->left; + y = ((vd.dpi.top - (vp->virtual_top&mask)) >> vp->zoom) + vp->top; + + vd.dpi.dst_ptr = old_dpi->dst_ptr + x - old_dpi->left + (y - old_dpi->top) * old_dpi->pitch; + + vd.parent_list = parent_list; + vd.spritelist_mem = mem; + vd.eof_spritelist_mem = &mem[sizeof(mem) - 0x40]; + vd.last_string = &vd.first_string; + vd.first_string = NULL; + vd.last_tile = &vd.first_tile; + vd.first_tile = NULL; + + ViewportAddLandscape(); +#if !defined(NEW_ROTATION) + ViewportAddVehicles(&vd.dpi); + DrawTextEffects(&vd.dpi); + + ViewportAddTownNames(&vd.dpi); + ViewportAddStationNames(&vd.dpi); + ViewportAddSigns(&vd.dpi); + ViewportAddCheckpoints(&vd.dpi); +#endif + + if (vd.first_tile != NULL) + ViewportDrawTileSprites(vd.first_tile); + + assert(vd.parent_list - parent_list <= lengthof(parent_list)); + + /* null terminate parent sprite list */ + *vd.parent_list = NULL; + + ViewportSortParentSprites(parent_list); + ViewportDrawParentSprites(parent_list); + + if (vd.first_string != NULL) + ViewportDrawStrings(&vd.dpi, vd.first_string); + + _cur_dpi = old_dpi; +} + +// Make sure we don't draw a too big area at a time. +// If we do, the sprite memory will overflow. +static void ViewportDrawChk(ViewPort *vp, int left, int top, int right, int bottom) +{ + if (((bottom - top) * (right - left) << vp->zoom) > 180000) { + if ((bottom - top) > (right - left)) { + int t = (top + bottom) >> 1; + ViewportDrawChk(vp, left, top, right, t); + ViewportDrawChk(vp, left, t, right, bottom); + } else { + int t = (left + right) >> 1; + ViewportDrawChk(vp, left, top, t, bottom); + ViewportDrawChk(vp, t, top, right, bottom); + } + } else { + ViewportDoDraw(vp, + ((left - vp->left) << vp->zoom) + vp->virtual_left, + ((top - vp->top) << vp->zoom) + vp->virtual_top, + ((right - vp->left) << vp->zoom) + vp->virtual_left, + ((bottom - vp->top) << vp->zoom) + vp->virtual_top + ); + } +} + +static void INLINE ViewportDraw(ViewPort *vp, int left, int top, int right, int bottom) +{ + int t; + + if (right <= vp->left || + bottom <= vp->top) + return; + + if (left >= (t=vp->left + vp->width)) + return; + + if (left < vp->left) left = vp->left; + if (right > t) right = t; + + if (top >= (t = vp->top + vp->height)) + return; + + if (top < vp->top) top = vp->top; + if (bottom > t) bottom = t; + + ViewportDrawChk(vp, left, top, right, bottom); +} + +void DrawWindowViewport(Window *w) { + DrawPixelInfo *dpi = _cur_dpi; + + dpi->left += w->left; + dpi->top += w->top; + + ViewportDraw(w->viewport, dpi->left, dpi->top, dpi->left + dpi->width, dpi->top + dpi->height); + + dpi->left -= w->left; + dpi->top -= w->top; + +} + +void UpdateViewportPosition(Window *w) +{ + ViewPort *vp = w->viewport; + + if (WP(w,vp_d).follow_vehicle != 0xFFFF) { + Vehicle *veh; + Point pt; + + veh = &_vehicles[WP(w,vp_d).follow_vehicle]; + pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); + SetViewportPosition(w, pt.x, pt.y); + } else { + int x,y,t; + int err; + + x = WP(w,vp_d).scrollpos_x >> 2; + y = WP(w,vp_d).scrollpos_y >> 1; + +#if !defined(NEW_ROTATION) + t = x; + x = y - t; + y = y + t; + + // check if inside bounds? + t = (-130) << vp->zoom; + err = 0; + if (y < t || y > (t += TILE_Y_MAX*16-1)) { y = t; err++; } + if (x < (t=0) || x > (t=TILE_X_MAX*16-1) ) { x = t; err++; } +#else + t = x; + x = x + y; + y = x - y; + err= 0; +#endif + + if (err != 0) { + /* coordinate remap */ + Point pt = RemapCoords(x, y, 0); + t = (-1) << vp->zoom; + WP(w,vp_d).scrollpos_x = pt.x & t; + WP(w,vp_d).scrollpos_y = pt.y & t; + } + SetViewportPosition(w, WP(w,vp_d).scrollpos_x, WP(w,vp_d).scrollpos_y); + } +} + +void MarkViewportDirty(ViewPort *vp, int left, int top, int right, int bottom) +{ + if ( (right -= vp->virtual_left) <= 0) + return; + + if ( (bottom -= vp->virtual_top) <= 0) + return; + + if ( (left -= vp->virtual_left) < 0) + left = 0; + + if ((uint)left >= (uint)vp->virtual_width) + return; + + if ( (top -= vp->virtual_top) < 0) + top = 0; + + if ((uint)top >= (uint)vp->virtual_height) + return; + + SetDirtyBlocks( + (left >> vp->zoom) + vp->left, + (top >> vp->zoom) + vp->top, + (right >> vp->zoom) + vp->left, + (bottom >> vp->zoom) + vp->top + ); +} + +void MarkAllViewportsDirty(int left, int top, int right, int bottom) +{ + ViewPort *vp = _viewports; + uint32 act = _active_viewports; + do { + if (act & 1) { + assert(vp->width != 0); + MarkViewportDirty(vp, left, top, right, bottom); + } + } while (vp++,act>>=1); +} + +void MarkTileDirtyByTile(TileIndex tile) { + Point pt = RemapCoords(GET_TILE_X(tile) * 16, GET_TILE_Y(tile) * 16, GetTileZ(tile)); + MarkAllViewportsDirty( + pt.x - 31, + pt.y - 122, + pt.x - 31 + 67, + pt.y - 122 + 154 + ); +} + +void MarkTileDirty(int x, int y) +{ + int z = 0; + Point pt; + if (IS_INT_INSIDE(x, 0, TILES_X*16) && IS_INT_INSIDE(y, 0, TILES_Y*16)) + z = GetTileZ(TILE_FROM_XY(x,y)); + pt = RemapCoords(x, y, z); + + MarkAllViewportsDirty( + pt.x - 31, + pt.y - 122, + pt.x - 31 + 67, + pt.y - 122 + 154 + ); +} + +void SetSelectionTilesDirty() +{ + int y_size, x_size; + TileHighlightData *thd = _thd_ptr; + int x = thd->pos.x; + int y = thd->pos.y; + + x_size=thd->size.x; + y_size=thd->size.y; + + if (thd->outersize.x) { + x_size += thd->outersize.x; + x += thd->offs.x; + y_size += thd->outersize.y; + y += thd->offs.y; + } + + assert(x_size > 0); + assert(y_size > 0); + + x_size += x; + y_size += y; + + do { + int y_bk = y; + do { + MarkTileDirty(x, y); + } while ( (y+=16) != y_size); + y = y_bk; + } while ( (x+=16) != x_size); +} + + +static bool CheckClickOnTown(ViewPort *vp, int x, int y) +{ + Town *t; + + if (!(_display_opt & DO_SHOW_TOWN_NAMES)) + return false; + + if (vp->zoom < 1) { + x = x - vp->left + vp->virtual_left; + y = y - vp->top + vp->virtual_top; + + FOR_ALL_TOWNS(t) { + if (t->xy && + y >= t->sign.top && + y < t->sign.top + 12 && + x >= t->sign.left && + x < t->sign.left + t->sign.width_1) { + ShowTownViewWindow(t->index); + return true; + } + } + } else if (vp->zoom == 1) { + x = (x - vp->left + 1) * 2 + vp->virtual_left; + y = (y - vp->top + 1) * 2 + vp->virtual_top; + FOR_ALL_TOWNS(t) { + if (t->xy && + y >= t->sign.top && + y < t->sign.top + 24 && + x >= t->sign.left && + x < t->sign.left + t->sign.width_1 * 2) { + ShowTownViewWindow(t->index); + return true; + } + } + } else { + x = (x - vp->left + 3) * 4 + vp->virtual_left; + y = (y - vp->top + 3) * 4 + vp->virtual_top; + FOR_ALL_TOWNS(t) { + if (t->xy && + y >= t->sign.top && + y < t->sign.top + 24 && + x >= t->sign.left && + x < t->sign.left + t->sign.width_2 * 4) { + ShowTownViewWindow(t->index); + return true; + } + } + } + + return false; +} + +static bool CheckClickOnStation(ViewPort *vp, int x, int y) +{ + Station *st; + + if (!(_display_opt & DO_SHOW_STATION_NAMES)) + return false; + + if (vp->zoom < 1) { + x = x - vp->left + vp->virtual_left; + y = y - vp->top + vp->virtual_top; + + FOR_ALL_STATIONS(st) { + if (st->xy && + y >= st->sign.top && + y < st->sign.top + 12 && + x >= st->sign.left && + x < st->sign.left + st->sign.width_1) { + ShowStationViewWindow(st->index); + return true; + } + } + } else if (vp->zoom == 1) { + x = (x - vp->left + 1) * 2 + vp->virtual_left; + y = (y - vp->top + 1) * 2 + vp->virtual_top; + FOR_ALL_STATIONS(st) { + if (st->xy && + y >= st->sign.top && + y < st->sign.top + 24 && + x >= st->sign.left && + x < st->sign.left + st->sign.width_1 * 2) { + ShowStationViewWindow(st->index); + return true; + } + } + } else { + x = (x - vp->left + 3) * 4 + vp->virtual_left; + y = (y - vp->top + 3) * 4 + vp->virtual_top; + FOR_ALL_STATIONS(st) { + if (st->xy && + y >= st->sign.top && + y < st->sign.top + 24 && + x >= st->sign.left && + x < st->sign.left + st->sign.width_2 * 4) { + ShowStationViewWindow(st->index); + return true; + } + } + } + + return false; +} + +static bool CheckClickOnSign(ViewPort *vp, int x, int y) +{ + SignStruct *ss; + + if (!(_display_opt & DO_SHOW_SIGNS)) + return false; + + if (vp->zoom < 1) { + x = x - vp->left + vp->virtual_left; + y = y - vp->top + vp->virtual_top; + + for(ss = _sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + y >= ss->sign.top && + y < ss->sign.top + 12 && + x >= ss->sign.left && + x < ss->sign.left + ss->sign.width_1) { + ShowRenameSignWindow(ss); + return true; + } + } + } else if (vp->zoom == 1) { + x = (x - vp->left + 1) * 2 + vp->virtual_left; + y = (y - vp->top + 1) * 2 + vp->virtual_top; + for(ss = _sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + y >= ss->sign.top && + y < ss->sign.top + 24 && + x >= ss->sign.left && + x < ss->sign.left + ss->sign.width_1 * 2) { + ShowRenameSignWindow(ss); + return true; + } + } + } else { + x = (x - vp->left + 3) * 4 + vp->virtual_left; + y = (y - vp->top + 3) * 4 + vp->virtual_top; + for(ss = _sign_list; ss != endof(_sign_list); ss++) { + if (ss->str && + y >= ss->sign.top && + y < ss->sign.top + 24 && + x >= ss->sign.left && + x < ss->sign.left + ss->sign.width_2 * 4) { + ShowRenameSignWindow(ss); + return true; + } + } + } + + return false; +} + +static bool CheckClickOnCheckpoint(ViewPort *vp, int x, int y) +{ + Checkpoint *cp; + + if (!(_display_opt & DO_CHECKPOINTS)) + return false; + + if (vp->zoom < 1) { + x = x - vp->left + vp->virtual_left; + y = y - vp->top + vp->virtual_top; + + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + y >= cp->sign.top && + y < cp->sign.top + 12 && + x >= cp->sign.left && + x < cp->sign.left + cp->sign.width_1) { + ShowRenameCheckpointWindow(cp); + return true; + } + } + } else if (vp->zoom == 1) { + x = (x - vp->left + 1) * 2 + vp->virtual_left; + y = (y - vp->top + 1) * 2 + vp->virtual_top; + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + y >= cp->sign.top && + y < cp->sign.top + 24 && + x >= cp->sign.left && + x < cp->sign.left + cp->sign.width_1 * 2) { + ShowRenameCheckpointWindow(cp); + return true; + } + } + } else { + x = (x - vp->left + 3) * 4 + vp->virtual_left; + y = (y - vp->top + 3) * 4 + vp->virtual_top; + for(cp = _checkpoints; cp != endof(_checkpoints); cp++) { + if (cp->xy && + y >= cp->sign.top && + y < cp->sign.top + 24 && + x >= cp->sign.left && + x < cp->sign.left + cp->sign.width_2 * 4) { + ShowRenameCheckpointWindow(cp); + return true; + } + } + } + + return false; +} + + +static void CheckClickOnLandscape(ViewPort *vp, int x, int y) +{ + Point pt = TranslateXYToTileCoord(vp,x,y); + if (pt.x != -1) { + uint tile = TILE_FROM_XY(pt.x, pt.y); + ClickTile(tile); + } +} + +void HandleClickOnTrain(Vehicle *v); +void HandleClickOnRoadVeh(Vehicle *v); +void HandleClickOnAircraft(Vehicle *v); +void HandleClickOnShip(Vehicle *v); +void HandleClickOnSpecialVeh(Vehicle *v) {} +void HandleClickOnDisasterVeh(Vehicle *v); +typedef void OnVehicleClickProc(Vehicle *v); +static OnVehicleClickProc * const _on_vehicle_click_proc[6] = { + HandleClickOnTrain, + HandleClickOnRoadVeh, + HandleClickOnShip, + HandleClickOnAircraft, + HandleClickOnSpecialVeh, + HandleClickOnDisasterVeh, +}; + +void HandleViewportClicked(ViewPort *vp, int x, int y) +{ + if (CheckClickOnTown(vp, x, y)) + return; + + if (CheckClickOnStation(vp, x, y)) + return; + + if (CheckClickOnSign(vp, x, y)) + return; + + if (CheckClickOnCheckpoint(vp, x, y)) + return; + + CheckClickOnLandscape(vp, x, y); + + { + Vehicle *v = CheckClickOnVehicle(vp, x, y); + if (v) _on_vehicle_click_proc[v->type - 0x10](v); + } +} + +Vehicle *CheckMouseOverVehicle() +{ + Window *w; + ViewPort *vp; + + int x = _cursor.pos.x; + int y = _cursor.pos.y; + + w = FindWindowFromPt(x, y); + if (w == NULL) + return NULL; + + vp = IsPtInWindowViewport(w, x, y); + if (vp) { + return CheckClickOnVehicle(vp, x, y); + } else { + return NULL; + } +} + + + +void PlaceObject() +{ + Point pt; + Window *w; + WindowEvent e; + + pt = GetTileBelowCursor(); + if (pt.x == -1) + return; + + if (_thd.place_mode == 2) { + pt.x += 8; + pt.y += 8; + } + + _tile_fract_coords.x = pt.x & 0xF; + _tile_fract_coords.y = pt.y & 0xF; + + if ((w = GetCallbackWnd()) != NULL) { + e.event = WE_PLACE_OBJ; + e.place.pt = pt; + e.place.tile = TILE_FROM_XY(pt.x, pt.y); + w->wndproc(w, &e); + } +} + +bool ScrollMainWindowTo(int x, int y) +{ + Window *w = FindWindowById(WC_MAIN_WINDOW, 0); + Point pt; + + pt = MapXYZToViewport(w->viewport, x, y, GetSlopeZ(x, y)); + WP(w,vp_d).follow_vehicle = -1; + + if (WP(w,vp_d).scrollpos_x == pt.x && + WP(w,vp_d).scrollpos_y == pt.y) + return false; + + WP(w,vp_d).scrollpos_x = pt.x; + WP(w,vp_d).scrollpos_y = pt.y; + return true; +} + + +bool ScrollMainWindowToTile(TileIndex tile) +{ + return ScrollMainWindowTo(GET_TILE_X(tile)*16+8, GET_TILE_Y(tile)*16+8); +} + +void SetRedErrorSquare(TileIndex tile) +{ + TileIndex old; + + old = _thd.redsq; + _thd.redsq = tile; + + if (tile != old) { + if (tile != 0) MarkTileDirtyByTile(tile); + if (old != 0) MarkTileDirtyByTile(old); + } +} + +void SetTileSelectSize(int w, int h) +{ + TileHighlightData *thd = _thd_ptr; + thd->new_size.x = w * 16; + thd->new_size.y = h * 16; + thd->new_outersize.x = 0; + thd->new_outersize.y = 0; +} + +void SetTileSelectBigSize(int ox, int oy, int sx, int sy) { + TileHighlightData *thd = _thd_ptr; + thd->offs.x = ox * 16; + thd->offs.y = oy * 16; + thd->new_outersize.x = sx * 16; + thd->new_outersize.y = sy * 16; +} + + +void UpdateTileSelection() +{ + TileHighlightData *thd = _thd_ptr; + Point pt; + int x1,y1; + + thd->new_drawstyle = 0; + + if (thd->place_mode == 3) { + x1 = thd->selend.x; + y1 = thd->selend.y; + if (x1 != -1) { + int x2 = thd->selstart.x; + int y2 = thd->selstart.y; + x1 &= ~0xF; + y1 &= ~0xF; + + if (x1 >= x2) intswap(x1,x2); + if (y1 >= y2) intswap(y1,y2); + thd->new_pos.x = x1; + thd->new_pos.y = y1; + thd->new_size.x = x2 - x1 + 16; + thd->new_size.y = y2 - y1 + 16; + thd->new_drawstyle = thd->next_drawstyle; + } + } else if (thd->place_mode != 0) { + pt = GetTileBelowCursor(); + x1 = pt.x; + y1 = pt.y; + if (x1 != -1) { + if (thd->place_mode == 1) { + thd->new_drawstyle = HT_RECT; + } else { + thd->new_drawstyle = HT_POINT; + x1 += 8; + y1 += 8; + } + thd->new_pos.x = x1 & ~0xF; + thd->new_pos.y = y1 & ~0xF; + } + } + + if (thd->drawstyle != thd->new_drawstyle || + thd->pos.x != thd->new_pos.x || thd->pos.y != thd->new_pos.y || + thd->size.x != thd->new_size.x || thd->size.y != thd->new_size.y) { + + // clear the old selection? + if (thd->drawstyle) SetSelectionTilesDirty(); + + thd->drawstyle = thd->new_drawstyle; + thd->pos = thd->new_pos; + thd->size = thd->new_size; + thd->outersize = thd->new_outersize; + thd->dirty = 0xff; + + // draw the new selection? + if (thd->new_drawstyle) SetSelectionTilesDirty(); + } +} + +void VpStartPlaceSizing(uint tile, int user) +{ + TileHighlightData *thd; + + thd = _thd_ptr; + thd->userdata = user; + thd->selend.x = GET_TILE_X(tile)*16; + thd->selstart.x = GET_TILE_X(tile)*16; + thd->selend.y = GET_TILE_Y(tile)*16; + thd->selstart.y = GET_TILE_Y(tile)*16; + if (thd->place_mode == 1) { + thd->place_mode = 3; + thd->next_drawstyle = HT_RECT; + } else { + thd->place_mode = 3; + thd->next_drawstyle = HT_POINT; + } + _special_mouse_mode = WSM_SIZING; +} + +void VpSetPlaceSizingLimit(int limit) +{ + _thd.sizelimit = limit; +} + +void VpSetPresizeRange(uint from, uint to) +{ + TileHighlightData *thd = _thd_ptr; + thd->selend.x = GET_TILE_X(to)*16; + thd->selend.y = GET_TILE_Y(to)*16; + thd->selstart.x = GET_TILE_X(from)*16; + thd->selstart.y = GET_TILE_Y(from)*16; + thd->next_drawstyle = HT_RECT; +} + +void VpStartPreSizing() +{ + _thd.selend.x = -1; + _special_mouse_mode = WSM_PRESIZE; +} + +static void CalcRaildirsDrawstyle(TileHighlightData *thd, int x, int y) +{ + int d; + bool b; + uint w,h; + + w = myabs((x & ~0xF) - thd->selstart.x) + 16; + h = myabs((y & ~0xF) - thd->selstart.y) + 16; + + // vertical and horizontal lines are really simple + if (w == 16 || h == 16) { + b = HT_RECT; + } else if (w * 2 < h) { // see if we're closer to rect? + x = thd->selstart.x; + b = HT_RECT; + } else if (w > h * 2) { + y = thd->selstart.y; + b = HT_RECT; + } else { + d = w - h; + + // four cases. + if (x > thd->selstart.x) { + if (y > thd->selstart.y) { + // south + if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | 0 : HT_LINE | 1; + else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | 0; } // return px == py || px == py + 16; + else { y = thd->selstart.y + w; b = HT_LINE | 1; } // return px == py || px == py - 16; + } else { + // west + if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | 2 : HT_LINE | 3; + else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | 2; } + else { y = thd->selstart.y - w; b = HT_LINE | 3; } + } + } else { + if (y > thd->selstart.y) { + // east + if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | 2 : HT_LINE | 3; + else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | 3; } // return px == -py || px == -py - 16; + else { y = thd->selstart.y + w; b = HT_LINE | 2; } // return px == -py || px == -py + 16; + } else { + // north + if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | 0 : HT_LINE | 1; + else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | 1; } // return px == py || px == py - 16; + else { y = thd->selstart.y - w; b = HT_LINE | 0; } //return px == py || px == py + 16; + } + } + } + thd->selend.x = x; + thd->selend.y = y; + thd->next_drawstyle = b; +} + +void VpSelectTilesWithMethod(int x, int y, int method) +{ + TileHighlightData *thd = _thd_ptr; + int sx,sy; + + if (x == -1) { + thd->selend.x = -1; + return; + } + + // allow drag in any rail direction + if (method == VPM_RAILDIRS) { + CalcRaildirsDrawstyle(thd, x, y); + return; + } + + if (_thd.next_drawstyle == HT_POINT) { x += 8; y += 8; } + + //thd->next_drawstyle = HT_RECT; + + sx = thd->selstart.x; + sy = thd->selstart.y; + + switch(method) { + case VPM_FIX_X: + x = sx; + break; + + case VPM_FIX_Y: + y = sy; + break; + + case VPM_X_OR_Y: + if (myabs(sy - y) < myabs(sx - x)) y = sy; else x = sx; + break; + + case VPM_X_AND_Y: + break; + + // limit the selected area to a 10x10 rect. + case VPM_X_AND_Y_LIMITED: { + int limit = (thd->sizelimit-1) * 16; + x = sx + clamp(x - sx, -limit, limit); + y = sy + clamp(y - sy, -limit, limit); + break; + } + } + + thd->selend.x = x; + thd->selend.y = y; +} + +bool VpHandlePlaceSizingDrag() +{ + Window *w; + WindowEvent e; + + if (_special_mouse_mode != WSM_SIZING) + return true; + + e.place.userdata = _thd.userdata; + + w = FindWindowById(_thd.window_class,_thd.window_number); + if (w == NULL) { + ResetObjectToPlace(); + return false; + } + + // while dragging... + if (_left_button_down) { + e.event = WE_PLACE_DRAG; + e.place.pt = GetTileBelowCursor(); + w->wndproc(w, &e); + return false; + } + + // mouse button released.. + // keep the selected tool, but reset it to the original mode. + _special_mouse_mode = WSM_NONE; + _thd.place_mode = (_thd.next_drawstyle == HT_RECT || _thd.next_drawstyle & HT_LINE) ? 1 : 2; + + SetTileSelectSize(1, 1); + + // and call the mouseup event. + e.event = WE_PLACE_MOUSEUP; + e.place.pt = _thd.selend; + e.place.tile = TILE_FROM_XY(e.place.pt.x, e.place.pt.y); + e.place.starttile = TILE_FROM_XY(_thd.selstart.x, _thd.selstart.y); + w->wndproc(w, &e); + + return false; +} + +void SetObjectToPlaceWnd(int icon, byte mode, Window *w) +{ + SetObjectToPlace(icon,mode,w->window_class, w->window_number); +} + +#include "table/animcursors.h" + +void SetObjectToPlace(int icon, byte mode, byte window_class, uint16 window_num) +{ + TileHighlightData *thd = _thd_ptr; + Window *w; + + if (thd->place_mode != 0) { + thd->place_mode = 0; + w = FindWindowById(thd->window_class, thd->window_number); + if (w != NULL) + CallWindowEventNP(w, WE_ABORT_PLACE_OBJ); + } + + SetTileSelectSize(1, 1); + + thd->make_square_red = false; + + if (mode == 4) { + mode = 0; + _special_mouse_mode = WSM_DRAGDROP; + } else { + _special_mouse_mode = WSM_NONE; + } + + thd->place_mode = mode; + thd->window_class = window_class; + thd->window_number = window_num; + + if (mode == 3) + VpStartPreSizing(); + + if ( (int)icon < 0) + SetAnimatedMouseCursor(_animcursors[~icon]); + else + SetMouseCursor(icon); +} + +void ResetObjectToPlace(){ + SetObjectToPlace(0,0,0,0); +} diff --git a/viewport.h b/viewport.h new file mode 100644 --- /dev/null +++ b/viewport.h @@ -0,0 +1,117 @@ +#ifndef VIEWPORT_H +#define VIEWPORT_H + +struct ViewPort { + int left,top; // screen coordinates for the viewport + int width, height; // screen width/height for the viewport + + int virtual_left, virtual_top; // virtual coordinates + int virtual_width, virtual_height; // these are just width << zoom, height << zoom + + byte zoom; +}; + +/* viewport.c */ +Point MapXYZToViewport(ViewPort *vp, uint x, uint y, uint z); +void AssignWindowViewport(Window *w, int x, int y, + int width, int height, uint32 follow_flags, byte zoom); +void SetViewportPosition(Window *w, int x, int y); +ViewPort *IsPtInWindowViewport(Window *w, int x, int y); +Point GetTileBelowCursor(); +Point GetTileZoomCenter(bool in); +void UpdateViewportPosition(Window *w); + +void OffsetGroundSprite(int x, int y); + +void DrawGroundSprite(uint32 image); +void DrawGroundSpriteAt(uint32 image, int x, int y, byte z); +void AddSortableSpriteToDraw(uint32 image, int x, int y, int w, int h, byte dz, byte z); +void *AddStringToDraw(int x, int y, StringID string, uint32 params_1, uint32 params_2); +void AddChildSpriteScreen(uint32 image, int x, int y); + + +void StartSpriteCombine(); +void EndSpriteCombine(); + +void HandleViewportClicked(ViewPort *vp, int x, int y); +void PlaceObject(); +void SetRedErrorSquare(TileIndex tile); +void SetTileSelectSize(int w, int h); +void SetTileSelectBigSize(int ox, int oy, int sx, int sy); + +void VpStartPlaceSizing(uint tile, int user); +void VpStartPreSizing(); +void VpSetPresizeRange(uint from, uint to); +void VpSetPlaceSizingLimit(int limit); + +Vehicle *CheckMouseOverVehicle(); + +enum { + VPM_X_OR_Y = 0, + VPM_FIX_X = 1, + VPM_FIX_Y = 2, + VPM_RAILDIRS = 3, + VPM_X_AND_Y = 4, + VPM_X_AND_Y_LIMITED = 5, +}; + +void VpSelectTilesWithMethod(int x, int y, int method); + +enum { + HT_NONE = 0, + HT_RECT = 0x80, + HT_POINT = 0x40, + HT_LINE = 0x20, +}; + +typedef struct TileHighlightData { + Point size; + Point outersize; + Point pos; + Point offs; + + Point new_pos; + Point new_size; + Point new_outersize; + + Point selend, selstart; + + byte dirty; + byte sizelimit; + + byte drawstyle; + byte new_drawstyle; + byte next_drawstyle; + + byte place_mode; + byte window_class; + bool make_square_red; + uint16 window_number; + + int userdata; + TileIndex redsq; +} TileHighlightData; + + +enum AnimCursors { + ANIMCURSOR_DEMOLISH = -1, + ANIMCURSOR_LOWERLAND = -2, + ANIMCURSOR_RAISELAND = -3, + ANIMCURSOR_PICKSTATION = -4, + ANIMCURSOR_BUILDSIGNALS = -5, +}; + +// common button handler +bool HandlePlacePushButton(Window *w, int widget, uint32 cursor, int mode, PlaceProc *placeproc); + +/* viewport.c */ +VARDEF ViewPort _viewports[18]; +VARDEF TileHighlightData _thd; +VARDEF uint32 _active_viewports; + +VARDEF Point _tile_fract_coords; + +extern TileHighlightData * const _thd_ptr; + + +#endif diff --git a/w32dm.c b/w32dm.c new file mode 100644 --- /dev/null +++ b/w32dm.c @@ -0,0 +1,114 @@ +/********************************************************************* + * OpenTTD: An Open Source Transport Tycoon Deluxe clone * + * Copyright (c) 2002-2004 OpenTTD Developers. All Rights Reserved. * + * * + * Web site: http://openttd.sourceforge.net/ * + *********************************************************************/ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* DirectMusic driver for Win32 */ +/* Based on dxmci from TTDPatch */ + +#include "stdafx.h" + +#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT + +#include "ttd.h" +#include "sound.h" +#include "hal.h" + +static char * DMusicMidiStart(char **parm); +static void DMusicMidiStop(); +static void DMusicMidiPlaySong(const char *filename); +static void DMusicMidiStopSong(); +static bool DMusicMidiIsSongPlaying(); +static void DMusicMidiSetVolume(byte vol); + +const HalMusicDriver _dmusic_midi_driver = { + DMusicMidiStart, + DMusicMidiStop, + DMusicMidiPlaySong, + DMusicMidiStopSong, + DMusicMidiIsSongPlaying, + DMusicMidiSetVolume, +}; + +extern bool LoadMIDI (char *directory, char *filename); +extern bool InitDirectMusic (void); +extern void ReleaseSegment (void); +extern void ShutdownDirectMusic (void); +extern bool LoadMIDI (char *directory, char *filename); +extern void PlaySegment (void); +extern void StopSegment (void); +extern bool IsSegmentPlaying (void); +extern void SetVolume (long); + +bool seeking = false; + +static char * DMusicMidiStart(char **parm) +{ + InitDirectMusic(); + return 0; +} + +static void DMusicMidiStop() +{ + StopSegment(); +} + +static void DMusicMidiPlaySong(const char *filename) +{ + char *pos; + char dir[MAX_PATH]; + char file[MAX_PATH]; + + // split full path into directory and file components + ttd_strlcpy(dir, filename, MAX_PATH); + pos = strrchr(dir, '\\') + 1; + ttd_strlcpy(file, pos, MAX_PATH); + //strchr(file, ' ')[0] = 0; + *pos = 0; + + LoadMIDI(dir, file); + PlaySegment(); + seeking = true; +} + +static void DMusicMidiStopSong() +{ + StopSegment(); +} + +static bool DMusicMidiIsSongPlaying() +{ + if ((IsSegmentPlaying() == 0) && (seeking == true)) // Not the nicest code, but there is a + return(true); // short delay before playing actually + // starts. OpenTTD makes no provision for + if (IsSegmentPlaying() == 1) // this. + seeking = false; + + + return(IsSegmentPlaying()); +} + +static void DMusicMidiSetVolume(byte vol) +{ + SetVolume(vol); +} + +#endif \ No newline at end of file diff --git a/w32dm2.cpp b/w32dm2.cpp new file mode 100644 --- /dev/null +++ b/w32dm2.cpp @@ -0,0 +1,305 @@ +/********************************************************************* + * OpenTTD: An Open Source Transport Tycoon Deluxe clone * + * Copyright (c) 2002-2004 OpenTTD Developers. All Rights Reserved. * + * * + * Web site: http://openttd.sourceforge.net/ * + *********************************************************************/ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* DirectMusic driver for Win32 */ +/* Based on dxmci from TTDPatch */ + +#include "stdafx.h" + +#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT + +// for gcc, the GUIDs are available in a library instead +#ifndef __GNUC__ +#define INITGUID +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ttd.h" +#include "sound.h" +#include "hal.h" + +#ifdef __cplusplus + } +#endif + +#include +#include + +#include +#include +#include +#include + +#define VARIANT int + +#define MSGBOX(output) DEBUG(misc, 0) ("DirectMusic driver: %s\n", output); //MessageBox(NULL, output, "dxmci",MB_OK); +#define MULTI_TO_WIDE( x,y ) MultiByteToWideChar( CP_ACP,MB_PRECOMPOSED, y,-1,x,_MAX_PATH); + +// the performance object controls manipulation of the segments +IDirectMusicPerformance *performance = NULL; + +// the segment object is where the MIDI data is stored for playback +IDirectMusicSegment *segment = NULL; + +// the loader bject can load many types of DMusic related files +IDirectMusicLoader *loader = NULL; + +// whether we've initialized COM or not (when deciding whether to shut down) +int COMInitialized = 0; + + +extern "C" bool LoadLibraryList(void **proc, const char *dll); + +// Use lazy linking +struct ProcPtrs { + unsigned long (WINAPI *CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID * ppv); + HRESULT (WINAPI *CoInitialize)( LPVOID pvReserved ); + void (WINAPI *CoUninitialize)( ); +}; + +#define M(x) x "\0" +static const char ole_files[] = + M("ole32.dll") + M("CoCreateInstance") + M("CoInitialize") + M("CoUninitialize") + M("") +; +#undef M + + +static ProcPtrs _proc; + +static bool LoadOleDLL() +{ + if (_proc.CoCreateInstance != NULL) + return true; + if (!LoadLibraryList((void**)&_proc, ole_files)) + return false; + return true; +} + + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize COM and DirectMusic +bool InitDirectMusic (void) +{ + if (NULL != performance) + return true; + + // Initialize COM + if (!COMInitialized) { + if (!LoadOleDLL()) { + MSGBOX("ole32.dll load failed"); + return false; + } + + _proc.CoInitialize(NULL); + COMInitialized = 1; + } + + // Create the performance object via CoCreateInstance + if (FAILED(_proc.CoCreateInstance( + (REFCLSID)CLSID_DirectMusicPerformance, + NULL, + CLSCTX_INPROC, + (REFIID)IID_IDirectMusicPerformance, + (LPVOID *)&performance))) { + MSGBOX ("Failed to create the performance object"); + return false; + } + + // Initialize it + if (FAILED(performance->Init(NULL, NULL, NULL))) { + MSGBOX("Failed to initialize performance object"); + return false; + } + + // Choose default Windows synth + if (FAILED(performance->AddPort (NULL))) { + MSGBOX("AddPort failed"); + return false; + } + + // now we'll create the loader object. This will be used to load the + // midi file for our demo. Again, we need to use CoCreateInstance + // and pass the appropriate ID parameters + if (FAILED(_proc.CoCreateInstance((REFCLSID)CLSID_DirectMusicLoader, + NULL, CLSCTX_INPROC, + (REFIID)IID_IDirectMusicLoader, + (LPVOID *)&loader))) { + MSGBOX("Failed to create loader object"); + return false; + } + + // that's it for initialization. If we made it this far we + // were successful. + return true; +} + +// Releases memory used by all of the initialized +// DirectMusic objects in the program +void ReleaseSegment (void) +{ + if (NULL != segment) { + segment->Release (); + segment = NULL; + } +} +void ShutdownDirectMusic (void) +{ + // release everything but the segment, which the performance + // will release automatically (and it'll crash if it's been + // released already) + + if (NULL != loader) { + loader->Release (); + loader = NULL; + } + + if (NULL != performance) + { + performance->CloseDown (); + performance->Release (); + performance = NULL; + } + + if (COMInitialized) { + _proc.CoUninitialize(); + COMInitialized = 0; + } +} + +// Load MIDI file for playing +bool LoadMIDI (char *directory, char *filename) +{ + DMUS_OBJECTDESC obj_desc; + WCHAR w_directory[_MAX_PATH]; // utf-16 version of the directory name. + WCHAR w_filename[_MAX_PATH]; // utf-16 version of the file name + + if (NULL == performance) + return false; + + MULTI_TO_WIDE(w_directory,directory); + + if (FAILED(loader->SetSearchDirectory((REFGUID) GUID_DirectMusicAllTypes, + w_directory, FALSE))) { + MSGBOX("LoadMIDI: SetSearchDirectory failed"); + return false; + } + + // set up the loader object info + ZeroMemory (&obj_desc, sizeof (obj_desc)); + obj_desc.dwSize = sizeof (obj_desc); + + MULTI_TO_WIDE(w_filename,filename); + obj_desc.guidClass = CLSID_DirectMusicSegment; + + wcscpy (obj_desc.wszFileName,w_filename); + obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME; + + // release the existing segment if we have any + if (NULL != segment) + ReleaseSegment(); + + // and make a new segment + if (FAILED(loader->GetObject(&obj_desc, + (REFIID)IID_IDirectMusicSegment, + (LPVOID *) &segment))) { + MSGBOX("LoadMIDI: Get object failed"); + return FALSE; + } + + // next we need to tell the segment what kind of data it contains. We do this + // with the IDirectMusicSegment::SetParam function. + if (FAILED(segment->SetParam((REFGUID)GUID_StandardMIDIFile, + -1, 0, 0, (LPVOID)performance))) { + MSGBOX("LoadMIDI: SetParam (MIDI file) failed"); + return false; + } + + // finally, we need to tell the segment to 'download' the instruments + if (FAILED(segment->SetParam((REFGUID)GUID_Download, + -1, 0, 0, (LPVOID)performance))) { + MSGBOX("LoadMIDI: Failed to download instruments"); + return false; + } + + // at this point, the MIDI file is loaded and ready to play! + return true; +} + +// Start playing the MIDI file +void PlaySegment (void) +{ + if (NULL == performance) + return; + + if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) { + MSGBOX("PlaySegment failed"); + } +} + +// Stop playing +void StopSegment (void) +{ + if (NULL == performance || NULL == segment) + return; + + if (FAILED(performance->Stop(segment, NULL, 0, 0))) { + MSGBOX("StopSegment failed"); + } +} + +// Find out whether playing has started or stopped +bool IsSegmentPlaying (void) +{ + if (NULL == performance || NULL == segment) + return FALSE; + + // IsPlaying return S_OK if the segment is currently playing + return performance->IsPlaying(segment, NULL) == S_OK ? TRUE : FALSE; +} + +void SetVolume(long vol) +{ + long db; + + if (performance == NULL && !InitDirectMusic()) + return; + + db = ((vol >> 21) & 0x7ff) - 1000; + performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db)); +} + +#if defined(__cplusplus) +} +#endif + +#endif // WIN32_ENABLE_DIRECTMUSIC_SUPPORT diff --git a/water_cmd.c b/water_cmd.c new file mode 100644 --- /dev/null +++ b/water_cmd.c @@ -0,0 +1,612 @@ +#include "stdafx.h" +#include "ttd.h" +#include "vehicle.h" +#include "viewport.h" +#include "command.h" +#include "town.h" + +bool IsShipDepotTile(TileIndex tile) +{ + return IS_TILETYPE(tile, MP_WATER) && (_map5[tile]&~3) == 0x80; +} + +bool IsClearWaterTile(uint tile) +{ + TileInfo ti; + FindLandscapeHeightByTile(&ti, tile); + return (ti.type == MP_WATER && ti.tileh == 0 && ti.map5 == 0); +} + +/* Build a ship depot + * p1 - direction + */ + +int32 CmdBuildShipDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile, tile2; + + int32 cost, ret; + Depot *dep; + + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + tile = TILE_FROM_XY(x,y); + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + tile2 = tile + (p1 ? TILE_XY(0,1) : TILE_XY(1,0)); + if (!EnsureNoVehicle(tile2)) + return CMD_ERROR; + + if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2)) + return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER); + + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + ret = DoCommandByTile(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) + return CMD_ERROR; + + // pretend that we're not making land from the water even though we actually are. + cost = 0; + + dep = AllocateDepot(); + if (dep == NULL) + return CMD_ERROR; + + if (flags & DC_EXEC) { + dep->xy = tile; + _last_built_ship_depot_tile = tile; + dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; + + ModifyTile(tile, + MP_SETTYPE(MP_WATER) | MP_MAPOWNER_CURRENT | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, + (0x80 + p1*2) + ); + + ModifyTile(tile2, + MP_SETTYPE(MP_WATER) | MP_MAPOWNER_CURRENT | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, + (0x81 + p1*2) + ); + } + + return cost + _price.build_ship_depot; +} + +static int32 RemoveShipDepot(uint tile, uint32 flags) +{ + uint tile2; + + if (!CheckTileOwnership(tile)) + return CMD_ERROR; + + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + tile2 = tile + ((_map5[tile] & 2) ? TILE_XY(0,1) : TILE_XY(1,0)); + + if (!EnsureNoVehicle(tile2)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + Depot *d; + + // convert the cleared tiles to water + ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0); + ModifyTile(tile2, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0); + + // Kill the entry from the depot table + for(d=_depots; d->xy != tile; d++) {} + d->xy = 0; + + DeleteWindowById(WC_VEHICLE_DEPOT, tile); + } + + return _price.remove_ship_depot; +} + +// build a shiplift +static int32 DoBuildShiplift(uint tile, int dir, uint32 flags) +{ + int32 ret; + int delta; + + // middle tile + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + + delta = _tileoffs_by_dir[dir]; + // lower tile + ret = DoCommandByTile(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + if (GetTileSlope(tile - delta, NULL)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + // upper tile + ret = DoCommandByTile(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret == CMD_ERROR) return CMD_ERROR; + if (GetTileSlope(tile + delta, NULL)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + if (flags & DC_EXEC) { + ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x10 + dir); + ModifyTile(tile - delta, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x14 + dir); + ModifyTile(tile + delta, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x18 + dir); + } + + return _price.clear_water * 22 >> 3; +} + +static int32 RemoveShiplift(uint tile, uint32 flags) +{ + int delta = _tileoffs_by_dir[_map5[tile] & 3]; + + // make sure no vehicle is on the tile. + if (!EnsureNoVehicle(tile) || !EnsureNoVehicle(tile + delta) || !EnsureNoVehicle(tile - delta)) + return CMD_ERROR; + + if (flags & DC_EXEC) { + DoClearSquare(tile); + DoClearSquare(tile + delta); + DoClearSquare(tile - delta); + } + + return _price.clear_water * 2; +} + +static void MarkTilesAroundDirty(uint tile) +{ + MarkTileDirtyByTile(TILE_ADDXY(tile, 0, 1)); + MarkTileDirtyByTile(TILE_ADDXY(tile, 0, -1)); + MarkTileDirtyByTile(TILE_ADDXY(tile, 1, 0)); + MarkTileDirtyByTile(TILE_ADDXY(tile, -1, 0)); +} + +int32 CmdBuildLock(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + int32 ret; + uint th; + th = GetTileSlope(tile, NULL); + + if (th==3 || th==6 || th==9 || th==12) { + static const byte _shiplift_dirs[16] = {0,0,0,2,0,0,1,0,0,3,0,0,0}; + ret = DoBuildShiplift(tile, _shiplift_dirs[th], flags); + return ret; + } + else + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + return 0; +} + +int32 CmdBuildCanal(int x, int y, uint32 flags, uint32 p1, uint32 p2) +{ + uint tile = TILE_FROM_XY(x,y); + int32 ret; + uint th; + uint endtile = (uint)p1; + int delta; + int32 cost; + SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + + // move in which direction? + delta = (GET_TILE_X(tile) == GET_TILE_X(endtile)) ? TILE_XY(0,1) : TILE_XY(1,0); + if (endtile < tile) delta = -delta; + + cost = 0; + for(;;) { + ret = 0; + th = GetTileSlope(tile, NULL); + if(th!=0) + return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); + + // can't make water of water! + if (IS_TILETYPE(tile, MP_WATER)) { + _error_message = STR_1007_ALREADY_BUILT; + } else { + + /* is middle piece of a bridge? */ + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && _map5[tile] & 0x40) { /* build under bridge */ + if(_map5[tile] & 0x20) { // transport route under bridge + _error_message = STR_5800_OBJECT_IN_THE_WAY; + ret = CMD_ERROR; + } + else if (_map5[tile] & 0x18) { // already water under bridge + _error_message = STR_1007_ALREADY_BUILT; + ret = CMD_ERROR; + } + + /* no bridge? then try to clear it. */ + } else { + ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + } + if (ret == CMD_ERROR) return ret; + cost += ret; + + /* execute modifications */ + if (flags & DC_EXEC) { + if(IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + // change owner to OWNER_WATER and set land under bridge bit to water + ModifyTile(tile, MP_MAP5 | MP_MAPOWNER, OWNER_WATER, _map5[tile] | 0x08); + } else { + ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0); + } + // mark the tiles around dirty too + MarkTilesAroundDirty(tile); + } + + cost += _price.clear_water; + } + if (tile == endtile) + break; + tile += delta; + } + if (cost == 0) return CMD_ERROR; + + return cost; +} + +static int32 ClearTile_Water(uint tile, byte flags) { + byte m5 = _map5[tile]; + uint slope; + + if (m5 <= 1) { // water and shore + // Allow building on water? It's ok to build on shores. + if (flags & DC_NO_WATER && m5 != 1) + return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); + + // Make sure no vehicle is on the tile + if (!EnsureNoVehicle(tile)) + return CMD_ERROR; + + // Make sure it's not an edge tile. + if (!(IS_INT_INSIDE(GET_TILE_X(tile),1,TILE_X_MAX-1) && + IS_INT_INSIDE(GET_TILE_Y(tile),1,TILE_Y_MAX-1))) + return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); + + if (m5 == 0) { + if (flags & DC_EXEC) + DoClearSquare(tile); + return _price.clear_water; + } else if (m5 == 1) { + slope = GetTileSlope(tile,NULL); + if (slope == 8 || slope == 4 || slope == 2 || slope == 1) { + if (flags & DC_EXEC) + DoClearSquare(tile); + return _price.clear_water; + } + if (flags & DC_EXEC) + DoClearSquare(tile); + return _price.purchase_land; + } else + return CMD_ERROR; + } else if ((m5 & 0x10) == 0x10) { + // shiplift + + static const TileIndexDiff _shiplift_tomiddle_offs[12] = { + 0,0,0,0, // middle + TILE_XY(-1, 0),TILE_XY(0, 1),TILE_XY(1, 0),TILE_XY(0, -1), // lower + TILE_XY(1, 0),TILE_XY(0, -1),TILE_XY(-1, 0),TILE_XY(0, 1), // upper + }; + + if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); + // don't allow water to delete it. + if (_current_player == OWNER_WATER) return CMD_ERROR; + // move to the middle tile.. + return RemoveShiplift(tile + _shiplift_tomiddle_offs[m5 & 0xF], flags); + } else { + // ship depot + if (flags & DC_AUTO) + return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); + + if (m5 == 0x80 || m5 == 0x82) {} + else if (m5 == 0x81) { tile -= TILE_XY(1,0); } + else if (m5 == 0x83) { tile -= TILE_XY(0,1); } + else + return CMD_ERROR; + + return RemoveShipDepot(tile,flags); + } +} + +// return true if a tile is a water tile. +static bool IsWateredTile(uint tile) +{ + byte m5 = _map5[tile]; + if (IS_TILETYPE(tile, MP_WATER)) { + return m5 != 1; + } else if (IS_TILETYPE(tile, MP_STATION)) { + // returns true if it is a dock-station (m5 inside values is m5<75 all stations, + // 83<=m5<=114 new airports + return !(m5 < 75 || (m5 >= 83 && m5 <= 114)); + } else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + return (m5 & 0xF8) == 0xC8; + } else + return false; +} + +// draw a canal styled water tile with dikes around +void DrawCanalWater(uint tile) +{ + uint wa; + + // determine the edges around with water. + wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0; + wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1; + wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2; + wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3; + + if (!(wa & 1)) DrawGroundSprite(SPR_CANALS_BASE + 57); + if (!(wa & 2)) DrawGroundSprite(SPR_CANALS_BASE + 58); + if (!(wa & 4)) DrawGroundSprite(SPR_CANALS_BASE + 59); + if (!(wa & 8)) DrawGroundSprite(SPR_CANALS_BASE + 60); + + // right corner + if ((wa & 3) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 4); + else if ((wa & 3) == 3 && !IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 8); + + // bottom corner + if ((wa & 6) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 5); + else if ((wa & 6) == 6 && !IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 9); + + // left corner + if ((wa & 12) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 6); + else if ((wa & 12) == 12 && !IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 10); + + // upper corner + if ((wa & 9) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 7); + else if ((wa & 9) == 9 && !IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 11); +} + +typedef struct WaterDrawTileStruct { + int8 delta_x; + int8 delta_y; + int8 delta_z; + byte width; + byte height; + byte unk; + SpriteID image; +} WaterDrawTileStruct; + +typedef struct LocksDrawTileStruct { + int8 delta_x, delta_y, delta_z; + byte width, height, depth; + SpriteID image; +} LocksDrawTileStruct; + +#include "table/water_land.h" + +static void DrawWaterStuff(TileInfo *ti, const byte *t, uint32 palette, uint base) +{ + const WaterDrawTileStruct *wdts; + uint32 image; + + DrawGroundSprite(*(uint16*)t); + t += sizeof(uint16); + + for(wdts = (WaterDrawTileStruct *)t; (byte)wdts->delta_x != 0x80; wdts++) { + image = wdts->image + base; + if (_display_opt & DO_TRANS_BUILDINGS) { + image |= palette; + } else { + image = (image & 0x3FFF) | 0x03224000; + } + AddSortableSpriteToDraw(image, ti->x + wdts->delta_x, ti->y + wdts->delta_y, wdts->width, wdts->height, wdts->unk, ti->z + wdts->delta_z); + } +} + +static void DrawTile_Water(TileInfo *ti) +{ + // draw water tile + if (ti->map5 == 0) { + DrawGroundSprite(0xFDD); + if (ti->z != 0) DrawCanalWater(ti->tile); + return; + } + + // draw shore + if (ti->map5 == 1) { + assert(ti->tileh < 16); + DrawGroundSprite(_water_shore_sprites[ti->tileh]); + return; + } + + // draw shiplift + if ((ti->map5 & 0xF0) == 0x10) { + const byte *t = _shiplift_display_seq[ti->map5 & 0xF]; + DrawWaterStuff(ti, t, 0, ti->z > t[19] ? 24 : 0); + return; + } + + DrawWaterStuff(ti, _shipdepot_display_seq[ti->map5 & 0x7F], PLAYER_SPRITE_COLOR(_map_owner[ti->tile]), 0); +} + +void DrawShipDepotSprite(int x, int y, int image) +{ + const byte *t; + const WaterDrawTileStruct *wdts; + + t = _shipdepot_display_seq[image]; + DrawSprite(*(uint16*)t, x, y); + t += sizeof(uint16); + + for(wdts = (WaterDrawTileStruct *)t; (byte)wdts->delta_x != 0x80; wdts++) { + Point pt = RemapCoords(wdts->delta_x, wdts->delta_y, wdts->delta_z); + DrawSprite(wdts->image + PLAYER_SPRITE_COLOR(_local_player), x + pt.x, y + pt.y); + } +} + + +uint GetSlopeZ_Water(TileInfo *ti) +{ + return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; +} + +static void GetAcceptedCargo_Water(uint tile, AcceptedCargo *ac) +{ + /* not used */ +} + +static void GetTileDesc_Water(uint tile, TileDesc *td) +{ + if (_map5[tile] == 0 && GET_TILEHEIGHT(tile) == 0) + td->str = STR_3804_WATER; + else if (_map5[tile] == 0) + td->str = STR_LANDINFO_CANAL; + else if (_map5[tile] == 1) + td->str = STR_3805_COAST_OR_RIVERBANK; + else if ((_map5[tile]&0xF0) == 0x10) + td->str = STR_LANDINFO_LOCK; + else + td->str = STR_3806_SHIP_DEPOT; + + td->owner = _map_owner[tile]; +} + +static void AnimateTile_Water(uint tile) +{ + /* not used */ +} + +static void TileLoopWaterHelper(uint tile, const int16 *offs) +{ + byte *p; + + p = &_map_type_and_height[tile]; + tile += offs[0]; + + // type of this tile mustn't be water already. + if (p[offs[0]] >> 4 == MP_WATER) + return; + + if ( (p[offs[1]] | p[offs[2]]) & 0xF ) + return; + + if ( (p[offs[3]] | p[offs[4]]) & 0xF ) { + // make coast.. + if (p[offs[0]] >> 4 == MP_CLEAR || p[offs[0]] >> 4 == MP_TREES) { + _current_player = OWNER_WATER; + if (DoCommandByTile(tile,0,0,DC_EXEC | DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) + ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,OWNER_WATER,1); + } + } else { + if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) { + byte m5 = _map5[tile]; + if ( (m5&0xF8) == 0xC8 || (m5&0xF8) == 0xF0) + return; + + if ( (m5&0xC0) == 0xC0) { + ModifyTile(tile, MP_MAPOWNER | MP_MAP5,OWNER_WATER,(m5 & ~0x38)|0x8); + return; + } + } + + _current_player = OWNER_WATER; + if (DoCommandByTile(tile,0,0,DC_EXEC, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) + ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,OWNER_WATER,0); + } +} + +// called from tunnelbridge_cmd +void TileLoop_Water(uint tile) +{ + int i; + static const TileIndexDiff _tile_loop_offs_array[4][5] = { + // tile to mod shore? shore? + {TILE_XY(-1,0), TILE_XY(0,0), TILE_XY(0,1), TILE_XY(-1,0), TILE_XY(-1,1)}, + {TILE_XY(0,1), TILE_XY(0,1), TILE_XY(1,1), TILE_XY(0,2), TILE_XY(1,2)}, + {TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,1), TILE_XY(2,0), TILE_XY(2,1)}, + {TILE_XY(0,-1), TILE_XY(0,0), TILE_XY(1,0), TILE_XY(0,-1), TILE_XY(1,-1)}, + }; + + if ( IS_INT_INSIDE(GET_TILE_X(tile),1,TILES_X-3+1) && + IS_INT_INSIDE(GET_TILE_Y(tile),1,TILES_Y-3+1)) { + for(i=0; i!=4; i++) + TileLoopWaterHelper(tile, _tile_loop_offs_array[i]); + } +} + + +static const byte _coast_tracks[16] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0}; +static const byte _shipdepot_tracks[4] = {1,1,2,2}; +static const byte _shiplift_tracks[12] = {1,2,1,2,1,2,1,2,1,2,1,2}; +static uint32 GetTileTrackStatus_Water(uint tile, int mode) +{ + uint m5; + uint b; + + if (mode != 4) + return 0; + + m5 = _map5[tile]; + if (m5 == 0) + return 0x3F3F; + + if (m5 == 1) { + b = _coast_tracks[GetTileSlope(tile, NULL)&0xF]; + return b + (b<<8); + } + + if ( (m5 & 0x10) == 0x10) { + // + b = _shiplift_tracks[m5 & 0xF]; + return b + (b<<8); + } + + if (!(m5 & 0x80)) + return 0; + + b = _shipdepot_tracks[m5 & 0x7F]; + return b + (b<<8); +} + +extern void ShowShipDepotWindow(uint tile); + +static void ClickTile_Water(uint tile) +{ + byte m5 = _map5[tile] - 0x80; + + if (IS_BYTE_INSIDE(m5, 0, 3+1)) { + if (m5 & 1) + tile += (m5==1) ? TILE_XY(-1,0) : TILE_XY(0,-1); + ShowShipDepotWindow(tile); + } +} + +static void ChangeTileOwner_Water(uint tile, byte old_player, byte new_player) +{ + if (_map_owner[tile] != old_player) + return; + + if (new_player != 255) { + _map_owner[tile] = new_player; + } else { + DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); + } +} + +static uint32 VehicleEnter_Water(Vehicle *v, uint tile, int x, int y) +{ + return 0; +} + +void InitializeDock() +{ + _last_built_ship_depot_tile = 0; +} + +const TileTypeProcs _tile_type_water_procs = { + DrawTile_Water, /* draw_tile_proc */ + GetSlopeZ_Water, /* get_slope_z_proc */ + ClearTile_Water, /* clear_tile_proc */ + GetAcceptedCargo_Water, /* get_accepted_cargo_proc */ + GetTileDesc_Water, /* get_tile_desc_proc */ + GetTileTrackStatus_Water, /* get_tile_track_status_proc */ + ClickTile_Water, /* click_tile_proc */ + AnimateTile_Water, /* animate_tile_proc */ + TileLoop_Water, /* tile_loop_clear */ + ChangeTileOwner_Water, /* change_tile_owner_clear */ + NULL, /* get_produced_cargo_proc */ + VehicleEnter_Water, /* vehicle_enter_tile_proc */ + NULL, /* vehicle_leave_tile_proc */ +}; + diff --git a/widget.c b/widget.c new file mode 100644 --- /dev/null +++ b/widget.c @@ -0,0 +1,375 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gfx.h" +#include "viewport.h" + +static Point HandleScrollbarHittest(Scrollbar *sb, int top, int bottom) +{ + Point pt; + int height, count, pos, cap; + + top += 10; + bottom -= 9; + + height = (bottom - top); + + pos = sb->pos; + count = sb->count; + cap = sb->cap; + + if (count != 0) top += height * pos / count; + + if (cap > count) cap = count; + if (count != 0) + bottom -= (count - pos - cap) * height / count; + + pt.x = top; + pt.y = bottom - 1; + return pt; +} + +/***************************************************** + * Special handling for the scrollbar widget type. + * Handles the special scrolling buttons and other + * scrolling. + * Parameters: + * w - Window. + * wi - Pointer to the scrollbar widget. + * x - The X coordinate of the mouse click. + * y - The Y coordinate of the mouse click. + */ + +void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y) +{ + int mi, ma, pos; + Scrollbar *sb; + + if (wi->type == WWT_SCROLLBAR) { + // vertical scroller + w->flags4 &= ~WF_HSCROLL; + mi = wi->top; + ma = wi->bottom; + pos = y; + sb = &w->vscroll; + } else { + // horizontal scroller + assert(wi->type == WWT_HSCROLLBAR); + w->flags4 |= WF_HSCROLL; + mi = wi->left; + ma = wi->right; + pos = x; + sb = &w->hscroll; + } + + if (pos <= mi+9) { + // Pressing the upper button? + if (!_demo_mode) { + w->flags4 |= WF_SCROLL_UP; + if (_scroller_click_timeout == 0) { + _scroller_click_timeout = 6; + if (sb->pos != 0) sb->pos--; + } + _left_button_clicked = false; + } + } else if (pos >= ma-10) { + // Pressing the lower button? + if (!_demo_mode) { + w->flags4 |= WF_SCROLL_DOWN; + + if (_scroller_click_timeout == 0) { + _scroller_click_timeout = 6; + if ((byte)(sb->pos + sb->cap) < sb->count) + sb->pos++; + } + _left_button_clicked = false; + } + } else { + // + Point pt = HandleScrollbarHittest(sb, mi, ma); + + if (pos < pt.x) { + sb->pos = max(sb->pos - sb->cap, 0); + } else if (pos > pt.y) { + sb->pos = min( + sb->pos + sb->cap, + max(sb->count - sb->cap, 0) + ); + } else { + _scrollbar_start_pos = pt.x - mi - 9; + _scrollbar_size = ma - mi - 23; + w->flags4 |= WF_SCROLL_MIDDLE; + _scrolling_scrollbar = true; + _cursorpos_drag_start = _cursor.pos; + } + } + + SetWindowDirty(w); +} + +/***************************************************** + * Returns the index for the widget located at the given + * position relative to the window. + * Parameters: + * w - Window + * x/y - Window client coordinates + * Returns: + * A widget index, or -1 if no widget was found. + */ +int GetWidgetFromPos(Window *w, int x, int y) +{ + const Widget *wi; + int index, found_index = -1; + + // Go through the widgets and check if we find the widget that the coordinate is + // inside. + for(index=0,wi=w->widget; wi->type != WWT_LAST; index++, wi++) { + if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) + continue; + + if (x >= wi->left && + x < wi->right && + y >= wi->top && + y < wi->bottom && !HASBIT(w->hidden_state,index)) { + found_index = index; + } + } + + // Return the index + return found_index; +} + + +void DrawWindowWidgets(Window *w) +{ + const Widget *wi; + DrawPixelInfo *dpi = _cur_dpi; + Rect r; + uint32 dparam_backup[10]; + uint32 cur_click, cur_disabled, cur_hidden; + + if (w->desc_flags & WDF_RESTORE_DPARAM) COPY_OUT_DPARAM(dparam_backup, 0, lengthof(dparam_backup)); + + wi = w->widget; + + cur_click = w->click_state; + cur_disabled = w->disabled_state; + cur_hidden = w->hidden_state; + + do { + if (dpi->left > (r.right=/*w->left + */wi->right) || + dpi->left + dpi->width <= (r.left=wi->left/* + w->left*/) || + dpi->top > (r.bottom=/*w->top +*/ wi->bottom) || + dpi->top + dpi->height <= (r.top = /*w->top +*/ wi->top) || + (cur_hidden&1)) + continue; + + switch(wi->type&WWT_MASK) { + case WWT_PANEL: + case WWT_PANEL_2: { + int img; + + DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, + (cur_click & 1) ? 0x20 : 0); + + if ((img=wi->unkA) != 0) { + if ((wi->type&WWT_MASK) == WWT_PANEL_2 && (cur_click&1)) img++; + DrawSprite(img, r.left+1, r.top+1); + } + goto draw_default; + } + + case WWT_CLOSEBOX: + case WWT_4: { + DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, + (cur_click & 1) ? 0x20 : 0); + } + /* fall through */ + + case WWT_5: { + StringID str = wi->unkA; + + if ((wi->type&WWT_MASK) == WWT_4 && (cur_click&1)) str++; + + DrawStringCentered((r.left + r.right+1)>>1, ((r.top+r.bottom + 1)>>1) - 5, str, 0); + goto restore_dparam; + } + + case WWT_6: { + StringID str; + DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, 0x60); + + if ((str = wi->unkA) != 0) { + DrawString(r.left+2, r.top+1, str, 0); + goto restore_dparam; + } + goto draw_default; + } + + case WWT_MATRIX: { + int c, d, ctr; + int x, amt1, amt2; + int color; + + DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, + (cur_click & 1) ? 0x20 : 0); + + c = (wi->unkA&0xFF); + amt1 = (wi->right - wi->left + 1) / c; + + d = (wi->unkA >> 8); + amt2 = (wi->bottom - wi->top + 1) / d; + + color = _color_list[wi->color&0xF].window_color_bgb; + + x = r.left; + for(ctr=c; --ctr; ) { + x += amt1; + GfxFillRect(x, r.top+1, x, r.bottom-1, color); + } + + x = r.top; + for(ctr=d; --ctr; ) { + x += amt2; + GfxFillRect(r.left+1, x, r.right-1, x, color); + } + + color = _color_list[wi->color&0xF].window_color_1b; + + x = r.left-1; + for(ctr=c; --ctr; ) { + x += amt1; + GfxFillRect(x, r.top+1, x, r.bottom-1, color); + } + + x = r.top-1; + for(ctr=d; --ctr; ) { + x += amt2; + GfxFillRect(r.left+1, x, r.right-1, x, color); + } + + goto draw_default; + } + + // vertical scrollbar + case WWT_SCROLLBAR: { + Point pt; + int c1,c2; + + // draw up/down buttons + DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == WF_SCROLL_UP ? 0x20 : 0); + DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == WF_SCROLL_DOWN ? 0x20 : 0); + + // draw icons in up/down buttons + DoDrawString("\xA0", r.left+2, r.top, 0x10); + DoDrawString("\xAA", r.left+2, r.bottom-9, 0x10); + + c1 = _color_list[wi->color&0xF].window_color_1a; + c2 = _color_list[wi->color&0xF].window_color_2; + + // draw "shaded" background + GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2); + GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | 0x8000); + + // draw shaded lines + GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1); + GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2); + GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1); + GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2); + + pt = HandleScrollbarHittest(&w->vscroll, r.top, r.bottom); + DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == WF_SCROLL_MIDDLE ? 0x20 : 0); + break; + } + + // horizontal scrollbar + case WWT_HSCROLLBAR: { + Point pt; + int c1,c2; + + DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL) ? 0x20 : 0); + DrawFrameRect(r.right-9, r.top, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL) ? 0x20 : 0); + + // draw icons in up/down buttons + DoDrawString("\xA0", r.left+1, r.top+1, 0x10); + DoDrawString("\xAA", r.right-8, r.top+1, 0x10); + + c1 = _color_list[wi->color&0xF].window_color_1a; + c2 = _color_list[wi->color&0xF].window_color_2; + + // draw "shaded" background + GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c2); + GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c1 | 0x8000); + + // draw shaded lines + GfxFillRect(r.left+10, r.top+2, r.right-10, r.top+2, c1); + GfxFillRect(r.left+10, r.top+3, r.right-10, r.top+3, c2); + GfxFillRect(r.left+10, r.top+7, r.right-10, r.top+7, c1); + GfxFillRect(r.left+10, r.top+8, r.right-10, r.top+8, c2); + + // draw actual scrollbar + pt = HandleScrollbarHittest(&w->hscroll, r.left, r.right); + DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? 0x20 : 0); + + break; + } + + case WWT_FRAME: { + int c1,c2; + int x2 = 0; + + if (wi->unkA != 0) { + x2 = DrawString(r.left+6, r.top, wi->unkA, 0); + } + + c1 = _color_list[wi->color].window_color_1a; + c2 = _color_list[wi->color].window_color_2; + + //Line from upper left corner to start of text + GfxFillRect(r.left, r.top+4, r.left+4,r.top+4, c1); + GfxFillRect(r.left+1, r.top+5, r.left+4,r.top+5, c2); + + // Line from end of text to upper right corner + GfxFillRect(x2, r.top+4, r.right-1,r.top+4,c1); + GfxFillRect(x2, r.top+5, r.right-2,r.top+5,c2); + + // Line from upper left corner to bottom left corner + GfxFillRect(r.left, r.top+5, r.left, r.bottom-1, c1); + GfxFillRect(r.left+1, r.top+6, r.left+1, r.bottom-2, c2); + + //Line from upper right corner to bottom right corner + GfxFillRect(r.right-1, r.top+5, r.right-1, r.bottom-2, c1); + GfxFillRect(r.right, r.top+4, r.right, r.bottom-1, c2); + + GfxFillRect(r.left+1, r.bottom-1, r.right-1, r.bottom-1, c1); + GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2); + + goto restore_dparam; + } + + case WWT_CAPTION: { + DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, 0x10); + DrawFrameRect(r.left+1, r.top+1, r.right-1, r.bottom-1, wi->color, (w->caption_color == 0xFF) ? 0x60 : 0x70); + + if (w->caption_color != 0xFF) { + GfxFillRect(r.left+2, r.top+2, r.right-2, r.bottom-2, _color_list[_player_colors[w->caption_color]].window_color_1b); + } + + DrawStringCentered( (r.left+r.right+1)>>1, r.top+2, wi->unkA, 0x84); +restore_dparam:; + if (w->desc_flags & WDF_RESTORE_DPARAM) COPY_IN_DPARAM(0, dparam_backup, lengthof(dparam_backup)); +draw_default:; + if (cur_disabled & 1) { + GfxFillRect(r.left+1, r.top+1, r.right-1, r.bottom-1, _color_list[wi->color&0xF].unk2 | 0x8000); + } + } + } + } while (cur_click>>=1, cur_disabled>>=1, cur_hidden >>= 1, (++wi)->type != WWT_LAST); + + + if (w->flags4 & WF_WHITE_BORDER_MASK) { + //DrawFrameRect(w->left, w->top, w->left + w->width-1, w->top+w->height-1, 0xF, 0x10); + DrawFrameRect(0, 0, w->width-1, w->height-1, 0xF, 0x10); + } + +} diff --git a/win32.c b/win32.c new file mode 100644 --- /dev/null +++ b/win32.c @@ -0,0 +1,1988 @@ +#include "stdafx.h" +#include "ttd.h" +#include "gfx.h" +#include "sound.h" +#include "window.h" +#include +#include +#include "hal.h" +#include +#include +#include +#include + +#define SMART_PALETTE_ANIM + +static struct { + HWND main_wnd; + HBITMAP dib_sect; + void *bitmap_bits; + void *buffer_bits; + void *alloced_bits; + HPALETTE gdi_palette; + int width,height; + int width_org, height_org; + bool cursor_visible; + bool switch_driver; + bool fullscreen; + bool double_size; + bool has_focus; + bool running; +} _wnd; + +static HINSTANCE _inst; +static bool _has_console; + +#if defined(MINGW32) || defined(__CYGWIN__) + #define __TIMESTAMP__ __DATE__ __TIME__ +#endif + +#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT +extern const HalMusicDriver _dmusic_midi_driver; +#endif + +static void MakePalette() +{ + LOGPALETTE *pal; + int i; + byte *b; + + pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY)); + + pal->palVersion = 0x300; + pal->palNumEntries = 256; + + for(i=0,b=_cur_palette; i!=256;i++,b+=3) { + pal->palPalEntry[i].peRed = b[0]; + pal->palPalEntry[i].peGreen = b[1]; + pal->palPalEntry[i].peBlue = b[2]; + pal->palPalEntry[i].peFlags = 0; + + } + _wnd.gdi_palette = CreatePalette(pal); + if (_wnd.gdi_palette == NULL) + error("CreatePalette failed!\n"); +} + +static void UpdatePalette(HDC dc, uint start, uint count) +{ + RGBQUAD rgb[256]; + uint i; + byte *b; + + for(i=0,b = _cur_palette + start*3; i!=count; i++,b+=3) { + rgb[i].rgbRed = b[0]; + rgb[i].rgbGreen = b[1]; + rgb[i].rgbBlue = b[2]; + rgb[i].rgbReserved = 0; + } + + SetDIBColorTable(dc, start, count, rgb); +} + +static bool MyShowCursor(bool show) +{ + if (_wnd.cursor_visible == show) + return show; + + _wnd.cursor_visible = show; + ShowCursor(show); + + return !show; +} + +typedef struct { + byte vk_from; + byte vk_count; + byte map_to; +} VkMapping; + +#define AS(x,z) {x,0,z} +#define AM(x,y,z,w) {x,y-x,z} + +static const VkMapping _vk_mapping[] = { + // Pageup stuff + up/down + AM(VK_PRIOR,VK_DOWN, WKC_PAGEUP, WKC_DOWN), + // Map letters & digits + AM('A','Z','A','Z'), + AM('0','9','0','9'), + + AS(VK_ESCAPE, WKC_ESC), + AS(VK_BACK, WKC_BACKSPACE), + AM(VK_INSERT,VK_DELETE,WKC_INSERT, WKC_DELETE), + + AS(VK_SPACE, WKC_SPACE), + AS(VK_RETURN, WKC_RETURN), + AS(VK_TAB, WKC_TAB), + + // Function keys + AM(VK_F1, VK_F12, WKC_F1, WKC_F12), + + // Numeric part. + // What is the virtual keycode for numeric enter?? + AM(VK_NUMPAD0,VK_NUMPAD9, WKC_NUM_0, WKC_NUM_9), + AS(VK_DIVIDE, WKC_NUM_DIV), + AS(VK_MULTIPLY, WKC_NUM_MUL), + AS(VK_SUBTRACT, WKC_NUM_MINUS), + AS(VK_ADD, WKC_NUM_PLUS), + AS(VK_DECIMAL, WKC_NUM_DECIMAL), + {0} +}; + +static uint MapWindowsKey(uint key) +{ + const VkMapping *map = _vk_mapping - 1; + uint from; + do { + map++; + from = map->vk_from; + if (from == 0) return 0; // Unknown key pressed. + } while ((uint)(key - from) > map->vk_count); + + key = key - from + map->map_to; + if (GetAsyncKeyState(VK_SHIFT)<0) key |= WKC_SHIFT; + if (GetAsyncKeyState(VK_CONTROL)<0) key |= WKC_CTRL; + if (GetAsyncKeyState(VK_MENU)<0) key |= WKC_ALT; + return key; +} + +static void MakeWindow(bool full_screen); +static bool AllocateDibSection(int w, int h); + +static void ClientSizeChanged(int w, int h) +{ + if (_wnd.double_size) { w >>= 1; h >>= 1; } + + // allocate new dib section of the new size + if (AllocateDibSection(w, h)) { + // mark all palette colors dirty + _pal_first_dirty = 0; + _pal_last_dirty = 255; + GameSizeChanged(); + + // redraw screen + if (_wnd.running) { + _screen.dst_ptr = _wnd.buffer_bits; + UpdateWindows(); + } + } +} + +static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_PAINT: { + PAINTSTRUCT ps; + HDC dc,dc2; + HBITMAP old_bmp; + HPALETTE old_palette; + BeginPaint(hwnd, &ps); + dc = ps.hdc; + dc2 = CreateCompatibleDC(dc); + old_bmp = SelectObject(dc2, _wnd.dib_sect); + old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); + + if (_pal_last_dirty != -1) { + UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); + _pal_last_dirty = -1; + } + + BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); + SelectPalette(dc, old_palette, TRUE); + SelectObject(dc2, old_bmp); + DeleteDC(dc2); + EndPaint(hwnd, &ps); + } + return 0; + + case WM_PALETTECHANGED: + if ((HWND)wParam == hwnd) + return 0; + // FALL THROUGH + case WM_QUERYNEWPALETTE: { + HDC hDC = GetWindowDC(hwnd); + HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); + UINT nChanged = RealizePalette(hDC); + SelectPalette(hDC, hOldPalette, TRUE); + ReleaseDC(hwnd, hDC); + if (nChanged) + InvalidateRect(hwnd, NULL, FALSE); + return 0; + } + + case WM_CLOSE: + AskExitGame(); + return 0; + + case WM_LBUTTONDOWN: + SetCapture(hwnd); + _left_button_down = true; + return 0; + + case WM_LBUTTONUP: + ReleaseCapture(); + _left_button_down = false; + _left_button_clicked = false; + return 0; + + case WM_RBUTTONDOWN: + SetCapture(hwnd); + _right_button_down = true; + _right_button_clicked = true; + return 0; + + case WM_RBUTTONUP: + ReleaseCapture(); + _right_button_down = false; + return 0; + + case WM_MOUSEMOVE: { + int x = (int16)LOWORD(lParam); + int y = (int16)HIWORD(lParam); + POINT pt; + + if (_wnd.double_size) { + x >>= 1; + y >>= 1; + } + + if (_cursor.fix_at) { + int dx = x - _cursor.pos.x; + int dy = y - _cursor.pos.y; + if (dx != 0 || dy != 0) { + _cursor.delta.x += dx; + _cursor.delta.y += dy; + + pt.x = _cursor.pos.x; + pt.y = _cursor.pos.y; + + if (_wnd.double_size) { + pt.x *= 2; + pt.y *= 2; + } + ClientToScreen(hwnd, &pt); + SetCursorPos(pt.x, pt.y); + } + } else { + _cursor.delta.x += x - _cursor.pos.x; + _cursor.delta.y += y - _cursor.pos.y; + _cursor.pos.x = x; + _cursor.pos.y = y; + _cursor.dirty = true; + } + MyShowCursor(false); + return 0; + } + + case WM_KEYDOWN: + _pressed_key = MapWindowsKey(wParam) << 16; + if ((_pressed_key>>16) == ('D' | WKC_CTRL) && !_wnd.fullscreen) { + _double_size ^= 1; + _wnd.double_size = _double_size; + ClientSizeChanged(_wnd.width, _wnd.height); + MarkWholeScreenDirty(); + } + break; + + case WM_CHAR: + _pressed_key |= wParam; + break; + + case WM_SYSKEYDOWN: + switch(wParam) { + case VK_RETURN: + MakeWindow(!_wnd.fullscreen); + return 0; + default: + _pressed_key = MapWindowsKey(wParam) << 16; + break; + } + break; + case WM_NCMOUSEMOVE: + MyShowCursor(true); + return 0; + + case WM_SIZE: { + if (wParam != SIZE_MINIMIZED) { + ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); + } + return 0; + } + case WM_SIZING: { + RECT* r = (RECT*)lParam; + RECT r2; + int w, h; + + SetRect(&r2, 0, 0, 0, 0); + AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); + + w = r->right - r->left - (r2.right - r2.left); + h = r->bottom - r->top - (r2.bottom - r2.top); + if (_wnd.double_size) { w >>= 1; h >>= 1; } + w = clamp(w & ~0x7, 64, MAX_SCREEN_WIDTH); + h = clamp(h & ~0x7, 64, MAX_SCREEN_HEIGHT); + if (_wnd.double_size) { w <<= 1; h <<= 1; } + SetRect(&r2, 0, 0, w, h); + + AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); + w = r2.right - r2.left; + h = r2.bottom - r2.top; + + switch (wParam) { + case WMSZ_BOTTOM: + r->bottom = r->top + h; + break; + case WMSZ_BOTTOMLEFT: + r->bottom = r->top + h; + r->left = r->right - w; + break; + case WMSZ_BOTTOMRIGHT: + r->bottom = r->top + h; + r->right = r->left + w; + break; + case WMSZ_LEFT: + r->left = r->right - w; + break; + case WMSZ_RIGHT: + r->right = r->left + w; + break; + case WMSZ_TOP: + r->top = r->bottom - h; + break; + case WMSZ_TOPLEFT: + r->top = r->bottom - h; + r->left = r->right - w; + break; + case WMSZ_TOPRIGHT: + r->top = r->bottom - h; + r->right = r->left + w; + break; + } + return TRUE; + } + +// needed for wheel +#if !defined(WM_MOUSEWHEEL) +# define WM_MOUSEWHEEL 0x020A +#endif //WM_MOUSEWHEEL +#if !defined(GET_WHEEL_DELTA_WPARAM) +# define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) +#endif //GET_WHEEL_DELTA_WPARAM + + case WM_MOUSEWHEEL: { + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + if (delta < 0) { + _cursor.wheel++; + } else if (delta > 0) { + _cursor.wheel--; + } + return 0; + } + + case WM_ACTIVATEAPP: + _wnd.has_focus = (bool)wParam; + break; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void RegisterWndClass() +{ + static bool registered; + if (!registered) { + HINSTANCE hinst = GetModuleHandle(NULL); + WNDCLASS wnd = { + 0, + WndProcGdi, + 0, + 0, + hinst, + LoadIcon(hinst, MAKEINTRESOURCE(100)), + LoadCursor(NULL, IDC_ARROW), + 0, + 0, + "TTD" + }; + registered = true; + if (!RegisterClass(&wnd)) + error("RegisterClass failed"); + } +} + +static void MakeWindow(bool full_screen) +{ + _fullscreen = full_screen; + + _wnd.double_size = _double_size && !full_screen; + + // recreate window? + if ((full_screen|_wnd.fullscreen) && _wnd.main_wnd) { + DestroyWindow(_wnd.main_wnd); + _wnd.main_wnd = 0; + } + + if (full_screen) { + DEVMODE settings; + memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + if (_fullscreen_bpp) { + settings.dmBitsPerPel = _fullscreen_bpp; + settings.dmFields |= DM_BITSPERPEL; + } + settings.dmPelsWidth = _wnd.width_org; + settings.dmPelsHeight = _wnd.height_org; + if ((settings.dmDisplayFrequency = _display_hz) != 0) + settings.dmFields |= DM_DISPLAYFREQUENCY; + if ( !ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) { + MakeWindow(false); + return; + } + } else if (_wnd.fullscreen) { + // restore display? + ChangeDisplaySettings(NULL, 0); + } + + { + RECT r; + uint style; + int x, y, w, h; + + if ((_wnd.fullscreen=full_screen) != false) { + style = WS_POPUP | WS_VISIBLE; + SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org); + } else { + style = WS_OVERLAPPEDWINDOW | WS_VISIBLE; + SetRect(&r, 0, 0, _wnd.width, _wnd.height); + } + + AdjustWindowRect(&r, style, FALSE); + w = r.right - r.left; + h = r.bottom - r.top; + x = (GetSystemMetrics(SM_CXSCREEN)-w)>>1; + y = (GetSystemMetrics(SM_CYSCREEN)-h)>>1; + + if (_wnd.main_wnd) { + SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); + } else { + _wnd.main_wnd = CreateWindow("TTD", "OpenTTD", style, x, y, w, h, 0, 0, _inst, 0); + if (_wnd.main_wnd == NULL) + error("CreateWindow failed"); + } + } +} + +static bool AllocateDibSection(int w, int h) +{ + BITMAPINFO *bi; + HDC dc; + + w = clamp(w & ~7, 64, MAX_SCREEN_WIDTH); + h = clamp(h & ~7, 64, MAX_SCREEN_HEIGHT); + + if (w == _screen.width && h == _screen.height) + return false; + + _screen.width = _screen.pitch = w; + _screen.height = h; + + if (_wnd.alloced_bits) { + free(_wnd.alloced_bits); + _wnd.alloced_bits = NULL; + } + + bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); + memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + { + if (_wnd.double_size) { + _wnd.alloced_bits = _wnd.buffer_bits = (byte*)malloc(w * h); + w *= 2; + h *= 2; + } + + bi->bmiHeader.biWidth = _wnd.width = w; + bi->bmiHeader.biHeight = -(_wnd.height = h); + } + + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biBitCount = 8; + bi->bmiHeader.biCompression = BI_RGB; + + if (_wnd.dib_sect) + DeleteObject(_wnd.dib_sect); + + dc = GetDC(0); + _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &_wnd.bitmap_bits, NULL, 0); + if (_wnd.dib_sect == NULL) + error("CreateDIBSection failed"); + ReleaseDC(0, dc); + + if (!_wnd.double_size) + _wnd.buffer_bits = _wnd.bitmap_bits; + + return true; +} + +static const uint16 default_resolutions[][2] = { + {640,480}, + {800,600}, + {1024,768}, + {1152,864}, + {1280,960}, + {1280,1024}, + {1400,1050}, + {1600,1200}, +}; + +static void FindResolutions() +{ + int i = 0, n = 0; + DEVMODE dm; + + while (EnumDisplaySettings(NULL, i++, &dm)) { + if (dm.dmBitsPerPel == 8 && + IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH+1) && + IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT+1) && + (n == 0 || _resolutions[n-1][0] != dm.dmPelsWidth || _resolutions[n-1][1] != dm.dmPelsHeight)) { + _resolutions[n][0] = dm.dmPelsWidth; + _resolutions[n][1] = dm.dmPelsHeight; + if (++n == sizeof(_resolutions) / (sizeof(uint16)*2)) break; + } + } + + if (n == 0) { + memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); + n = 6; + } + + _num_resolutions = n; +} + + +static char *Win32GdiStart(char **parm) +{ + memset(&_wnd, 0, sizeof(_wnd)); + _wnd.cursor_visible = true; + + RegisterWndClass(); + + MakePalette(); + + FindResolutions(); + + // fullscreen uses those + _wnd.width_org = _cur_resolution[0]; + _wnd.height_org = _cur_resolution[1]; + + AllocateDibSection(_cur_resolution[0], _cur_resolution[1]); + MarkWholeScreenDirty(); + + MakeWindow(_fullscreen); + + return NULL; +} + +static void Win32GdiStop() +{ + if ( _wnd.fullscreen ) { + ChangeDisplaySettings(NULL, 0); + } + MyShowCursor(true); + DeleteObject(_wnd.gdi_palette); + DeleteObject(_wnd.dib_sect); + DestroyWindow(_wnd.main_wnd); +} + +// simple upscaler by 2 +static void filter(int left, int top, int width, int height) +{ + uint p = _screen.pitch; + byte *s = (byte*)_wnd.buffer_bits + top * p + left; + byte *d = (byte*)_wnd.bitmap_bits + top * p * 4 + left * 2; + int i; + + while (height) { + for(i=0; i!=width; i++) { + d[i*2] = d[i*2+1] = d[i*2+p*2] = d[i*2+1+p*2] = s[i]; + } + s += p; + d += p * 4; + height--; + } +} + +static void Win32GdiMakeDirty(int left, int top, int width, int height) +{ + RECT r = {left, top, left+width, top+height}; + if (_wnd.double_size) { + filter(left, top, width, height); + //filter(0, 0, 640, 480); + r.left *= 2;r.top *= 2;r.right *= 2;r.bottom *= 2; + } + InvalidateRect(_wnd.main_wnd, &r, FALSE); +} + +static void CheckPaletteAnim() +{ + if (_pal_last_dirty == -1) + return; + InvalidateRect(_wnd.main_wnd, NULL, FALSE); +} + +static int Win32GdiMainLoop() +{ + MSG mesg; + uint32 next_tick = GetTickCount() + 30, cur_ticks; + + _wnd.running = true; + + while(true) { + while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) { + InteractiveRandom(); // randomness + TranslateMessage(&mesg); + DispatchMessage(&mesg); + } + if (_exit_game) return ML_QUIT; + if (_wnd.switch_driver) return ML_SWITCHDRIVER; + +#if defined(_DEBUG) + if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) { +#else + if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0) { +#endif + _fast_forward |= 2; + } else if (_fast_forward&2) { + _fast_forward = 0; + } + + + cur_ticks=GetTickCount(); + if ((_fast_forward && !_pause) || cur_ticks > next_tick) + next_tick = cur_ticks; + + if (cur_ticks == next_tick) { + next_tick += 30; + _ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0; + _shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0; + _dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0; + + // determine which directional keys are down + _dirkeys = + (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) + + (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) + + (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) + + (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0); + + GameLoop(); + _cursor.delta.x = _cursor.delta.y = 0; + + if (_force_full_redraw) + MarkWholeScreenDirty(); + + GdiFlush(); + _screen.dst_ptr = _wnd.buffer_bits; + UpdateWindows(); + CheckPaletteAnim(); + } else { + Sleep(1); + GdiFlush(); + _screen.dst_ptr = _wnd.buffer_bits; + DrawMouseCursor(); + } + } +} + +static bool Win32GdiChangeRes(int w, int h) +{ + _wnd.width = _wnd.width_org = w; + _wnd.height = _wnd.height_org = h; + + MakeWindow(_wnd.fullscreen); + + return true; +} + +const HalVideoDriver _win32_video_driver = { + Win32GdiStart, + Win32GdiStop, + Win32GdiMakeDirty, + Win32GdiMainLoop, + Win32GdiChangeRes, +}; + + +/********************** + * WIN32 MIDI PLAYER + **********************/ + +struct { + bool stop_song; + bool terminate; + bool playing; + int new_vol; + HANDLE wait_obj; + char start_song[260]; +} _midi; + +static void Win32MidiPlaySong(const char *filename) +{ + strcpy(_midi.start_song, filename); + _midi.playing = true; + _midi.stop_song = false; + SetEvent(_midi.wait_obj); +} + +static void Win32MidiStopSong() +{ + if (_midi.playing) { + _midi.stop_song = true; + _midi.start_song[0] = 0; + SetEvent(_midi.wait_obj); + } +} + +static bool Win32MidiIsSongPlaying() +{ + return _midi.playing; +} + +static void Win32MidiSetVolume(byte vol) +{ + _midi.new_vol = vol; + SetEvent(_midi.wait_obj); +} + +static long CDECL MidiSendCommand(const char *cmd, ...) { + va_list va; + char buf[512]; + va_start(va, cmd); + vsprintf(buf, cmd, va); + va_end(va); + return mciSendStringA(buf, NULL, 0, 0); +} + +static bool MidiIntPlaySong(const char *filename) +{ + MidiSendCommand("close all"); + if (MidiSendCommand("open %s type sequencer alias song", filename) != 0) + return false; + + if (MidiSendCommand("play song from 0") != 0) + return false; + return true; +} + +static void MidiIntStopSong() +{ + MidiSendCommand("close all"); +} + +static void MidiIntSetVolume(int vol) +{ + uint v = (vol * 65535 / 127); + midiOutSetVolume((HMIDIOUT)-1, v + (v<<16)); +} + +static bool MidiIntIsSongPlaying() +{ + char buf[16]; + mciSendStringA("status song mode", buf, sizeof(buf), 0); + return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0; +} + +static DWORD WINAPI MidiThread(LPVOID arg) +{ + char *s; + int vol; + + _midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL); + + do { + if ((vol=_midi.new_vol) != -1) { + _midi.new_vol = -1; + MidiIntSetVolume(vol); + + } + if ((s=_midi.start_song)[0]) { + _midi.playing = MidiIntPlaySong(s); + s[0] = 0; + + // Delay somewhat in case we don't manage to play. + if (!_midi.playing) { + Sleep(5000); + } + } + if (_midi.stop_song != false && _midi.playing) { + _midi.stop_song = false; + _midi.playing = false; + MidiIntStopSong(); + } + + if (_midi.playing && !MidiIntIsSongPlaying()) + _midi.playing = false; + + WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000); + } while (!_midi.terminate); + + DeleteObject(_midi.wait_obj); + return 0; +} + +static char *Win32MidiStart(char **parm) +{ + DWORD threadId; + memset(&_midi, 0, sizeof(_midi)); + _midi.new_vol = -1; + CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId); + return 0; +} + +static void Win32MidiStop() +{ + _midi.terminate = true; + SetEvent(_midi.wait_obj); +} + +const HalMusicDriver _win32_music_driver = { + Win32MidiStart, + Win32MidiStop, + Win32MidiPlaySong, + Win32MidiStopSong, + Win32MidiIsSongPlaying, + Win32MidiSetVolume, +}; + +// WIN32 Sound code. + +static HWAVEOUT _waveout; +static WAVEHDR _wave_hdr[2]; +static int _bufsize; +static void PrepareHeader(WAVEHDR *hdr) +{ + hdr->dwBufferLength = _bufsize*4; + hdr->dwFlags = 0; + hdr->lpData = malloc(_bufsize*4); + if (hdr->lpData == NULL || waveOutPrepareHeader(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) + error("waveOutPrepareHeader failed"); +} + +static void FillHeaders() +{ + WAVEHDR *hdr; + for(hdr=_wave_hdr; hdr != endof(_wave_hdr); hdr++) { + if (!(hdr->dwFlags & WHDR_INQUEUE)) { + MxMixSamples(_mixer, hdr->lpData, hdr->dwBufferLength >> 2); + if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) + error("waveOutWrite failed"); + } + } +} + +static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) +{ + switch(uMsg) { + case WOM_DONE: + if (_waveout) + FillHeaders(); + break; + } +} + +static char *Win32SoundStart(char **parm) +{ + WAVEFORMATEX wfex; + int hz; + + _bufsize = GetDriverParamInt(parm, "bufsize", 1024); + hz = GetDriverParamInt(parm, "hz", 11025); + wfex.wFormatTag = WAVE_FORMAT_PCM; + wfex.nChannels = 2; + wfex.nSamplesPerSec = hz; + wfex.nAvgBytesPerSec = hz*2*2; + wfex.nBlockAlign = 4; + wfex.wBitsPerSample = 16; + if (waveOutOpen(&_waveout, WAVE_MAPPER, &wfex, (DWORD)&waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) + return "waveOutOpen failed"; + PrepareHeader(&_wave_hdr[0]); + PrepareHeader(&_wave_hdr[1]); + FillHeaders(); + return NULL; +} + +static void Win32SoundStop() +{ + HWAVEOUT waveout = _waveout; + _waveout = NULL; + waveOutReset(waveout); + waveOutUnprepareHeader(waveout, &_wave_hdr[0], sizeof(WAVEHDR)); + waveOutUnprepareHeader(waveout, &_wave_hdr[1], sizeof(WAVEHDR)); + waveOutClose(waveout); +} + +const HalSoundDriver _win32_sound_driver = { + Win32SoundStart, + Win32SoundStop, +}; + +// Helper function needed by dynamically loading SDL +bool LoadLibraryList(void **proc, const char *dll) +{ + HMODULE lib; + void *p; + + while (*dll) { + lib = LoadLibrary(dll); + if (lib == NULL) + return false; + while (true) { + while(*dll++); + if (!*dll) + break; + p = GetProcAddress(lib, dll); + if (p == NULL) + return false; + *proc++ = p; + } + dll++; + } + return true; +} + +static const char *_exception_string; +static void *_safe_esp; +static char *_crash_msg; +static bool _expanded; +static bool _did_emerg_save; +static int _ident; + +void ShowOSErrorBox(const char *buf) +{ + MyShowCursor(true); + MessageBoxA(GetActiveWindow(), buf, "Error!", MB_ICONSTOP); + +// if exception tracker is enabled, we crash here to let the exception handler handle it. +#if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG) + if (*buf == '!') { + _exception_string = buf; + *(byte*)0 = 0; + } +#endif + +} + +#ifdef _MSC_VER + +typedef struct DebugFileInfo { + uint32 size; + uint32 crc32; + SYSTEMTIME file_time; +} DebugFileInfo; + + + +static uint32 *_crc_table; + +static void MakeCRCTable(uint32 *table) { + uint32 crc, poly = 0xEDB88320L; + int i, j; + + _crc_table = table; + + for (i=0; i!=256; i++) { + crc = i; + for (j=8; j!=0; j--) { + if (crc & 1) + crc = (crc >> 1) ^ poly; + else + crc>>=1; + } + table[i] = crc; + } +} + +static uint32 CalcCRC(byte *data, uint size, uint32 crc) { + do { + crc = ((crc>>8) & 0x00FFFFFF) ^ _crc_table[ (crc^(*data++)) & 0xFF ]; + } while (--size); + return crc; +} + +static void GetFileInfo(DebugFileInfo *dfi, const char *filename) +{ + memset(dfi, 0, sizeof(dfi)); + + { + HANDLE file; + byte buffer[1024]; + DWORD numread; + uint32 filesize = 0; + FILETIME write_time; + uint32 crc = (uint32)-1; + + file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + if (file != INVALID_HANDLE_VALUE) { + while(true) { + if (ReadFile(file, buffer, sizeof(buffer), &numread, NULL) == 0 || numread==0) + break; + filesize += numread; + crc = CalcCRC(buffer, numread, crc); + } + dfi->size = filesize; + dfi->crc32 = crc ^ (uint32)-1; + + if (GetFileTime(file, NULL, NULL, &write_time)) { + FileTimeToSystemTime(&write_time, &dfi->file_time); + } + CloseHandle(file); + } + } +} + + +static char *PrintModuleInfo(char *output, HMODULE mod) +{ + char *buffer = alloca(MAX_PATH); + DebugFileInfo dfi; + GetModuleFileName(mod, buffer, MAX_PATH); + GetFileInfo(&dfi, buffer); + output += sprintf(output, " %-20s handle: %.8X size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", + buffer, + mod, + dfi.size, + dfi.crc32, + dfi.file_time.wYear, + dfi.file_time.wMonth, + dfi.file_time.wDay, + dfi.file_time.wHour, + dfi.file_time.wMinute, + dfi.file_time.wSecond + ); + return output; +} + +static char *PrintModuleList(char *output) +{ + BOOL (WINAPI *EnumProcessModules)(HANDLE,HMODULE*,DWORD,LPDWORD); + HANDLE proc; + HMODULE modules[100]; + DWORD needed; + BOOL res; + int count,i; + + if (LoadLibraryList((void*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0")) { + proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); + if (proc) { + res = EnumProcessModules(proc, modules, sizeof(modules), &needed); + CloseHandle(proc); + if (res) { + count = min(needed/sizeof(HMODULE*), sizeof(modules)/sizeof(HMODULE*)); + for(i=0; i!=count; i++) + output = PrintModuleInfo(output, modules[i]); + return output; + } + } + } + output = PrintModuleInfo(output, NULL); + return output; +} + +static const char _crash_desc[] = + "A serious fault condition occured in the game. The game will shut down.\n" + "Press \"Submit report\" to send crash information to the developers. " + "This will greatly help debugging. The information contained in the report is " + "displayed below.\n" + "Press \"Emergency save\" to attempt saving the game."; + +static const char _save_succeeded[] = + "Emergency save succeeded.\nBe aware that critical parts of the internal game state " + "may have become corrupted. The saved game is not guaranteed to work."; + +bool EmergencySave(); + + +typedef struct { + HINTERNET (WINAPI *InternetOpenA)(LPCSTR,DWORD, LPCSTR, LPCSTR, DWORD); + HINTERNET (WINAPI *InternetConnectA)(HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD); + HINTERNET (WINAPI *HttpOpenRequestA)(HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR *, DWORD, DWORD); + BOOL (WINAPI *HttpSendRequestA)(HINTERNET, LPCSTR, DWORD, LPVOID, DWORD); + BOOL (WINAPI *InternetCloseHandle)(HINTERNET); + BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); +} WinInetProcs; + +#define M(x) x "\0" +static const char wininet_files[] = + M("wininet.dll") + M("InternetOpenA") + M("InternetConnectA") + M("HttpOpenRequestA") + M("HttpSendRequestA") + M("InternetCloseHandle") + M("HttpQueryInfoA") + M(""); +#undef M + +static WinInetProcs _wininet; + + +static char *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const char *arg) +{ + HINTERNET inet, conn, http; + char *err = NULL; + DWORD code, len; + static char buf[100]; + char buff[100]; + + if (_wininet.InternetOpen == NULL && !LoadLibraryList((void**)&_wininet, wininet_files)) return "can't load wininet.dll"; + + inet = _wininet.InternetOpen("TTD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); + if (inet == NULL) { err = "internetopen failed"; goto error1; } + + conn = _wininet.InternetConnect(inet, "openttd.com", INTERNET_DEFAULT_HTTP_PORT, "", "", INTERNET_SERVICE_HTTP, 0, 0); + if (conn == NULL) { err = "internetconnect failed"; goto error2; } + + sprintf(buff, "/crash.php?file=%s&ident=%d", arg, _ident); + + http = _wininet.HttpOpenRequest(conn, "POST", buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0); + if (http == NULL) { err = "httpopenrequest failed"; goto error3; } + + if (!_wininet.HttpSendRequest(http, "Content-type: application/binary", -1, msg, msglen)) { err = "httpsendrequest failed"; goto error4; } + + len = sizeof(code); + if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = "httpqueryinfo failed"; goto error4; } + + if (code != 200) { + int l = sprintf(buf, "Server said: %d ", code); + len = sizeof(buf) - l; + _wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0); + err = buf; + } + +error4: + _wininet.InternetCloseHandle(http); +error3: + _wininet.InternetCloseHandle(conn); +error2: + _wininet.InternetCloseHandle(inet); +error1: + return err; +} + +static void SubmitFile(HWND wnd, const char *file) +{ + HANDLE h; + unsigned long size; + unsigned long read; + void *mem; + + h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (h == NULL) return; + + size = GetFileSize(h, NULL); + if (size > 500000) goto error1; + + mem = malloc(size); + if (mem == NULL) goto error1; + + if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2; + + SubmitCrashReport(wnd, mem, size, file); + +error2: + free(mem); +error1: + CloseHandle(h); +} + +static const char * const _expand_texts[] = {"S&how report >>", "&Hide report <<" }; + +static void SetWndSize(HWND wnd, int mode) +{ + RECT r,r2; + int offs; + + GetWindowRect(wnd, &r); + + SetDlgItemText(wnd, 15, _expand_texts[mode == 1]); + + if (mode >= 0) { + GetWindowRect(GetDlgItem(wnd, 11), &r2); + offs = r2.bottom - r2.top + 10; + if (!mode) offs=-offs; + SetWindowPos(wnd, HWND_TOPMOST, 0, 0, r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER); + } else { + SetWindowPos(wnd, HWND_TOPMOST, + (GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) >> 1, + (GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) >> 1, + 0, 0, SWP_NOSIZE); + } +} + +static bool DoEmergencySave(HWND wnd) +{ + bool b = false; + + EnableWindow(GetDlgItem(wnd, 13), FALSE); + _did_emerg_save = true; + __try { + b = EmergencySave(); + } __except (1) {} + return b; +} + +static BOOL CALLBACK CrashDialogFunc(HWND wnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + SetDlgItemText(wnd, 10, _crash_desc); + SetDlgItemText(wnd, 11, _crash_msg); + SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE); + SetWndSize(wnd, -1); + return TRUE; + case WM_COMMAND: + switch(wParam) { + case 12: // Close + ExitProcess(0); + case 13: { // Emergency save + if (DoEmergencySave(wnd)) + MessageBoxA(wnd, _save_succeeded, "Save successful", MB_ICONINFORMATION); + else + MessageBoxA(wnd, "Save failed", "Save failed", MB_ICONINFORMATION); + break; + } + case 14: { // Submit crash report + char *s; + + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), ""); + if (s) { + MessageBoxA(wnd, s, "Error", MB_ICONSTOP); + break; + } + + // try to submit emergency savegame + if (_did_emerg_save || DoEmergencySave(wnd)) { + SubmitFile(wnd, "crash.sav"); + } + // try to submit the autosaved game + if (_opt.autosave) { + char buf[40]; + sprintf(buf, "autosave%d.sav", (_autosave_ctr - 1) & 3); + SubmitFile(wnd, buf); + } + EnableWindow(GetDlgItem(wnd, 14), FALSE); + SetCursor(LoadCursor(NULL, IDC_ARROW)); + MessageBoxA(wnd, "Crash report submitted. Thank you.", "Crash Report", MB_ICONINFORMATION); + break; + } + case 15: // Expand + _expanded ^= 1; + SetWndSize(wnd, _expanded); + break; + } + return TRUE; + case WM_CLOSE: + ExitProcess(0); + } + + return FALSE; +} + +static void Handler2() +{ + ShowCursor(TRUE); + ShowWindow(GetActiveWindow(), FALSE); + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(100), NULL, CrashDialogFunc); +} + +static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) +{ + char *output; + static bool had_exception; + + if (had_exception) { ExitProcess(0); } + had_exception = true; + + _ident = GetTickCount(); // something pretty unique + + MakeCRCTable(alloca(256 * sizeof(uint32))); + _crash_msg = output = LocalAlloc(LMEM_FIXED, 8192); + + { + SYSTEMTIME time; + GetLocalTime(&time); + output += sprintf(output, + "*** OpenTTD Crash Report ***\r\n" + "Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n" + "Build: %s built on " __TIMESTAMP__ "\r\n", + time.wYear, + time.wMonth, + time.wDay, + time.wHour, + time.wMinute, + time.wSecond, + "???" + ); + } + + if (_exception_string) output += sprintf(output, "Reason: %s\r\n", _exception_string); + + output += sprintf(output, "Exception %.8X at %.8X\r\n" + "Registers:\r\n" + " EAX: %.8X EBX: %.8X ECX: %.8X EDX: %.8X\r\n" + " ESI: %.8X EDI: %.8X EBP: %.8X ESP: %.8X\r\n" + " EIP: %.8X EFLAGS: %.8X\r\n" + "\r\nBytes at CS:EIP:\r\n", + ep->ExceptionRecord->ExceptionCode, + ep->ExceptionRecord->ExceptionAddress, + ep->ContextRecord->Eax, + ep->ContextRecord->Ebx, + ep->ContextRecord->Ecx, + ep->ContextRecord->Edx, + ep->ContextRecord->Esi, + ep->ContextRecord->Edi, + ep->ContextRecord->Ebp, + ep->ContextRecord->Esp, + ep->ContextRecord->Eip, + ep->ContextRecord->EFlags + ); + + { + byte *b = (byte*)ep->ContextRecord->Eip; + int i; + for(i=0; i!=24; i++) { + if (IsBadReadPtr(b, 1)) { + output += sprintf(output, " ??"); // OCR: WAS: , 0); + } else { + output += sprintf(output, " %.2X", *b); + } + b++; + } + output += sprintf(output, + "\r\n" + "\r\nStack trace: \r\n" + ); + } + + { + int i,j; + uint32 *b = (uint32*)ep->ContextRecord->Esp; + for(j=0; j!=24; j++) { + for(i=0; i!=8; i++) { + if (IsBadReadPtr(b,sizeof(uint32))) { + output += sprintf(output, " ????????"); //OCR: WAS - , 0); + } else { + output += sprintf(output, " %.8X", *b); + } + b++; + } + output += sprintf(output, "\r\n"); + } + } + + output += sprintf(output, "\r\nModule information:\r\n"); + output = PrintModuleList(output); + + { + OSVERSIONINFO os; + os.dwOSVersionInfoSize = sizeof(os); + GetVersionEx(&os); + output += sprintf(output, "\r\nSystem information:\r\n" + " Windows version %d.%d %d %s\r\n", os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion); + } + + { + HANDLE file = CreateFile("crash.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + DWORD num_written; + if (file != INVALID_HANDLE_VALUE) { + WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL); + CloseHandle(file); + } + } + + if (_safe_esp) { + ep->ContextRecord->Eip = (DWORD)Handler2; + ep->ContextRecord->Esp = (DWORD)_safe_esp; + return EXCEPTION_CONTINUE_EXECUTION; + } else { + return EXCEPTION_EXECUTE_HANDLER; + } +} + +static void Win32InitializeExceptions() +{ + _asm { + mov _safe_esp,esp + } + + SetUnhandledExceptionFilter(ExceptionHandler); +} +#endif + +static char *_fios_path; +static char *_fios_save_path; +static char *_fios_scn_path; +static FiosItem *_fios_items; +static int _fios_count, _fios_alloc; + +static FiosItem *FiosAlloc() +{ + if (_fios_count == _fios_alloc) { + _fios_alloc += 256; + _fios_items = realloc(_fios_items, _fios_alloc * sizeof(FiosItem)); + } + return &_fios_items[_fios_count++]; +} + +static HANDLE MyFindFirstFile(char *path, char *file, WIN32_FIND_DATA *fd) +{ + char paths[MAX_PATH]; + + sprintf(paths, "%s\\%s", path, file); + return FindFirstFile(paths, fd); +} + +int CDECL compare_FiosItems (const void *a, const void *b) { + const FiosItem *da = (const FiosItem *) a; + const FiosItem *db = (const FiosItem *) b; + int r; + + if (_savegame_sort_order < 2) // sort by date + r = da->mtime < db->mtime ? 1 : -1; + else + r = stricmp(da->title[0] ? da->title : da->name, db->title[0] ? db->title : db->name); + + if (_savegame_sort_order & 1) r = -r; + return r; +} + +// Get a list of savegames +FiosItem *FiosGetSavegameList(int *num, int mode) +{ + WIN32_FIND_DATA fd; + HANDLE h; + FiosItem *fios; + int sort_start; + char buf[MAX_PATH]; + + if (_fios_save_path == NULL) { + _fios_save_path = malloc(MAX_PATH); + strcpy(_fios_save_path, _path.save_dir); + } + + if (_game_mode == GM_EDITOR) + _fios_path = _fios_scn_path; + else + _fios_path = _fios_save_path; + + // Parent directory, only if not of the type C:\. + if (_fios_path[3] != 0) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_PARENT; + strcpy(fios->title, ".. (Parent directory)"); + } + + + // Show subdirectories first + h = MyFindFirstFile(_fios_path, "*.*", &fd); + if (h != INVALID_HANDLE_VALUE) { + do { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + !(fd.cFileName[0]=='.' && (fd.cFileName[1]==0 || fd.cFileName[1]=='.' && fd.cFileName[2]==0))) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_DIR; + strcpy(fios->name, fd.cFileName); + sprintf(fios->title, "\\%s (Directory)", fd.cFileName); + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } + + // this is where to start sorting + sort_start = _fios_count; + + /* Show savegame files + * .SAV OpenTTD saved game + * .SS1 Transport Tycoon Deluxe preset game + * .SV1 Transport Tycoon Deluxe (Patch) saved game + * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game + */ + h = MyFindFirstFile(_fios_path, "*.*", &fd); + if (h != INVALID_HANDLE_VALUE) { + do { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + char *t = strrchr(fd.cFileName, '.'); + if (t && !stricmp(t, ".SAV")) { // OpenTTD + fios = FiosAlloc(); + fios->mtime = *(uint64*)&fd.ftLastWriteTime; + sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); + fios->type = FIOS_TYPE_FILE; + fios->title[0] = 0; + ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); + } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) { + int ext = 0; // start of savegame extensions in _old_extensions[] + if (t && ((ext++, !stricmp(t, ".SS1")) || (ext++, !stricmp(t, ".SV1")) || (ext++, !stricmp(t, ".SV2"))) ) { // TTDLX(Patch) + fios = FiosAlloc(); + fios->old_extension = ext-1; + fios->mtime = *(uint64*)&fd.ftLastWriteTime; + sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); + fios->type = FIOS_TYPE_OLDFILE; + GetOldSaveGameName(fios->title, buf); + ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); + } + } + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } + + qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); + + // Drives + { + char drives[256]; + char *s; + GetLogicalDriveStrings(sizeof(drives), drives); + s=drives; + while (*s) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_DRIVE; + fios->title[0] = s[0]; + fios->title[1] = ':'; + fios->title[2] = 0; + while (*s++) {} + } + } + *num = _fios_count; + return _fios_items; +} + +// Get a list of scenarios +FiosItem *FiosGetScenarioList(int *num, int mode) +{ + FiosItem *fios; + WIN32_FIND_DATA fd; + HANDLE h; + int sort_start; + char buf[MAX_PATH]; + + if (mode == SLD_NEW_GAME || _fios_scn_path == NULL) { + if (_fios_scn_path == NULL) + _fios_scn_path = malloc(MAX_PATH); + strcpy(_fios_scn_path, _path.scenario_dir); + } + + _fios_path = _fios_scn_path; + + // Parent directory, only if not of the type C:\. + if (_fios_path[3] != 0 && mode != SLD_NEW_GAME) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_PARENT; + strcpy(fios->title, ".. (Parent directory)"); + } + + // Show subdirectories first + h = MyFindFirstFile(_fios_scn_path, "*.*", &fd); + if (h != INVALID_HANDLE_VALUE && mode != SLD_NEW_GAME) { + do { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + !(fd.cFileName[0]=='.' && (fd.cFileName[1]==0 || fd.cFileName[1]=='.' && fd.cFileName[2]==0))) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_DIR; + strcpy(fios->name, fd.cFileName); + sprintf(fios->title, "\\%s (Directory)", fd.cFileName); + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } + + // this is where to start sorting + sort_start = _fios_count; + + /* Show scenario files + * .SCN OpenTTD style scenario file + * .SV0 Transport Tycoon Deluxe (Patch) scenario + * .SS0 Transport Tycoon Deluxe preset scenario + */ + h = MyFindFirstFile(_fios_scn_path, "*.*", &fd); + if (h != INVALID_HANDLE_VALUE) { + do { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + char *t = strrchr(fd.cFileName, '.'); + if (t && !stricmp(t, ".SCN")) { // OpenTTD + fios = FiosAlloc(); + fios->mtime = *(uint64*)&fd.ftLastWriteTime; + sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); + fios->type = FIOS_TYPE_SCENARIO; + fios->title[0] = 0; + ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); + } else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO || mode == SLD_NEW_GAME) { + int ext = 3; // start of scenario extensions in _old_extensions[] + if (t && ((ext++, !stricmp(t, ".SV0")) || (ext++, !stricmp(t, ".SS0"))) ) { // TTDLX(Patch) + fios = FiosAlloc(); + fios->old_extension = ext-1; + fios->mtime = *(uint64*)&fd.ftLastWriteTime; + sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); + fios->type = FIOS_TYPE_OLD_SCENARIO; + GetOldScenarioGameName(fios->title, buf); + ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); + } + } + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } + + qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); + + // Drives + if (mode != SLD_NEW_GAME) { + char drives[256]; + char *s; + GetLogicalDriveStrings(sizeof(drives), drives); + s=drives; + while (*s) { + fios = FiosAlloc(); + fios->type = FIOS_TYPE_DRIVE; + fios->title[0] = s[0]; + fios->title[1] = ':'; + fios->title[2] = 0; + while (*s++) {} + } + } + + *num = _fios_count; + return _fios_items; +} + +// Free the list of savegames +void FiosFreeSavegameList() +{ + free(_fios_items); + _fios_items = NULL; + _fios_alloc = _fios_count = 0; +} + +// Browse to +char *FiosBrowseTo(const FiosItem *item) +{ + char *path = _fios_path; + char *s; + + switch(item->type) { + case FIOS_TYPE_DRIVE: + sprintf(path, "%c:\\", item->title[0]); + break; + + case FIOS_TYPE_PARENT: + // Skip drive part + path += 3; + s = path; + while (*path) { + if (*path== '\\') + s = path; + path++; + } + *s = 0; + break; + + case FIOS_TYPE_DIR: + // Scan to end + while (*++path); + // Add backslash? + if (path[-1] != '\\') *path++ = '\\'; + + strcpy(path, item->name); + break; + + case FIOS_TYPE_FILE: + FiosMakeSavegameName(str_buffr, item->name); + return str_buffr; + + case FIOS_TYPE_OLDFILE: + sprintf(str_buffr, "%s\\%s.%s", _fios_path, item->name, _old_extensions[item->old_extension]); + return str_buffr; + + case FIOS_TYPE_SCENARIO: + sprintf(str_buffr, "%s\\%s.scn", path, item->name); + return str_buffr; + case FIOS_TYPE_OLD_SCENARIO: + sprintf(str_buffr, "%s\\%s.%s", path, item->name, _old_extensions[item->old_extension]); + return str_buffr; + } + + return NULL; +} + +// Get descriptive texts. +// Returns a path as well as a +// string describing the path. +StringID FiosGetDescText(char **path) +{ + char root[4]; + DWORD spc, bps, nfc, tnc; + *path = _fios_path; + + root[0] = _fios_path[0]; + root[1] = ':'; + root[2] = '\\'; + root[3] = 0; + if (GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) { + uint32 tot = ((spc*bps)*(uint64)nfc) >> 20; + SET_DPARAM32(0, tot); + return STR_4005_BYTES_FREE; + } else { + return STR_4006_UNABLE_TO_READ_DRIVE; + } +} + +void FiosMakeSavegameName(char *buf, const char *name) +{ + if(_game_mode == GM_EDITOR) + sprintf(buf, "%s\\%s.scn", _fios_path, name); + else + sprintf(buf, "%s\\%s.sav", _fios_path, name); +} + +void FiosDelete(const char *name) +{ + char *path = str_buffr; + FiosMakeSavegameName(path, name); + DeleteFile(path); +} + +const DriverDesc _video_driver_descs[] = { + {"null", "Null Video Driver", &_null_video_driver, 0}, +#if defined(WITH_SDL) + {"sdl", "SDL Video Driver", &_sdl_video_driver, 1}, +#endif + {"win32", "Win32 GDI Video Driver", &_win32_video_driver, 2}, + {NULL} +}; + +const DriverDesc _sound_driver_descs[] = { + {"null", "Null Sound Driver", &_null_sound_driver, 0}, +#if defined(WITH_SDL) + {"sdl", "SDL Sound Driver", &_sdl_sound_driver, 1}, +#endif + {"win32", "Win32 WaveOut Driver", &_win32_sound_driver, 2}, + {NULL} +}; + +const DriverDesc _music_driver_descs[] = { + {"null", "Null Music Driver", &_null_music_driver, 0}, + {"win32", "Win32 MIDI Driver", &_win32_music_driver, 1}, +#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT + {"dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver, 2}, +#endif + {NULL} +}; + +bool FileExists(const char *filename) +{ + HANDLE hand = CreateFile(filename, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hand == INVALID_HANDLE_VALUE) return false; + CloseHandle(hand); + return true; +} + +static int CDECL LanguageCompareFunc(const void *a, const void *b) +{ + return strcmp(*(char**)a, *(char**)b); +} + +int GetLanguageList(char **languages, int max) +{ + HANDLE hand; + int num = 0; + char filedir[MAX_PATH]; + WIN32_FIND_DATA fd; + sprintf(filedir, "%s*.lng", _path.lang_dir); + + hand = FindFirstFile(filedir, &fd); + if (hand != INVALID_HANDLE_VALUE) { + do { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + languages[num++] = strdup(fd.cFileName); + if (num == max) break; + } + } while (FindNextFile(hand, &fd)); + FindClose(hand); + } + + qsort(languages, num, sizeof(char*), LanguageCompareFunc); + return num; +} + +static int ParseCommandLine(char *line, char **argv, int max_argc) +{ + int n = 0; + + do { + // skip whitespace + while (*line == ' ' || *line == '\t') + line++; + + // end? + if (*line == 0) + break; + + // special handling when quoted + if (*line == '"') { + argv[n++] = ++line; + while (*line != '"') { + if (*line == 0) return n; + line++; + } + } else { + argv[n++] = line; + while (*line != ' ' && *line != '\t') { + if (*line == 0) return n; + line++; + } + } + *line++ = 0; + } while (n != max_argc); + + return n; +} + + +#if defined(_MSC_VER) +__int64 _declspec(naked) rdtsc() +{ + _asm { + rdtsc + ret + } +} +#endif + +void CreateConsole() +{ + HANDLE hand; + CONSOLE_SCREEN_BUFFER_INFO coninfo; + + if (_has_console) return; + + _has_console = true; + + AllocConsole(); + + hand = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hand, &coninfo); + coninfo.dwSize.Y = 500; + SetConsoleScreenBufferSize(hand, coninfo.dwSize); + + // redirect unbuffered STDIN, STDOUT, STDERR to the console +#if !defined(__CYGWIN__) + *stdout = *_fdopen( _open_osfhandle((long)hand, _O_TEXT), "w" ); + *stdin = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "w" ); + *stderr = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" ); +#else + // open_osfhandle is not in cygwin + *stdout = *fdopen(1, "w" ); + *stdin = *fdopen(0, "w" ); + *stderr = *fdopen(2, "w" ); +#endif + + setvbuf( stdin, NULL, _IONBF, 0 ); + setvbuf( stdout, NULL, _IONBF, 0 ); + setvbuf( stderr, NULL, _IONBF, 0 ); +} + +void ShowInfo(const char *str) +{ + if (_has_console) + puts(str); + else { + bool old; + + ReleaseCapture(); + _left_button_clicked =_left_button_down = false; + + old = MyShowCursor(true); + if (MessageBoxA(GetActiveWindow(), str, "OpenTTD", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) { + CreateConsole(); + } + MyShowCursor(old); + } +} + + +int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) +{ + int argc; + char *argv[64]; // max 64 command line arguments + _inst = hInstance; + +#if defined(_DEBUG) + CreateConsole(); +#endif + + // make sure we have an autosave folder - Done in DeterminePaths + // CreateDirectory("autosave", NULL); + + // setup random seed to something quite random +#if defined(_MSC_VER) + { + uint64 seed = rdtsc(); + _random_seed_1 = ((uint32*)&seed)[0]; + _random_seed_2 = ((uint32*)&seed)[1]; + } +#else + _random_seed_1 = GetTickCount(); + _random_seed_2 = _random_seed_1 * 0x1234567; +#endif + + argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv)); + +#if defined(WIN32_EXCEPTION_TRACKER) + { + Win32InitializeExceptions(); + } +#endif + +#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) + _try { + uint32 _stdcall ExceptionHandler(void *ep); +#endif + ttd_main(argc, argv); + +#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) + } _except (ExceptionHandler(_exception_info())) {} +#endif + + return 0; +} + +void DeterminePaths() +{ + char *s; + char *cfg; + + _path.personal_dir = _path.game_data_dir = cfg = malloc(MAX_PATH); + GetCurrentDirectory(MAX_PATH - 1, cfg); + + + s = strchr(cfg, 0); + if (s[-1] != '\\') { s[0] = '\\'; s[1] = 0; } + + _path.save_dir = str_fmt("%ssave", cfg); + _path.autosave_dir = str_fmt("%s\\autosave", _path.save_dir); + _path.scenario_dir = str_fmt("%sscenario", cfg); + _path.gm_dir = str_fmt("%sgm\\", cfg); + _path.data_dir = str_fmt("%sdata\\", cfg); + _path.lang_dir = str_fmt("%slang\\", cfg); + + _config_file = str_fmt("%sopenttd.cfg", _path.personal_dir); + + // make (auto)save and scenario folder + CreateDirectory(_path.save_dir, NULL); + CreateDirectory(_path.autosave_dir, NULL); + CreateDirectory(_path.scenario_dir, NULL); +} + diff --git a/window.c b/window.c new file mode 100644 --- /dev/null +++ b/window.c @@ -0,0 +1,1209 @@ +#include "stdafx.h" +#include "ttd.h" +#include "window.h" +#include "gfx.h" +#include "viewport.h" + +void HandleButtonClick(Window *w, byte widget) +{ + w->click_state |= (1 << widget); + w->flags4 |= 5 << WF_TIMEOUT_SHL; + InvalidateWidget(w, widget); +} + +void DispatchLeftClickEvent(Window *w, int x, int y) { + WindowEvent e; + const Widget *wi; + + e.click.pt.x = x; + e.click.pt.y = y; + e.event = WE_CLICK; + + if (w->desc_flags & WDF_DEF_WIDGET) { + e.click.widget = GetWidgetFromPos(w, x, y); + if (e.click.widget < 0) return; /* exit if clicked outside of widgets */ + + wi = &w->widget[e.click.widget]; + + if (wi->type & 0xE0) { + /* special widget handling */ + switch(wi->type) { + case WWT_IMGBTN | WWB_PUSHBUTTON: + case WWT_TEXTBTN | WWB_PUSHBUTTON: + if (HASBIT(w->disabled_state, e.click.widget)) + return; /* don't allow click if disabled */ + HandleButtonClick(w, e.click.widget); + break; + case WWT_NODISTXTBTN: + if (HASBIT(w->disabled_state, e.click.widget)) + return; /* don't allow click if disabled */ + break; + } + } else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_HSCROLLBAR) { + ScrollbarClickHandler(w, wi, e.click.pt.x, e.click.pt.y); + } + + w->wndproc(w, &e); + + if (w->desc_flags & WDF_STD_BTN) { + if (e.click.widget == 0) DeleteWindow(w); + else { + if (e.click.widget == 1) { + if (_ctrl_pressed) + StartWindowSizing(w); + else + StartWindowDrag(w); + } + } + } + } else { + w->wndproc(w, &e); + } +} + +void DispatchRightClickEvent(Window *w, int x, int y) { + WindowEvent e; + + /* default tooltips handler? */ + if (w->desc_flags & WDF_STD_TOOLTIPS) { + e.click.widget = GetWidgetFromPos(w, x, y); + if (e.click.widget < 0) + return; /* exit if clicked outside of widgets */ + + if (w->widget[e.click.widget].tooltips != 0) { + GuiShowTooltips(w->widget[e.click.widget].tooltips); + return; + } + } + + e.event = WE_RCLICK; + e.click.pt.x = x; + e.click.pt.y = y; + w->wndproc(w, &e); +} + + +void DispatchMouseWheelEvent(Window *w, int wheel) +{ + + if (w->vscroll.count) { + int pos = clamp(w->vscroll.pos + wheel, 0, w->vscroll.count - w->vscroll.cap); + if (pos != w->vscroll.pos) { + w->vscroll.pos = pos; + SetWindowDirty(w); + } + } +} + + +void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) +{ + Window *w; + DrawPixelInfo bk; + _cur_dpi = &bk; + + for(w=_windows; w!=_last_window; w++) { + if (right > w->left && + bottom > w->top && + left < w->left + w->width && + top < w->top + w->height) { + DrawOverlappedWindow(w, left, top, right, bottom); + } + } +} + +void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom) +{ + Window *v = w; + int x; + + while (++v != _last_window) { + if (right > v->left && + bottom > v->top && + left < v->left + v->width && + top < v->top + v->height) { + + if (left < (x=v->left)) { + DrawOverlappedWindow(w, left, top, x, bottom); + DrawOverlappedWindow(w, x, top, right, bottom); + return; + } + + if (right > (x=v->left + v->width)) { + DrawOverlappedWindow(w, left, top, x, bottom); + DrawOverlappedWindow(w, x, top, right, bottom); + return; + } + + if (top < (x=v->top)) { + DrawOverlappedWindow(w, left, top, right, x); + DrawOverlappedWindow(w, left, x, right, bottom); + return; + } + + if (bottom > (x=v->top + v->height)) { + DrawOverlappedWindow(w, left, top, right, x); + DrawOverlappedWindow(w, left, x, right, bottom); + return; + } + + return; + } + } + + { + DrawPixelInfo *dp = _cur_dpi; + dp->width = right - left; + dp->height = bottom - top; + dp->left = left - w->left; + dp->top = top - w->top; + dp->pitch = _screen.pitch; + dp->dst_ptr = _screen.dst_ptr + top * _screen.pitch + left; + dp->zoom = 0; + CallWindowEventNP(w, WE_PAINT); + } +} + +void CallWindowEventNP(Window *w, int event) +{ + WindowEvent e; + e.event = event; + w->wndproc(w, &e); +} + +void SetWindowDirty(Window *w) +{ + if (w == NULL) + return; + + SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height); +} + +void DeleteWindow(Window *w) +{ + WindowClass wc; + WindowNumber wn; + ViewPort *vp; + Window *v; + int count; + + if (w == NULL) + return; + + if (_thd.place_mode != 0 && _thd.window_class == w->window_class && _thd.window_number == w->window_number) { + ResetObjectToPlace(); + } + + wc = w->window_class; + wn = w->window_number; + + CallWindowEventNP(w, WE_DESTROY); + + w = FindWindowById(wc, wn); + + vp = w->viewport; + w->viewport = NULL; + if (vp != NULL) { + _active_viewports &= ~(1 << (vp - _viewports)); + vp->width = 0; + } + + SetWindowDirty(w); + + v = --_last_window; + count = (byte*)v - (byte*)w; + memcpy(w, w + 1, count); +} + +Window *FindWindowById(WindowClass cls, WindowNumber number) +{ + Window *w; + + for(w=_windows; w!=_last_window; w++) { + if (w->window_class == cls && + w->window_number == number) { + return w; + } + } + + return NULL; +} + +void DeleteWindowById(WindowClass cls, WindowNumber number) +{ + DeleteWindow(FindWindowById(cls, number)); +} + +Window *BringWindowToFrontById(WindowClass cls, WindowNumber number) +{ + Window *w = FindWindowById(cls, number); + + if (w != NULL) { + w->flags4 |= WF_WHITE_BORDER_MASK; + SetWindowDirty(w); + BringWindowToFront(w); + } + + return w; +} + +Window *BringWindowToFront(Window *w) +{ + Window *v; + + v = _last_window; + do { + if (--v < _windows) + return w; + } while (v->window_class == WC_MAIN_TOOLBAR || v->window_class == WC_STATUS_BAR || v->window_class == WC_NEWS_WINDOW); + + if (w == v) + return w; + + assert(w < v); + + do { + memswap(w, w+1, sizeof(Window)); + w++; + } while (v != w); + + SetWindowDirty(w); + + return w; +} + +Window *AllocateWindow( + int x, + int y, + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget) +{ + Window *w; + +restart:; + w = _last_window; + + if (w >= endof(_windows)) { + for(w=_windows; ;w++) { + assert(w < _last_window); + + if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR && + w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW) { + + DeleteWindow(w); + goto restart; + } + } + } + + if (w != _windows && cls != WC_NEWS_WINDOW) { + Window *v; + + v = FindWindowById(WC_MAIN_TOOLBAR, 0); + if (v) { + memmove(v+1, v, (byte*)w - (byte*)v); + w = v; + } + + v = FindWindowById(WC_STATUS_BAR, 0); + if (v) { + memmove(v+1, v, (byte*)w - (byte*)v); + w = v; + } + } + + /* XXX: some more code here */ + w->window_class = cls; + w->flags4 = WF_WHITE_BORDER_MASK; + w->caption_color = 0xFF; + w->window_number = 0; + w->left = x; + w->top = y; + w->width = width; + w->height = height; + w->viewport = NULL; + w->desc_flags = 0; +// w->landscape_assoc = 0xFFFF; + w->wndproc = proc; + w->click_state = 0; + w->disabled_state = 0; + w->hidden_state = 0; +// w->unk22 = 0xFFFF; + w->vscroll.pos = 0; + w->vscroll.count = 0; + w->hscroll.pos = 0; + w->hscroll.count = 0; + w->widget = widget; + + ((uint32*)w->custom)[0] = 0; + ((uint32*)w->custom)[1] = 0; + ((uint32*)w->custom)[2] = 0; + ((uint32*)w->custom)[3] = 0; + + + _last_window++; + + SetWindowDirty(w); + + return w; +} + +Window *AllocateWindowAutoPlace2( + WindowClass exist_class, + WindowNumber exist_num, + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget) +{ + Window *w; + int x; + + w = FindWindowById(exist_class, exist_num); + if (w == NULL || w->left >= (_screen.width-20) || w->left <= -60 || w->top >= (_screen.height-20)) { + return AllocateWindowAutoPlace(width,height,proc,cls,widget); + } + + x = w->left; + if (x > _screen.width - width) + x = (_screen.width - width) - 20; + + return AllocateWindow(x+10,w->top+10,width,height,proc,cls,widget); +} + + +typedef struct SizeRect { + int left,top,width,height; +} SizeRect; + + +static SizeRect _awap_r; + +static bool IsGoodAutoPlace1(int left, int top) +{ + int right,bottom; + Window *w; + + _awap_r.left= left; + _awap_r.top = top; + right = _awap_r.width + left; + bottom = _awap_r.height + top; + + if (left < 0 || top < 22 || right > _screen.width || bottom > _screen.height) + return false; + + // Make sure it is not obscured by any window. + for(w=_windows; w!=_last_window; w++) { + if (w->window_class == WC_MAIN_WINDOW) + continue; + + if (right > w->left && + w->left + w->width > left && + bottom > w->top && + w->top + w->height > top) + return false; + } + + return true; +} + +static bool IsGoodAutoPlace2(int left, int top) +{ + int width,height; + Window *w; + + _awap_r.left= left; + _awap_r.top = top; + width = _awap_r.width; + height = _awap_r.height; + + if (left < -(width>>2) || left > _screen.width - (width>>1)) + return false; + if (top < 22 || top > _screen.height - (height>>2)) + return false; + + // Make sure it is not obscured by any window. + for(w=_windows; w!=_last_window; w++) { + if (w->window_class == WC_MAIN_WINDOW) + continue; + + if (left + width > w->left && + w->left + w->width > left && + top + height > w->top && + w->top + w->height > top) + return false; + } + + return true; +} + +Point GetAutoPlacePosition(int width, int height) { + Window *w; + Point pt; + + _awap_r.width = width; + _awap_r.height = height; + + if (IsGoodAutoPlace1(0, 24)) goto ok_pos; + + for(w=_windows; w!=_last_window; w++) { + if (w->window_class == WC_MAIN_WINDOW) + continue; + + if (IsGoodAutoPlace1(w->left+w->width+2,w->top)) goto ok_pos; + if (IsGoodAutoPlace1(w->left- width-2,w->top)) goto ok_pos; + if (IsGoodAutoPlace1(w->left,w->top+w->height+2)) goto ok_pos; + if (IsGoodAutoPlace1(w->left,w->top- height-2)) goto ok_pos; + if (IsGoodAutoPlace1(w->left+w->width+2,w->top+w->height-height)) goto ok_pos; + if (IsGoodAutoPlace1(w->left- width-2,w->top+w->height-height)) goto ok_pos; + if (IsGoodAutoPlace1(w->left+w->width-width,w->top+w->height+2)) goto ok_pos; + if (IsGoodAutoPlace1(w->left+w->width-width,w->top- height-2)) goto ok_pos; + } + + for(w=_windows; w!=_last_window; w++) { + if (w->window_class == WC_MAIN_WINDOW) + continue; + + if (IsGoodAutoPlace2(w->left+w->width+2,w->top)) goto ok_pos; + if (IsGoodAutoPlace2(w->left- width-2,w->top)) goto ok_pos; + if (IsGoodAutoPlace2(w->left,w->top+w->height+2)) goto ok_pos; + if (IsGoodAutoPlace2(w->left,w->top- height-2)) goto ok_pos; + } + + { + int left=0,top=24; + +restart:; + for(w=_windows; w!=_last_window; w++) { + if (w->left == left && w->top == top) { + left += 5; + top += 5; + goto restart; + } + } + + pt.x = left; + pt.y = top; + return pt; + } + +ok_pos:; + pt.x = _awap_r.left; + pt.y = _awap_r.top; + return pt; +} + +Window *AllocateWindowAutoPlace( + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget) { + + Point pt = GetAutoPlacePosition(width, height); + return AllocateWindow(pt.x, pt.y, width, height, proc, cls, widget); +} + +Window *AllocateWindowDescFront(const WindowDesc *desc, int value) +{ + Window *w; + + if (BringWindowToFrontById(desc->cls, value)) + return NULL; + w = AllocateWindowDesc(desc); + w->window_number = value; + return w; +} + +Window *AllocateWindowDesc(const WindowDesc *desc) +{ + Point pt; + Window *w; + + if (desc->parent_cls != WC_MAIN_WINDOW && + (w = FindWindowById(desc->parent_cls, _alloc_wnd_parent_num), _alloc_wnd_parent_num=0, w) != NULL && + w->left < _screen.width-20 && w->left > -60 && w->top < _screen.height-20) { + pt.x = w->left + 10; + if (pt.x > _screen.width + 10 - desc->width) + pt.x = (_screen.width + 10 - desc->width) - 20; + pt.y = w->top + 10; + } else { + pt.x = desc->left; + pt.y = desc->top; + if (pt.x == WDP_AUTO) { + pt = GetAutoPlacePosition(desc->width, desc->height); + } else { + if (pt.x == WDP_CENTER) pt.x = (_screen.width - desc->width) >> 1; + if (pt.y == WDP_CENTER) pt.y = (_screen.height - desc->height) >> 1; + } + } + + w = AllocateWindow(pt.x, pt.y, desc->width, desc->height, desc->proc, desc->cls, desc->widgets); + w->desc_flags = desc->flags; + return w; +} + +Window *FindWindowFromPt(int x, int y) +{ + Window *w; + + for(w=_last_window; w != _windows;) { + --w; + if (IS_INSIDE_1D(x, w->left, w->width) && + IS_INSIDE_1D(y, w->top, w->height)) + return w; + } + + return NULL; +} + + +void InitWindowSystem() +{ + memset(&_windows, 0, sizeof(_windows)); + _last_window = _windows; + memset(_viewports, 0, sizeof(_viewports)); + _active_viewports = 0; +} + +void DecreaseWindowCounters() +{ + Window *w; + + + for(w=_last_window; w != _windows;) { + --w; + // Unclick scrollbar buttons if they are pressed. + if (w->flags4 & (WF_SCROLL_DOWN | WF_SCROLL_UP)) { + w->flags4 &= ~(WF_SCROLL_DOWN | WF_SCROLL_UP); + SetWindowDirty(w); + } + CallWindowEventNP(w, WE_MOUSELOOP); + } + + for(w=_last_window; w != _windows;) { + --w; + + if (w->flags4&WF_TIMEOUT_MASK && !(--w->flags4&WF_TIMEOUT_MASK)) { + CallWindowEventNP(w, WE_TIMEOUT); + if (w->desc_flags & WDF_UNCLICK_BUTTONS) + UnclickWindowButtons(w); + } + } +} + +Window *GetCallbackWnd() +{ + return FindWindowById(_thd.window_class, _thd.window_number); +} + +void HandlePlacePresize() +{ + Window *w; + WindowEvent e; + + if (_special_mouse_mode != WSM_PRESIZE) + return; + + if ((w = GetCallbackWnd()) == NULL) + return; + + e.place.pt = GetTileBelowCursor(); + if (e.place.pt.x == -1) { + _thd.selend.x = -1; + return; + } + e.place.tile = TILE_FROM_XY(e.place.pt.x, e.place.pt.y); + e.event = WE_PLACE_PRESIZE; + w->wndproc(w, &e); +} + +bool HandleDragDrop() +{ + Window *w; + WindowEvent e; + + if (_special_mouse_mode != WSM_DRAGDROP) + return true; + + if (_left_button_down) + return false; + + w = GetCallbackWnd(); + + ResetObjectToPlace(); + + if (w) { + // send an event in client coordinates. + e.event = WE_DRAGDROP; + e.dragdrop.pt.x = _cursor.pos.x - w->left; + e.dragdrop.pt.y = _cursor.pos.y - w->top; + e.dragdrop.widget = GetWidgetFromPos(w, e.dragdrop.pt.x, e.dragdrop.pt.y); + w->wndproc(w, &e); + } + return false; +} + +bool HandlePopupMenu() +{ + Window *w; + WindowEvent e; + + if (!_popup_menu_active) + return true; + + w = FindWindowById(WC_TOOLBAR_MENU, 0); + if (w == NULL) { + _popup_menu_active = false; + return false; + } + + if (_left_button_down) { + e.event = WE_POPUPMENU_OVER; + e.popupmenu.pt = _cursor.pos; + w->wndproc(w, &e); + } else { + _popup_menu_active = false; + e.event = WE_POPUPMENU_SELECT; + e.popupmenu.pt = _cursor.pos; + w->wndproc(w, &e); + } + + return false; +} + +bool HandleWindowDragging() +{ + Window *w; + int x, y, t; + + // Get out immediately if no window is being dragged at all. + if (!_dragging_window) + return true; + + // Otherwise find the window... + for(w=_windows; w != _last_window; w++) { + if (w->flags4&(WF_DRAGGING|WF_SIZING)) { + + // Stop the dragging if the left mouse button was released + if (!_left_button_down) { + w->flags4 &= ~(WF_DRAGGING | WF_SIZING); + break; + } + + // Otherwise calculate the delta position. + x = _cursor.pos.x; + y = clamp2(_cursor.pos.y, 23, _screen.height-12); + t = _cursorpos_drag_start.x; _cursorpos_drag_start.x = x; x-=t; + t = _cursorpos_drag_start.y; _cursorpos_drag_start.y = y; y-=t; + + // No movement? + if (x == 0 && y == 0) + return false; + + // Mark the old position dirty + SetWindowDirty(w); + + if (w->flags4 & WF_SIZING) { + // Size the window + w->width += x; + w->height += y; + } else { + // Move the window and viewport + w->left += x; + w->top += y; + if (w->viewport) { + w->viewport->left += x; + w->viewport->top += y; + } + } + + // And also mark the new position dirty. + SetWindowDirty(w); + return false; + } + } + + _dragging_window = false; + return false; +} + +Window *StartWindowDrag(Window *w) +{ + w->flags4 |= WF_DRAGGING; + _dragging_window = true; + _cursorpos_drag_start = _cursor.pos; + w = BringWindowToFront(w); + DeleteWindowById(WC_DROPDOWN_MENU, 0); + return w; +} + +Window *StartWindowSizing(Window *w) +{ + w->flags4 |= WF_SIZING; + _dragging_window = true; + _cursorpos_drag_start = _cursor.pos; + w = BringWindowToFront(w); + DeleteWindowById(WC_DROPDOWN_MENU, 0); + return w; +} + + +bool HandleScrollbarScrolling() +{ + Window *w; + int i; + int pos; + Scrollbar *sb; + + // Get out quickly if no item is being scrolled + if (!_scrolling_scrollbar) + return true; + + // Find the scrolling window + for(w=_windows; w != _last_window; w++) { + if (w->flags4 & WF_SCROLL_MIDDLE) { + // Abort if no button is clicked any more. + if (!_left_button_down) { + w->flags4 &= ~WF_SCROLL_MIDDLE; + SetWindowDirty(w); + break; + } + + if (w->flags4 & WF_HSCROLL) { + sb = &w->hscroll; + i = _cursor.pos.x - _cursorpos_drag_start.x; + } else { + sb = &w->vscroll; + i = _cursor.pos.y - _cursorpos_drag_start.y; + } + + // Find the item we want to move to and make sure it's inside bounds. + pos = min(max(0, i + _scrollbar_start_pos) * sb->count / _scrollbar_size, max(0, sb->count - sb->cap)); + if (pos != sb->pos) { + sb->pos = pos; + SetWindowDirty(w); + } + return false; + } + } + + _scrolling_scrollbar = false; + return false; +} + +bool HandleViewportScroll() +{ + Window *w; + ViewPort *vp; + int dx,dy, x, y, sub; + + if (!_scrolling_viewport) + return true; + + if (!_right_button_down) { +stop_capt:; + _cursor.fix_at = false; + _scrolling_viewport = false; + return true; + } + + w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); + if (w == NULL) goto stop_capt; + + if (w->window_class != WC_SMALLMAP) { + vp = IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y); + if (vp == NULL) + goto stop_capt; + + WP(w,vp_d).scrollpos_x += _cursor.delta.x << vp->zoom; + WP(w,vp_d).scrollpos_y += _cursor.delta.y << vp->zoom; + _cursor.delta.x = _cursor.delta.y = 0; + return false; + } else { + // scroll the smallmap ? + + _cursor.fix_at = true; + + dx = _cursor.delta.x; + dy = _cursor.delta.y; + + x = WP(w,smallmap_d).scroll_x; + y = WP(w,smallmap_d).scroll_y; + + sub = WP(w,smallmap_d).subscroll + dx; + + x -= (sub >> 2) << 4; + y += (sub >> 2) << 4; + sub &= 3; + + x += (dy >> 1) << 4; + y += (dy >> 1) << 4; + + if (dy & 1) { + x += 16; + sub += 2; + if (sub > 3) { + sub -= 4; + x -= 16; + y += 16; + } + } + + if (x < 16) { x = 16; sub = 0; } + if (x > (TILES_X-2)*16) { x = (TILES_X-2)*16; sub = 0; } + if (y < -1120) { y = -1120; sub = 0; } + if (y > (TILE_X_MAX-40) * 16) { y = (TILE_X_MAX-40) * 16; sub = 0; } + + WP(w,smallmap_d).scroll_x = x; + WP(w,smallmap_d).scroll_y = y; + WP(w,smallmap_d).subscroll = sub; + + _cursor.delta.x = _cursor.delta.y = 0; + + SetWindowDirty(w); + return false; + } +} + +static Window *MaybeBringWindowToFront(Window *w) +{ + Window *u; + + if (w->window_class == WC_MAIN_WINDOW || + w->window_class == WC_MAIN_TOOLBAR || + w->window_class == WC_STATUS_BAR || + w->window_class == WC_NEWS_WINDOW || + w->window_class == WC_TOOLTIPS || + w->window_class == WC_DROPDOWN_MENU) + return w; + + for(u=w; ++u != _last_window;) { + if (u->window_class == WC_MAIN_WINDOW || u->window_class==WC_MAIN_TOOLBAR || u->window_class==WC_STATUS_BAR || + u->window_class == WC_NEWS_WINDOW || u->window_class == WC_TOOLTIPS || u->window_class == WC_DROPDOWN_MENU) + continue; + + if (w->left + w->width <= u->left || + u->left + u->width <= w->left || + w->top + w->height <= u->top || + u->top + u->height <= w->top) + continue; + + return BringWindowToFront(w); + } + + return w; +} + +static void HandleKeypress(uint32 key) +{ + Window *w; + WindowEvent we; + + // Setup event + we.keypress.event = WE_KEYPRESS; + we.keypress.ascii = key & 0xFF; + we.keypress.keycode = key >> 16; + we.keypress.cont = true; + + // Call the event, start with the uppermost window. + for(w=_last_window; w != _windows;) { + --w; + w->wndproc(w, &we); + if (!we.keypress.cont) + break; + } +} + +extern void UpdateTileSelection(); +extern bool VpHandlePlaceSizingDrag(); + +void MouseLoop() +{ + int x,y; + Window *w; + ViewPort *vp; + int click; + int mousewheel; + + _current_player = _local_player; + + // Handle pressed keys + if (_pressed_key) { + uint32 key = _pressed_key; _pressed_key = 0; + HandleKeypress(key); + } + + // Mouse event? + click = 0; + if (_left_button_down && !_left_button_clicked) { + _left_button_clicked = true; + click = 1; + } else if (_right_button_clicked) { + _right_button_clicked = false; + click = 2; + } + + mousewheel = 0; + if (_cursor.wheel) { + mousewheel = _cursor.wheel; + _cursor.wheel = 0; + } + + DecreaseWindowCounters(); + HandlePlacePresize(); + UpdateTileSelection(); + if (!VpHandlePlaceSizingDrag()) + return; + + if (!HandleDragDrop()) + return; + + if (!HandlePopupMenu()) + return; + + if (!HandleWindowDragging()) + return; + + if (!HandleScrollbarScrolling()) + return; + + if (!HandleViewportScroll()) + return; + + x = _cursor.pos.x; + y = _cursor.pos.y; + + + if (click == 0 && mousewheel == 0) { + if (_patches.autoscroll && _game_mode != GM_MENU) { + w = FindWindowFromPt(x, y); + if (w == NULL || w->flags4 & WF_DISABLE_VP_SCROLL ) return; + vp = IsPtInWindowViewport(w, x, y); + if (vp) { + x -= vp->left; + y -= vp->top; + //here allows scrolling in both x and y axis +#define scrollspeed 3 + if (x-15<0) { WP(w,vp_d).scrollpos_x += (x-15) * scrollspeed << vp->zoom; } + else if (15-(vp->width-x) > 0) { WP(w,vp_d).scrollpos_x += (15-(vp->width-x))*scrollspeed << vp->zoom; } + if (y-15<0) { WP(w,vp_d).scrollpos_y += (y-15)*scrollspeed << vp->zoom; } + else if (15-(vp->height-y) > 0) { WP(w,vp_d).scrollpos_y += (15-(vp->height-y))*scrollspeed << vp->zoom; } +#undef scrollspeed + } + } + return; + } + + w = FindWindowFromPt(x, y); + if (w == NULL) + return; + w = MaybeBringWindowToFront(w); + vp = IsPtInWindowViewport(w, x, y); + if (vp != NULL) { + if (_game_mode == GM_MENU) + return; + + if (mousewheel && !(w->flags4 & WF_DISABLE_VP_SCROLL)) { + ZoomInOrOutToCursor(mousewheel < 0); + } + + if (click == 1) { + if (_thd.place_mode != 0 && + _cursor.sprite != 0x2CF && + _pause != 0 && + !_patches.build_in_pause) + return; + + if (_thd.place_mode == 0) { + HandleViewportClicked(vp, x, y); + } else { + PlaceObject(); + } + } else if (click == 2) { + if (!(w->flags4 & WF_DISABLE_VP_SCROLL)) { + _scrolling_viewport = true; + _cursor.fix_at = true; + } + } + } else { + if (mousewheel) + DispatchMouseWheelEvent(w, mousewheel); + + if (click == 1) + DispatchLeftClickEvent(w, x - w->left, y - w->top); + else if (click == 2) + DispatchRightClickEvent(w, x - w->left, y - w->top); + } +} + +static int _we4_timer; + +extern uint32 _pixels_redrawn; + +void UpdateWindows() +{ + Window *w; + int t; + + + if ((t=_we4_timer+1) >= 100) { + for(w = _last_window; w != _windows;) { + w--; + CallWindowEventNP(w, WE_4); + } + t = 0; + } + _we4_timer = t; + + for(w = _last_window; w != _windows;) { + w--; + if (w->flags4 & WF_WHITE_BORDER_MASK) { + w->flags4 -= WF_WHITE_BORDER_ONE; + if (!(w->flags4 & WF_WHITE_BORDER_MASK)) { + SetWindowDirty(w); + } + } + } + + DrawDirtyBlocks(); + + for(w = _windows; w!=_last_window; w++) { + if (w->viewport != NULL) + UpdateViewportPosition(w); + } + // Redraw mouse cursor in case it was hidden + DrawMouseCursor(); +} + + +int GetMenuItemIndex(Window *w, int x, int y) +{ + if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) { + y /= 10; + + if (y < WP(w,menu_d).item_count) + return y; + } + return -1; +} + +void InvalidateWindow(byte cls, WindowNumber number) +{ + Window *w; + + for(w=_windows; w!=_last_window; w++) { + if (w->window_class==cls && w->window_number==number) + SetWindowDirty(w); + } +} + +void InvalidateWidget(Window *w, byte widget_index) +{ + const Widget *wi = &w->widget[widget_index]; +// if (wi->left != -2) { + SetDirtyBlocks( + w->left + wi->left, + w->top + wi->top, + w->left + wi->right + 1, + w->top + wi->bottom + 1); +// } +} + +void InvalidateWindowWidget(byte cls, WindowNumber number, byte widget_index) +{ + Window *w; + + for(w=_windows; w!=_last_window; w++) { + if (w->window_class==cls && w->window_number==number) { + InvalidateWidget(w, widget_index); + } + } +} + +void InvalidateWindowClasses(byte cls) +{ + Window *w; + for(w=_windows; w!=_last_window; w++) { + if (w->window_class==cls) + SetWindowDirty(w); + } +} + + +void CallWindowTickEvent() +{ + Window *w; + for(w=_last_window; w != _windows;) { + --w; + CallWindowEventNP(w, WE_TICK); + } +} + +void DeleteNonVitalWindows() +{ + Window *w; + for(w=_windows; w!=_last_window;) { + if (w->window_class != WC_MAIN_WINDOW && + w->window_class != WC_SELECT_GAME && + w->window_class != WC_MAIN_TOOLBAR && + w->window_class != WC_STATUS_BAR && + w->window_class != WC_TOOLBAR_MENU && + w->window_class != WC_TOOLTIPS) { + DeleteWindow(w); + w = _windows; + } else { + w++; + } + } +} + +void RelocateAllWindows(int neww, int newh) +{ + Window *w; + + for(w=_windows; w!= _last_window ;w++) { + int left, top; + + if (w->window_class == WC_MAIN_WINDOW) { + ViewPort *vp = w->viewport; + vp->width = w->width = neww; + vp->height = w->height = newh; + vp->virtual_width = neww << vp->zoom; + vp->virtual_height = newh << vp->zoom; + continue; // don't modify top,left + } + + if (w->window_class == WC_MAIN_TOOLBAR) { + top = w->top; + left = (neww - w->width) >> 1; + } else if (w->window_class == WC_SELECT_GAME || w->window_class == WC_GAME_OPTIONS || w->window_class == WC_NETWORK_WINDOW){ + top = (newh - w->height) >> 1; + left = (neww - w->width) >> 1; + } else if (w->window_class == WC_NEWS_WINDOW) { + top = newh - w->height; + left = (neww - w->width) >> 1; + } else if (w->window_class == WC_STATUS_BAR) { + top = newh - w->height; + left = (neww - w->width) >> 1; + } else { + left = w->left; + if (left + (w->width>>1) >= neww) left = neww - w->width; + top = w->top; + if (top + (w->height>>1) >= newh) top = newh - w->height; + } + + if (w->viewport) { + w->viewport->left += left - w->left; + w->viewport->top += top - w->top; + } + + w->left = left; + w->top = top; + } +} + diff --git a/window.h b/window.h new file mode 100644 --- /dev/null +++ b/window.h @@ -0,0 +1,458 @@ +#ifndef WINDOW_H +#define WINDOW_H + +typedef union WindowEvent WindowEvent; + +//typedef void WindowProc(Window *w, int event, int wparam, long lparam); + +typedef void WindowProc(Window *w, WindowEvent *e); + +typedef struct Widget { + byte type; + byte color; + uint16 left, right, top, bottom; + uint16 unkA; + uint16 tooltips; +} Widget; + +union WindowEvent { + byte event; + struct { + byte event; + Point pt; + int widget; + } click; + + struct { + byte event; + Point pt; + uint tile; + uint starttile; + int userdata; + } place; + + struct { + byte event; + Point pt; + int widget; + } dragdrop; + + struct { + byte event; + byte *str; + } edittext; + + struct { + byte event; + Point pt; + } popupmenu; + + struct { + byte event; + int button; + int index; + } dropdown; + + struct { + byte event; + bool cont; // continue the search? (default true) + byte ascii; // 8-bit ASCII-value of the key + uint16 keycode;// untranslated key (including shift-state) + } keypress; +}; + +enum WindowKeyCodes { + WKC_SHIFT = 0x8000, + WKC_CTRL = 0x4000, + WKC_ALT = 0x2000, + WKC_META = 0x1000, + + // Special ones + WKC_NONE = 0, + WKC_ESC=1, + WKC_BACKSPACE = 2, + WKC_INSERT = 3, + WKC_DELETE = 4, + + WKC_PAGEUP = 5, + WKC_PAGEDOWN = 6, + WKC_END = 7, + WKC_HOME = 8, + + // Arrow keys + WKC_LEFT = 9, + WKC_UP = 10, + WKC_RIGHT = 11, + WKC_DOWN = 12, + + // Return & tab + WKC_RETURN = 13, + WKC_TAB = 14, + + // Numerical keyboard + WKC_NUM_0 = 16, + WKC_NUM_1 = 17, + WKC_NUM_2 = 18, + WKC_NUM_3 = 19, + WKC_NUM_4 = 20, + WKC_NUM_5 = 21, + WKC_NUM_6 = 22, + WKC_NUM_7 = 23, + WKC_NUM_8 = 24, + WKC_NUM_9 = 25, + WKC_NUM_DIV = 26, + WKC_NUM_MUL = 27, + WKC_NUM_MINUS = 28, + WKC_NUM_PLUS = 29, + WKC_NUM_ENTER = 30, + WKC_NUM_DECIMAL = 31, + + // Space + WKC_SPACE = 32, + + // Function keys + WKC_F1 = 33, + WKC_F2 = 34, + WKC_F3 = 35, + WKC_F4 = 36, + WKC_F5 = 37, + WKC_F6 = 38, + WKC_F7 = 39, + WKC_F8 = 40, + WKC_F9 = 41, + WKC_F10 = 42, + WKC_F11 = 43, + WKC_F12 = 44, + + // Required for french keyboard + WKC_AMPERSAND = 45, + + // 0-9 are mapped to 48-57 + // A-Z are mapped to 65-90 + // a-z are mapped to 97-122 + + + //WKC_UNKNOWN = 0xFF, + +}; + +typedef struct WindowDesc { + int16 left, top, width, height; + byte cls; + byte parent_cls; + uint32 flags; + const Widget *widgets; + WindowProc *proc; +} WindowDesc; + +enum { + WDF_STD_TOOLTIPS = 1, /* use standard routine when displaying tooltips */ + WDF_DEF_WIDGET = 2, /* default widget control for some widgets in the on click event */ + WDF_STD_BTN = 4, /* default handling for close and drag widgets (widget no 0 and 1) */ + WDF_RESTORE_DPARAM = 8, /* when drawing widgets, restore the dparam so all widgets recieve the same set of them */ + WDF_UNCLICK_BUTTONS=16, /* Unclick buttons when the window event times out */ +}; + +/* can be used as x or y coordinates to cause a specific placement */ +enum { + WDP_AUTO = -1, + WDP_CENTER = -2, +}; + +#define WP(ptr,str) (*(str*)(ptr)->custom) + +typedef struct { + byte count, cap, pos; +} Scrollbar; + +struct Window { + uint16 flags4; + WindowClass window_class; + WindowNumber window_number; + + int left,top; + int width,height; + + Scrollbar hscroll, vscroll; + + byte caption_color; + + uint32 click_state, disabled_state, hidden_state; + WindowProc *wndproc; + ViewPort *viewport; + const Widget *widget; + //const WindowDesc *desc; + uint32 desc_flags; + + byte custom[16]; +}; + +typedef struct { + byte item_count; /* follow_vehicle */ + byte sel_index; /* scrollpos_x */ + byte main_button; /* scrollpos_y */ + byte action_id; + StringID string_id; /* unk30 */ + uint16 checked_items; /* unk32 */ +} menu_d; + +typedef struct { + int16 data_1, data_2, data_3; + int16 data_4, data_5; + bool close; /* scrollpos_y */ + byte byte_1; +} def_d; + +typedef struct { + void *data; +} void_d; + +typedef struct { + uint16 base; /* follow_vehicle */ + uint16 count;/* scrollpos_x */ +} tree_d; + +typedef struct { + byte refresh_counter; /* follow_vehicle */ +} plstations_d; + +typedef struct { + StringID string_id; +} tooltips_d; + +typedef struct { + byte railtype; + byte sel_index; + int16 sel_engine; + int16 rename_engine; +} buildtrain_d; + +typedef struct { + VehicleID sel; +} traindepot_d; + +typedef struct { + int sel; +} order_d; + +typedef struct { + byte tab; +} traindetails_d; + +typedef struct { + int16 scroll_x, scroll_y, subscroll; +} smallmap_d; + +typedef struct { + uint32 face; + byte gender; +} facesel_d; + +typedef struct { + StringID caption; + bool caret; + WindowClass wnd_class; + WindowNumber wnd_num; + uint16 maxlen, maxwidth; + byte *buf; +} querystr_d; + +typedef struct { + int sel; + byte cargo; +} refit_d; + +typedef struct { + uint16 follow_vehicle; + int16 scrollpos_x, scrollpos_y; +} vp_d; + +typedef struct { + uint16 follow_vehicle; + int16 scrollpos_x, scrollpos_y; + NewsItem *ni; +} news_d; + +enum WindowEvents { + WE_CLICK = 0, + WE_PAINT = 1, + WE_MOUSELOOP = 2, + WE_TICK = 3, + WE_4 = 4, + WE_TIMEOUT = 5, + WE_PLACE_OBJ = 6, + WE_ABORT_PLACE_OBJ = 7, + WE_DESTROY = 8, + WE_ON_EDIT_TEXT = 9, + WE_POPUPMENU_SELECT = 10, + WE_POPUPMENU_OVER = 11, + WE_DRAGDROP = 12, + WE_PLACE_DRAG = 13, + WE_PLACE_MOUSEUP = 14, + WE_PLACE_PRESIZE = 15, + WE_DROPDOWN_SELECT = 16, + WE_RCLICK = 17, + WE_KEYPRESS = 18, +}; + + +/****************** THESE ARE NOT WIDGET TYPES!!!!! *******************/ +enum WindowWidgetBehaviours { + WWB_PUSHBUTTON = 1 << 5, + WWB_NODISBUTTON = 2 << 5, +}; + + +enum WindowWidgetTypes { + WWT_EMPTY = 0, + + WWT_IMGBTN = 1, /* button with image */ + WWT_PANEL = WWT_IMGBTN, + WWT_PANEL_2 = 2,/* button with diff image when clicked */ + + WWT_TEXTBTN = 3,/* button with text */ + WWT_CLOSEBOX = WWT_TEXTBTN, + WWT_4 = 4, /* button with diff text when clicked */ + WWT_5 = 5, /* label */ + WWT_6 = 6, /* combo box text area */ + WWT_MATRIX = 7, + WWT_SCROLLBAR = 8, + WWT_FRAME = 9, /* frame */ + WWT_CAPTION = 10, + + WWT_HSCROLLBAR = 11, + WWT_LAST = 12, + + WWT_MASK = 31, + + WWT_PUSHTXTBTN = WWT_TEXTBTN | WWB_PUSHBUTTON, + WWT_PUSHIMGBTN = WWT_IMGBTN | WWB_PUSHBUTTON, + WWT_NODISTXTBTN = WWT_TEXTBTN | WWB_NODISBUTTON, +}; + +enum WindowFlags { + WF_TIMEOUT_SHL = 0, + WF_TIMEOUT_MASK = 7, + WF_DRAGGING = 1 << 3, + WF_SCROLL_UP = 1 << 4, + WF_SCROLL_DOWN = 1 << 5, + WF_SCROLL_MIDDLE = 1 << 6, + WF_HSCROLL = 1 << 7, + WF_SIZING = 1 << 8, + + WF_DISABLE_VP_SCROLL = 1 << 10, + + WF_WHITE_BORDER_ONE = 1 << 11, + WF_WHITE_BORDER_MASK = 3 << 11, +}; + + +void DispatchLeftClickEvent(Window *w, int x, int y); +void DispatchRightClickEvent(Window *w, int x, int y); +void DispatchMouseWheelEvent(Window *w, int wheel); + +/* window.c */ +void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom); +void CallWindowEventNP(Window *w, int event); +void CallWindowTickEvent(); +void DrawDirtyBlocks(); +void SetDirtyBlocks(int left, int top, int right, int bottom); +void SetWindowDirty(Window *w); + +Window *FindWindowById(WindowClass cls, WindowNumber number); +void DeleteWindow(Window *w); +Window *BringWindowToFrontById(WindowClass cls, WindowNumber number); +Window *BringWindowToFront(Window *w); +Window *StartWindowDrag(Window *w); +Window *StartWindowSizing(Window *w); +Window *FindWindowFromPt(int x, int y); + +Window *AllocateWindow( + int x, + int y, + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget); + +Window *AllocateWindowDesc(const WindowDesc *desc); +Window *AllocateWindowDescFront(const WindowDesc *desc, int value); + +Window *AllocateWindowAutoPlace( + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget); + +Window *AllocateWindowAutoPlace2( + WindowClass exist_class, + WindowNumber exist_num, + int width, + int height, + WindowProc *proc, + WindowClass cls, + const Widget *widget); + +void DrawWindowViewport(Window *w); + +void InitWindowSystem(); +int GetMenuItemIndex(Window *w, int x, int y); +void MouseLoop(); +void UpdateWindows(); +void InvalidateWidget(Window *w, byte widget_index); + +void GuiShowTooltips(uint16 string_id); + +void UnclickWindowButtons(Window *w); +void UnclickSomeWindowButtons(Window *w, uint32 mask); +void RelocateAllWindows(int neww, int newh); + +/* widget.c */ +int GetWidgetFromPos(Window *w, int x, int y); +void DrawWindowWidgets(Window *w); + +void HandleButtonClick(Window *w, byte widget); + +Window *GetCallbackWnd(); +void DeleteNonVitalWindows(); + +/* window.c */ +VARDEF Window _windows[20]; +VARDEF Window *_last_window; + +VARDEF Point _cursorpos_drag_start; + +VARDEF bool _left_button_down; +VARDEF bool _left_button_clicked; + +VARDEF bool _right_button_down; +VARDEF bool _right_button_clicked; + +VARDEF int _alloc_wnd_parent_num; + +VARDEF int _scrollbar_start_pos; +VARDEF int _scrollbar_size; +VARDEF bool _demo_mode; +VARDEF byte _scroller_click_timeout; + +VARDEF bool _dragging_window; +VARDEF bool _scrolling_scrollbar; +VARDEF bool _scrolling_viewport; +VARDEF bool _popup_menu_active; +//VARDEF bool _dragdrop_active; + +VARDEF Point _fix_mouse_at; + +VARDEF byte _special_mouse_mode; +enum SpecialMouseMode { + WSM_NONE = 0, + WSM_DRAGDROP = 1, + WSM_SIZING = 2, + WSM_PRESIZE = 3, +}; + +void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y); + +#endif /* WINDOW_H */